blob: c73b470c28cb47592e502879253901488ce9483f [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright (c) 1994-2006 Sun Microsystems Inc.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010033// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000034
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#include "src/assembler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037#include <cmath>
38#include "src/api.h"
39#include "src/base/cpu.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040040#include "src/base/functional.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041#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"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056#include "src/runtime/runtime.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057#include "src/serialize.h"
58#include "src/token.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +010059
60#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061#include "src/ia32/assembler-ia32-inl.h" // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +010062#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063#include "src/x64/assembler-x64-inl.h" // NOLINT
64#elif V8_TARGET_ARCH_ARM64
65#include "src/arm64/assembler-arm64-inl.h" // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +010066#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067#include "src/arm/assembler-arm-inl.h" // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +010068#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069#include "src/mips/assembler-mips-inl.h" // NOLINT
70#elif V8_TARGET_ARCH_MIPS64
71#include "src/mips64/assembler-mips64-inl.h" // NOLINT
72#elif V8_TARGET_ARCH_X87
73#include "src/x87/assembler-x87-inl.h" // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +010074#else
75#error "Unknown architecture."
76#endif
77
Steve Blocka7e24c12009-10-30 11:49:00 +000078// Include native regexp-macro-assembler.
Steve Block6ded16b2010-05-10 14:33:55 +010079#ifndef V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +000080#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081#include "src/ia32/regexp-macro-assembler-ia32.h" // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +000082#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083#include "src/x64/regexp-macro-assembler-x64.h" // NOLINT
84#elif V8_TARGET_ARCH_ARM64
85#include "src/arm64/regexp-macro-assembler-arm64.h" // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +000086#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087#include "src/arm/regexp-macro-assembler-arm.h" // NOLINT
Steve Block44f0eee2011-05-26 01:26:41 +010088#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089#include "src/mips/regexp-macro-assembler-mips.h" // NOLINT
90#elif V8_TARGET_ARCH_MIPS64
91#include "src/mips64/regexp-macro-assembler-mips64.h" // NOLINT
92#elif V8_TARGET_ARCH_X87
93#include "src/x87/regexp-macro-assembler-x87.h" // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +000094#else // Unknown architecture.
95#error "Unknown architecture."
96#endif // Target architecture.
Steve Block6ded16b2010-05-10 14:33:55 +010097#endif // V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +000098
99namespace v8 {
100namespace internal {
101
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100102// -----------------------------------------------------------------------------
103// Common double constants.
Steve Blocka7e24c12009-10-30 11:49:00 +0000104
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100105struct DoubleConstant BASE_EMBEDDED {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106double min_int;
107double one_half;
108double minus_one_half;
109double negative_infinity;
110double canonical_non_hole_nan;
111double the_hole_nan;
112double uint32_bias;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100113};
114
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115static DoubleConstant double_constants;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100116
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000117const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100118
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119static bool math_exp_data_initialized = false;
120static base::Mutex* math_exp_data_mutex = NULL;
121static double* math_exp_constants_array = NULL;
122static double* math_exp_log_table_array = NULL;
123
Steve Blocka7e24c12009-10-30 11:49:00 +0000124// -----------------------------------------------------------------------------
Steve Block053d10c2011-06-13 19:13:29 +0100125// Implementation of AssemblerBase
126
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size)
Steve Block053d10c2011-06-13 19:13:29 +0100128 : isolate_(isolate),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 jit_cookie_(0),
130 enabled_cpu_features_(0),
131 emit_debug_code_(FLAG_debug_code),
132 predictable_code_size_(false),
133 // We may use the assembler without an isolate.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400134 serializer_enabled_(isolate && isolate->serializer_enabled()),
135 ool_constant_pool_available_(false) {
Steve Block053d10c2011-06-13 19:13:29 +0100136 if (FLAG_mask_constants_with_cookie && isolate != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 jit_cookie_ = isolate->random_number_generator()->NextInt();
Steve Block053d10c2011-06-13 19:13:29 +0100138 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 own_buffer_ = buffer == NULL;
140 if (buffer_size == 0) buffer_size = kMinimalBufferSize;
141 DCHECK(buffer_size > 0);
142 if (own_buffer_) buffer = NewArray<byte>(buffer_size);
143 buffer_ = static_cast<byte*>(buffer);
144 buffer_size_ = buffer_size;
145
146 pc_ = buffer_;
Steve Block053d10c2011-06-13 19:13:29 +0100147}
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150AssemblerBase::~AssemblerBase() {
151 if (own_buffer_) DeleteArray(buffer_);
152}
153
154
155// -----------------------------------------------------------------------------
156// Implementation of PredictableCodeSizeScope
157
158PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
159 int expected_size)
160 : assembler_(assembler),
161 expected_size_(expected_size),
162 start_offset_(assembler->pc_offset()),
163 old_value_(assembler->predictable_code_size()) {
164 assembler_->set_predictable_code_size(true);
165}
166
167
168PredictableCodeSizeScope::~PredictableCodeSizeScope() {
169 // TODO(svenpanne) Remove the 'if' when everything works.
170 if (expected_size_ >= 0) {
171 CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
172 }
173 assembler_->set_predictable_code_size(old_value_);
174}
175
176
177// -----------------------------------------------------------------------------
178// Implementation of CpuFeatureScope
179
180#ifdef DEBUG
181CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f)
182 : assembler_(assembler) {
183 DCHECK(CpuFeatures::IsSupported(f));
184 old_enabled_ = assembler_->enabled_cpu_features();
185 uint64_t mask = static_cast<uint64_t>(1) << f;
186 // TODO(svenpanne) This special case below doesn't belong here!
187#if V8_TARGET_ARCH_ARM
188 // ARMv7 is implied by VFP3.
189 if (f == VFP3) {
190 mask |= static_cast<uint64_t>(1) << ARMv7;
191 }
192#endif
193 assembler_->set_enabled_cpu_features(old_enabled_ | mask);
194}
195
196
197CpuFeatureScope::~CpuFeatureScope() {
198 assembler_->set_enabled_cpu_features(old_enabled_);
199}
200#endif
201
202
203bool CpuFeatures::initialized_ = false;
204unsigned CpuFeatures::supported_ = 0;
205unsigned CpuFeatures::cache_line_size_ = 0;
206
207
Steve Block053d10c2011-06-13 19:13:29 +0100208// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000209// Implementation of Label
210
211int Label::pos() const {
212 if (pos_ < 0) return -pos_ - 1;
213 if (pos_ > 0) return pos_ - 1;
214 UNREACHABLE();
215 return 0;
216}
217
218
219// -----------------------------------------------------------------------------
220// Implementation of RelocInfoWriter and RelocIterator
221//
Ben Murdoch257744e2011-11-30 15:57:28 +0000222// Relocation information is written backwards in memory, from high addresses
223// towards low addresses, byte by byte. Therefore, in the encodings listed
224// below, the first byte listed it at the highest address, and successive
225// bytes in the record are at progressively lower addresses.
226//
Steve Blocka7e24c12009-10-30 11:49:00 +0000227// Encoding
228//
229// The most common modes are given single-byte encodings. Also, it is
230// easy to identify the type of reloc info and skip unwanted modes in
231// an iteration.
232//
Ben Murdoch257744e2011-11-30 15:57:28 +0000233// The encoding relies on the fact that there are fewer than 14
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234// different relocation modes using standard non-compact encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000235//
Ben Murdoch257744e2011-11-30 15:57:28 +0000236// The first byte of a relocation record has a tag in its low 2 bits:
237// Here are the record schemes, depending on the low tag and optional higher
238// tags.
Steve Blocka7e24c12009-10-30 11:49:00 +0000239//
Ben Murdoch257744e2011-11-30 15:57:28 +0000240// Low tag:
241// 00: embedded_object: [6-bit pc delta] 00
Steve Blocka7e24c12009-10-30 11:49:00 +0000242//
Ben Murdoch257744e2011-11-30 15:57:28 +0000243// 01: code_target: [6-bit pc delta] 01
Steve Blocka7e24c12009-10-30 11:49:00 +0000244//
Ben Murdoch257744e2011-11-30 15:57:28 +0000245// 10: short_data_record: [6-bit pc delta] 10 followed by
246// [6-bit data delta] [2-bit data type tag]
Steve Blocka7e24c12009-10-30 11:49:00 +0000247//
Ben Murdoch257744e2011-11-30 15:57:28 +0000248// 11: long_record [2-bit high tag][4 bit middle_tag] 11
249// followed by variable data depending on type.
Steve Blocka7e24c12009-10-30 11:49:00 +0000250//
Ben Murdoch257744e2011-11-30 15:57:28 +0000251// 2-bit data type tags, used in short_data_record and data_jump long_record:
252// code_target_with_id: 00
253// position: 01
254// statement_position: 10
255// comment: 11 (not used in short_data_record)
Steve Blocka7e24c12009-10-30 11:49:00 +0000256//
Ben Murdoch257744e2011-11-30 15:57:28 +0000257// Long record format:
258// 4-bit middle_tag:
259// 0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2
260// (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM,
261// and is between 0000 and 1100)
262// The format is:
263// 00 [4 bit middle_tag] 11 followed by
264// 00 [6 bit pc delta]
Steve Blocka7e24c12009-10-30 11:49:00 +0000265//
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266// 1101: constant or veneer pool. Used only on ARM and ARM64 for now.
267// The format is: [2-bit sub-type] 1101 11
268// signed int (size of the pool).
269// The 2-bit sub-types are:
270// 00: constant pool
271// 01: veneer pool
Ben Murdoch257744e2011-11-30 15:57:28 +0000272// 1110: long_data_record
273// The format is: [2-bit data_type_tag] 1110 11
274// signed intptr_t, lowest byte written first
275// (except data_type code_target_with_id, which
276// is followed by a signed int, not intptr_t.)
Steve Blocka7e24c12009-10-30 11:49:00 +0000277//
Ben Murdoch257744e2011-11-30 15:57:28 +0000278// 1111: long_pc_jump
279// The format is:
280// pc-jump: 00 1111 11,
281// 00 [6 bits pc delta]
282// or
283// pc-jump (variable length):
284// 01 1111 11,
285// [7 bits data] 0
286// ...
287// [7 bits data] 1
288// (Bits 6..31 of pc delta, with leading zeroes
289// dropped, and last non-zero chunk tagged with 1.)
290
291
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292#ifdef DEBUG
293const int kMaxStandardNonCompactModes = 14;
294#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000295
296const int kTagBits = 2;
297const int kTagMask = (1 << kTagBits) - 1;
298const int kExtraTagBits = 4;
Ben Murdoch257744e2011-11-30 15:57:28 +0000299const int kLocatableTypeTagBits = 2;
300const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits;
Steve Blocka7e24c12009-10-30 11:49:00 +0000301
302const int kEmbeddedObjectTag = 0;
303const int kCodeTargetTag = 1;
Ben Murdoch257744e2011-11-30 15:57:28 +0000304const int kLocatableTag = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +0000305const int kDefaultTag = 3;
306
Ben Murdoch257744e2011-11-30 15:57:28 +0000307const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000308
309const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
310const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
Steve Block44f0eee2011-05-26 01:26:41 +0100311const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000312
313const int kVariableLengthPCJumpTopTag = 1;
314const int kChunkBits = 7;
315const int kChunkMask = (1 << kChunkBits) - 1;
316const int kLastChunkTagBits = 1;
317const int kLastChunkTagMask = 1;
318const int kLastChunkTag = 1;
319
320
Ben Murdoch257744e2011-11-30 15:57:28 +0000321const int kDataJumpExtraTag = kPCJumpExtraTag - 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000322
Ben Murdoch257744e2011-11-30 15:57:28 +0000323const int kCodeWithIdTag = 0;
324const int kNonstatementPositionTag = 1;
325const int kStatementPositionTag = 2;
326const int kCommentTag = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +0000327
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328const int kPoolExtraTag = kPCJumpExtraTag - 2;
329const int kConstPoolTag = 0;
330const int kVeneerPoolTag = 1;
331
Steve Blocka7e24c12009-10-30 11:49:00 +0000332
333uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
334 // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
335 // Otherwise write a variable length PC jump for the bits that do
336 // not fit in the kSmallPCDeltaBits bits.
337 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
Ben Murdoch257744e2011-11-30 15:57:28 +0000338 WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 DCHECK(pc_jump > 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 // Write kChunkBits size chunks of the pc_jump.
342 for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
343 byte b = pc_jump & kChunkMask;
344 *--pos_ = b << kLastChunkTagBits;
345 }
346 // Tag the last chunk so it can be identified.
347 *pos_ = *pos_ | kLastChunkTag;
348 // Return the remaining kSmallPCDeltaBits of the pc_delta.
349 return pc_delta & kSmallPCDeltaMask;
350}
351
352
353void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
354 // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
355 pc_delta = WriteVariableLengthPCJump(pc_delta);
356 *--pos_ = pc_delta << kTagBits | tag;
357}
358
359
360void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000361 *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000362}
363
364
365void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
Steve Blockd0582a62009-12-15 09:54:21 +0000366 *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
367 extra_tag << kTagBits |
368 kDefaultTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000369}
370
371
372void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
373 // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
374 pc_delta = WriteVariableLengthPCJump(pc_delta);
375 WriteExtraTag(extra_tag, 0);
376 *--pos_ = pc_delta;
377}
378
379
Ben Murdoch257744e2011-11-30 15:57:28 +0000380void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
381 WriteExtraTag(kDataJumpExtraTag, top_tag);
382 for (int i = 0; i < kIntSize; i++) {
383 *--pos_ = static_cast<byte>(data_delta);
384 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
385 data_delta = data_delta >> kBitsPerByte;
386 }
387}
388
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389
390void RelocInfoWriter::WriteExtraTaggedPoolData(int data, int pool_type) {
391 WriteExtraTag(kPoolExtraTag, pool_type);
392 for (int i = 0; i < kIntSize; i++) {
393 *--pos_ = static_cast<byte>(data);
394 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
395 data = data >> kBitsPerByte;
396 }
397}
398
399
Steve Blocka7e24c12009-10-30 11:49:00 +0000400void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000401 WriteExtraTag(kDataJumpExtraTag, top_tag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 for (int i = 0; i < kIntptrSize; i++) {
Steve Blockd0582a62009-12-15 09:54:21 +0000403 *--pos_ = static_cast<byte>(data_delta);
Ben Murdoch257744e2011-11-30 15:57:28 +0000404 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 data_delta = data_delta >> kBitsPerByte;
406 }
407}
408
409
410void RelocInfoWriter::Write(const RelocInfo* rinfo) {
411#ifdef DEBUG
412 byte* begin_pos = pos_;
413#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 DCHECK(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES);
415 DCHECK(rinfo->pc() - last_pc_ >= 0);
416 DCHECK(RelocInfo::LAST_STANDARD_NONCOMPACT_ENUM - RelocInfo::LAST_COMPACT_ENUM
417 <= kMaxStandardNonCompactModes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000418 // Use unsigned delta-encoding for pc.
Steve Blockd0582a62009-12-15 09:54:21 +0000419 uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000420 RelocInfo::Mode rmode = rinfo->rmode();
421
422 // The two most common modes are given small tags, and usually fit in a byte.
423 if (rmode == RelocInfo::EMBEDDED_OBJECT) {
424 WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
425 } else if (rmode == RelocInfo::CODE_TARGET) {
426 WriteTaggedPC(pc_delta, kCodeTargetTag);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 DCHECK(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
Ben Murdoch257744e2011-11-30 15:57:28 +0000428 } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
429 // Use signed delta-encoding for id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
Ben Murdoch257744e2011-11-30 15:57:28 +0000431 int id_delta = static_cast<int>(rinfo->data()) - last_id_;
432 // Check if delta is small enough to fit in a tagged byte.
433 if (is_intn(id_delta, kSmallDataBits)) {
434 WriteTaggedPC(pc_delta, kLocatableTag);
435 WriteTaggedData(id_delta, kCodeWithIdTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000436 } else {
437 // Otherwise, use costly encoding.
Ben Murdoch257744e2011-11-30 15:57:28 +0000438 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
439 WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000440 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000441 last_id_ = static_cast<int>(rinfo->data());
442 } else if (RelocInfo::IsPosition(rmode)) {
443 // Use signed delta-encoding for position.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000444 DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
Ben Murdoch257744e2011-11-30 15:57:28 +0000445 int pos_delta = static_cast<int>(rinfo->data()) - last_position_;
446 int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
447 : kStatementPositionTag;
448 // Check if delta is small enough to fit in a tagged byte.
449 if (is_intn(pos_delta, kSmallDataBits)) {
450 WriteTaggedPC(pc_delta, kLocatableTag);
451 WriteTaggedData(pos_delta, pos_type_tag);
452 } else {
453 // Otherwise, use costly encoding.
454 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
455 WriteExtraTaggedIntData(pos_delta, pos_type_tag);
456 }
457 last_position_ = static_cast<int>(rinfo->data());
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 } else if (RelocInfo::IsComment(rmode)) {
459 // Comments are normally not generated, so we use the costly encoding.
Ben Murdoch257744e2011-11-30 15:57:28 +0000460 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
461 WriteExtraTaggedData(rinfo->data(), kCommentTag);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462 DCHECK(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
463 } else if (RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)) {
464 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
465 WriteExtraTaggedPoolData(static_cast<int>(rinfo->data()),
466 RelocInfo::IsConstPool(rmode) ? kConstPoolTag
467 : kVeneerPoolTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 DCHECK(rmode > RelocInfo::LAST_COMPACT_ENUM);
Ben Murdoch257744e2011-11-30 15:57:28 +0000470 int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
Steve Blocka7e24c12009-10-30 11:49:00 +0000471 // For all other modes we simply use the mode as the extra tag.
472 // None of these modes need a data component.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 DCHECK(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag);
Ben Murdoch257744e2011-11-30 15:57:28 +0000474 WriteExtraTaggedPC(pc_delta, saved_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 }
476 last_pc_ = rinfo->pc();
477#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 DCHECK(begin_pos - pos_ <= kMaxSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000479#endif
480}
481
482
483inline int RelocIterator::AdvanceGetTag() {
484 return *--pos_ & kTagMask;
485}
486
487
488inline int RelocIterator::GetExtraTag() {
489 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
490}
491
492
493inline int RelocIterator::GetTopTag() {
494 return *pos_ >> (kTagBits + kExtraTagBits);
495}
496
497
498inline void RelocIterator::ReadTaggedPC() {
499 rinfo_.pc_ += *pos_ >> kTagBits;
500}
501
502
503inline void RelocIterator::AdvanceReadPC() {
504 rinfo_.pc_ += *--pos_;
505}
506
507
Ben Murdoch257744e2011-11-30 15:57:28 +0000508void RelocIterator::AdvanceReadId() {
509 int x = 0;
510 for (int i = 0; i < kIntSize; i++) {
511 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
512 }
513 last_id_ += x;
514 rinfo_.data_ = last_id_;
515}
516
517
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518void RelocIterator::AdvanceReadPoolData() {
519 int x = 0;
520 for (int i = 0; i < kIntSize; i++) {
521 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
522 }
523 rinfo_.data_ = x;
524}
525
526
Ben Murdoch257744e2011-11-30 15:57:28 +0000527void RelocIterator::AdvanceReadPosition() {
528 int x = 0;
529 for (int i = 0; i < kIntSize; i++) {
530 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
531 }
532 last_position_ += x;
533 rinfo_.data_ = last_position_;
534}
535
536
Steve Blocka7e24c12009-10-30 11:49:00 +0000537void RelocIterator::AdvanceReadData() {
538 intptr_t x = 0;
539 for (int i = 0; i < kIntptrSize; i++) {
540 x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
541 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000542 rinfo_.data_ = x;
Steve Blocka7e24c12009-10-30 11:49:00 +0000543}
544
545
546void RelocIterator::AdvanceReadVariableLengthPCJump() {
547 // Read the 32-kSmallPCDeltaBits most significant bits of the
548 // pc jump in kChunkBits bit chunks and shift them into place.
549 // Stop when the last chunk is encountered.
550 uint32_t pc_jump = 0;
551 for (int i = 0; i < kIntSize; i++) {
552 byte pc_jump_part = *--pos_;
553 pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
554 if ((pc_jump_part & kLastChunkTagMask) == 1) break;
555 }
556 // The least significant kSmallPCDeltaBits bits will be added
557 // later.
558 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
559}
560
561
Ben Murdoch257744e2011-11-30 15:57:28 +0000562inline int RelocIterator::GetLocatableTypeTag() {
563 return *pos_ & ((1 << kLocatableTypeTagBits) - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000564}
565
566
Ben Murdoch257744e2011-11-30 15:57:28 +0000567inline void RelocIterator::ReadTaggedId() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000568 int8_t signed_b = *pos_;
569 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
Ben Murdoch257744e2011-11-30 15:57:28 +0000570 last_id_ += signed_b >> kLocatableTypeTagBits;
571 rinfo_.data_ = last_id_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000572}
573
574
Ben Murdoch257744e2011-11-30 15:57:28 +0000575inline void RelocIterator::ReadTaggedPosition() {
576 int8_t signed_b = *pos_;
577 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
578 last_position_ += signed_b >> kLocatableTypeTagBits;
579 rinfo_.data_ = last_position_;
580}
581
582
583static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 DCHECK(tag == kNonstatementPositionTag ||
Ben Murdoch257744e2011-11-30 15:57:28 +0000585 tag == kStatementPositionTag);
586 return (tag == kNonstatementPositionTag) ?
587 RelocInfo::POSITION :
588 RelocInfo::STATEMENT_POSITION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000589}
590
591
592void RelocIterator::next() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 // Basically, do the opposite of RelocInfoWriter::Write.
595 // Reading of data is as far as possible avoided for unwanted modes,
596 // but we must always update the pc.
597 //
598 // We exit this loop by returning when we find a mode we want.
599 while (pos_ > end_) {
600 int tag = AdvanceGetTag();
601 if (tag == kEmbeddedObjectTag) {
602 ReadTaggedPC();
603 if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
604 } else if (tag == kCodeTargetTag) {
605 ReadTaggedPC();
Steve Blocka7e24c12009-10-30 11:49:00 +0000606 if (SetMode(RelocInfo::CODE_TARGET)) return;
Ben Murdoch257744e2011-11-30 15:57:28 +0000607 } else if (tag == kLocatableTag) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000608 ReadTaggedPC();
609 Advance();
Ben Murdoch257744e2011-11-30 15:57:28 +0000610 int locatable_tag = GetLocatableTypeTag();
611 if (locatable_tag == kCodeWithIdTag) {
612 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
613 ReadTaggedId();
614 return;
615 }
616 } else {
617 // Compact encoding is never used for comments,
618 // so it must be a position.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 DCHECK(locatable_tag == kNonstatementPositionTag ||
Ben Murdoch257744e2011-11-30 15:57:28 +0000620 locatable_tag == kStatementPositionTag);
621 if (mode_mask_ & RelocInfo::kPositionMask) {
622 ReadTaggedPosition();
623 if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
624 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000625 }
626 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 DCHECK(tag == kDefaultTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000628 int extra_tag = GetExtraTag();
Ben Murdoch257744e2011-11-30 15:57:28 +0000629 if (extra_tag == kPCJumpExtraTag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000630 if (GetTopTag() == kVariableLengthPCJumpTopTag) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000631 AdvanceReadVariableLengthPCJump();
632 } else {
633 AdvanceReadPC();
634 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000635 } else if (extra_tag == kDataJumpExtraTag) {
636 int locatable_tag = GetTopTag();
637 if (locatable_tag == kCodeWithIdTag) {
638 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
639 AdvanceReadId();
640 return;
641 }
642 Advance(kIntSize);
643 } else if (locatable_tag != kCommentTag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644 DCHECK(locatable_tag == kNonstatementPositionTag ||
Ben Murdoch257744e2011-11-30 15:57:28 +0000645 locatable_tag == kStatementPositionTag);
646 if (mode_mask_ & RelocInfo::kPositionMask) {
647 AdvanceReadPosition();
648 if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
649 } else {
650 Advance(kIntSize);
651 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 DCHECK(locatable_tag == kCommentTag);
Ben Murdoch257744e2011-11-30 15:57:28 +0000654 if (SetMode(RelocInfo::COMMENT)) {
655 AdvanceReadData();
656 return;
657 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000658 Advance(kIntptrSize);
659 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 } else if (extra_tag == kPoolExtraTag) {
661 int pool_type = GetTopTag();
662 DCHECK(pool_type == kConstPoolTag || pool_type == kVeneerPoolTag);
663 RelocInfo::Mode rmode = (pool_type == kConstPoolTag) ?
664 RelocInfo::CONST_POOL : RelocInfo::VENEER_POOL;
665 if (SetMode(rmode)) {
666 AdvanceReadPoolData();
667 return;
668 }
669 Advance(kIntSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 } else {
671 AdvanceReadPC();
Ben Murdoch257744e2011-11-30 15:57:28 +0000672 int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM;
673 if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 }
675 }
676 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 if (code_age_sequence_ != NULL) {
678 byte* old_code_age_sequence = code_age_sequence_;
679 code_age_sequence_ = NULL;
680 if (SetMode(RelocInfo::CODE_AGE_SEQUENCE)) {
681 rinfo_.data_ = 0;
682 rinfo_.pc_ = old_code_age_sequence;
683 return;
684 }
685 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000686 done_ = true;
687}
688
689
690RelocIterator::RelocIterator(Code* code, int mode_mask) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100691 rinfo_.host_ = code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000692 rinfo_.pc_ = code->instruction_start();
693 rinfo_.data_ = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100694 // Relocation info is read backwards.
Steve Blocka7e24c12009-10-30 11:49:00 +0000695 pos_ = code->relocation_start() + code->relocation_size();
696 end_ = code->relocation_start();
697 done_ = false;
698 mode_mask_ = mode_mask;
Ben Murdoch257744e2011-11-30 15:57:28 +0000699 last_id_ = 0;
700 last_position_ = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000701 byte* sequence = code->FindCodeAgeSequence();
702 // We get the isolate from the map, because at serialization time
703 // the code pointer has been cloned and isn't really in heap space.
704 Isolate* isolate = code->map()->GetIsolate();
705 if (sequence != NULL && !Code::IsYoungSequence(isolate, sequence)) {
706 code_age_sequence_ = sequence;
707 } else {
708 code_age_sequence_ = NULL;
709 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000710 if (mode_mask_ == 0) pos_ = end_;
711 next();
712}
713
714
715RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
716 rinfo_.pc_ = desc.buffer;
717 rinfo_.data_ = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100718 // Relocation info is read backwards.
Steve Blocka7e24c12009-10-30 11:49:00 +0000719 pos_ = desc.buffer + desc.buffer_size;
720 end_ = pos_ - desc.reloc_size;
721 done_ = false;
722 mode_mask_ = mode_mask;
Ben Murdoch257744e2011-11-30 15:57:28 +0000723 last_id_ = 0;
724 last_position_ = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000725 code_age_sequence_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000726 if (mode_mask_ == 0) pos_ = end_;
727 next();
728}
729
730
731// -----------------------------------------------------------------------------
732// Implementation of RelocInfo
733
734
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735#ifdef DEBUG
736bool RelocInfo::RequiresRelocation(const CodeDesc& desc) {
737 // Ensure there are no code targets or embedded objects present in the
738 // deoptimization entries, they would require relocation after code
739 // generation.
740 int mode_mask = RelocInfo::kCodeTargetMask |
741 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
742 RelocInfo::ModeMask(RelocInfo::CELL) |
743 RelocInfo::kApplyMask;
744 RelocIterator it(desc, mode_mask);
745 return !it.done();
746}
747#endif
748
749
Steve Blocka7e24c12009-10-30 11:49:00 +0000750#ifdef ENABLE_DISASSEMBLER
751const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
752 switch (rmode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 case RelocInfo::NONE32:
754 return "no reloc 32";
755 case RelocInfo::NONE64:
756 return "no reloc 64";
Steve Blocka7e24c12009-10-30 11:49:00 +0000757 case RelocInfo::EMBEDDED_OBJECT:
758 return "embedded object";
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 case RelocInfo::CONSTRUCT_CALL:
760 return "code target (js construct call)";
Andrei Popescu402d9372010-02-26 13:31:12 +0000761 case RelocInfo::DEBUG_BREAK:
Andrei Popescu402d9372010-02-26 13:31:12 +0000762 return "debug break";
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 case RelocInfo::CODE_TARGET:
764 return "code target";
Ben Murdoch257744e2011-11-30 15:57:28 +0000765 case RelocInfo::CODE_TARGET_WITH_ID:
766 return "code target with id";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767 case RelocInfo::CELL:
768 return "property cell";
Steve Blocka7e24c12009-10-30 11:49:00 +0000769 case RelocInfo::RUNTIME_ENTRY:
770 return "runtime entry";
771 case RelocInfo::JS_RETURN:
772 return "js return";
773 case RelocInfo::COMMENT:
774 return "comment";
775 case RelocInfo::POSITION:
776 return "position";
777 case RelocInfo::STATEMENT_POSITION:
778 return "statement position";
779 case RelocInfo::EXTERNAL_REFERENCE:
780 return "external reference";
781 case RelocInfo::INTERNAL_REFERENCE:
782 return "internal reference";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000783 case RelocInfo::CONST_POOL:
784 return "constant pool";
785 case RelocInfo::VENEER_POOL:
786 return "veneer pool";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100787 case RelocInfo::DEBUG_BREAK_SLOT:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100788 return "debug break slot";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 case RelocInfo::CODE_AGE_SEQUENCE:
790 return "code_age_sequence";
Steve Blocka7e24c12009-10-30 11:49:00 +0000791 case RelocInfo::NUMBER_OF_MODES:
792 UNREACHABLE();
793 return "number_of_modes";
794 }
795 return "unknown relocation type";
796}
797
798
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400799void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
800 os << static_cast<const void*>(pc_) << " " << RelocModeName(rmode_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000801 if (IsComment(rmode_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 os << " (" << reinterpret_cast<char*>(data_) << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000803 } else if (rmode_ == EMBEDDED_OBJECT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 os << " (" << Brief(target_object()) << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000805 } else if (rmode_ == EXTERNAL_REFERENCE) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 ExternalReferenceEncoder ref_encoder(isolate);
807 os << " (" << ref_encoder.NameOfAddress(target_reference()) << ") ("
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400808 << static_cast<const void*>(target_reference()) << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 } else if (IsCodeTarget(rmode_)) {
810 Code* code = Code::GetCodeFromTargetAddress(target_address());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400811 os << " (" << Code::Kind2String(code->kind()) << ") ("
812 << static_cast<const void*>(target_address()) << ")";
Ben Murdoch257744e2011-11-30 15:57:28 +0000813 if (rmode_ == CODE_TARGET_WITH_ID) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 os << " (id=" << static_cast<int>(data_) << ")";
Ben Murdoch257744e2011-11-30 15:57:28 +0000815 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 } else if (IsPosition(rmode_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 os << " (" << data() << ")";
818 } else if (IsRuntimeEntry(rmode_) &&
819 isolate->deoptimizer_data() != NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100820 // Depotimization bailouts are stored as runtime entries.
821 int id = Deoptimizer::GetDeoptimizationId(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000822 isolate, target_address(), Deoptimizer::EAGER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100823 if (id != Deoptimizer::kNotDeoptimizationEntry) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 os << " (deoptimization bailout " << id << ")";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100825 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 }
827
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +0000829}
830#endif // ENABLE_DISASSEMBLER
831
832
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000833#ifdef VERIFY_HEAP
834void RelocInfo::Verify(Isolate* isolate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000835 switch (rmode_) {
836 case EMBEDDED_OBJECT:
837 Object::VerifyPointer(target_object());
838 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 case CELL:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100840 Object::VerifyPointer(target_cell());
841 break;
Andrei Popescu402d9372010-02-26 13:31:12 +0000842 case DEBUG_BREAK:
Steve Blocka7e24c12009-10-30 11:49:00 +0000843 case CONSTRUCT_CALL:
Ben Murdoch257744e2011-11-30 15:57:28 +0000844 case CODE_TARGET_WITH_ID:
Steve Blocka7e24c12009-10-30 11:49:00 +0000845 case CODE_TARGET: {
846 // convert inline target address to code object
847 Address addr = target_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 CHECK(addr != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 // Check that we can find the right code object.
850 Code* code = Code::GetCodeFromTargetAddress(addr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 Object* found = isolate->FindCodeObject(addr);
852 CHECK(found->IsCode());
853 CHECK(code->address() == HeapObject::cast(found)->address());
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 break;
855 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 case RUNTIME_ENTRY:
857 case JS_RETURN:
858 case COMMENT:
859 case POSITION:
860 case STATEMENT_POSITION:
861 case EXTERNAL_REFERENCE:
862 case INTERNAL_REFERENCE:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 case CONST_POOL:
864 case VENEER_POOL:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100865 case DEBUG_BREAK_SLOT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 case NONE32:
867 case NONE64:
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 break;
869 case NUMBER_OF_MODES:
870 UNREACHABLE();
871 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000872 case CODE_AGE_SEQUENCE:
873 DCHECK(Code::IsYoungSequence(isolate, pc_) || code_age_stub()->IsCode());
874 break;
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 }
876}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877#endif // VERIFY_HEAP
Steve Blocka7e24c12009-10-30 11:49:00 +0000878
879
880// -----------------------------------------------------------------------------
881// Implementation of ExternalReference
882
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883void ExternalReference::SetUp() {
884 double_constants.min_int = kMinInt;
885 double_constants.one_half = 0.5;
886 double_constants.minus_one_half = -0.5;
887 double_constants.canonical_non_hole_nan = base::OS::nan_value();
888 double_constants.the_hole_nan = bit_cast<double>(kHoleNanInt64);
889 double_constants.negative_infinity = -V8_INFINITY;
890 double_constants.uint32_bias =
891 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
892
893 math_exp_data_mutex = new base::Mutex();
894}
895
896
897void ExternalReference::InitializeMathExpData() {
898 // Early return?
899 if (math_exp_data_initialized) return;
900
901 base::LockGuard<base::Mutex> lock_guard(math_exp_data_mutex);
902 if (!math_exp_data_initialized) {
903 // If this is changed, generated code must be adapted too.
904 const int kTableSizeBits = 11;
905 const int kTableSize = 1 << kTableSizeBits;
906 const double kTableSizeDouble = static_cast<double>(kTableSize);
907
908 math_exp_constants_array = new double[9];
909 // Input values smaller than this always return 0.
910 math_exp_constants_array[0] = -708.39641853226408;
911 // Input values larger than this always return +Infinity.
912 math_exp_constants_array[1] = 709.78271289338397;
913 math_exp_constants_array[2] = V8_INFINITY;
914 // The rest is black magic. Do not attempt to understand it. It is
915 // loosely based on the "expd" function published at:
916 // http://herumi.blogspot.com/2011/08/fast-double-precision-exponential.html
917 const double constant3 = (1 << kTableSizeBits) / std::log(2.0);
918 math_exp_constants_array[3] = constant3;
919 math_exp_constants_array[4] =
920 static_cast<double>(static_cast<int64_t>(3) << 51);
921 math_exp_constants_array[5] = 1 / constant3;
922 math_exp_constants_array[6] = 3.0000000027955394;
923 math_exp_constants_array[7] = 0.16666666685227835;
924 math_exp_constants_array[8] = 1;
925
926 math_exp_log_table_array = new double[kTableSize];
927 for (int i = 0; i < kTableSize; i++) {
928 double value = std::pow(2, i / kTableSizeDouble);
929 uint64_t bits = bit_cast<uint64_t, double>(value);
930 bits &= (static_cast<uint64_t>(1) << 52) - 1;
931 double mantissa = bit_cast<double, uint64_t>(bits);
932 math_exp_log_table_array[i] = mantissa;
933 }
934
935 math_exp_data_initialized = true;
936 }
937}
938
939
940void ExternalReference::TearDownMathExpData() {
941 delete[] math_exp_constants_array;
942 math_exp_constants_array = NULL;
943 delete[] math_exp_log_table_array;
944 math_exp_log_table_array = NULL;
945 delete math_exp_data_mutex;
946 math_exp_data_mutex = NULL;
947}
948
949
Steve Block44f0eee2011-05-26 01:26:41 +0100950ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
951 : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000952
953
Steve Block1e0659c2011-05-24 12:43:12 +0100954ExternalReference::ExternalReference(
Steve Block44f0eee2011-05-26 01:26:41 +0100955 ApiFunction* fun,
956 Type type = ExternalReference::BUILTIN_CALL,
957 Isolate* isolate = NULL)
958 : address_(Redirect(isolate, fun->address(), type)) {}
Steve Blockd0582a62009-12-15 09:54:21 +0000959
960
Steve Block44f0eee2011-05-26 01:26:41 +0100961ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
962 : address_(isolate->builtins()->builtin_address(name)) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000963
964
Steve Block44f0eee2011-05-26 01:26:41 +0100965ExternalReference::ExternalReference(Runtime::FunctionId id,
966 Isolate* isolate)
967 : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000968
969
Steve Block44f0eee2011-05-26 01:26:41 +0100970ExternalReference::ExternalReference(const Runtime::Function* f,
971 Isolate* isolate)
972 : address_(Redirect(isolate, f->entry)) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000973
974
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
976 return ExternalReference(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100977}
978
979
980ExternalReference::ExternalReference(const IC_Utility& ic_utility,
981 Isolate* isolate)
982 : address_(Redirect(isolate, ic_utility.address())) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000983
Steve Blocka7e24c12009-10-30 11:49:00 +0000984
985ExternalReference::ExternalReference(StatsCounter* counter)
986 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
987
988
Steve Block44f0eee2011-05-26 01:26:41 +0100989ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
990 : address_(isolate->get_address_from_id(id)) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000991
992
993ExternalReference::ExternalReference(const SCTableReference& table_ref)
994 : address_(table_ref.address()) {}
995
996
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100997ExternalReference ExternalReference::
998 incremental_marking_record_write_function(Isolate* isolate) {
999 return ExternalReference(Redirect(
1000 isolate,
1001 FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode)));
1002}
1003
1004
1005ExternalReference ExternalReference::
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001006 store_buffer_overflow_function(Isolate* isolate) {
1007 return ExternalReference(Redirect(
1008 isolate,
1009 FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow)));
1010}
1011
1012
1013ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 return ExternalReference(
1015 Redirect(isolate, FUNCTION_ADDR(CpuFeatures::FlushICache)));
Steve Block6ded16b2010-05-10 14:33:55 +01001016}
1017
1018
Steve Block44f0eee2011-05-26 01:26:41 +01001019ExternalReference ExternalReference::delete_handle_scope_extensions(
1020 Isolate* isolate) {
1021 return ExternalReference(Redirect(
1022 isolate,
1023 FUNCTION_ADDR(HandleScope::DeleteExtensions)));
John Reck59135872010-11-02 12:39:01 -07001024}
1025
1026
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001027ExternalReference ExternalReference::get_date_field_function(
1028 Isolate* isolate) {
1029 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField)));
1030}
1031
1032
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033ExternalReference ExternalReference::get_make_code_young_function(
1034 Isolate* isolate) {
1035 return ExternalReference(Redirect(
1036 isolate, FUNCTION_ADDR(Code::MakeCodeAgeSequenceYoung)));
1037}
1038
1039
1040ExternalReference ExternalReference::get_mark_code_as_executed_function(
1041 Isolate* isolate) {
1042 return ExternalReference(Redirect(
1043 isolate, FUNCTION_ADDR(Code::MarkCodeAsExecuted)));
1044}
1045
1046
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001047ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
1048 return ExternalReference(isolate->date_cache()->stamp_address());
1049}
1050
1051
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) {
1053 return ExternalReference(isolate->stress_deopt_count_address());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001054}
1055
1056
Steve Block44f0eee2011-05-26 01:26:41 +01001057ExternalReference ExternalReference::new_deoptimizer_function(
1058 Isolate* isolate) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001059 return ExternalReference(
Steve Block44f0eee2011-05-26 01:26:41 +01001060 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001061}
1062
1063
Steve Block44f0eee2011-05-26 01:26:41 +01001064ExternalReference ExternalReference::compute_output_frames_function(
1065 Isolate* isolate) {
1066 return ExternalReference(
1067 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001068}
1069
1070
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071ExternalReference ExternalReference::log_enter_external_function(
1072 Isolate* isolate) {
1073 return ExternalReference(
1074 Redirect(isolate, FUNCTION_ADDR(Logger::EnterExternal)));
1075}
1076
1077
1078ExternalReference ExternalReference::log_leave_external_function(
1079 Isolate* isolate) {
1080 return ExternalReference(
1081 Redirect(isolate, FUNCTION_ADDR(Logger::LeaveExternal)));
1082}
1083
1084
Steve Block44f0eee2011-05-26 01:26:41 +01001085ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
1086 return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001087}
1088
1089
Steve Block44f0eee2011-05-26 01:26:41 +01001090ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
1091 Isolate* isolate) {
1092 return ExternalReference(
1093 isolate->keyed_lookup_cache()->field_offsets_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001094}
1095
1096
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001097ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
1098 return ExternalReference(isolate->heap()->roots_array_start());
Steve Blocka7e24c12009-10-30 11:49:00 +00001099}
1100
1101
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102ExternalReference ExternalReference::allocation_sites_list_address(
1103 Isolate* isolate) {
1104 return ExternalReference(isolate->heap()->allocation_sites_list_address());
1105}
1106
1107
Steve Block44f0eee2011-05-26 01:26:41 +01001108ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
1109 return ExternalReference(isolate->stack_guard()->address_of_jslimit());
Steve Blockd0582a62009-12-15 09:54:21 +00001110}
1111
1112
Steve Block44f0eee2011-05-26 01:26:41 +01001113ExternalReference ExternalReference::address_of_real_stack_limit(
1114 Isolate* isolate) {
1115 return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
Steve Blocka7e24c12009-10-30 11:49:00 +00001116}
1117
1118
Steve Block44f0eee2011-05-26 01:26:41 +01001119ExternalReference ExternalReference::address_of_regexp_stack_limit(
1120 Isolate* isolate) {
1121 return ExternalReference(isolate->regexp_stack()->limit_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001122}
1123
1124
Steve Block44f0eee2011-05-26 01:26:41 +01001125ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
1126 return ExternalReference(isolate->heap()->NewSpaceStart());
Andrei Popescu402d9372010-02-26 13:31:12 +00001127}
1128
1129
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001130ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
1131 return ExternalReference(isolate->heap()->store_buffer()->TopAddress());
1132}
1133
1134
Steve Block44f0eee2011-05-26 01:26:41 +01001135ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001136 return ExternalReference(reinterpret_cast<Address>(
1137 isolate->heap()->NewSpaceMask()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001138}
1139
1140
Steve Block44f0eee2011-05-26 01:26:41 +01001141ExternalReference ExternalReference::new_space_allocation_top_address(
1142 Isolate* isolate) {
1143 return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
Steve Blocka7e24c12009-10-30 11:49:00 +00001144}
1145
1146
Steve Block44f0eee2011-05-26 01:26:41 +01001147ExternalReference ExternalReference::new_space_allocation_limit_address(
1148 Isolate* isolate) {
1149 return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
Steve Blocka7e24c12009-10-30 11:49:00 +00001150}
1151
Steve Blockd0582a62009-12-15 09:54:21 +00001152
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153ExternalReference ExternalReference::old_pointer_space_allocation_top_address(
1154 Isolate* isolate) {
1155 return ExternalReference(
1156 isolate->heap()->OldPointerSpaceAllocationTopAddress());
Steve Blockd0582a62009-12-15 09:54:21 +00001157}
1158
1159
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160ExternalReference ExternalReference::old_pointer_space_allocation_limit_address(
1161 Isolate* isolate) {
1162 return ExternalReference(
1163 isolate->heap()->OldPointerSpaceAllocationLimitAddress());
Steve Blockd0582a62009-12-15 09:54:21 +00001164}
1165
1166
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001167ExternalReference ExternalReference::old_data_space_allocation_top_address(
1168 Isolate* isolate) {
1169 return ExternalReference(
1170 isolate->heap()->OldDataSpaceAllocationTopAddress());
1171}
1172
1173
1174ExternalReference ExternalReference::old_data_space_allocation_limit_address(
1175 Isolate* isolate) {
1176 return ExternalReference(
1177 isolate->heap()->OldDataSpaceAllocationLimitAddress());
1178}
1179
1180
1181ExternalReference ExternalReference::handle_scope_level_address(
1182 Isolate* isolate) {
1183 return ExternalReference(HandleScope::current_level_address(isolate));
1184}
1185
1186
1187ExternalReference ExternalReference::handle_scope_next_address(
1188 Isolate* isolate) {
1189 return ExternalReference(HandleScope::current_next_address(isolate));
1190}
1191
1192
1193ExternalReference ExternalReference::handle_scope_limit_address(
1194 Isolate* isolate) {
1195 return ExternalReference(HandleScope::current_limit_address(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +00001196}
1197
1198
Steve Block44f0eee2011-05-26 01:26:41 +01001199ExternalReference ExternalReference::scheduled_exception_address(
1200 Isolate* isolate) {
1201 return ExternalReference(isolate->scheduled_exception_address());
Steve Blockd0582a62009-12-15 09:54:21 +00001202}
1203
1204
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205ExternalReference ExternalReference::address_of_pending_message_obj(
1206 Isolate* isolate) {
1207 return ExternalReference(isolate->pending_message_obj_address());
1208}
1209
1210
1211ExternalReference ExternalReference::address_of_has_pending_message(
1212 Isolate* isolate) {
1213 return ExternalReference(isolate->has_pending_message_address());
1214}
1215
1216
1217ExternalReference ExternalReference::address_of_pending_message_script(
1218 Isolate* isolate) {
1219 return ExternalReference(isolate->pending_message_script_address());
1220}
1221
1222
Ben Murdochb0fe1622011-05-05 13:52:32 +01001223ExternalReference ExternalReference::address_of_min_int() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001225}
1226
1227
1228ExternalReference ExternalReference::address_of_one_half() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 return ExternalReference(reinterpret_cast<void*>(&double_constants.one_half));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001230}
1231
1232
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233ExternalReference ExternalReference::address_of_minus_one_half() {
1234 return ExternalReference(
1235 reinterpret_cast<void*>(&double_constants.minus_one_half));
Ben Murdoch257744e2011-11-30 15:57:28 +00001236}
1237
1238
Ben Murdochb0fe1622011-05-05 13:52:32 +01001239ExternalReference ExternalReference::address_of_negative_infinity() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001240 return ExternalReference(
1241 reinterpret_cast<void*>(&double_constants.negative_infinity));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001242}
1243
1244
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001245ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246 return ExternalReference(
1247 reinterpret_cast<void*>(&double_constants.canonical_non_hole_nan));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001248}
1249
1250
1251ExternalReference ExternalReference::address_of_the_hole_nan() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001252 return ExternalReference(
1253 reinterpret_cast<void*>(&double_constants.the_hole_nan));
1254}
1255
1256
1257ExternalReference ExternalReference::address_of_uint32_bias() {
1258 return ExternalReference(
1259 reinterpret_cast<void*>(&double_constants.uint32_bias));
1260}
1261
1262
1263ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
1264 return ExternalReference(isolate->cpu_profiler()->is_profiling_address());
1265}
1266
1267
1268ExternalReference ExternalReference::invoke_function_callback(
1269 Isolate* isolate) {
1270 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
1271 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
1272 ApiFunction thunk_fun(thunk_address);
1273 return ExternalReference(&thunk_fun, thunk_type, isolate);
1274}
1275
1276
1277ExternalReference ExternalReference::invoke_accessor_getter_callback(
1278 Isolate* isolate) {
1279 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1280 ExternalReference::Type thunk_type =
1281 ExternalReference::PROFILING_GETTER_CALL;
1282 ApiFunction thunk_fun(thunk_address);
1283 return ExternalReference(&thunk_fun, thunk_type, isolate);
Steve Block44f0eee2011-05-26 01:26:41 +01001284}
1285
1286
Steve Block6ded16b2010-05-10 14:33:55 +01001287#ifndef V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +00001288
Steve Block44f0eee2011-05-26 01:26:41 +01001289ExternalReference ExternalReference::re_check_stack_guard_state(
1290 Isolate* isolate) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 Address function;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292#if V8_TARGET_ARCH_X64
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
1294#elif V8_TARGET_ARCH_IA32
1295 function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296#elif V8_TARGET_ARCH_ARM64
1297 function = FUNCTION_ADDR(RegExpMacroAssemblerARM64::CheckStackGuardState);
Steve Blocka7e24c12009-10-30 11:49:00 +00001298#elif V8_TARGET_ARCH_ARM
1299 function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
Steve Block44f0eee2011-05-26 01:26:41 +01001300#elif V8_TARGET_ARCH_MIPS
1301 function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302#elif V8_TARGET_ARCH_MIPS64
1303 function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1304#elif V8_TARGET_ARCH_X87
1305 function = FUNCTION_ADDR(RegExpMacroAssemblerX87::CheckStackGuardState);
Steve Blocka7e24c12009-10-30 11:49:00 +00001306#else
Leon Clarke4515c472010-02-03 11:58:03 +00001307 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +00001308#endif
Steve Block44f0eee2011-05-26 01:26:41 +01001309 return ExternalReference(Redirect(isolate, function));
Steve Blocka7e24c12009-10-30 11:49:00 +00001310}
1311
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312
Steve Block44f0eee2011-05-26 01:26:41 +01001313ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001314 return ExternalReference(
Steve Block44f0eee2011-05-26 01:26:41 +01001315 Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001316}
1317
Steve Block44f0eee2011-05-26 01:26:41 +01001318ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
1319 Isolate* isolate) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001320 return ExternalReference(Redirect(
Steve Block44f0eee2011-05-26 01:26:41 +01001321 isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +00001322 FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
1323}
1324
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001325
Leon Clarkee46be812010-01-19 14:06:41 +00001326ExternalReference ExternalReference::re_word_character_map() {
1327 return ExternalReference(
1328 NativeRegExpMacroAssembler::word_character_map_address());
1329}
1330
Steve Block44f0eee2011-05-26 01:26:41 +01001331ExternalReference ExternalReference::address_of_static_offsets_vector(
1332 Isolate* isolate) {
1333 return ExternalReference(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector()));
Leon Clarkee46be812010-01-19 14:06:41 +00001335}
1336
Steve Block44f0eee2011-05-26 01:26:41 +01001337ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
1338 Isolate* isolate) {
1339 return ExternalReference(
1340 isolate->regexp_stack()->memory_address());
Leon Clarkee46be812010-01-19 14:06:41 +00001341}
1342
Steve Block44f0eee2011-05-26 01:26:41 +01001343ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
1344 Isolate* isolate) {
1345 return ExternalReference(isolate->regexp_stack()->memory_size_address());
Leon Clarkee46be812010-01-19 14:06:41 +00001346}
1347
Steve Block6ded16b2010-05-10 14:33:55 +01001348#endif // V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +00001349
1350
Steve Block44f0eee2011-05-26 01:26:41 +01001351ExternalReference ExternalReference::math_log_double_function(
1352 Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 typedef double (*d2d)(double x);
Steve Block44f0eee2011-05-26 01:26:41 +01001354 return ExternalReference(Redirect(isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 FUNCTION_ADDR(static_cast<d2d>(std::log)),
Ben Murdoch257744e2011-11-30 15:57:28 +00001356 BUILTIN_FP_CALL));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001357}
1358
1359
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360ExternalReference ExternalReference::math_exp_constants(int constant_index) {
1361 DCHECK(math_exp_data_initialized);
1362 return ExternalReference(
1363 reinterpret_cast<void*>(math_exp_constants_array + constant_index));
1364}
1365
1366
1367ExternalReference ExternalReference::math_exp_log_table() {
1368 DCHECK(math_exp_data_initialized);
1369 return ExternalReference(reinterpret_cast<void*>(math_exp_log_table_array));
1370}
1371
1372
1373ExternalReference ExternalReference::page_flags(Page* page) {
1374 return ExternalReference(reinterpret_cast<Address>(page) +
1375 MemoryChunk::kFlagsOffset);
1376}
1377
1378
1379ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
1380 return ExternalReference(entry);
1381}
1382
1383
1384ExternalReference ExternalReference::cpu_features() {
1385 DCHECK(CpuFeatures::initialized_);
1386 return ExternalReference(&CpuFeatures::supported_);
1387}
1388
1389
1390ExternalReference ExternalReference::debug_is_active_address(
1391 Isolate* isolate) {
1392 return ExternalReference(isolate->debug()->is_active_address());
1393}
1394
1395
1396ExternalReference ExternalReference::debug_after_break_target_address(
1397 Isolate* isolate) {
1398 return ExternalReference(isolate->debug()->after_break_target_address());
1399}
1400
1401
1402ExternalReference
1403 ExternalReference::debug_restarter_frame_function_pointer_address(
1404 Isolate* isolate) {
1405 return ExternalReference(
1406 isolate->debug()->restarter_frame_function_pointer_address());
1407}
1408
1409
1410double power_helper(double x, double y) {
1411 int y_int = static_cast<int>(y);
1412 if (y == y_int) {
1413 return power_double_int(x, y_int); // Returns 1 if exponent is 0.
1414 }
1415 if (y == 0.5) {
1416 return (std::isinf(x)) ? V8_INFINITY
1417 : fast_sqrt(x + 0.0); // Convert -0 to +0.
1418 }
1419 if (y == -0.5) {
1420 return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0); // Convert -0 to +0.
1421 }
1422 return power_double_double(x, y);
1423}
1424
1425
Ben Murdochb0fe1622011-05-05 13:52:32 +01001426// Helper function to compute x^y, where y is known to be an
1427// integer. Uses binary decomposition to limit the number of
1428// multiplications; see the discussion in "Hacker's Delight" by Henry
1429// S. Warren, Jr., figure 11-6, page 213.
1430double power_double_int(double x, int y) {
1431 double m = (y < 0) ? 1 / x : x;
1432 unsigned n = (y < 0) ? -y : y;
1433 double p = 1;
1434 while (n != 0) {
1435 if ((n & 1) != 0) p *= m;
1436 m *= m;
1437 if ((n & 2) != 0) p *= m;
1438 m *= m;
1439 n >>= 2;
1440 }
1441 return p;
1442}
1443
1444
1445double power_double_double(double x, double y) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446#if defined(__MINGW64_VERSION_MAJOR) && \
1447 (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)
1448 // MinGW64 has a custom implementation for pow. This handles certain
1449 // special cases that are different.
1450 if ((x == 0.0 || std::isinf(x)) && std::isfinite(y)) {
1451 double f;
1452 if (std::modf(y, &f) != 0.0) {
1453 return ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
1454 }
1455 }
1456
1457 if (x == 2.0) {
1458 int y_int = static_cast<int>(y);
1459 if (y == y_int) {
1460 return std::ldexp(1.0, y_int);
1461 }
1462 }
1463#endif
1464
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001465 // The checks for special cases can be dropped in ia32 because it has already
1466 // been done in generated code before bailing out here.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001467 if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
1468 return base::OS::nan_value();
1469 }
1470 return std::pow(x, y);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001471}
1472
1473
Steve Block44f0eee2011-05-26 01:26:41 +01001474ExternalReference ExternalReference::power_double_double_function(
1475 Isolate* isolate) {
1476 return ExternalReference(Redirect(isolate,
1477 FUNCTION_ADDR(power_double_double),
Ben Murdoch257744e2011-11-30 15:57:28 +00001478 BUILTIN_FP_FP_CALL));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001479}
1480
1481
Steve Block44f0eee2011-05-26 01:26:41 +01001482ExternalReference ExternalReference::power_double_int_function(
1483 Isolate* isolate) {
1484 return ExternalReference(Redirect(isolate,
1485 FUNCTION_ADDR(power_double_int),
Ben Murdoch257744e2011-11-30 15:57:28 +00001486 BUILTIN_FP_INT_CALL));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001487}
1488
1489
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001490bool EvalComparison(Token::Value op, double op1, double op2) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 DCHECK(Token::IsCompareOp(op));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001492 switch (op) {
1493 case Token::EQ:
1494 case Token::EQ_STRICT: return (op1 == op2);
1495 case Token::NE: return (op1 != op2);
1496 case Token::LT: return (op1 < op2);
1497 case Token::GT: return (op1 > op2);
1498 case Token::LTE: return (op1 <= op2);
1499 case Token::GTE: return (op1 >= op2);
1500 default:
1501 UNREACHABLE();
1502 return false;
1503 }
1504}
1505
1506
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001507ExternalReference ExternalReference::mod_two_doubles_operation(
1508 Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01001509 return ExternalReference(Redirect(isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510 FUNCTION_ADDR(modulo),
Ben Murdoch257744e2011-11-30 15:57:28 +00001511 BUILTIN_FP_FP_CALL));
Steve Blocka7e24c12009-10-30 11:49:00 +00001512}
1513
1514
Steve Block44f0eee2011-05-26 01:26:41 +01001515ExternalReference ExternalReference::debug_break(Isolate* isolate) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001516 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001517}
1518
1519
Steve Block44f0eee2011-05-26 01:26:41 +01001520ExternalReference ExternalReference::debug_step_in_fp_address(
1521 Isolate* isolate) {
1522 return ExternalReference(isolate->debug()->step_in_fp_addr());
Steve Blocka7e24c12009-10-30 11:49:00 +00001523}
Steve Blocka7e24c12009-10-30 11:49:00 +00001524
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001525
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001526bool operator==(ExternalReference lhs, ExternalReference rhs) {
1527 return lhs.address() == rhs.address();
1528}
1529
1530
1531bool operator!=(ExternalReference lhs, ExternalReference rhs) {
1532 return !(lhs == rhs);
1533}
1534
1535
1536size_t hash_value(ExternalReference reference) {
1537 return base::hash<Address>()(reference.address());
1538}
1539
1540
1541std::ostream& operator<<(std::ostream& os, ExternalReference reference) {
1542 os << static_cast<const void*>(reference.address());
1543 const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address());
1544 if (fn) os << "<" << fn->name << ".entry>";
1545 return os;
1546}
1547
1548
Ben Murdochb0fe1622011-05-05 13:52:32 +01001549void PositionsRecorder::RecordPosition(int pos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550 DCHECK(pos != RelocInfo::kNoPosition);
1551 DCHECK(pos >= 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001552 state_.current_position = pos;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001553 LOG_CODE_EVENT(assembler_->isolate(),
1554 CodeLinePosInfoAddPositionEvent(jit_handler_data_,
1555 assembler_->pc_offset(),
1556 pos));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001557}
1558
1559
1560void PositionsRecorder::RecordStatementPosition(int pos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 DCHECK(pos != RelocInfo::kNoPosition);
1562 DCHECK(pos >= 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001563 state_.current_statement_position = pos;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001564 LOG_CODE_EVENT(assembler_->isolate(),
1565 CodeLinePosInfoAddStatementPositionEvent(
1566 jit_handler_data_,
1567 assembler_->pc_offset(),
1568 pos));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001569}
1570
1571
1572bool PositionsRecorder::WriteRecordedPositions() {
1573 bool written = false;
1574
1575 // Write the statement position if it is different from what was written last
1576 // time.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001577 if (state_.current_statement_position != state_.written_statement_position) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001578 EnsureSpace ensure_space(assembler_);
1579 assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001580 state_.current_statement_position);
1581 state_.written_statement_position = state_.current_statement_position;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001582 written = true;
1583 }
1584
1585 // Write the position if it is different from what was written last time and
Ben Murdochb0fe1622011-05-05 13:52:32 +01001586 // also different from the written statement position.
1587 if (state_.current_position != state_.written_position &&
1588 state_.current_position != state_.written_statement_position) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001589 EnsureSpace ensure_space(assembler_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001590 assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
1591 state_.written_position = state_.current_position;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001592 written = true;
1593 }
1594
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001595 // Return whether something was written.
1596 return written;
1597}
1598
Steve Blocka7e24c12009-10-30 11:49:00 +00001599} } // namespace v8::internal