• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 #include "v8.h"
36 
37 #include "arguments.h"
38 #include "deoptimizer.h"
39 #include "execution.h"
40 #include "ic-inl.h"
41 #include "factory.h"
42 #include "runtime.h"
43 #include "runtime-profiler.h"
44 #include "serialize.h"
45 #include "stub-cache.h"
46 #include "regexp-stack.h"
47 #include "ast.h"
48 #include "regexp-macro-assembler.h"
49 #include "platform.h"
50 // Include native regexp-macro-assembler.
51 #ifndef V8_INTERPRETED_REGEXP
52 #if V8_TARGET_ARCH_IA32
53 #include "ia32/regexp-macro-assembler-ia32.h"
54 #elif V8_TARGET_ARCH_X64
55 #include "x64/regexp-macro-assembler-x64.h"
56 #elif V8_TARGET_ARCH_ARM
57 #include "arm/regexp-macro-assembler-arm.h"
58 #elif V8_TARGET_ARCH_MIPS
59 #include "mips/regexp-macro-assembler-mips.h"
60 #else  // Unknown architecture.
61 #error "Unknown architecture."
62 #endif  // Target architecture.
63 #endif  // V8_INTERPRETED_REGEXP
64 
65 namespace v8 {
66 namespace internal {
67 
68 
69 const double DoubleConstant::min_int = kMinInt;
70 const double DoubleConstant::one_half = 0.5;
71 const double DoubleConstant::minus_zero = -0.0;
72 const double DoubleConstant::nan = OS::nan_value();
73 const double DoubleConstant::negative_infinity = -V8_INFINITY;
74 const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
75 
76 // -----------------------------------------------------------------------------
77 // Implementation of AssemblerBase
78 
AssemblerBase(Isolate * isolate)79 AssemblerBase::AssemblerBase(Isolate* isolate)
80     : isolate_(isolate),
81       jit_cookie_(0) {
82   if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
83     jit_cookie_ = V8::RandomPrivate(isolate);
84   }
85 }
86 
87 
88 // -----------------------------------------------------------------------------
89 // Implementation of Label
90 
pos() const91 int Label::pos() const {
92   if (pos_ < 0) return -pos_ - 1;
93   if (pos_ > 0) return  pos_ - 1;
94   UNREACHABLE();
95   return 0;
96 }
97 
98 
99 // -----------------------------------------------------------------------------
100 // Implementation of RelocInfoWriter and RelocIterator
101 //
102 // Encoding
103 //
104 // The most common modes are given single-byte encodings.  Also, it is
105 // easy to identify the type of reloc info and skip unwanted modes in
106 // an iteration.
107 //
108 // The encoding relies on the fact that there are less than 14
109 // different relocation modes.
110 //
111 // embedded_object:    [6 bits pc delta] 00
112 //
113 // code_taget:         [6 bits pc delta] 01
114 //
115 // position:           [6 bits pc delta] 10,
116 //                     [7 bits signed data delta] 0
117 //
118 // statement_position: [6 bits pc delta] 10,
119 //                     [7 bits signed data delta] 1
120 //
121 // any nondata mode:   00 [4 bits rmode] 11,  // rmode: 0..13 only
122 //                     00 [6 bits pc delta]
123 //
124 // pc-jump:            00 1111 11,
125 //                     00 [6 bits pc delta]
126 //
127 // pc-jump:            01 1111 11,
128 // (variable length)   7 - 26 bit pc delta, written in chunks of 7
129 //                     bits, the lowest 7 bits written first.
130 //
131 // data-jump + pos:    00 1110 11,
132 //                     signed intptr_t, lowest byte written first
133 //
134 // data-jump + st.pos: 01 1110 11,
135 //                     signed intptr_t, lowest byte written first
136 //
137 // data-jump + comm.:  10 1110 11,
138 //                     signed intptr_t, lowest byte written first
139 //
140 const int kMaxRelocModes = 14;
141 
142 const int kTagBits = 2;
143 const int kTagMask = (1 << kTagBits) - 1;
144 const int kExtraTagBits = 4;
145 const int kPositionTypeTagBits = 1;
146 const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits;
147 
148 const int kEmbeddedObjectTag = 0;
149 const int kCodeTargetTag = 1;
150 const int kPositionTag = 2;
151 const int kDefaultTag = 3;
152 
153 const int kPCJumpTag = (1 << kExtraTagBits) - 1;
154 
155 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
156 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
157 const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
158 
159 const int kVariableLengthPCJumpTopTag = 1;
160 const int kChunkBits = 7;
161 const int kChunkMask = (1 << kChunkBits) - 1;
162 const int kLastChunkTagBits = 1;
163 const int kLastChunkTagMask = 1;
164 const int kLastChunkTag = 1;
165 
166 
167 const int kDataJumpTag = kPCJumpTag - 1;
168 
169 const int kNonstatementPositionTag = 0;
170 const int kStatementPositionTag = 1;
171 const int kCommentTag = 2;
172 
173 
WriteVariableLengthPCJump(uint32_t pc_delta)174 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
175   // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
176   // Otherwise write a variable length PC jump for the bits that do
177   // not fit in the kSmallPCDeltaBits bits.
178   if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
179   WriteExtraTag(kPCJumpTag, kVariableLengthPCJumpTopTag);
180   uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
181   ASSERT(pc_jump > 0);
182   // Write kChunkBits size chunks of the pc_jump.
183   for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
184     byte b = pc_jump & kChunkMask;
185     *--pos_ = b << kLastChunkTagBits;
186   }
187   // Tag the last chunk so it can be identified.
188   *pos_ = *pos_ | kLastChunkTag;
189   // Return the remaining kSmallPCDeltaBits of the pc_delta.
190   return pc_delta & kSmallPCDeltaMask;
191 }
192 
193 
WriteTaggedPC(uint32_t pc_delta,int tag)194 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
195   // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
196   pc_delta = WriteVariableLengthPCJump(pc_delta);
197   *--pos_ = pc_delta << kTagBits | tag;
198 }
199 
200 
WriteTaggedData(intptr_t data_delta,int tag)201 void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
202   *--pos_ = static_cast<byte>(data_delta << kPositionTypeTagBits | tag);
203 }
204 
205 
WriteExtraTag(int extra_tag,int top_tag)206 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
207   *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
208                              extra_tag << kTagBits |
209                              kDefaultTag);
210 }
211 
212 
WriteExtraTaggedPC(uint32_t pc_delta,int extra_tag)213 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
214   // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
215   pc_delta = WriteVariableLengthPCJump(pc_delta);
216   WriteExtraTag(extra_tag, 0);
217   *--pos_ = pc_delta;
218 }
219 
220 
WriteExtraTaggedData(intptr_t data_delta,int top_tag)221 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
222   WriteExtraTag(kDataJumpTag, top_tag);
223   for (int i = 0; i < kIntptrSize; i++) {
224     *--pos_ = static_cast<byte>(data_delta);
225   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
226     data_delta = data_delta >> kBitsPerByte;
227   }
228 }
229 
230 
Write(const RelocInfo * rinfo)231 void RelocInfoWriter::Write(const RelocInfo* rinfo) {
232 #ifdef DEBUG
233   byte* begin_pos = pos_;
234 #endif
235   ASSERT(rinfo->pc() - last_pc_ >= 0);
236   ASSERT(RelocInfo::NUMBER_OF_MODES <= kMaxRelocModes);
237   // Use unsigned delta-encoding for pc.
238   uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
239   RelocInfo::Mode rmode = rinfo->rmode();
240 
241   // The two most common modes are given small tags, and usually fit in a byte.
242   if (rmode == RelocInfo::EMBEDDED_OBJECT) {
243     WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
244   } else if (rmode == RelocInfo::CODE_TARGET) {
245     WriteTaggedPC(pc_delta, kCodeTargetTag);
246     ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
247   } else if (RelocInfo::IsPosition(rmode)) {
248     // Use signed delta-encoding for data.
249     intptr_t data_delta = rinfo->data() - last_data_;
250     int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag
251                                                     : kStatementPositionTag;
252     // Check if data is small enough to fit in a tagged byte.
253     // We cannot use is_intn because data_delta is not an int32_t.
254     if (data_delta >= -(1 << (kSmallDataBits-1)) &&
255         data_delta < 1 << (kSmallDataBits-1)) {
256       WriteTaggedPC(pc_delta, kPositionTag);
257       WriteTaggedData(data_delta, pos_type_tag);
258       last_data_ = rinfo->data();
259     } else {
260       // Otherwise, use costly encoding.
261       WriteExtraTaggedPC(pc_delta, kPCJumpTag);
262       WriteExtraTaggedData(data_delta, pos_type_tag);
263       last_data_ = rinfo->data();
264     }
265   } else if (RelocInfo::IsComment(rmode)) {
266     // Comments are normally not generated, so we use the costly encoding.
267     WriteExtraTaggedPC(pc_delta, kPCJumpTag);
268     WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag);
269     last_data_ = rinfo->data();
270     ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
271   } else {
272     // For all other modes we simply use the mode as the extra tag.
273     // None of these modes need a data component.
274     ASSERT(rmode < kPCJumpTag && rmode < kDataJumpTag);
275     WriteExtraTaggedPC(pc_delta, rmode);
276   }
277   last_pc_ = rinfo->pc();
278 #ifdef DEBUG
279   ASSERT(begin_pos - pos_ <= kMaxSize);
280 #endif
281 }
282 
283 
AdvanceGetTag()284 inline int RelocIterator::AdvanceGetTag() {
285   return *--pos_ & kTagMask;
286 }
287 
288 
GetExtraTag()289 inline int RelocIterator::GetExtraTag() {
290   return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
291 }
292 
293 
GetTopTag()294 inline int RelocIterator::GetTopTag() {
295   return *pos_ >> (kTagBits + kExtraTagBits);
296 }
297 
298 
ReadTaggedPC()299 inline void RelocIterator::ReadTaggedPC() {
300   rinfo_.pc_ += *pos_ >> kTagBits;
301 }
302 
303 
AdvanceReadPC()304 inline void RelocIterator::AdvanceReadPC() {
305   rinfo_.pc_ += *--pos_;
306 }
307 
308 
AdvanceReadData()309 void RelocIterator::AdvanceReadData() {
310   intptr_t x = 0;
311   for (int i = 0; i < kIntptrSize; i++) {
312     x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
313   }
314   rinfo_.data_ += x;
315 }
316 
317 
AdvanceReadVariableLengthPCJump()318 void RelocIterator::AdvanceReadVariableLengthPCJump() {
319   // Read the 32-kSmallPCDeltaBits most significant bits of the
320   // pc jump in kChunkBits bit chunks and shift them into place.
321   // Stop when the last chunk is encountered.
322   uint32_t pc_jump = 0;
323   for (int i = 0; i < kIntSize; i++) {
324     byte pc_jump_part = *--pos_;
325     pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
326     if ((pc_jump_part & kLastChunkTagMask) == 1) break;
327   }
328   // The least significant kSmallPCDeltaBits bits will be added
329   // later.
330   rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
331 }
332 
333 
GetPositionTypeTag()334 inline int RelocIterator::GetPositionTypeTag() {
335   return *pos_ & ((1 << kPositionTypeTagBits) - 1);
336 }
337 
338 
ReadTaggedData()339 inline void RelocIterator::ReadTaggedData() {
340   int8_t signed_b = *pos_;
341   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
342   rinfo_.data_ += signed_b >> kPositionTypeTagBits;
343 }
344 
345 
DebugInfoModeFromTag(int tag)346 inline RelocInfo::Mode RelocIterator::DebugInfoModeFromTag(int tag) {
347   if (tag == kStatementPositionTag) {
348     return RelocInfo::STATEMENT_POSITION;
349   } else if (tag == kNonstatementPositionTag) {
350     return RelocInfo::POSITION;
351   } else {
352     ASSERT(tag == kCommentTag);
353     return RelocInfo::COMMENT;
354   }
355 }
356 
357 
next()358 void RelocIterator::next() {
359   ASSERT(!done());
360   // Basically, do the opposite of RelocInfoWriter::Write.
361   // Reading of data is as far as possible avoided for unwanted modes,
362   // but we must always update the pc.
363   //
364   // We exit this loop by returning when we find a mode we want.
365   while (pos_ > end_) {
366     int tag = AdvanceGetTag();
367     if (tag == kEmbeddedObjectTag) {
368       ReadTaggedPC();
369       if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
370     } else if (tag == kCodeTargetTag) {
371       ReadTaggedPC();
372       if (SetMode(RelocInfo::CODE_TARGET)) return;
373     } else if (tag == kPositionTag) {
374       ReadTaggedPC();
375       Advance();
376       // Check if we want source positions.
377       if (mode_mask_ & RelocInfo::kPositionMask) {
378         ReadTaggedData();
379         if (SetMode(DebugInfoModeFromTag(GetPositionTypeTag()))) return;
380       }
381     } else {
382       ASSERT(tag == kDefaultTag);
383       int extra_tag = GetExtraTag();
384       if (extra_tag == kPCJumpTag) {
385         int top_tag = GetTopTag();
386         if (top_tag == kVariableLengthPCJumpTopTag) {
387           AdvanceReadVariableLengthPCJump();
388         } else {
389           AdvanceReadPC();
390         }
391       } else if (extra_tag == kDataJumpTag) {
392         // Check if we want debug modes (the only ones with data).
393         if (mode_mask_ & RelocInfo::kDebugMask) {
394           int top_tag = GetTopTag();
395           AdvanceReadData();
396           if (SetMode(DebugInfoModeFromTag(top_tag))) return;
397         } else {
398           // Otherwise, just skip over the data.
399           Advance(kIntptrSize);
400         }
401       } else {
402         AdvanceReadPC();
403         if (SetMode(static_cast<RelocInfo::Mode>(extra_tag))) return;
404       }
405     }
406   }
407   done_ = true;
408 }
409 
410 
RelocIterator(Code * code,int mode_mask)411 RelocIterator::RelocIterator(Code* code, int mode_mask) {
412   rinfo_.pc_ = code->instruction_start();
413   rinfo_.data_ = 0;
414   // Relocation info is read backwards.
415   pos_ = code->relocation_start() + code->relocation_size();
416   end_ = code->relocation_start();
417   done_ = false;
418   mode_mask_ = mode_mask;
419   if (mode_mask_ == 0) pos_ = end_;
420   next();
421 }
422 
423 
RelocIterator(const CodeDesc & desc,int mode_mask)424 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
425   rinfo_.pc_ = desc.buffer;
426   rinfo_.data_ = 0;
427   // Relocation info is read backwards.
428   pos_ = desc.buffer + desc.buffer_size;
429   end_ = pos_ - desc.reloc_size;
430   done_ = false;
431   mode_mask_ = mode_mask;
432   if (mode_mask_ == 0) pos_ = end_;
433   next();
434 }
435 
436 
437 // -----------------------------------------------------------------------------
438 // Implementation of RelocInfo
439 
440 
441 #ifdef ENABLE_DISASSEMBLER
RelocModeName(RelocInfo::Mode rmode)442 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
443   switch (rmode) {
444     case RelocInfo::NONE:
445       return "no reloc";
446     case RelocInfo::EMBEDDED_OBJECT:
447       return "embedded object";
448     case RelocInfo::CONSTRUCT_CALL:
449       return "code target (js construct call)";
450     case RelocInfo::CODE_TARGET_CONTEXT:
451       return "code target (context)";
452     case RelocInfo::DEBUG_BREAK:
453 #ifndef ENABLE_DEBUGGER_SUPPORT
454       UNREACHABLE();
455 #endif
456       return "debug break";
457     case RelocInfo::CODE_TARGET:
458       return "code target";
459     case RelocInfo::GLOBAL_PROPERTY_CELL:
460       return "global property cell";
461     case RelocInfo::RUNTIME_ENTRY:
462       return "runtime entry";
463     case RelocInfo::JS_RETURN:
464       return "js return";
465     case RelocInfo::COMMENT:
466       return "comment";
467     case RelocInfo::POSITION:
468       return "position";
469     case RelocInfo::STATEMENT_POSITION:
470       return "statement position";
471     case RelocInfo::EXTERNAL_REFERENCE:
472       return "external reference";
473     case RelocInfo::INTERNAL_REFERENCE:
474       return "internal reference";
475     case RelocInfo::DEBUG_BREAK_SLOT:
476 #ifndef ENABLE_DEBUGGER_SUPPORT
477       UNREACHABLE();
478 #endif
479       return "debug break slot";
480     case RelocInfo::NUMBER_OF_MODES:
481       UNREACHABLE();
482       return "number_of_modes";
483   }
484   return "unknown relocation type";
485 }
486 
487 
Print(FILE * out)488 void RelocInfo::Print(FILE* out) {
489   PrintF(out, "%p  %s", pc_, RelocModeName(rmode_));
490   if (IsComment(rmode_)) {
491     PrintF(out, "  (%s)", reinterpret_cast<char*>(data_));
492   } else if (rmode_ == EMBEDDED_OBJECT) {
493     PrintF(out, "  (");
494     target_object()->ShortPrint(out);
495     PrintF(out, ")");
496   } else if (rmode_ == EXTERNAL_REFERENCE) {
497     ExternalReferenceEncoder ref_encoder;
498     PrintF(out, " (%s)  (%p)",
499            ref_encoder.NameOfAddress(*target_reference_address()),
500            *target_reference_address());
501   } else if (IsCodeTarget(rmode_)) {
502     Code* code = Code::GetCodeFromTargetAddress(target_address());
503     PrintF(out, " (%s)  (%p)", Code::Kind2String(code->kind()),
504            target_address());
505   } else if (IsPosition(rmode_)) {
506     PrintF(out, "  (%" V8_PTR_PREFIX "d)", data());
507   } else if (rmode_ == RelocInfo::RUNTIME_ENTRY &&
508              Isolate::Current()->deoptimizer_data() != NULL) {
509     // Depotimization bailouts are stored as runtime entries.
510     int id = Deoptimizer::GetDeoptimizationId(
511         target_address(), Deoptimizer::EAGER);
512     if (id != Deoptimizer::kNotDeoptimizationEntry) {
513       PrintF(out, "  (deoptimization bailout %d)", id);
514     }
515   }
516 
517   PrintF(out, "\n");
518 }
519 #endif  // ENABLE_DISASSEMBLER
520 
521 
522 #ifdef DEBUG
Verify()523 void RelocInfo::Verify() {
524   switch (rmode_) {
525     case EMBEDDED_OBJECT:
526       Object::VerifyPointer(target_object());
527       break;
528     case GLOBAL_PROPERTY_CELL:
529       Object::VerifyPointer(target_cell());
530       break;
531     case DEBUG_BREAK:
532 #ifndef ENABLE_DEBUGGER_SUPPORT
533       UNREACHABLE();
534       break;
535 #endif
536     case CONSTRUCT_CALL:
537     case CODE_TARGET_CONTEXT:
538     case CODE_TARGET: {
539       // convert inline target address to code object
540       Address addr = target_address();
541       ASSERT(addr != NULL);
542       // Check that we can find the right code object.
543       Code* code = Code::GetCodeFromTargetAddress(addr);
544       Object* found = HEAP->FindCodeObject(addr);
545       ASSERT(found->IsCode());
546       ASSERT(code->address() == HeapObject::cast(found)->address());
547       break;
548     }
549     case RUNTIME_ENTRY:
550     case JS_RETURN:
551     case COMMENT:
552     case POSITION:
553     case STATEMENT_POSITION:
554     case EXTERNAL_REFERENCE:
555     case INTERNAL_REFERENCE:
556     case DEBUG_BREAK_SLOT:
557     case NONE:
558       break;
559     case NUMBER_OF_MODES:
560       UNREACHABLE();
561       break;
562   }
563 }
564 #endif  // DEBUG
565 
566 
567 // -----------------------------------------------------------------------------
568 // Implementation of ExternalReference
569 
ExternalReference(Builtins::CFunctionId id,Isolate * isolate)570 ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
571   : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
572 
573 
ExternalReference(ApiFunction * fun,Type type=ExternalReference::BUILTIN_CALL,Isolate * isolate=NULL)574 ExternalReference::ExternalReference(
575     ApiFunction* fun,
576     Type type = ExternalReference::BUILTIN_CALL,
577     Isolate* isolate = NULL)
578   : address_(Redirect(isolate, fun->address(), type)) {}
579 
580 
ExternalReference(Builtins::Name name,Isolate * isolate)581 ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
582   : address_(isolate->builtins()->builtin_address(name)) {}
583 
584 
ExternalReference(Runtime::FunctionId id,Isolate * isolate)585 ExternalReference::ExternalReference(Runtime::FunctionId id,
586                                      Isolate* isolate)
587   : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
588 
589 
ExternalReference(const Runtime::Function * f,Isolate * isolate)590 ExternalReference::ExternalReference(const Runtime::Function* f,
591                                      Isolate* isolate)
592   : address_(Redirect(isolate, f->entry)) {}
593 
594 
isolate_address()595 ExternalReference ExternalReference::isolate_address() {
596   return ExternalReference(Isolate::Current());
597 }
598 
599 
ExternalReference(const IC_Utility & ic_utility,Isolate * isolate)600 ExternalReference::ExternalReference(const IC_Utility& ic_utility,
601                                      Isolate* isolate)
602   : address_(Redirect(isolate, ic_utility.address())) {}
603 
604 #ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference(const Debug_Address & debug_address,Isolate * isolate)605 ExternalReference::ExternalReference(const Debug_Address& debug_address,
606                                      Isolate* isolate)
607   : address_(debug_address.address(isolate)) {}
608 #endif
609 
ExternalReference(StatsCounter * counter)610 ExternalReference::ExternalReference(StatsCounter* counter)
611   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
612 
613 
ExternalReference(Isolate::AddressId id,Isolate * isolate)614 ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
615   : address_(isolate->get_address_from_id(id)) {}
616 
617 
ExternalReference(const SCTableReference & table_ref)618 ExternalReference::ExternalReference(const SCTableReference& table_ref)
619   : address_(table_ref.address()) {}
620 
621 
perform_gc_function(Isolate * isolate)622 ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
623   return ExternalReference(Redirect(isolate,
624                                     FUNCTION_ADDR(Runtime::PerformGC)));
625 }
626 
627 
fill_heap_number_with_random_function(Isolate * isolate)628 ExternalReference ExternalReference::fill_heap_number_with_random_function(
629     Isolate* isolate) {
630   return ExternalReference(Redirect(
631       isolate,
632       FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
633 }
634 
635 
delete_handle_scope_extensions(Isolate * isolate)636 ExternalReference ExternalReference::delete_handle_scope_extensions(
637     Isolate* isolate) {
638   return ExternalReference(Redirect(
639       isolate,
640       FUNCTION_ADDR(HandleScope::DeleteExtensions)));
641 }
642 
643 
random_uint32_function(Isolate * isolate)644 ExternalReference ExternalReference::random_uint32_function(
645     Isolate* isolate) {
646   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
647 }
648 
649 
transcendental_cache_array_address(Isolate * isolate)650 ExternalReference ExternalReference::transcendental_cache_array_address(
651     Isolate* isolate) {
652   return ExternalReference(
653       isolate->transcendental_cache()->cache_array_address());
654 }
655 
656 
new_deoptimizer_function(Isolate * isolate)657 ExternalReference ExternalReference::new_deoptimizer_function(
658     Isolate* isolate) {
659   return ExternalReference(
660       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
661 }
662 
663 
compute_output_frames_function(Isolate * isolate)664 ExternalReference ExternalReference::compute_output_frames_function(
665     Isolate* isolate) {
666   return ExternalReference(
667       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
668 }
669 
670 
global_contexts_list(Isolate * isolate)671 ExternalReference ExternalReference::global_contexts_list(Isolate* isolate) {
672   return ExternalReference(isolate->heap()->global_contexts_list_address());
673 }
674 
675 
keyed_lookup_cache_keys(Isolate * isolate)676 ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
677   return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
678 }
679 
680 
keyed_lookup_cache_field_offsets(Isolate * isolate)681 ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
682     Isolate* isolate) {
683   return ExternalReference(
684       isolate->keyed_lookup_cache()->field_offsets_address());
685 }
686 
687 
the_hole_value_location(Isolate * isolate)688 ExternalReference ExternalReference::the_hole_value_location(Isolate* isolate) {
689   return ExternalReference(isolate->factory()->the_hole_value().location());
690 }
691 
692 
arguments_marker_location(Isolate * isolate)693 ExternalReference ExternalReference::arguments_marker_location(
694     Isolate* isolate) {
695   return ExternalReference(isolate->factory()->arguments_marker().location());
696 }
697 
698 
roots_address(Isolate * isolate)699 ExternalReference ExternalReference::roots_address(Isolate* isolate) {
700   return ExternalReference(isolate->heap()->roots_address());
701 }
702 
703 
address_of_stack_limit(Isolate * isolate)704 ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
705   return ExternalReference(isolate->stack_guard()->address_of_jslimit());
706 }
707 
708 
address_of_real_stack_limit(Isolate * isolate)709 ExternalReference ExternalReference::address_of_real_stack_limit(
710     Isolate* isolate) {
711   return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
712 }
713 
714 
address_of_regexp_stack_limit(Isolate * isolate)715 ExternalReference ExternalReference::address_of_regexp_stack_limit(
716     Isolate* isolate) {
717   return ExternalReference(isolate->regexp_stack()->limit_address());
718 }
719 
720 
new_space_start(Isolate * isolate)721 ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
722   return ExternalReference(isolate->heap()->NewSpaceStart());
723 }
724 
725 
new_space_mask(Isolate * isolate)726 ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
727   Address mask = reinterpret_cast<Address>(isolate->heap()->NewSpaceMask());
728   return ExternalReference(mask);
729 }
730 
731 
new_space_allocation_top_address(Isolate * isolate)732 ExternalReference ExternalReference::new_space_allocation_top_address(
733     Isolate* isolate) {
734   return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
735 }
736 
737 
heap_always_allocate_scope_depth(Isolate * isolate)738 ExternalReference ExternalReference::heap_always_allocate_scope_depth(
739     Isolate* isolate) {
740   Heap* heap = isolate->heap();
741   return ExternalReference(heap->always_allocate_scope_depth_address());
742 }
743 
744 
new_space_allocation_limit_address(Isolate * isolate)745 ExternalReference ExternalReference::new_space_allocation_limit_address(
746     Isolate* isolate) {
747   return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
748 }
749 
750 
handle_scope_level_address()751 ExternalReference ExternalReference::handle_scope_level_address() {
752   return ExternalReference(HandleScope::current_level_address());
753 }
754 
755 
handle_scope_next_address()756 ExternalReference ExternalReference::handle_scope_next_address() {
757   return ExternalReference(HandleScope::current_next_address());
758 }
759 
760 
handle_scope_limit_address()761 ExternalReference ExternalReference::handle_scope_limit_address() {
762   return ExternalReference(HandleScope::current_limit_address());
763 }
764 
765 
scheduled_exception_address(Isolate * isolate)766 ExternalReference ExternalReference::scheduled_exception_address(
767     Isolate* isolate) {
768   return ExternalReference(isolate->scheduled_exception_address());
769 }
770 
771 
address_of_min_int()772 ExternalReference ExternalReference::address_of_min_int() {
773   return ExternalReference(reinterpret_cast<void*>(
774       const_cast<double*>(&DoubleConstant::min_int)));
775 }
776 
777 
address_of_one_half()778 ExternalReference ExternalReference::address_of_one_half() {
779   return ExternalReference(reinterpret_cast<void*>(
780       const_cast<double*>(&DoubleConstant::one_half)));
781 }
782 
783 
address_of_minus_zero()784 ExternalReference ExternalReference::address_of_minus_zero() {
785   return ExternalReference(reinterpret_cast<void*>(
786       const_cast<double*>(&DoubleConstant::minus_zero)));
787 }
788 
789 
address_of_negative_infinity()790 ExternalReference ExternalReference::address_of_negative_infinity() {
791   return ExternalReference(reinterpret_cast<void*>(
792       const_cast<double*>(&DoubleConstant::negative_infinity)));
793 }
794 
795 
address_of_nan()796 ExternalReference ExternalReference::address_of_nan() {
797   return ExternalReference(reinterpret_cast<void*>(
798       const_cast<double*>(&DoubleConstant::nan)));
799 }
800 
801 
802 #ifndef V8_INTERPRETED_REGEXP
803 
re_check_stack_guard_state(Isolate * isolate)804 ExternalReference ExternalReference::re_check_stack_guard_state(
805     Isolate* isolate) {
806   Address function;
807 #ifdef V8_TARGET_ARCH_X64
808   function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
809 #elif V8_TARGET_ARCH_IA32
810   function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
811 #elif V8_TARGET_ARCH_ARM
812   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
813 #elif V8_TARGET_ARCH_MIPS
814   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
815 #else
816   UNREACHABLE();
817 #endif
818   return ExternalReference(Redirect(isolate, function));
819 }
820 
re_grow_stack(Isolate * isolate)821 ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
822   return ExternalReference(
823       Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
824 }
825 
re_case_insensitive_compare_uc16(Isolate * isolate)826 ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
827     Isolate* isolate) {
828   return ExternalReference(Redirect(
829       isolate,
830       FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
831 }
832 
re_word_character_map()833 ExternalReference ExternalReference::re_word_character_map() {
834   return ExternalReference(
835       NativeRegExpMacroAssembler::word_character_map_address());
836 }
837 
address_of_static_offsets_vector(Isolate * isolate)838 ExternalReference ExternalReference::address_of_static_offsets_vector(
839     Isolate* isolate) {
840   return ExternalReference(
841       OffsetsVector::static_offsets_vector_address(isolate));
842 }
843 
address_of_regexp_stack_memory_address(Isolate * isolate)844 ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
845     Isolate* isolate) {
846   return ExternalReference(
847       isolate->regexp_stack()->memory_address());
848 }
849 
address_of_regexp_stack_memory_size(Isolate * isolate)850 ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
851     Isolate* isolate) {
852   return ExternalReference(isolate->regexp_stack()->memory_size_address());
853 }
854 
855 #endif  // V8_INTERPRETED_REGEXP
856 
857 
add_two_doubles(double x,double y)858 static double add_two_doubles(double x, double y) {
859   return x + y;
860 }
861 
862 
sub_two_doubles(double x,double y)863 static double sub_two_doubles(double x, double y) {
864   return x - y;
865 }
866 
867 
mul_two_doubles(double x,double y)868 static double mul_two_doubles(double x, double y) {
869   return x * y;
870 }
871 
872 
div_two_doubles(double x,double y)873 static double div_two_doubles(double x, double y) {
874   return x / y;
875 }
876 
877 
mod_two_doubles(double x,double y)878 static double mod_two_doubles(double x, double y) {
879   return modulo(x, y);
880 }
881 
882 
math_sin_double(double x)883 static double math_sin_double(double x) {
884   return sin(x);
885 }
886 
887 
math_cos_double(double x)888 static double math_cos_double(double x) {
889   return cos(x);
890 }
891 
892 
math_log_double(double x)893 static double math_log_double(double x) {
894   return log(x);
895 }
896 
897 
math_sin_double_function(Isolate * isolate)898 ExternalReference ExternalReference::math_sin_double_function(
899     Isolate* isolate) {
900   return ExternalReference(Redirect(isolate,
901                                     FUNCTION_ADDR(math_sin_double),
902                                     FP_RETURN_CALL));
903 }
904 
905 
math_cos_double_function(Isolate * isolate)906 ExternalReference ExternalReference::math_cos_double_function(
907     Isolate* isolate) {
908   return ExternalReference(Redirect(isolate,
909                                     FUNCTION_ADDR(math_cos_double),
910                                     FP_RETURN_CALL));
911 }
912 
913 
math_log_double_function(Isolate * isolate)914 ExternalReference ExternalReference::math_log_double_function(
915     Isolate* isolate) {
916   return ExternalReference(Redirect(isolate,
917                                     FUNCTION_ADDR(math_log_double),
918                                     FP_RETURN_CALL));
919 }
920 
921 
922 // Helper function to compute x^y, where y is known to be an
923 // integer. Uses binary decomposition to limit the number of
924 // multiplications; see the discussion in "Hacker's Delight" by Henry
925 // S. Warren, Jr., figure 11-6, page 213.
power_double_int(double x,int y)926 double power_double_int(double x, int y) {
927   double m = (y < 0) ? 1 / x : x;
928   unsigned n = (y < 0) ? -y : y;
929   double p = 1;
930   while (n != 0) {
931     if ((n & 1) != 0) p *= m;
932     m *= m;
933     if ((n & 2) != 0) p *= m;
934     m *= m;
935     n >>= 2;
936   }
937   return p;
938 }
939 
940 
power_double_double(double x,double y)941 double power_double_double(double x, double y) {
942   int y_int = static_cast<int>(y);
943   if (y == y_int) {
944     return power_double_int(x, y_int);  // Returns 1.0 for exponent 0.
945   }
946   if (!isinf(x)) {
947     if (y == 0.5) return sqrt(x + 0.0);  // -0 must be converted to +0.
948     if (y == -0.5) return 1.0 / sqrt(x + 0.0);
949   }
950   if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
951     return OS::nan_value();
952   }
953   return pow(x, y);
954 }
955 
956 
power_double_double_function(Isolate * isolate)957 ExternalReference ExternalReference::power_double_double_function(
958     Isolate* isolate) {
959   return ExternalReference(Redirect(isolate,
960                                     FUNCTION_ADDR(power_double_double),
961                                     FP_RETURN_CALL));
962 }
963 
964 
power_double_int_function(Isolate * isolate)965 ExternalReference ExternalReference::power_double_int_function(
966     Isolate* isolate) {
967   return ExternalReference(Redirect(isolate,
968                                     FUNCTION_ADDR(power_double_int),
969                                     FP_RETURN_CALL));
970 }
971 
972 
native_compare_doubles(double y,double x)973 static int native_compare_doubles(double y, double x) {
974   if (x == y) return EQUAL;
975   return x < y ? LESS : GREATER;
976 }
977 
978 
double_fp_operation(Token::Value operation,Isolate * isolate)979 ExternalReference ExternalReference::double_fp_operation(
980     Token::Value operation, Isolate* isolate) {
981   typedef double BinaryFPOperation(double x, double y);
982   BinaryFPOperation* function = NULL;
983   switch (operation) {
984     case Token::ADD:
985       function = &add_two_doubles;
986       break;
987     case Token::SUB:
988       function = &sub_two_doubles;
989       break;
990     case Token::MUL:
991       function = &mul_two_doubles;
992       break;
993     case Token::DIV:
994       function = &div_two_doubles;
995       break;
996     case Token::MOD:
997       function = &mod_two_doubles;
998       break;
999     default:
1000       UNREACHABLE();
1001   }
1002   // Passing true as 2nd parameter indicates that they return an fp value.
1003   return ExternalReference(Redirect(isolate,
1004                                     FUNCTION_ADDR(function),
1005                                     FP_RETURN_CALL));
1006 }
1007 
1008 
compare_doubles(Isolate * isolate)1009 ExternalReference ExternalReference::compare_doubles(Isolate* isolate) {
1010   return ExternalReference(Redirect(isolate,
1011                                     FUNCTION_ADDR(native_compare_doubles),
1012                                     BUILTIN_CALL));
1013 }
1014 
1015 
1016 #ifdef ENABLE_DEBUGGER_SUPPORT
debug_break(Isolate * isolate)1017 ExternalReference ExternalReference::debug_break(Isolate* isolate) {
1018   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
1019 }
1020 
1021 
debug_step_in_fp_address(Isolate * isolate)1022 ExternalReference ExternalReference::debug_step_in_fp_address(
1023     Isolate* isolate) {
1024   return ExternalReference(isolate->debug()->step_in_fp_addr());
1025 }
1026 #endif
1027 
1028 
RecordPosition(int pos)1029 void PositionsRecorder::RecordPosition(int pos) {
1030   ASSERT(pos != RelocInfo::kNoPosition);
1031   ASSERT(pos >= 0);
1032   state_.current_position = pos;
1033 #ifdef ENABLE_GDB_JIT_INTERFACE
1034   if (gdbjit_lineinfo_ != NULL) {
1035     gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
1036   }
1037 #endif
1038 }
1039 
1040 
RecordStatementPosition(int pos)1041 void PositionsRecorder::RecordStatementPosition(int pos) {
1042   ASSERT(pos != RelocInfo::kNoPosition);
1043   ASSERT(pos >= 0);
1044   state_.current_statement_position = pos;
1045 #ifdef ENABLE_GDB_JIT_INTERFACE
1046   if (gdbjit_lineinfo_ != NULL) {
1047     gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
1048   }
1049 #endif
1050 }
1051 
1052 
WriteRecordedPositions()1053 bool PositionsRecorder::WriteRecordedPositions() {
1054   bool written = false;
1055 
1056   // Write the statement position if it is different from what was written last
1057   // time.
1058   if (state_.current_statement_position != state_.written_statement_position) {
1059     EnsureSpace ensure_space(assembler_);
1060     assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
1061                                 state_.current_statement_position);
1062     state_.written_statement_position = state_.current_statement_position;
1063     written = true;
1064   }
1065 
1066   // Write the position if it is different from what was written last time and
1067   // also different from the written statement position.
1068   if (state_.current_position != state_.written_position &&
1069       state_.current_position != state_.written_statement_position) {
1070     EnsureSpace ensure_space(assembler_);
1071     assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
1072     state_.written_position = state_.current_position;
1073     written = true;
1074   }
1075 
1076   // Return whether something was written.
1077   return written;
1078 }
1079 
1080 } }  // namespace v8::internal
1081