blob: 8ebbfadf80f0c3bc88a991233434686986d086b4 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
33// Copyright 2006-2009 the V8 project authors. All rights reserved.
34
35#ifndef V8_ASSEMBLER_H_
36#define V8_ASSEMBLER_H_
37
Ben Murdochb8e0da22011-05-16 14:20:40 +010038#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "runtime.h"
40#include "top.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "token.h"
42
43namespace v8 {
44namespace internal {
45
46
47// -----------------------------------------------------------------------------
Ben Murdochb0fe1622011-05-05 13:52:32 +010048// Common double constants.
49
50class DoubleConstant: public AllStatic {
51 public:
52 static const double min_int;
53 static const double one_half;
Ben Murdochb8e0da22011-05-16 14:20:40 +010054 static const double minus_zero;
Ben Murdochb0fe1622011-05-05 13:52:32 +010055 static const double negative_infinity;
56};
57
58
59// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +000060// Labels represent pc locations; they are typically jump or call targets.
61// After declaration, a label can be freely used to denote known or (yet)
62// unknown pc location. Assembler::bind() is used to bind a label to the
63// current pc. A label can be bound only once.
64
65class Label BASE_EMBEDDED {
66 public:
67 INLINE(Label()) { Unuse(); }
68 INLINE(~Label()) { ASSERT(!is_linked()); }
69
70 INLINE(void Unuse()) { pos_ = 0; }
71
Kristian Monsen0d5e1162010-09-30 15:31:59 +010072 INLINE(bool is_bound() const) { return pos_ < 0; }
Steve Blocka7e24c12009-10-30 11:49:00 +000073 INLINE(bool is_unused() const) { return pos_ == 0; }
74 INLINE(bool is_linked() const) { return pos_ > 0; }
75
76 // Returns the position of bound or linked labels. Cannot be used
77 // for unused labels.
78 int pos() const;
79
80 private:
81 // pos_ encodes both the binding state (via its sign)
82 // and the binding position (via its value) of a label.
83 //
84 // pos_ < 0 bound label, pos() returns the jump target position
85 // pos_ == 0 unused label
86 // pos_ > 0 linked label, pos() returns the last reference position
87 int pos_;
88
89 void bind_to(int pos) {
90 pos_ = -pos - 1;
91 ASSERT(is_bound());
92 }
93 void link_to(int pos) {
94 pos_ = pos + 1;
95 ASSERT(is_linked());
96 }
97
98 friend class Assembler;
99 friend class RegexpAssembler;
100 friend class Displacement;
101 friend class ShadowTarget;
102 friend class RegExpMacroAssemblerIrregexp;
103};
104
105
106// -----------------------------------------------------------------------------
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100107// NearLabels are labels used for short jumps (in Intel jargon).
108// NearLabels should be used if it can be guaranteed that the jump range is
109// within -128 to +127. We already use short jumps when jumping backwards,
110// so using a NearLabel will only have performance impact if used for forward
111// jumps.
112class NearLabel BASE_EMBEDDED {
113 public:
114 NearLabel() { Unuse(); }
115 ~NearLabel() { ASSERT(!is_linked()); }
116
117 void Unuse() {
118 pos_ = -1;
119 unresolved_branches_ = 0;
120#ifdef DEBUG
121 for (int i = 0; i < kMaxUnresolvedBranches; i++) {
122 unresolved_positions_[i] = -1;
123 }
124#endif
125 }
126
127 int pos() {
128 ASSERT(is_bound());
129 return pos_;
130 }
131
132 bool is_bound() { return pos_ >= 0; }
133 bool is_linked() { return !is_bound() && unresolved_branches_ > 0; }
134 bool is_unused() { return !is_bound() && unresolved_branches_ == 0; }
135
136 void bind_to(int position) {
137 ASSERT(!is_bound());
138 pos_ = position;
139 }
140
141 void link_to(int position) {
142 ASSERT(!is_bound());
143 ASSERT(unresolved_branches_ < kMaxUnresolvedBranches);
144 unresolved_positions_[unresolved_branches_++] = position;
145 }
146
147 private:
148 static const int kMaxUnresolvedBranches = 8;
149 int pos_;
150 int unresolved_branches_;
151 int unresolved_positions_[kMaxUnresolvedBranches];
152
153 friend class Assembler;
154};
155
156
157// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000158// Relocation information
159
160
161// Relocation information consists of the address (pc) of the datum
162// to which the relocation information applies, the relocation mode
163// (rmode), and an optional data field. The relocation mode may be
164// "descriptive" and not indicate a need for relocation, but simply
165// describe a property of the datum. Such rmodes are useful for GC
166// and nice disassembly output.
167
168class RelocInfo BASE_EMBEDDED {
169 public:
170 // The constant kNoPosition is used with the collecting of source positions
171 // in the relocation information. Two types of source positions are collected
172 // "position" (RelocMode position) and "statement position" (RelocMode
173 // statement_position). The "position" is collected at places in the source
174 // code which are of interest when making stack traces to pin-point the source
175 // location of a stack frame as close as possible. The "statement position" is
176 // collected at the beginning at each statement, and is used to indicate
177 // possible break locations. kNoPosition is used to indicate an
178 // invalid/uninitialized position value.
179 static const int kNoPosition = -1;
180
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100181 // This string is used to add padding comments to the reloc info in cases
182 // where we are not sure to have enough space for patching in during
183 // lazy deoptimization. This is the case if we have indirect calls for which
184 // we do not normally record relocation info.
185 static const char* kFillerCommentString;
186
187 // The minimum size of a comment is equal to three bytes for the extra tagged
188 // pc + the tag for the data, and kPointerSize for the actual pointer to the
189 // comment.
190 static const int kMinRelocCommentSize = 3 + kPointerSize;
191
192 // The maximum size for a call instruction including pc-jump.
193 static const int kMaxCallSize = 6;
194
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 enum Mode {
196 // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
197 CONSTRUCT_CALL, // code target that is a call to a JavaScript constructor.
Steve Block1e0659c2011-05-24 12:43:12 +0100198 CODE_TARGET_CONTEXT, // Code target used for contextual loads and stores.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100199 DEBUG_BREAK, // Code target for the debugger statement.
200 CODE_TARGET, // Code target which is not any of the above.
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 EMBEDDED_OBJECT,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100202 GLOBAL_PROPERTY_CELL,
203
Steve Blocka7e24c12009-10-30 11:49:00 +0000204 // Everything after runtime_entry (inclusive) is not GC'ed.
205 RUNTIME_ENTRY,
206 JS_RETURN, // Marks start of the ExitJSFrame code.
207 COMMENT,
208 POSITION, // See comment for kNoPosition above.
209 STATEMENT_POSITION, // See comment for kNoPosition above.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100210 DEBUG_BREAK_SLOT, // Additional code inserted for debug break slot.
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 EXTERNAL_REFERENCE, // The address of an external C++ function.
212 INTERNAL_REFERENCE, // An address inside the same function.
213
214 // add more as needed
215 // Pseudo-types
216 NUMBER_OF_MODES, // must be no greater than 14 - see RelocInfoWriter
217 NONE, // never recorded
218 LAST_CODE_ENUM = CODE_TARGET,
Steve Block1e0659c2011-05-24 12:43:12 +0100219 LAST_GCED_ENUM = GLOBAL_PROPERTY_CELL
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 };
221
222
223 RelocInfo() {}
224 RelocInfo(byte* pc, Mode rmode, intptr_t data)
225 : pc_(pc), rmode_(rmode), data_(data) {
226 }
227
228 static inline bool IsConstructCall(Mode mode) {
229 return mode == CONSTRUCT_CALL;
230 }
231 static inline bool IsCodeTarget(Mode mode) {
232 return mode <= LAST_CODE_ENUM;
233 }
234 // Is the relocation mode affected by GC?
235 static inline bool IsGCRelocMode(Mode mode) {
236 return mode <= LAST_GCED_ENUM;
237 }
238 static inline bool IsJSReturn(Mode mode) {
239 return mode == JS_RETURN;
240 }
241 static inline bool IsComment(Mode mode) {
242 return mode == COMMENT;
243 }
244 static inline bool IsPosition(Mode mode) {
245 return mode == POSITION || mode == STATEMENT_POSITION;
246 }
247 static inline bool IsStatementPosition(Mode mode) {
248 return mode == STATEMENT_POSITION;
249 }
250 static inline bool IsExternalReference(Mode mode) {
251 return mode == EXTERNAL_REFERENCE;
252 }
253 static inline bool IsInternalReference(Mode mode) {
254 return mode == INTERNAL_REFERENCE;
255 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100256 static inline bool IsDebugBreakSlot(Mode mode) {
257 return mode == DEBUG_BREAK_SLOT;
258 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000259 static inline int ModeMask(Mode mode) { return 1 << mode; }
260
261 // Accessors
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100262 byte* pc() const { return pc_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000263 void set_pc(byte* pc) { pc_ = pc; }
264 Mode rmode() const { return rmode_; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100265 intptr_t data() const { return data_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000266
267 // Apply a relocation by delta bytes
268 INLINE(void apply(intptr_t delta));
269
Leon Clarkef7060e22010-06-03 12:02:55 +0100270 // Is the pointer this relocation info refers to coded like a plain pointer
271 // or is it strange in some way (eg relative or patched into a series of
272 // instructions).
273 bool IsCodedSpecially();
274
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 // Read/modify the code target in the branch/call instruction
276 // this relocation applies to;
277 // can only be called if IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
278 INLINE(Address target_address());
279 INLINE(void set_target_address(Address target));
280 INLINE(Object* target_object());
Steve Block3ce2e202009-11-05 08:53:23 +0000281 INLINE(Handle<Object> target_object_handle(Assembler* origin));
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 INLINE(Object** target_object_address());
283 INLINE(void set_target_object(Object* target));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100284 INLINE(JSGlobalPropertyCell* target_cell());
285 INLINE(Handle<JSGlobalPropertyCell> target_cell_handle());
286 INLINE(void set_target_cell(JSGlobalPropertyCell* cell));
287
Steve Blocka7e24c12009-10-30 11:49:00 +0000288
Leon Clarkef7060e22010-06-03 12:02:55 +0100289 // Read the address of the word containing the target_address in an
290 // instruction stream. What this means exactly is architecture-independent.
291 // The only architecture-independent user of this function is the serializer.
292 // The serializer uses it to find out how many raw bytes of instruction to
293 // output before the next target. Architecture-independent code shouldn't
294 // dereference the pointer it gets back from this.
Steve Blocka7e24c12009-10-30 11:49:00 +0000295 INLINE(Address target_address_address());
Leon Clarkef7060e22010-06-03 12:02:55 +0100296 // This indicates how much space a target takes up when deserializing a code
297 // stream. For most architectures this is just the size of a pointer. For
298 // an instruction like movw/movt where the target bits are mixed into the
299 // instruction bits the size of the target will be zero, indicating that the
300 // serializer should not step forwards in memory after a target is resolved
301 // and written. In this case the target_address_address function above
302 // should return the end of the instructions to be patched, allowing the
303 // deserializer to deserialize the instructions as raw bytes and put them in
304 // place, ready to be patched with the target.
305 INLINE(int target_address_size());
Steve Blocka7e24c12009-10-30 11:49:00 +0000306
307 // Read/modify the reference in the instruction this relocation
308 // applies to; can only be called if rmode_ is external_reference
309 INLINE(Address* target_reference_address());
310
311 // Read/modify the address of a call instruction. This is used to relocate
312 // the break points where straight-line code is patched with a call
313 // instruction.
314 INLINE(Address call_address());
315 INLINE(void set_call_address(Address target));
316 INLINE(Object* call_object());
Steve Blocka7e24c12009-10-30 11:49:00 +0000317 INLINE(void set_call_object(Object* target));
Ben Murdochbb769b22010-08-11 14:56:33 +0100318 INLINE(Object** call_object_address());
Steve Blocka7e24c12009-10-30 11:49:00 +0000319
Iain Merrick75681382010-08-19 15:07:18 +0100320 template<typename StaticVisitor> inline void Visit();
Leon Clarkef7060e22010-06-03 12:02:55 +0100321 inline void Visit(ObjectVisitor* v);
322
Steve Blocka7e24c12009-10-30 11:49:00 +0000323 // Patch the code with some other code.
324 void PatchCode(byte* instructions, int instruction_count);
325
326 // Patch the code with a call.
327 void PatchCodeWithCall(Address target, int guard_bytes);
Steve Block3ce2e202009-11-05 08:53:23 +0000328
329 // Check whether this return sequence has been patched
330 // with a call to the debugger.
331 INLINE(bool IsPatchedReturnSequence());
Steve Blocka7e24c12009-10-30 11:49:00 +0000332
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100333 // Check whether this debug break slot has been patched with a call to the
334 // debugger.
335 INLINE(bool IsPatchedDebugBreakSlotSequence());
336
Steve Blocka7e24c12009-10-30 11:49:00 +0000337#ifdef ENABLE_DISASSEMBLER
338 // Printing
339 static const char* RelocModeName(Mode rmode);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100340 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000341#endif // ENABLE_DISASSEMBLER
342#ifdef DEBUG
343 // Debugging
344 void Verify();
345#endif
346
347 static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
348 static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION;
349 static const int kDebugMask = kPositionMask | 1 << COMMENT;
350 static const int kApplyMask; // Modes affected by apply. Depends on arch.
351
352 private:
353 // On ARM, note that pc_ is the address of the constant pool entry
354 // to be relocated and not the address of the instruction
355 // referencing the constant pool entry (except when rmode_ ==
356 // comment).
357 byte* pc_;
358 Mode rmode_;
359 intptr_t data_;
360 friend class RelocIterator;
361};
362
363
364// RelocInfoWriter serializes a stream of relocation info. It writes towards
365// lower addresses.
366class RelocInfoWriter BASE_EMBEDDED {
367 public:
368 RelocInfoWriter() : pos_(NULL), last_pc_(NULL), last_data_(0) {}
369 RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), last_pc_(pc),
370 last_data_(0) {}
371
372 byte* pos() const { return pos_; }
373 byte* last_pc() const { return last_pc_; }
374
375 void Write(const RelocInfo* rinfo);
376
377 // Update the state of the stream after reloc info buffer
378 // and/or code is moved while the stream is active.
379 void Reposition(byte* pos, byte* pc) {
380 pos_ = pos;
381 last_pc_ = pc;
382 }
383
384 // Max size (bytes) of a written RelocInfo. Longest encoding is
385 // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta.
386 // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12.
387 // On x64 this is 1 + 4 + 1 + 1 + 1 + 8 == 16;
388 // Here we use the maximum of the two.
389 static const int kMaxSize = 16;
390
391 private:
392 inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
393 inline void WriteTaggedPC(uint32_t pc_delta, int tag);
394 inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
395 inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
396 inline void WriteTaggedData(intptr_t data_delta, int tag);
397 inline void WriteExtraTag(int extra_tag, int top_tag);
398
399 byte* pos_;
400 byte* last_pc_;
401 intptr_t last_data_;
402 DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
403};
404
405
406// A RelocIterator iterates over relocation information.
407// Typical use:
408//
409// for (RelocIterator it(code); !it.done(); it.next()) {
410// // do something with it.rinfo() here
411// }
412//
413// A mask can be specified to skip unwanted modes.
414class RelocIterator: public Malloced {
415 public:
416 // Create a new iterator positioned at
417 // the beginning of the reloc info.
418 // Relocation information with mode k is included in the
419 // iteration iff bit k of mode_mask is set.
420 explicit RelocIterator(Code* code, int mode_mask = -1);
421 explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
422
423 // Iteration
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100424 bool done() const { return done_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000425 void next();
426
427 // Return pointer valid until next next().
428 RelocInfo* rinfo() {
429 ASSERT(!done());
430 return &rinfo_;
431 }
432
433 private:
434 // Advance* moves the position before/after reading.
435 // *Read* reads from current byte(s) into rinfo_.
436 // *Get* just reads and returns info on current byte.
437 void Advance(int bytes = 1) { pos_ -= bytes; }
438 int AdvanceGetTag();
439 int GetExtraTag();
440 int GetTopTag();
441 void ReadTaggedPC();
442 void AdvanceReadPC();
443 void AdvanceReadData();
444 void AdvanceReadVariableLengthPCJump();
445 int GetPositionTypeTag();
446 void ReadTaggedData();
447
448 static RelocInfo::Mode DebugInfoModeFromTag(int tag);
449
450 // If the given mode is wanted, set it in rinfo_ and return true.
451 // Else return false. Used for efficiently skipping unwanted modes.
452 bool SetMode(RelocInfo::Mode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100453 return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 }
455
456 byte* pos_;
457 byte* end_;
458 RelocInfo rinfo_;
459 bool done_;
460 int mode_mask_;
461 DISALLOW_COPY_AND_ASSIGN(RelocIterator);
462};
463
464
465//------------------------------------------------------------------------------
466// External function
467
468//----------------------------------------------------------------------------
469class IC_Utility;
470class SCTableReference;
471#ifdef ENABLE_DEBUGGER_SUPPORT
472class Debug_Address;
473#endif
474
475
Steve Blocka7e24c12009-10-30 11:49:00 +0000476// An ExternalReference represents a C++ address used in the generated
477// code. All references to C++ functions and variables must be encapsulated in
478// an ExternalReference instance. This is done in order to track the origin of
479// all external references in the code so that they can be bound to the correct
480// addresses when deserializing a heap.
481class ExternalReference BASE_EMBEDDED {
482 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100483 // Used in the simulator to support different native api calls.
Steve Block1e0659c2011-05-24 12:43:12 +0100484 enum Type {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100485 // Builtin call.
486 // MaybeObject* f(v8::internal::Arguments).
Steve Block1e0659c2011-05-24 12:43:12 +0100487 BUILTIN_CALL, // default
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100488
489 // Builtin call that returns floating point.
490 // double f(double, double).
Steve Block1e0659c2011-05-24 12:43:12 +0100491 FP_RETURN_CALL,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100492
493 // Direct call to API function callback.
494 // Handle<Value> f(v8::Arguments&)
495 DIRECT_API_CALL,
496
497 // Direct call to accessor getter callback.
498 // Handle<value> f(Local<String> property, AccessorInfo& info)
499 DIRECT_GETTER_CALL
Steve Block1e0659c2011-05-24 12:43:12 +0100500 };
501
502 typedef void* ExternalReferenceRedirector(void* original, Type type);
503
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 explicit ExternalReference(Builtins::CFunctionId id);
505
Steve Block1e0659c2011-05-24 12:43:12 +0100506 explicit ExternalReference(ApiFunction* ptr, Type type);
Steve Blockd0582a62009-12-15 09:54:21 +0000507
Steve Blocka7e24c12009-10-30 11:49:00 +0000508 explicit ExternalReference(Builtins::Name name);
509
510 explicit ExternalReference(Runtime::FunctionId id);
511
512 explicit ExternalReference(Runtime::Function* f);
513
514 explicit ExternalReference(const IC_Utility& ic_utility);
515
516#ifdef ENABLE_DEBUGGER_SUPPORT
517 explicit ExternalReference(const Debug_Address& debug_address);
518#endif
519
520 explicit ExternalReference(StatsCounter* counter);
521
522 explicit ExternalReference(Top::AddressId id);
523
524 explicit ExternalReference(const SCTableReference& table_ref);
525
526 // One-of-a-kind references. These references are not part of a general
527 // pattern. This means that they have to be added to the
528 // ExternalReferenceTable in serialize.cc manually.
529
530 static ExternalReference perform_gc_function();
Steve Block6ded16b2010-05-10 14:33:55 +0100531 static ExternalReference fill_heap_number_with_random_function();
532 static ExternalReference random_uint32_function();
Andrei Popescu402d9372010-02-26 13:31:12 +0000533 static ExternalReference transcendental_cache_array_address();
John Reck59135872010-11-02 12:39:01 -0700534 static ExternalReference delete_handle_scope_extensions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000535
Ben Murdochb0fe1622011-05-05 13:52:32 +0100536 // Deoptimization support.
537 static ExternalReference new_deoptimizer_function();
538 static ExternalReference compute_output_frames_function();
539 static ExternalReference global_contexts_list();
540
Leon Clarkee46be812010-01-19 14:06:41 +0000541 // Static data in the keyed lookup cache.
542 static ExternalReference keyed_lookup_cache_keys();
543 static ExternalReference keyed_lookup_cache_field_offsets();
544
Steve Blocka7e24c12009-10-30 11:49:00 +0000545 // Static variable Factory::the_hole_value.location()
546 static ExternalReference the_hole_value_location();
547
Ben Murdoch086aeea2011-05-13 15:57:08 +0100548 // Static variable Factory::arguments_marker.location()
549 static ExternalReference arguments_marker_location();
550
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 // Static variable Heap::roots_address()
552 static ExternalReference roots_address();
553
554 // Static variable StackGuard::address_of_jslimit()
Steve Blockd0582a62009-12-15 09:54:21 +0000555 static ExternalReference address_of_stack_limit();
556
557 // Static variable StackGuard::address_of_real_jslimit()
558 static ExternalReference address_of_real_stack_limit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000559
560 // Static variable RegExpStack::limit_address()
561 static ExternalReference address_of_regexp_stack_limit();
562
Leon Clarkee46be812010-01-19 14:06:41 +0000563 // Static variables for RegExp.
564 static ExternalReference address_of_static_offsets_vector();
565 static ExternalReference address_of_regexp_stack_memory_address();
566 static ExternalReference address_of_regexp_stack_memory_size();
567
Steve Blocka7e24c12009-10-30 11:49:00 +0000568 // Static variable Heap::NewSpaceStart()
569 static ExternalReference new_space_start();
Andrei Popescu402d9372010-02-26 13:31:12 +0000570 static ExternalReference new_space_mask();
Steve Blocka7e24c12009-10-30 11:49:00 +0000571 static ExternalReference heap_always_allocate_scope_depth();
572
573 // Used for fast allocation in generated code.
574 static ExternalReference new_space_allocation_top_address();
575 static ExternalReference new_space_allocation_limit_address();
576
577 static ExternalReference double_fp_operation(Token::Value operation);
578 static ExternalReference compare_doubles();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100579 static ExternalReference power_double_double_function();
580 static ExternalReference power_double_int_function();
Steve Blocka7e24c12009-10-30 11:49:00 +0000581
Steve Blockd0582a62009-12-15 09:54:21 +0000582 static ExternalReference handle_scope_next_address();
583 static ExternalReference handle_scope_limit_address();
John Reck59135872010-11-02 12:39:01 -0700584 static ExternalReference handle_scope_level_address();
Steve Blockd0582a62009-12-15 09:54:21 +0000585
586 static ExternalReference scheduled_exception_address();
587
Ben Murdochb0fe1622011-05-05 13:52:32 +0100588 // Static variables containing common double constants.
589 static ExternalReference address_of_min_int();
590 static ExternalReference address_of_one_half();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100591 static ExternalReference address_of_minus_zero();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100592 static ExternalReference address_of_negative_infinity();
593
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100594 static ExternalReference math_sin_double_function();
595 static ExternalReference math_cos_double_function();
596 static ExternalReference math_log_double_function();
597
Steve Blocka7e24c12009-10-30 11:49:00 +0000598 Address address() const {return reinterpret_cast<Address>(address_);}
599
600#ifdef ENABLE_DEBUGGER_SUPPORT
601 // Function Debug::Break()
602 static ExternalReference debug_break();
603
604 // Used to check if single stepping is enabled in generated code.
605 static ExternalReference debug_step_in_fp_address();
606#endif
607
Steve Block6ded16b2010-05-10 14:33:55 +0100608#ifndef V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +0000609 // C functions called from RegExp generated code.
610
611 // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
612 static ExternalReference re_case_insensitive_compare_uc16();
613
614 // Function RegExpMacroAssembler*::CheckStackGuardState()
615 static ExternalReference re_check_stack_guard_state();
616
617 // Function NativeRegExpMacroAssembler::GrowStack()
618 static ExternalReference re_grow_stack();
Leon Clarkee46be812010-01-19 14:06:41 +0000619
620 // byte NativeRegExpMacroAssembler::word_character_bitmap
621 static ExternalReference re_word_character_map();
622
Steve Blocka7e24c12009-10-30 11:49:00 +0000623#endif
624
625 // This lets you register a function that rewrites all external references.
626 // Used by the ARM simulator to catch calls to external references.
627 static void set_redirector(ExternalReferenceRedirector* redirector) {
628 ASSERT(redirector_ == NULL); // We can't stack them.
629 redirector_ = redirector;
630 }
631
632 private:
633 explicit ExternalReference(void* address)
634 : address_(address) {}
635
636 static ExternalReferenceRedirector* redirector_;
637
Steve Block1e0659c2011-05-24 12:43:12 +0100638 static void* Redirect(void* address,
639 Type type = ExternalReference::BUILTIN_CALL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000640 if (redirector_ == NULL) return address;
Steve Block1e0659c2011-05-24 12:43:12 +0100641 void* answer = (*redirector_)(address, type);
Steve Blockd0582a62009-12-15 09:54:21 +0000642 return answer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000643 }
644
Steve Block1e0659c2011-05-24 12:43:12 +0100645 static void* Redirect(Address address_arg,
646 Type type = ExternalReference::BUILTIN_CALL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 void* address = reinterpret_cast<void*>(address_arg);
Steve Blockd0582a62009-12-15 09:54:21 +0000648 void* answer = (redirector_ == NULL) ?
649 address :
Steve Block1e0659c2011-05-24 12:43:12 +0100650 (*redirector_)(address, type);
Steve Blockd0582a62009-12-15 09:54:21 +0000651 return answer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 }
653
654 void* address_;
655};
656
657
658// -----------------------------------------------------------------------------
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800659// Position recording support
660
Ben Murdochb0fe1622011-05-05 13:52:32 +0100661struct PositionState {
662 PositionState() : current_position(RelocInfo::kNoPosition),
663 written_position(RelocInfo::kNoPosition),
664 current_statement_position(RelocInfo::kNoPosition),
665 written_statement_position(RelocInfo::kNoPosition) {}
666
667 int current_position;
668 int written_position;
669
670 int current_statement_position;
671 int written_statement_position;
672};
673
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800674
675class PositionsRecorder BASE_EMBEDDED {
676 public:
677 explicit PositionsRecorder(Assembler* assembler)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100678 : assembler_(assembler) {
679#ifdef ENABLE_GDB_JIT_INTERFACE
680 gdbjit_lineinfo_ = NULL;
681#endif
682 }
683
684#ifdef ENABLE_GDB_JIT_INTERFACE
685 ~PositionsRecorder() {
686 delete gdbjit_lineinfo_;
687 }
688
689 void StartGDBJITLineInfoRecording() {
690 if (FLAG_gdbjit) {
691 gdbjit_lineinfo_ = new GDBJITLineInfo();
692 }
693 }
694
695 GDBJITLineInfo* DetachGDBJITLineInfo() {
696 GDBJITLineInfo* lineinfo = gdbjit_lineinfo_;
697 gdbjit_lineinfo_ = NULL; // To prevent deallocation in destructor.
698 return lineinfo;
699 }
700#endif
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800701
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 // Set current position to pos.
703 void RecordPosition(int pos);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800704
705 // Set current statement position to pos.
706 void RecordStatementPosition(int pos);
707
708 // Write recorded positions to relocation information.
709 bool WriteRecordedPositions();
710
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 int current_position() const { return state_.current_position; }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800712
Ben Murdochb0fe1622011-05-05 13:52:32 +0100713 int current_statement_position() const {
714 return state_.current_statement_position;
715 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800716
717 private:
718 Assembler* assembler_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100719 PositionState state_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100720#ifdef ENABLE_GDB_JIT_INTERFACE
721 GDBJITLineInfo* gdbjit_lineinfo_;
722#endif
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800723
Ben Murdochb0fe1622011-05-05 13:52:32 +0100724 friend class PreservePositionScope;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800725
Ben Murdochb0fe1622011-05-05 13:52:32 +0100726 DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800727};
728
729
Ben Murdochb0fe1622011-05-05 13:52:32 +0100730class PreservePositionScope BASE_EMBEDDED {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800731 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100732 explicit PreservePositionScope(PositionsRecorder* positions_recorder)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800733 : positions_recorder_(positions_recorder),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100734 saved_state_(positions_recorder->state_) {}
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800735
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736 ~PreservePositionScope() {
737 positions_recorder_->state_ = saved_state_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800738 }
739
740 private:
741 PositionsRecorder* positions_recorder_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100742 const PositionState saved_state_;
743
744 DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800745};
746
747
748// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000749// Utility functions
750
751static inline bool is_intn(int x, int n) {
752 return -(1 << (n-1)) <= x && x < (1 << (n-1));
753}
754
Steve Blocka7e24c12009-10-30 11:49:00 +0000755static inline bool is_int8(int x) { return is_intn(x, 8); }
Andrei Popescu31002712010-02-23 13:46:05 +0000756static inline bool is_int16(int x) { return is_intn(x, 16); }
757static inline bool is_int18(int x) { return is_intn(x, 18); }
758static inline bool is_int24(int x) { return is_intn(x, 24); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000759
760static inline bool is_uintn(int x, int n) {
761 return (x & -(1 << n)) == 0;
762}
763
764static inline bool is_uint2(int x) { return is_uintn(x, 2); }
765static inline bool is_uint3(int x) { return is_uintn(x, 3); }
766static inline bool is_uint4(int x) { return is_uintn(x, 4); }
767static inline bool is_uint5(int x) { return is_uintn(x, 5); }
768static inline bool is_uint6(int x) { return is_uintn(x, 6); }
769static inline bool is_uint8(int x) { return is_uintn(x, 8); }
Andrei Popescu31002712010-02-23 13:46:05 +0000770static inline bool is_uint10(int x) { return is_uintn(x, 10); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000771static inline bool is_uint12(int x) { return is_uintn(x, 12); }
772static inline bool is_uint16(int x) { return is_uintn(x, 16); }
773static inline bool is_uint24(int x) { return is_uintn(x, 24); }
Andrei Popescu31002712010-02-23 13:46:05 +0000774static inline bool is_uint26(int x) { return is_uintn(x, 26); }
775static inline bool is_uint28(int x) { return is_uintn(x, 28); }
776
777static inline int NumberOfBitsSet(uint32_t x) {
778 unsigned int num_bits_set;
779 for (num_bits_set = 0; x; x >>= 1) {
780 num_bits_set += x & 1;
781 }
782 return num_bits_set;
783}
Steve Blocka7e24c12009-10-30 11:49:00 +0000784
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785// Computes pow(x, y) with the special cases in the spec for Math.pow.
786double power_double_int(double x, int y);
787double power_double_double(double x, double y);
788
Steve Blocka7e24c12009-10-30 11:49:00 +0000789} } // namespace v8::internal
790
791#endif // V8_ASSEMBLER_H_