f4299ed7170936fd0b2bb11da07c41840155effd
[platform/upstream/nodejs.git] / deps / v8 / src / assembler.cc
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 2012 the V8 project authors. All rights reserved.
34
35 #include "src/assembler.h"
36
37 #include <cmath>
38 #include "src/api.h"
39 #include "src/base/cpu.h"
40 #include "src/base/functional.h"
41 #include "src/base/lazy-instance.h"
42 #include "src/base/platform/platform.h"
43 #include "src/builtins.h"
44 #include "src/codegen.h"
45 #include "src/counters.h"
46 #include "src/cpu-profiler.h"
47 #include "src/debug.h"
48 #include "src/deoptimizer.h"
49 #include "src/execution.h"
50 #include "src/ic/ic.h"
51 #include "src/ic/stub-cache.h"
52 #include "src/isolate-inl.h"
53 #include "src/jsregexp.h"
54 #include "src/regexp-macro-assembler.h"
55 #include "src/regexp-stack.h"
56 #include "src/runtime/runtime.h"
57 #include "src/serialize.h"
58 #include "src/token.h"
59
60 #if V8_TARGET_ARCH_IA32
61 #include "src/ia32/assembler-ia32-inl.h"  // NOLINT
62 #elif V8_TARGET_ARCH_X64
63 #include "src/x64/assembler-x64-inl.h"  // NOLINT
64 #elif V8_TARGET_ARCH_ARM64
65 #include "src/arm64/assembler-arm64-inl.h"  // NOLINT
66 #elif V8_TARGET_ARCH_ARM
67 #include "src/arm/assembler-arm-inl.h"  // NOLINT
68 #elif V8_TARGET_ARCH_PPC
69 #include "src/ppc/assembler-ppc-inl.h"  // NOLINT
70 #elif V8_TARGET_ARCH_MIPS
71 #include "src/mips/assembler-mips-inl.h"  // NOLINT
72 #elif V8_TARGET_ARCH_MIPS64
73 #include "src/mips64/assembler-mips64-inl.h"  // NOLINT
74 #elif V8_TARGET_ARCH_X87
75 #include "src/x87/assembler-x87-inl.h"  // NOLINT
76 #else
77 #error "Unknown architecture."
78 #endif
79
80 // Include native regexp-macro-assembler.
81 #ifndef V8_INTERPRETED_REGEXP
82 #if V8_TARGET_ARCH_IA32
83 #include "src/ia32/regexp-macro-assembler-ia32.h"  // NOLINT
84 #elif V8_TARGET_ARCH_X64
85 #include "src/x64/regexp-macro-assembler-x64.h"  // NOLINT
86 #elif V8_TARGET_ARCH_ARM64
87 #include "src/arm64/regexp-macro-assembler-arm64.h"  // NOLINT
88 #elif V8_TARGET_ARCH_ARM
89 #include "src/arm/regexp-macro-assembler-arm.h"  // NOLINT
90 #elif V8_TARGET_ARCH_PPC
91 #include "src/ppc/regexp-macro-assembler-ppc.h"  // NOLINT
92 #elif V8_TARGET_ARCH_MIPS
93 #include "src/mips/regexp-macro-assembler-mips.h"  // NOLINT
94 #elif V8_TARGET_ARCH_MIPS64
95 #include "src/mips64/regexp-macro-assembler-mips64.h"  // NOLINT
96 #elif V8_TARGET_ARCH_X87
97 #include "src/x87/regexp-macro-assembler-x87.h"  // NOLINT
98 #else  // Unknown architecture.
99 #error "Unknown architecture."
100 #endif  // Target architecture.
101 #endif  // V8_INTERPRETED_REGEXP
102
103 namespace v8 {
104 namespace internal {
105
106 // -----------------------------------------------------------------------------
107 // Common double constants.
108
109 struct DoubleConstant BASE_EMBEDDED {
110 double min_int;
111 double one_half;
112 double minus_one_half;
113 double negative_infinity;
114 double the_hole_nan;
115 double uint32_bias;
116 };
117
118 static DoubleConstant double_constants;
119
120 const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
121
122 static bool math_exp_data_initialized = false;
123 static base::Mutex* math_exp_data_mutex = NULL;
124 static double* math_exp_constants_array = NULL;
125 static double* math_exp_log_table_array = NULL;
126
127 // -----------------------------------------------------------------------------
128 // Implementation of AssemblerBase
129
130 AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size)
131     : isolate_(isolate),
132       jit_cookie_(0),
133       enabled_cpu_features_(0),
134       emit_debug_code_(FLAG_debug_code),
135       predictable_code_size_(false),
136       // We may use the assembler without an isolate.
137       serializer_enabled_(isolate && isolate->serializer_enabled()),
138       ool_constant_pool_available_(false) {
139   if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
140     jit_cookie_ = isolate->random_number_generator()->NextInt();
141   }
142   own_buffer_ = buffer == NULL;
143   if (buffer_size == 0) buffer_size = kMinimalBufferSize;
144   DCHECK(buffer_size > 0);
145   if (own_buffer_) buffer = NewArray<byte>(buffer_size);
146   buffer_ = static_cast<byte*>(buffer);
147   buffer_size_ = buffer_size;
148
149   pc_ = buffer_;
150 }
151
152
153 AssemblerBase::~AssemblerBase() {
154   if (own_buffer_) DeleteArray(buffer_);
155 }
156
157
158 // -----------------------------------------------------------------------------
159 // Implementation of PredictableCodeSizeScope
160
161 PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
162                                                    int expected_size)
163     : assembler_(assembler),
164       expected_size_(expected_size),
165       start_offset_(assembler->pc_offset()),
166       old_value_(assembler->predictable_code_size()) {
167   assembler_->set_predictable_code_size(true);
168 }
169
170
171 PredictableCodeSizeScope::~PredictableCodeSizeScope() {
172   // TODO(svenpanne) Remove the 'if' when everything works.
173   if (expected_size_ >= 0) {
174     CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
175   }
176   assembler_->set_predictable_code_size(old_value_);
177 }
178
179
180 // -----------------------------------------------------------------------------
181 // Implementation of CpuFeatureScope
182
183 #ifdef DEBUG
184 CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f)
185     : assembler_(assembler) {
186   DCHECK(CpuFeatures::IsSupported(f));
187   old_enabled_ = assembler_->enabled_cpu_features();
188   uint64_t mask = static_cast<uint64_t>(1) << f;
189   // TODO(svenpanne) This special case below doesn't belong here!
190 #if V8_TARGET_ARCH_ARM
191   // ARMv7 is implied by VFP3.
192   if (f == VFP3) {
193     mask |= static_cast<uint64_t>(1) << ARMv7;
194   }
195 #endif
196   assembler_->set_enabled_cpu_features(old_enabled_ | mask);
197 }
198
199
200 CpuFeatureScope::~CpuFeatureScope() {
201   assembler_->set_enabled_cpu_features(old_enabled_);
202 }
203 #endif
204
205
206 bool CpuFeatures::initialized_ = false;
207 unsigned CpuFeatures::supported_ = 0;
208 unsigned CpuFeatures::cache_line_size_ = 0;
209
210
211 // -----------------------------------------------------------------------------
212 // Implementation of Label
213
214 int Label::pos() const {
215   if (pos_ < 0) return -pos_ - 1;
216   if (pos_ > 0) return  pos_ - 1;
217   UNREACHABLE();
218   return 0;
219 }
220
221
222 // -----------------------------------------------------------------------------
223 // Implementation of RelocInfoWriter and RelocIterator
224 //
225 // Relocation information is written backwards in memory, from high addresses
226 // towards low addresses, byte by byte.  Therefore, in the encodings listed
227 // below, the first byte listed it at the highest address, and successive
228 // bytes in the record are at progressively lower addresses.
229 //
230 // Encoding
231 //
232 // The most common modes are given single-byte encodings.  Also, it is
233 // easy to identify the type of reloc info and skip unwanted modes in
234 // an iteration.
235 //
236 // The encoding relies on the fact that there are fewer than 14
237 // different relocation modes using standard non-compact encoding.
238 //
239 // The first byte of a relocation record has a tag in its low 2 bits:
240 // Here are the record schemes, depending on the low tag and optional higher
241 // tags.
242 //
243 // Low tag:
244 //   00: embedded_object:      [6-bit pc delta] 00
245 //
246 //   01: code_target:          [6-bit pc delta] 01
247 //
248 //   10: short_data_record:    [6-bit pc delta] 10 followed by
249 //                             [6-bit data delta] [2-bit data type tag]
250 //
251 //   11: long_record           [2-bit high tag][4 bit middle_tag] 11
252 //                             followed by variable data depending on type.
253 //
254 //  2-bit data type tags, used in short_data_record and data_jump long_record:
255 //   code_target_with_id: 00
256 //   position:            01
257 //   statement_position:  10
258 //   comment:             11 (not used in short_data_record)
259 //   deopt_reason:        11 (not used in long_data_record)
260 //
261 //  Long record format:
262 //    4-bit middle_tag:
263 //      0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2
264 //         (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM,
265 //          and is between 0000 and 1100)
266 //        The format is:
267 //                              00 [4 bit middle_tag] 11 followed by
268 //                              00 [6 bit pc delta]
269 //
270 //      1101: constant or veneer pool. Used only on ARM and ARM64 for now.
271 //        The format is:       [2-bit sub-type] 1101 11
272 //                             signed int (size of the pool).
273 //          The 2-bit sub-types are:
274 //            00: constant pool
275 //            01: veneer pool
276 //      1110: long_data_record
277 //        The format is:       [2-bit data_type_tag] 1110 11
278 //                             signed intptr_t, lowest byte written first
279 //                             (except data_type code_target_with_id, which
280 //                             is followed by a signed int, not intptr_t.)
281 //
282 //      1111: long_pc_jump
283 //        The format is:
284 //          pc-jump:             00 1111 11,
285 //                               00 [6 bits pc delta]
286 //        or
287 //          pc-jump (variable length):
288 //                               01 1111 11,
289 //                               [7 bits data] 0
290 //                                  ...
291 //                               [7 bits data] 1
292 //               (Bits 6..31 of pc delta, with leading zeroes
293 //                dropped, and last non-zero chunk tagged with 1.)
294
295
296 #ifdef DEBUG
297 const int kMaxStandardNonCompactModes = 14;
298 #endif
299
300 const int kTagBits = 2;
301 const int kTagMask = (1 << kTagBits) - 1;
302 const int kExtraTagBits = 4;
303 const int kLocatableTypeTagBits = 2;
304 const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits;
305
306 const int kEmbeddedObjectTag = 0;
307 const int kCodeTargetTag = 1;
308 const int kLocatableTag = 2;
309 const int kDefaultTag = 3;
310
311 const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1;
312
313 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
314 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
315 const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
316
317 const int kVariableLengthPCJumpTopTag = 1;
318 const int kChunkBits = 7;
319 const int kChunkMask = (1 << kChunkBits) - 1;
320 const int kLastChunkTagBits = 1;
321 const int kLastChunkTagMask = 1;
322 const int kLastChunkTag = 1;
323
324
325 const int kDataJumpExtraTag = kPCJumpExtraTag - 1;
326
327 const int kCodeWithIdTag = 0;
328 const int kNonstatementPositionTag = 1;
329 const int kStatementPositionTag = 2;
330 const int kCommentTag = 3;
331
332 // Reuse the same value for deopt reason tag in short record format.
333 // It is possible because we use kCommentTag only for the long record format.
334 const int kDeoptReasonTag = 3;
335
336 const int kPoolExtraTag = kPCJumpExtraTag - 2;
337 const int kConstPoolTag = 0;
338 const int kVeneerPoolTag = 1;
339
340
341 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
342   // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
343   // Otherwise write a variable length PC jump for the bits that do
344   // not fit in the kSmallPCDeltaBits bits.
345   if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
346   WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag);
347   uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
348   DCHECK(pc_jump > 0);
349   // Write kChunkBits size chunks of the pc_jump.
350   for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
351     byte b = pc_jump & kChunkMask;
352     *--pos_ = b << kLastChunkTagBits;
353   }
354   // Tag the last chunk so it can be identified.
355   *pos_ = *pos_ | kLastChunkTag;
356   // Return the remaining kSmallPCDeltaBits of the pc_delta.
357   return pc_delta & kSmallPCDeltaMask;
358 }
359
360
361 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
362   // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
363   pc_delta = WriteVariableLengthPCJump(pc_delta);
364   *--pos_ = pc_delta << kTagBits | tag;
365 }
366
367
368 void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
369   *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag);
370 }
371
372
373 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
374   *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
375                              extra_tag << kTagBits |
376                              kDefaultTag);
377 }
378
379
380 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
381   // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
382   pc_delta = WriteVariableLengthPCJump(pc_delta);
383   WriteExtraTag(extra_tag, 0);
384   *--pos_ = pc_delta;
385 }
386
387
388 void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
389   WriteExtraTag(kDataJumpExtraTag, top_tag);
390   for (int i = 0; i < kIntSize; i++) {
391     *--pos_ = static_cast<byte>(data_delta);
392     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
393     data_delta = data_delta >> kBitsPerByte;
394   }
395 }
396
397
398 void RelocInfoWriter::WriteExtraTaggedPoolData(int data, int pool_type) {
399   WriteExtraTag(kPoolExtraTag, pool_type);
400   for (int i = 0; i < kIntSize; i++) {
401     *--pos_ = static_cast<byte>(data);
402     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
403     data = data >> kBitsPerByte;
404   }
405 }
406
407
408 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
409   WriteExtraTag(kDataJumpExtraTag, top_tag);
410   for (int i = 0; i < kIntptrSize; i++) {
411     *--pos_ = static_cast<byte>(data_delta);
412     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
413     data_delta = data_delta >> kBitsPerByte;
414   }
415 }
416
417
418 void RelocInfoWriter::WritePosition(int pc_delta, int pos_delta,
419                                     RelocInfo::Mode rmode) {
420   int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
421                                                     : kStatementPositionTag;
422   // Check if delta is small enough to fit in a tagged byte.
423   if (is_intn(pos_delta, kSmallDataBits)) {
424     WriteTaggedPC(pc_delta, kLocatableTag);
425     WriteTaggedData(pos_delta, pos_type_tag);
426   } else {
427     // Otherwise, use costly encoding.
428     WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
429     WriteExtraTaggedIntData(pos_delta, pos_type_tag);
430   }
431 }
432
433
434 void RelocInfoWriter::FlushPosition() {
435   if (!next_position_candidate_flushed_) {
436     WritePosition(next_position_candidate_pc_delta_,
437                   next_position_candidate_pos_delta_, RelocInfo::POSITION);
438     next_position_candidate_pos_delta_ = 0;
439     next_position_candidate_pc_delta_ = 0;
440     next_position_candidate_flushed_ = true;
441   }
442 }
443
444
445 void RelocInfoWriter::Write(const RelocInfo* rinfo) {
446   RelocInfo::Mode rmode = rinfo->rmode();
447   if (rmode != RelocInfo::POSITION) {
448     FlushPosition();
449   }
450 #ifdef DEBUG
451   byte* begin_pos = pos_;
452 #endif
453   DCHECK(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES);
454   DCHECK(rinfo->pc() - last_pc_ >= 0);
455   DCHECK(RelocInfo::LAST_STANDARD_NONCOMPACT_ENUM - RelocInfo::LAST_COMPACT_ENUM
456          <= kMaxStandardNonCompactModes);
457   // Use unsigned delta-encoding for pc.
458   uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
459
460   // The two most common modes are given small tags, and usually fit in a byte.
461   if (rmode == RelocInfo::EMBEDDED_OBJECT) {
462     WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
463   } else if (rmode == RelocInfo::CODE_TARGET) {
464     WriteTaggedPC(pc_delta, kCodeTargetTag);
465     DCHECK(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
466   } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
467     // Use signed delta-encoding for id.
468     DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
469     int id_delta = static_cast<int>(rinfo->data()) - last_id_;
470     // Check if delta is small enough to fit in a tagged byte.
471     if (is_intn(id_delta, kSmallDataBits)) {
472       WriteTaggedPC(pc_delta, kLocatableTag);
473       WriteTaggedData(id_delta, kCodeWithIdTag);
474     } else {
475       // Otherwise, use costly encoding.
476       WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
477       WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
478     }
479     last_id_ = static_cast<int>(rinfo->data());
480   } else if (rmode == RelocInfo::DEOPT_REASON) {
481     DCHECK(rinfo->data() < (1 << kSmallDataBits));
482     WriteTaggedPC(pc_delta, kLocatableTag);
483     WriteTaggedData(rinfo->data(), kDeoptReasonTag);
484   } else if (RelocInfo::IsPosition(rmode)) {
485     // Use signed delta-encoding for position.
486     DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
487     int pos_delta = static_cast<int>(rinfo->data()) - last_position_;
488     if (rmode == RelocInfo::STATEMENT_POSITION) {
489       WritePosition(pc_delta, pos_delta, rmode);
490     } else {
491       DCHECK(rmode == RelocInfo::POSITION);
492       if (pc_delta != 0 || last_mode_ != RelocInfo::POSITION) {
493         FlushPosition();
494         next_position_candidate_pc_delta_ = pc_delta;
495         next_position_candidate_pos_delta_ = pos_delta;
496       } else {
497         next_position_candidate_pos_delta_ += pos_delta;
498       }
499       next_position_candidate_flushed_ = false;
500     }
501     last_position_ = static_cast<int>(rinfo->data());
502   } else if (RelocInfo::IsComment(rmode)) {
503     // Comments are normally not generated, so we use the costly encoding.
504     WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
505     WriteExtraTaggedData(rinfo->data(), kCommentTag);
506     DCHECK(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
507   } else if (RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)) {
508       WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
509       WriteExtraTaggedPoolData(static_cast<int>(rinfo->data()),
510                                RelocInfo::IsConstPool(rmode) ? kConstPoolTag
511                                                              : kVeneerPoolTag);
512   } else {
513     DCHECK(rmode > RelocInfo::LAST_COMPACT_ENUM);
514     int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
515     // For all other modes we simply use the mode as the extra tag.
516     // None of these modes need a data component.
517     DCHECK(saved_mode < kPoolExtraTag);
518     WriteExtraTaggedPC(pc_delta, saved_mode);
519   }
520   last_pc_ = rinfo->pc();
521   last_mode_ = rmode;
522 #ifdef DEBUG
523   DCHECK(begin_pos - pos_ <= kMaxSize);
524 #endif
525 }
526
527
528 inline int RelocIterator::AdvanceGetTag() {
529   return *--pos_ & kTagMask;
530 }
531
532
533 inline int RelocIterator::GetExtraTag() {
534   return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
535 }
536
537
538 inline int RelocIterator::GetTopTag() {
539   return *pos_ >> (kTagBits + kExtraTagBits);
540 }
541
542
543 inline void RelocIterator::ReadTaggedPC() {
544   rinfo_.pc_ += *pos_ >> kTagBits;
545 }
546
547
548 inline void RelocIterator::AdvanceReadPC() {
549   rinfo_.pc_ += *--pos_;
550 }
551
552
553 void RelocIterator::AdvanceReadId() {
554   int x = 0;
555   for (int i = 0; i < kIntSize; i++) {
556     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
557   }
558   last_id_ += x;
559   rinfo_.data_ = last_id_;
560 }
561
562
563 void RelocIterator::AdvanceReadPoolData() {
564   int x = 0;
565   for (int i = 0; i < kIntSize; i++) {
566     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
567   }
568   rinfo_.data_ = x;
569 }
570
571
572 void RelocIterator::AdvanceReadPosition() {
573   int x = 0;
574   for (int i = 0; i < kIntSize; i++) {
575     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
576   }
577   last_position_ += x;
578   rinfo_.data_ = last_position_;
579 }
580
581
582 void RelocIterator::AdvanceReadData() {
583   intptr_t x = 0;
584   for (int i = 0; i < kIntptrSize; i++) {
585     x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
586   }
587   rinfo_.data_ = x;
588 }
589
590
591 void RelocIterator::AdvanceReadVariableLengthPCJump() {
592   // Read the 32-kSmallPCDeltaBits most significant bits of the
593   // pc jump in kChunkBits bit chunks and shift them into place.
594   // Stop when the last chunk is encountered.
595   uint32_t pc_jump = 0;
596   for (int i = 0; i < kIntSize; i++) {
597     byte pc_jump_part = *--pos_;
598     pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
599     if ((pc_jump_part & kLastChunkTagMask) == 1) break;
600   }
601   // The least significant kSmallPCDeltaBits bits will be added
602   // later.
603   rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
604 }
605
606
607 inline int RelocIterator::GetLocatableTypeTag() {
608   return *pos_ & ((1 << kLocatableTypeTagBits) - 1);
609 }
610
611
612 inline void RelocIterator::ReadTaggedId() {
613   int8_t signed_b = *pos_;
614   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
615   last_id_ += signed_b >> kLocatableTypeTagBits;
616   rinfo_.data_ = last_id_;
617 }
618
619
620 inline void RelocIterator::ReadTaggedPosition() {
621   int8_t signed_b = *pos_;
622   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
623   last_position_ += signed_b >> kLocatableTypeTagBits;
624   rinfo_.data_ = last_position_;
625 }
626
627
628 inline void RelocIterator::ReadTaggedData() {
629   uint8_t unsigned_b = *pos_;
630   rinfo_.data_ = unsigned_b >> kTagBits;
631 }
632
633
634 static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
635   DCHECK(tag == kNonstatementPositionTag ||
636          tag == kStatementPositionTag);
637   return (tag == kNonstatementPositionTag) ?
638          RelocInfo::POSITION :
639          RelocInfo::STATEMENT_POSITION;
640 }
641
642
643 void RelocIterator::next() {
644   DCHECK(!done());
645   // Basically, do the opposite of RelocInfoWriter::Write.
646   // Reading of data is as far as possible avoided for unwanted modes,
647   // but we must always update the pc.
648   //
649   // We exit this loop by returning when we find a mode we want.
650   while (pos_ > end_) {
651     int tag = AdvanceGetTag();
652     if (tag == kEmbeddedObjectTag) {
653       ReadTaggedPC();
654       if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
655     } else if (tag == kCodeTargetTag) {
656       ReadTaggedPC();
657       if (SetMode(RelocInfo::CODE_TARGET)) return;
658     } else if (tag == kLocatableTag) {
659       ReadTaggedPC();
660       Advance();
661       int locatable_tag = GetLocatableTypeTag();
662       if (locatable_tag == kCodeWithIdTag) {
663         if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
664           ReadTaggedId();
665           return;
666         }
667       } else if (locatable_tag == kDeoptReasonTag) {
668         ReadTaggedData();
669         if (SetMode(RelocInfo::DEOPT_REASON)) return;
670       } else {
671         DCHECK(locatable_tag == kNonstatementPositionTag ||
672                locatable_tag == kStatementPositionTag);
673         if (mode_mask_ & RelocInfo::kPositionMask) {
674           ReadTaggedPosition();
675           if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
676         }
677       }
678     } else {
679       DCHECK(tag == kDefaultTag);
680       int extra_tag = GetExtraTag();
681       if (extra_tag == kPCJumpExtraTag) {
682         if (GetTopTag() == kVariableLengthPCJumpTopTag) {
683           AdvanceReadVariableLengthPCJump();
684         } else {
685           AdvanceReadPC();
686         }
687       } else if (extra_tag == kDataJumpExtraTag) {
688         int locatable_tag = GetTopTag();
689         if (locatable_tag == kCodeWithIdTag) {
690           if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
691             AdvanceReadId();
692             return;
693           }
694           Advance(kIntSize);
695         } else if (locatable_tag != kCommentTag) {
696           DCHECK(locatable_tag == kNonstatementPositionTag ||
697                  locatable_tag == kStatementPositionTag);
698           if (mode_mask_ & RelocInfo::kPositionMask) {
699             AdvanceReadPosition();
700             if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
701           } else {
702             Advance(kIntSize);
703           }
704         } else {
705           DCHECK(locatable_tag == kCommentTag);
706           if (SetMode(RelocInfo::COMMENT)) {
707             AdvanceReadData();
708             return;
709           }
710           Advance(kIntptrSize);
711         }
712       } else if (extra_tag == kPoolExtraTag) {
713         int pool_type = GetTopTag();
714         DCHECK(pool_type == kConstPoolTag || pool_type == kVeneerPoolTag);
715         RelocInfo::Mode rmode = (pool_type == kConstPoolTag) ?
716           RelocInfo::CONST_POOL : RelocInfo::VENEER_POOL;
717         if (SetMode(rmode)) {
718           AdvanceReadPoolData();
719           return;
720         }
721         Advance(kIntSize);
722       } else {
723         AdvanceReadPC();
724         int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM;
725         if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
726       }
727     }
728   }
729   if (code_age_sequence_ != NULL) {
730     byte* old_code_age_sequence = code_age_sequence_;
731     code_age_sequence_ = NULL;
732     if (SetMode(RelocInfo::CODE_AGE_SEQUENCE)) {
733       rinfo_.data_ = 0;
734       rinfo_.pc_ = old_code_age_sequence;
735       return;
736     }
737   }
738   done_ = true;
739 }
740
741
742 RelocIterator::RelocIterator(Code* code, int mode_mask) {
743   rinfo_.host_ = code;
744   rinfo_.pc_ = code->instruction_start();
745   rinfo_.data_ = 0;
746   // Relocation info is read backwards.
747   pos_ = code->relocation_start() + code->relocation_size();
748   end_ = code->relocation_start();
749   done_ = false;
750   mode_mask_ = mode_mask;
751   last_id_ = 0;
752   last_position_ = 0;
753   byte* sequence = code->FindCodeAgeSequence();
754   // We get the isolate from the map, because at serialization time
755   // the code pointer has been cloned and isn't really in heap space.
756   Isolate* isolate = code->map()->GetIsolate();
757   if (sequence != NULL && !Code::IsYoungSequence(isolate, sequence)) {
758     code_age_sequence_ = sequence;
759   } else {
760     code_age_sequence_ = NULL;
761   }
762   if (mode_mask_ == 0) pos_ = end_;
763   next();
764 }
765
766
767 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
768   rinfo_.pc_ = desc.buffer;
769   rinfo_.data_ = 0;
770   // Relocation info is read backwards.
771   pos_ = desc.buffer + desc.buffer_size;
772   end_ = pos_ - desc.reloc_size;
773   done_ = false;
774   mode_mask_ = mode_mask;
775   last_id_ = 0;
776   last_position_ = 0;
777   code_age_sequence_ = NULL;
778   if (mode_mask_ == 0) pos_ = end_;
779   next();
780 }
781
782
783 // -----------------------------------------------------------------------------
784 // Implementation of RelocInfo
785
786
787 #ifdef DEBUG
788 bool RelocInfo::RequiresRelocation(const CodeDesc& desc) {
789   // Ensure there are no code targets or embedded objects present in the
790   // deoptimization entries, they would require relocation after code
791   // generation.
792   int mode_mask = RelocInfo::kCodeTargetMask |
793                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
794                   RelocInfo::ModeMask(RelocInfo::CELL) |
795                   RelocInfo::kApplyMask;
796   RelocIterator it(desc, mode_mask);
797   return !it.done();
798 }
799 #endif
800
801
802 #ifdef ENABLE_DISASSEMBLER
803 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
804   switch (rmode) {
805     case RelocInfo::NONE32:
806       return "no reloc 32";
807     case RelocInfo::NONE64:
808       return "no reloc 64";
809     case RelocInfo::EMBEDDED_OBJECT:
810       return "embedded object";
811     case RelocInfo::CONSTRUCT_CALL:
812       return "code target (js construct call)";
813     case RelocInfo::DEBUG_BREAK:
814       return "debug break";
815     case RelocInfo::CODE_TARGET:
816       return "code target";
817     case RelocInfo::CODE_TARGET_WITH_ID:
818       return "code target with id";
819     case RelocInfo::CELL:
820       return "property cell";
821     case RelocInfo::RUNTIME_ENTRY:
822       return "runtime entry";
823     case RelocInfo::JS_RETURN:
824       return "js return";
825     case RelocInfo::COMMENT:
826       return "comment";
827     case RelocInfo::POSITION:
828       return "position";
829     case RelocInfo::STATEMENT_POSITION:
830       return "statement position";
831     case RelocInfo::EXTERNAL_REFERENCE:
832       return "external reference";
833     case RelocInfo::INTERNAL_REFERENCE:
834       return "internal reference";
835     case RelocInfo::DEOPT_REASON:
836       return "deopt reason";
837     case RelocInfo::CONST_POOL:
838       return "constant pool";
839     case RelocInfo::VENEER_POOL:
840       return "veneer pool";
841     case RelocInfo::DEBUG_BREAK_SLOT:
842       return "debug break slot";
843     case RelocInfo::CODE_AGE_SEQUENCE:
844       return "code_age_sequence";
845     case RelocInfo::NUMBER_OF_MODES:
846       UNREACHABLE();
847       return "number_of_modes";
848   }
849   return "unknown relocation type";
850 }
851
852
853 void RelocInfo::Print(Isolate* isolate, std::ostream& os) {  // NOLINT
854   os << static_cast<const void*>(pc_) << "  " << RelocModeName(rmode_);
855   if (IsComment(rmode_)) {
856     os << "  (" << reinterpret_cast<char*>(data_) << ")";
857   } else if (rmode_ == DEOPT_REASON) {
858     os << "  (" << Deoptimizer::GetDeoptReason(
859                        static_cast<Deoptimizer::DeoptReason>(data_)) << ")";
860   } else if (rmode_ == EMBEDDED_OBJECT) {
861     os << "  (" << Brief(target_object()) << ")";
862   } else if (rmode_ == EXTERNAL_REFERENCE) {
863     ExternalReferenceEncoder ref_encoder(isolate);
864     os << " (" << ref_encoder.NameOfAddress(target_reference()) << ")  ("
865        << static_cast<const void*>(target_reference()) << ")";
866   } else if (IsCodeTarget(rmode_)) {
867     Code* code = Code::GetCodeFromTargetAddress(target_address());
868     os << " (" << Code::Kind2String(code->kind()) << ")  ("
869        << static_cast<const void*>(target_address()) << ")";
870     if (rmode_ == CODE_TARGET_WITH_ID) {
871       os << " (id=" << static_cast<int>(data_) << ")";
872     }
873   } else if (IsPosition(rmode_)) {
874     os << "  (" << data() << ")";
875   } else if (IsRuntimeEntry(rmode_) &&
876              isolate->deoptimizer_data() != NULL) {
877     // Depotimization bailouts are stored as runtime entries.
878     int id = Deoptimizer::GetDeoptimizationId(
879         isolate, target_address(), Deoptimizer::EAGER);
880     if (id != Deoptimizer::kNotDeoptimizationEntry) {
881       os << "  (deoptimization bailout " << id << ")";
882     }
883   }
884
885   os << "\n";
886 }
887 #endif  // ENABLE_DISASSEMBLER
888
889
890 #ifdef VERIFY_HEAP
891 void RelocInfo::Verify(Isolate* isolate) {
892   switch (rmode_) {
893     case EMBEDDED_OBJECT:
894       Object::VerifyPointer(target_object());
895       break;
896     case CELL:
897       Object::VerifyPointer(target_cell());
898       break;
899     case DEBUG_BREAK:
900     case CONSTRUCT_CALL:
901     case CODE_TARGET_WITH_ID:
902     case CODE_TARGET: {
903       // convert inline target address to code object
904       Address addr = target_address();
905       CHECK(addr != NULL);
906       // Check that we can find the right code object.
907       Code* code = Code::GetCodeFromTargetAddress(addr);
908       Object* found = isolate->FindCodeObject(addr);
909       CHECK(found->IsCode());
910       CHECK(code->address() == HeapObject::cast(found)->address());
911       break;
912     }
913     case RUNTIME_ENTRY:
914     case JS_RETURN:
915     case COMMENT:
916     case POSITION:
917     case STATEMENT_POSITION:
918     case EXTERNAL_REFERENCE:
919     case INTERNAL_REFERENCE:
920     case DEOPT_REASON:
921     case CONST_POOL:
922     case VENEER_POOL:
923     case DEBUG_BREAK_SLOT:
924     case NONE32:
925     case NONE64:
926       break;
927     case NUMBER_OF_MODES:
928       UNREACHABLE();
929       break;
930     case CODE_AGE_SEQUENCE:
931       DCHECK(Code::IsYoungSequence(isolate, pc_) || code_age_stub()->IsCode());
932       break;
933   }
934 }
935 #endif  // VERIFY_HEAP
936
937
938 // -----------------------------------------------------------------------------
939 // Implementation of ExternalReference
940
941 void ExternalReference::SetUp() {
942   double_constants.min_int = kMinInt;
943   double_constants.one_half = 0.5;
944   double_constants.minus_one_half = -0.5;
945   double_constants.the_hole_nan = bit_cast<double>(kHoleNanInt64);
946   double_constants.negative_infinity = -V8_INFINITY;
947   double_constants.uint32_bias =
948     static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
949
950   math_exp_data_mutex = new base::Mutex();
951 }
952
953
954 void ExternalReference::InitializeMathExpData() {
955   // Early return?
956   if (math_exp_data_initialized) return;
957
958   base::LockGuard<base::Mutex> lock_guard(math_exp_data_mutex);
959   if (!math_exp_data_initialized) {
960     // If this is changed, generated code must be adapted too.
961     const int kTableSizeBits = 11;
962     const int kTableSize = 1 << kTableSizeBits;
963     const double kTableSizeDouble = static_cast<double>(kTableSize);
964
965     math_exp_constants_array = new double[9];
966     // Input values smaller than this always return 0.
967     math_exp_constants_array[0] = -708.39641853226408;
968     // Input values larger than this always return +Infinity.
969     math_exp_constants_array[1] = 709.78271289338397;
970     math_exp_constants_array[2] = V8_INFINITY;
971     // The rest is black magic. Do not attempt to understand it. It is
972     // loosely based on the "expd" function published at:
973     // http://herumi.blogspot.com/2011/08/fast-double-precision-exponential.html
974     const double constant3 = (1 << kTableSizeBits) / std::log(2.0);
975     math_exp_constants_array[3] = constant3;
976     math_exp_constants_array[4] =
977         static_cast<double>(static_cast<int64_t>(3) << 51);
978     math_exp_constants_array[5] = 1 / constant3;
979     math_exp_constants_array[6] = 3.0000000027955394;
980     math_exp_constants_array[7] = 0.16666666685227835;
981     math_exp_constants_array[8] = 1;
982
983     math_exp_log_table_array = new double[kTableSize];
984     for (int i = 0; i < kTableSize; i++) {
985       double value = std::pow(2, i / kTableSizeDouble);
986       uint64_t bits = bit_cast<uint64_t, double>(value);
987       bits &= (static_cast<uint64_t>(1) << 52) - 1;
988       double mantissa = bit_cast<double, uint64_t>(bits);
989       math_exp_log_table_array[i] = mantissa;
990     }
991
992     math_exp_data_initialized = true;
993   }
994 }
995
996
997 void ExternalReference::TearDownMathExpData() {
998   delete[] math_exp_constants_array;
999   math_exp_constants_array = NULL;
1000   delete[] math_exp_log_table_array;
1001   math_exp_log_table_array = NULL;
1002   delete math_exp_data_mutex;
1003   math_exp_data_mutex = NULL;
1004 }
1005
1006
1007 ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
1008   : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
1009
1010
1011 ExternalReference::ExternalReference(
1012     ApiFunction* fun,
1013     Type type = ExternalReference::BUILTIN_CALL,
1014     Isolate* isolate = NULL)
1015   : address_(Redirect(isolate, fun->address(), type)) {}
1016
1017
1018 ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
1019   : address_(isolate->builtins()->builtin_address(name)) {}
1020
1021
1022 ExternalReference::ExternalReference(Runtime::FunctionId id,
1023                                      Isolate* isolate)
1024   : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
1025
1026
1027 ExternalReference::ExternalReference(const Runtime::Function* f,
1028                                      Isolate* isolate)
1029   : address_(Redirect(isolate, f->entry)) {}
1030
1031
1032 ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
1033   return ExternalReference(isolate);
1034 }
1035
1036
1037 ExternalReference::ExternalReference(const IC_Utility& ic_utility,
1038                                      Isolate* isolate)
1039   : address_(Redirect(isolate, ic_utility.address())) {}
1040
1041
1042 ExternalReference::ExternalReference(StatsCounter* counter)
1043   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
1044
1045
1046 ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
1047   : address_(isolate->get_address_from_id(id)) {}
1048
1049
1050 ExternalReference::ExternalReference(const SCTableReference& table_ref)
1051   : address_(table_ref.address()) {}
1052
1053
1054 ExternalReference ExternalReference::
1055     incremental_marking_record_write_function(Isolate* isolate) {
1056   return ExternalReference(Redirect(
1057       isolate,
1058       FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode)));
1059 }
1060
1061
1062 ExternalReference ExternalReference::
1063     store_buffer_overflow_function(Isolate* isolate) {
1064   return ExternalReference(Redirect(
1065       isolate,
1066       FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow)));
1067 }
1068
1069
1070 ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) {
1071   return ExternalReference(
1072       Redirect(isolate, FUNCTION_ADDR(CpuFeatures::FlushICache)));
1073 }
1074
1075
1076 ExternalReference ExternalReference::delete_handle_scope_extensions(
1077     Isolate* isolate) {
1078   return ExternalReference(Redirect(
1079       isolate,
1080       FUNCTION_ADDR(HandleScope::DeleteExtensions)));
1081 }
1082
1083
1084 ExternalReference ExternalReference::get_date_field_function(
1085     Isolate* isolate) {
1086   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField)));
1087 }
1088
1089
1090 ExternalReference ExternalReference::get_make_code_young_function(
1091     Isolate* isolate) {
1092   return ExternalReference(Redirect(
1093       isolate, FUNCTION_ADDR(Code::MakeCodeAgeSequenceYoung)));
1094 }
1095
1096
1097 ExternalReference ExternalReference::get_mark_code_as_executed_function(
1098     Isolate* isolate) {
1099   return ExternalReference(Redirect(
1100       isolate, FUNCTION_ADDR(Code::MarkCodeAsExecuted)));
1101 }
1102
1103
1104 ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
1105   return ExternalReference(isolate->date_cache()->stamp_address());
1106 }
1107
1108
1109 ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) {
1110   return ExternalReference(isolate->stress_deopt_count_address());
1111 }
1112
1113
1114 ExternalReference ExternalReference::new_deoptimizer_function(
1115     Isolate* isolate) {
1116   return ExternalReference(
1117       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
1118 }
1119
1120
1121 ExternalReference ExternalReference::compute_output_frames_function(
1122     Isolate* isolate) {
1123   return ExternalReference(
1124       Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
1125 }
1126
1127
1128 ExternalReference ExternalReference::log_enter_external_function(
1129     Isolate* isolate) {
1130   return ExternalReference(
1131       Redirect(isolate, FUNCTION_ADDR(Logger::EnterExternal)));
1132 }
1133
1134
1135 ExternalReference ExternalReference::log_leave_external_function(
1136     Isolate* isolate) {
1137   return ExternalReference(
1138       Redirect(isolate, FUNCTION_ADDR(Logger::LeaveExternal)));
1139 }
1140
1141
1142 ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
1143   return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
1144 }
1145
1146
1147 ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
1148     Isolate* isolate) {
1149   return ExternalReference(
1150       isolate->keyed_lookup_cache()->field_offsets_address());
1151 }
1152
1153
1154 ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
1155   return ExternalReference(isolate->heap()->roots_array_start());
1156 }
1157
1158
1159 ExternalReference ExternalReference::allocation_sites_list_address(
1160     Isolate* isolate) {
1161   return ExternalReference(isolate->heap()->allocation_sites_list_address());
1162 }
1163
1164
1165 ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
1166   return ExternalReference(isolate->stack_guard()->address_of_jslimit());
1167 }
1168
1169
1170 ExternalReference ExternalReference::address_of_real_stack_limit(
1171     Isolate* isolate) {
1172   return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
1173 }
1174
1175
1176 ExternalReference ExternalReference::address_of_regexp_stack_limit(
1177     Isolate* isolate) {
1178   return ExternalReference(isolate->regexp_stack()->limit_address());
1179 }
1180
1181
1182 ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
1183   return ExternalReference(isolate->heap()->NewSpaceStart());
1184 }
1185
1186
1187 ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
1188   return ExternalReference(isolate->heap()->store_buffer()->TopAddress());
1189 }
1190
1191
1192 ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
1193   return ExternalReference(reinterpret_cast<Address>(
1194       isolate->heap()->NewSpaceMask()));
1195 }
1196
1197
1198 ExternalReference ExternalReference::new_space_allocation_top_address(
1199     Isolate* isolate) {
1200   return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
1201 }
1202
1203
1204 ExternalReference ExternalReference::new_space_allocation_limit_address(
1205     Isolate* isolate) {
1206   return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
1207 }
1208
1209
1210 ExternalReference ExternalReference::old_pointer_space_allocation_top_address(
1211     Isolate* isolate) {
1212   return ExternalReference(
1213       isolate->heap()->OldPointerSpaceAllocationTopAddress());
1214 }
1215
1216
1217 ExternalReference ExternalReference::old_pointer_space_allocation_limit_address(
1218     Isolate* isolate) {
1219   return ExternalReference(
1220       isolate->heap()->OldPointerSpaceAllocationLimitAddress());
1221 }
1222
1223
1224 ExternalReference ExternalReference::old_data_space_allocation_top_address(
1225     Isolate* isolate) {
1226   return ExternalReference(
1227       isolate->heap()->OldDataSpaceAllocationTopAddress());
1228 }
1229
1230
1231 ExternalReference ExternalReference::old_data_space_allocation_limit_address(
1232     Isolate* isolate) {
1233   return ExternalReference(
1234       isolate->heap()->OldDataSpaceAllocationLimitAddress());
1235 }
1236
1237
1238 ExternalReference ExternalReference::handle_scope_level_address(
1239     Isolate* isolate) {
1240   return ExternalReference(HandleScope::current_level_address(isolate));
1241 }
1242
1243
1244 ExternalReference ExternalReference::handle_scope_next_address(
1245     Isolate* isolate) {
1246   return ExternalReference(HandleScope::current_next_address(isolate));
1247 }
1248
1249
1250 ExternalReference ExternalReference::handle_scope_limit_address(
1251     Isolate* isolate) {
1252   return ExternalReference(HandleScope::current_limit_address(isolate));
1253 }
1254
1255
1256 ExternalReference ExternalReference::scheduled_exception_address(
1257     Isolate* isolate) {
1258   return ExternalReference(isolate->scheduled_exception_address());
1259 }
1260
1261
1262 ExternalReference ExternalReference::address_of_pending_message_obj(
1263     Isolate* isolate) {
1264   return ExternalReference(isolate->pending_message_obj_address());
1265 }
1266
1267
1268 ExternalReference ExternalReference::address_of_has_pending_message(
1269     Isolate* isolate) {
1270   return ExternalReference(isolate->has_pending_message_address());
1271 }
1272
1273
1274 ExternalReference ExternalReference::address_of_pending_message_script(
1275     Isolate* isolate) {
1276   return ExternalReference(isolate->pending_message_script_address());
1277 }
1278
1279
1280 ExternalReference ExternalReference::address_of_min_int() {
1281   return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int));
1282 }
1283
1284
1285 ExternalReference ExternalReference::address_of_one_half() {
1286   return ExternalReference(reinterpret_cast<void*>(&double_constants.one_half));
1287 }
1288
1289
1290 ExternalReference ExternalReference::address_of_minus_one_half() {
1291   return ExternalReference(
1292       reinterpret_cast<void*>(&double_constants.minus_one_half));
1293 }
1294
1295
1296 ExternalReference ExternalReference::address_of_negative_infinity() {
1297   return ExternalReference(
1298       reinterpret_cast<void*>(&double_constants.negative_infinity));
1299 }
1300
1301
1302 ExternalReference ExternalReference::address_of_the_hole_nan() {
1303   return ExternalReference(
1304       reinterpret_cast<void*>(&double_constants.the_hole_nan));
1305 }
1306
1307
1308 ExternalReference ExternalReference::address_of_uint32_bias() {
1309   return ExternalReference(
1310       reinterpret_cast<void*>(&double_constants.uint32_bias));
1311 }
1312
1313
1314 ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
1315   return ExternalReference(isolate->cpu_profiler()->is_profiling_address());
1316 }
1317
1318
1319 ExternalReference ExternalReference::invoke_function_callback(
1320     Isolate* isolate) {
1321   Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
1322   ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
1323   ApiFunction thunk_fun(thunk_address);
1324   return ExternalReference(&thunk_fun, thunk_type, isolate);
1325 }
1326
1327
1328 ExternalReference ExternalReference::invoke_accessor_getter_callback(
1329     Isolate* isolate) {
1330   Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1331   ExternalReference::Type thunk_type =
1332       ExternalReference::PROFILING_GETTER_CALL;
1333   ApiFunction thunk_fun(thunk_address);
1334   return ExternalReference(&thunk_fun, thunk_type, isolate);
1335 }
1336
1337
1338 #ifndef V8_INTERPRETED_REGEXP
1339
1340 ExternalReference ExternalReference::re_check_stack_guard_state(
1341     Isolate* isolate) {
1342   Address function;
1343 #if V8_TARGET_ARCH_X64
1344   function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
1345 #elif V8_TARGET_ARCH_IA32
1346   function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
1347 #elif V8_TARGET_ARCH_ARM64
1348   function = FUNCTION_ADDR(RegExpMacroAssemblerARM64::CheckStackGuardState);
1349 #elif V8_TARGET_ARCH_ARM
1350   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
1351 #elif V8_TARGET_ARCH_PPC
1352   function = FUNCTION_ADDR(RegExpMacroAssemblerPPC::CheckStackGuardState);
1353 #elif V8_TARGET_ARCH_MIPS
1354   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1355 #elif V8_TARGET_ARCH_MIPS64
1356   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1357 #elif V8_TARGET_ARCH_X87
1358   function = FUNCTION_ADDR(RegExpMacroAssemblerX87::CheckStackGuardState);
1359 #else
1360   UNREACHABLE();
1361 #endif
1362   return ExternalReference(Redirect(isolate, function));
1363 }
1364
1365
1366 ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
1367   return ExternalReference(
1368       Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
1369 }
1370
1371 ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
1372     Isolate* isolate) {
1373   return ExternalReference(Redirect(
1374       isolate,
1375       FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
1376 }
1377
1378
1379 ExternalReference ExternalReference::re_word_character_map() {
1380   return ExternalReference(
1381       NativeRegExpMacroAssembler::word_character_map_address());
1382 }
1383
1384 ExternalReference ExternalReference::address_of_static_offsets_vector(
1385     Isolate* isolate) {
1386   return ExternalReference(
1387       reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector()));
1388 }
1389
1390 ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
1391     Isolate* isolate) {
1392   return ExternalReference(
1393       isolate->regexp_stack()->memory_address());
1394 }
1395
1396 ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
1397     Isolate* isolate) {
1398   return ExternalReference(isolate->regexp_stack()->memory_size_address());
1399 }
1400
1401 #endif  // V8_INTERPRETED_REGEXP
1402
1403
1404 ExternalReference ExternalReference::math_log_double_function(
1405     Isolate* isolate) {
1406   typedef double (*d2d)(double x);
1407   return ExternalReference(Redirect(isolate,
1408                                     FUNCTION_ADDR(static_cast<d2d>(std::log)),
1409                                     BUILTIN_FP_CALL));
1410 }
1411
1412
1413 ExternalReference ExternalReference::math_exp_constants(int constant_index) {
1414   DCHECK(math_exp_data_initialized);
1415   return ExternalReference(
1416       reinterpret_cast<void*>(math_exp_constants_array + constant_index));
1417 }
1418
1419
1420 ExternalReference ExternalReference::math_exp_log_table() {
1421   DCHECK(math_exp_data_initialized);
1422   return ExternalReference(reinterpret_cast<void*>(math_exp_log_table_array));
1423 }
1424
1425
1426 ExternalReference ExternalReference::page_flags(Page* page) {
1427   return ExternalReference(reinterpret_cast<Address>(page) +
1428                            MemoryChunk::kFlagsOffset);
1429 }
1430
1431
1432 ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
1433   return ExternalReference(entry);
1434 }
1435
1436
1437 ExternalReference ExternalReference::cpu_features() {
1438   DCHECK(CpuFeatures::initialized_);
1439   return ExternalReference(&CpuFeatures::supported_);
1440 }
1441
1442
1443 ExternalReference ExternalReference::debug_is_active_address(
1444     Isolate* isolate) {
1445   return ExternalReference(isolate->debug()->is_active_address());
1446 }
1447
1448
1449 ExternalReference ExternalReference::debug_after_break_target_address(
1450     Isolate* isolate) {
1451   return ExternalReference(isolate->debug()->after_break_target_address());
1452 }
1453
1454
1455 ExternalReference
1456     ExternalReference::debug_restarter_frame_function_pointer_address(
1457         Isolate* isolate) {
1458   return ExternalReference(
1459       isolate->debug()->restarter_frame_function_pointer_address());
1460 }
1461
1462
1463 double power_helper(double x, double y) {
1464   int y_int = static_cast<int>(y);
1465   if (y == y_int) {
1466     return power_double_int(x, y_int);  // Returns 1 if exponent is 0.
1467   }
1468   if (y == 0.5) {
1469     return (std::isinf(x)) ? V8_INFINITY
1470                            : fast_sqrt(x + 0.0);  // Convert -0 to +0.
1471   }
1472   if (y == -0.5) {
1473     return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0);  // Convert -0 to +0.
1474   }
1475   return power_double_double(x, y);
1476 }
1477
1478
1479 // Helper function to compute x^y, where y is known to be an
1480 // integer. Uses binary decomposition to limit the number of
1481 // multiplications; see the discussion in "Hacker's Delight" by Henry
1482 // S. Warren, Jr., figure 11-6, page 213.
1483 double power_double_int(double x, int y) {
1484   double m = (y < 0) ? 1 / x : x;
1485   unsigned n = (y < 0) ? -y : y;
1486   double p = 1;
1487   while (n != 0) {
1488     if ((n & 1) != 0) p *= m;
1489     m *= m;
1490     if ((n & 2) != 0) p *= m;
1491     m *= m;
1492     n >>= 2;
1493   }
1494   return p;
1495 }
1496
1497
1498 double power_double_double(double x, double y) {
1499 #if (defined(__MINGW64_VERSION_MAJOR) &&                              \
1500      (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)) || \
1501     defined(V8_OS_AIX)
1502   // MinGW64 and AIX have a custom implementation for pow.  This handles certain
1503   // special cases that are different.
1504   if ((x == 0.0 || std::isinf(x)) && y != 0.0 && std::isfinite(y)) {
1505     double f;
1506     double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
1507     /* retain sign if odd integer exponent */
1508     return ((std::modf(y, &f) == 0.0) && (static_cast<int64_t>(y) & 1))
1509                ? copysign(result, x)
1510                : result;
1511   }
1512
1513   if (x == 2.0) {
1514     int y_int = static_cast<int>(y);
1515     if (y == y_int) {
1516       return std::ldexp(1.0, y_int);
1517     }
1518   }
1519 #endif
1520
1521   // The checks for special cases can be dropped in ia32 because it has already
1522   // been done in generated code before bailing out here.
1523   if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
1524     return std::numeric_limits<double>::quiet_NaN();
1525   }
1526   return std::pow(x, y);
1527 }
1528
1529
1530 ExternalReference ExternalReference::power_double_double_function(
1531     Isolate* isolate) {
1532   return ExternalReference(Redirect(isolate,
1533                                     FUNCTION_ADDR(power_double_double),
1534                                     BUILTIN_FP_FP_CALL));
1535 }
1536
1537
1538 ExternalReference ExternalReference::power_double_int_function(
1539     Isolate* isolate) {
1540   return ExternalReference(Redirect(isolate,
1541                                     FUNCTION_ADDR(power_double_int),
1542                                     BUILTIN_FP_INT_CALL));
1543 }
1544
1545
1546 bool EvalComparison(Token::Value op, double op1, double op2) {
1547   DCHECK(Token::IsCompareOp(op));
1548   switch (op) {
1549     case Token::EQ:
1550     case Token::EQ_STRICT: return (op1 == op2);
1551     case Token::NE: return (op1 != op2);
1552     case Token::LT: return (op1 < op2);
1553     case Token::GT: return (op1 > op2);
1554     case Token::LTE: return (op1 <= op2);
1555     case Token::GTE: return (op1 >= op2);
1556     default:
1557       UNREACHABLE();
1558       return false;
1559   }
1560 }
1561
1562
1563 ExternalReference ExternalReference::mod_two_doubles_operation(
1564     Isolate* isolate) {
1565   return ExternalReference(Redirect(isolate,
1566                                     FUNCTION_ADDR(modulo),
1567                                     BUILTIN_FP_FP_CALL));
1568 }
1569
1570
1571 ExternalReference ExternalReference::debug_break(Isolate* isolate) {
1572   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
1573 }
1574
1575
1576 ExternalReference ExternalReference::debug_step_in_fp_address(
1577     Isolate* isolate) {
1578   return ExternalReference(isolate->debug()->step_in_fp_addr());
1579 }
1580
1581
1582 bool operator==(ExternalReference lhs, ExternalReference rhs) {
1583   return lhs.address() == rhs.address();
1584 }
1585
1586
1587 bool operator!=(ExternalReference lhs, ExternalReference rhs) {
1588   return !(lhs == rhs);
1589 }
1590
1591
1592 size_t hash_value(ExternalReference reference) {
1593   return base::hash<Address>()(reference.address());
1594 }
1595
1596
1597 std::ostream& operator<<(std::ostream& os, ExternalReference reference) {
1598   os << static_cast<const void*>(reference.address());
1599   const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address());
1600   if (fn) os << "<" << fn->name << ".entry>";
1601   return os;
1602 }
1603
1604
1605 void PositionsRecorder::RecordPosition(int pos) {
1606   DCHECK(pos != RelocInfo::kNoPosition);
1607   DCHECK(pos >= 0);
1608   state_.current_position = pos;
1609   LOG_CODE_EVENT(assembler_->isolate(),
1610                  CodeLinePosInfoAddPositionEvent(jit_handler_data_,
1611                                                  assembler_->pc_offset(),
1612                                                  pos));
1613 }
1614
1615
1616 void PositionsRecorder::RecordStatementPosition(int pos) {
1617   DCHECK(pos != RelocInfo::kNoPosition);
1618   DCHECK(pos >= 0);
1619   state_.current_statement_position = pos;
1620   LOG_CODE_EVENT(assembler_->isolate(),
1621                  CodeLinePosInfoAddStatementPositionEvent(
1622                      jit_handler_data_,
1623                      assembler_->pc_offset(),
1624                      pos));
1625 }
1626
1627
1628 bool PositionsRecorder::WriteRecordedPositions() {
1629   bool written = false;
1630
1631   // Write the statement position if it is different from what was written last
1632   // time.
1633   if (state_.current_statement_position != state_.written_statement_position) {
1634     EnsureSpace ensure_space(assembler_);
1635     assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
1636                                 state_.current_statement_position);
1637     state_.written_statement_position = state_.current_statement_position;
1638     written = true;
1639   }
1640
1641   // Write the position if it is different from what was written last time and
1642   // also different from the written statement position.
1643   if (state_.current_position != state_.written_position &&
1644       state_.current_position != state_.written_statement_position) {
1645     EnsureSpace ensure_space(assembler_);
1646     assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
1647     state_.written_position = state_.current_position;
1648     written = true;
1649   }
1650
1651   // Return whether something was written.
1652   return written;
1653 }
1654
1655
1656 // Platform specific but identical code for all the platforms.
1657
1658
1659 void Assembler::RecordDeoptReason(const int reason, const int raw_position) {
1660   if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling()) {
1661     EnsureSpace ensure_space(this);
1662     RecordRelocInfo(RelocInfo::POSITION, raw_position);
1663     RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
1664   }
1665 }
1666
1667
1668 void Assembler::RecordComment(const char* msg) {
1669   if (FLAG_code_comments) {
1670     EnsureSpace ensure_space(this);
1671     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1672   }
1673 }
1674
1675
1676 void Assembler::RecordJSReturn() {
1677   positions_recorder()->WriteRecordedPositions();
1678   EnsureSpace ensure_space(this);
1679   RecordRelocInfo(RelocInfo::JS_RETURN);
1680 }
1681
1682
1683 void Assembler::RecordDebugBreakSlot() {
1684   positions_recorder()->WriteRecordedPositions();
1685   EnsureSpace ensure_space(this);
1686   RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
1687 }
1688 } }  // namespace v8::internal