assembler.cc 63.5 KB
Newer Older
1
// Copyright (c) 1994-2006 Sun Microsystems Inc.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// - Redistribution in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of Sun Microsystems or the names of contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The original source code covered by the above license above has been
// modified significantly by Google Inc.
33
// Copyright 2012 the V8 project authors. All rights reserved.
34

35
#include "src/assembler.h"
36

37
#include <math.h>
38
#include <string.h>
39
#include <cmath>
40

41
#include "src/api.h"
42
#include "src/assembler-inl.h"
43
#include "src/base/cpu.h"
44
#include "src/base/functional.h"
45
#include "src/base/ieee754.h"
46
#include "src/base/lazy-instance.h"
47
#include "src/base/platform/platform.h"
48
#include "src/base/utils/random-number-generator.h"
49
#include "src/codegen.h"
50
#include "src/counters.h"
51
#include "src/debug/debug.h"
52
#include "src/deoptimizer.h"
53
#include "src/disassembler.h"
54
#include "src/execution.h"
55
#include "src/ic/ic.h"
56
#include "src/ic/stub-cache.h"
57
#include "src/interpreter/interpreter.h"
58
#include "src/isolate.h"
59
#include "src/ostreams.h"
60 61 62
#include "src/regexp/jsregexp.h"
#include "src/regexp/regexp-macro-assembler.h"
#include "src/regexp/regexp-stack.h"
63
#include "src/register-configuration.h"
64
#include "src/runtime/runtime.h"
65
#include "src/simulator.h"  // For flushing instruction cache.
66
#include "src/snapshot/serializer-common.h"
67
#include "src/string-search.h"
68
#include "src/wasm/wasm-external-refs.h"
69

lrn@chromium.org's avatar
lrn@chromium.org committed
70
// Include native regexp-macro-assembler.
71
#ifndef V8_INTERPRETED_REGEXP
lrn@chromium.org's avatar
lrn@chromium.org committed
72
#if V8_TARGET_ARCH_IA32
73
#include "src/regexp/ia32/regexp-macro-assembler-ia32.h"  // NOLINT
lrn@chromium.org's avatar
lrn@chromium.org committed
74
#elif V8_TARGET_ARCH_X64
75
#include "src/regexp/x64/regexp-macro-assembler-x64.h"  // NOLINT
76
#elif V8_TARGET_ARCH_ARM64
77
#include "src/regexp/arm64/regexp-macro-assembler-arm64.h"  // NOLINT
lrn@chromium.org's avatar
lrn@chromium.org committed
78
#elif V8_TARGET_ARCH_ARM
79
#include "src/regexp/arm/regexp-macro-assembler-arm.h"  // NOLINT
80
#elif V8_TARGET_ARCH_PPC
81
#include "src/regexp/ppc/regexp-macro-assembler-ppc.h"  // NOLINT
82
#elif V8_TARGET_ARCH_MIPS
83
#include "src/regexp/mips/regexp-macro-assembler-mips.h"  // NOLINT
84
#elif V8_TARGET_ARCH_MIPS64
85
#include "src/regexp/mips64/regexp-macro-assembler-mips64.h"  // NOLINT
86 87
#elif V8_TARGET_ARCH_S390
#include "src/regexp/s390/regexp-macro-assembler-s390.h"  // NOLINT
lrn@chromium.org's avatar
lrn@chromium.org committed
88 89 90
#else  // Unknown architecture.
#error "Unknown architecture."
#endif  // Target architecture.
91
#endif  // V8_INTERPRETED_REGEXP
92

93 94 95 96
#ifdef V8_INTL_SUPPORT
#include "src/intl.h"
#endif  // V8_INTL_SUPPORT

97 98
namespace v8 {
namespace internal {
99

100 101 102 103
// -----------------------------------------------------------------------------
// Common double constants.

struct DoubleConstant BASE_EMBEDDED {
104 105 106 107
double min_int;
double one_half;
double minus_one_half;
double negative_infinity;
108
uint64_t the_hole_nan;
109
double uint32_bias;
110 111
};

112
static DoubleConstant double_constants;
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
static struct V8_ALIGNED(16) {
  uint32_t a;
  uint32_t b;
  uint32_t c;
  uint32_t d;
} float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};

static struct V8_ALIGNED(16) {
  uint32_t a;
  uint32_t b;
  uint32_t c;
  uint32_t d;
} float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000};

static struct V8_ALIGNED(16) {
  uint64_t a;
  uint64_t b;
} double_absolute_constant = {V8_UINT64_C(0x7FFFFFFFFFFFFFFF),
                              V8_UINT64_C(0x7FFFFFFFFFFFFFFF)};

static struct V8_ALIGNED(16) {
  uint64_t a;
  uint64_t b;
} double_negate_constant = {V8_UINT64_C(0x8000000000000000),
                            V8_UINT64_C(0x8000000000000000)};

140
const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
141

142 143 144
// -----------------------------------------------------------------------------
// Implementation of AssemblerBase

145
AssemblerBase::IsolateData::IsolateData(Isolate* isolate)
146
    : serializer_enabled_(isolate->serializer_enabled())
147 148 149 150 151 152 153 154 155 156 157
#if V8_TARGET_ARCH_X64
      ,
      code_range_start_(
          isolate->heap()->memory_allocator()->code_range()->start())
#endif
{
}

AssemblerBase::AssemblerBase(IsolateData isolate_data, void* buffer,
                             int buffer_size)
    : isolate_data_(isolate_data),
158
      enabled_cpu_features_(0),
159
      emit_debug_code_(FLAG_debug_code),
160
      predictable_code_size_(false),
161
      constant_pool_available_(false) {
162 163 164 165
  own_buffer_ = buffer == NULL;
  if (buffer_size == 0) buffer_size = kMinimalBufferSize;
  DCHECK(buffer_size > 0);
  if (own_buffer_) buffer = NewArray<byte>(buffer_size);
166 167 168 169 170 171
  buffer_ = static_cast<byte*>(buffer);
  buffer_size_ = buffer_size;
  pc_ = buffer_;
}

AssemblerBase::~AssemblerBase() {
172
  if (own_buffer_) DeleteArray(buffer_);
173 174
}

175 176 177 178
void AssemblerBase::FlushICache(Isolate* isolate, void* start, size_t size) {
  if (size == 0) return;

#if defined(USE_SIMULATOR)
179
  base::LockGuard<base::Mutex> lock_guard(isolate->simulator_i_cache_mutex());
180 181 182 183 184 185
  Simulator::FlushICache(isolate->simulator_i_cache(), start, size);
#else
  CpuFeatures::FlushICache(start, size);
#endif  // USE_SIMULATOR
}

186
void AssemblerBase::Print(Isolate* isolate) {
187
  OFStream os(stdout);
188
  v8::internal::Disassembler::Decode(isolate, &os, buffer_, pc_, nullptr);
189 190 191
}


192 193 194
// -----------------------------------------------------------------------------
// Implementation of PredictableCodeSizeScope

195 196 197 198
PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler)
    : PredictableCodeSizeScope(assembler, -1) {}


199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
                                                   int expected_size)
    : assembler_(assembler),
      expected_size_(expected_size),
      start_offset_(assembler->pc_offset()),
      old_value_(assembler->predictable_code_size()) {
  assembler_->set_predictable_code_size(true);
}


PredictableCodeSizeScope::~PredictableCodeSizeScope() {
  // TODO(svenpanne) Remove the 'if' when everything works.
  if (expected_size_ >= 0) {
    CHECK_EQ(expected_size_, assembler_->pc_offset() - start_offset_);
  }
  assembler_->set_predictable_code_size(old_value_);
}


218 219 220 221
// -----------------------------------------------------------------------------
// Implementation of CpuFeatureScope

#ifdef DEBUG
222 223
CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
                                 CheckPolicy check)
224
    : assembler_(assembler) {
225
  DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
226
  old_enabled_ = assembler_->enabled_cpu_features();
227
  assembler_->EnableCpuFeature(f);
228 229 230 231 232 233 234 235
}

CpuFeatureScope::~CpuFeatureScope() {
  assembler_->set_enabled_cpu_features(old_enabled_);
}
#endif


236 237
bool CpuFeatures::initialized_ = false;
unsigned CpuFeatures::supported_ = 0;
238 239
unsigned CpuFeatures::icache_line_size_ = 0;
unsigned CpuFeatures::dcache_line_size_ = 0;
240

241 242 243
// -----------------------------------------------------------------------------
// Implementation of RelocInfoWriter and RelocIterator
//
244 245 246 247 248
// Relocation information is written backwards in memory, from high addresses
// towards low addresses, byte by byte.  Therefore, in the encodings listed
// below, the first byte listed it at the highest address, and successive
// bytes in the record are at progressively lower addresses.
//
249 250 251 252 253 254
// Encoding
//
// The most common modes are given single-byte encodings.  Also, it is
// easy to identify the type of reloc info and skip unwanted modes in
// an iteration.
//
255
// The encoding relies on the fact that there are fewer than 14
256
// different relocation modes using standard non-compact encoding.
257
//
258 259 260
// The first byte of a relocation record has a tag in its low 2 bits:
// Here are the record schemes, depending on the low tag and optional higher
// tags.
261
//
262 263
// Low tag:
//   00: embedded_object:      [6-bit pc delta] 00
264
//
265
//   01: code_target:          [6-bit pc delta] 01
266
//
267
//   10: short_data_record:    [6-bit pc delta] 10 followed by
268
//                             [8-bit data delta]
269
//
270 271 272
//   11: long_record           [6 bit reloc mode] 11
//                             followed by pc delta
//                             followed by optional data depending on type.
273
//
274 275 276 277 278 279
//  If a pc delta exceeds 6 bits, it is split into a remainder that fits into
//  6 bits and a part that does not. The latter is encoded as a long record
//  with PC_JUMP as pseudo reloc info mode. The former is encoded as part of
//  the following record in the usual way. The long pc jump record has variable
//  length:
//               pc-jump:        [PC_JUMP] 11
280 281 282 283 284 285
//                               [7 bits data] 0
//                                  ...
//                               [7 bits data] 1
//               (Bits 6..31 of pc delta, with leading zeroes
//                dropped, and last non-zero chunk tagged with 1.)

286 287
const int kTagBits = 2;
const int kTagMask = (1 << kTagBits) - 1;
288
const int kLongTagBits = 6;
289 290 291

const int kEmbeddedObjectTag = 0;
const int kCodeTargetTag = 1;
292
const int kLocatableTag = 2;
293 294 295 296
const int kDefaultTag = 3;

const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
297
const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
298 299 300 301 302 303 304

const int kChunkBits = 7;
const int kChunkMask = (1 << kChunkBits) - 1;
const int kLastChunkTagBits = 1;
const int kLastChunkTagMask = 1;
const int kLastChunkTag = 1;

305
void RelocInfo::update_wasm_memory_reference(
306 307
    Isolate* isolate, Address old_base, Address new_base,
    ICacheFlushMode icache_flush_mode) {
308 309 310 311
  DCHECK(IsWasmMemoryReference(rmode_));
  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
  // The reference is not checked here but at runtime. Validity of references
  // may change over time.
312 313
  unchecked_update_wasm_memory_reference(isolate, updated_reference,
                                         icache_flush_mode);
314 315
}

316 317
void RelocInfo::update_wasm_memory_size(Isolate* isolate, uint32_t old_size,
                                        uint32_t new_size,
318 319 320 321 322
                                        ICacheFlushMode icache_flush_mode) {
  DCHECK(IsWasmMemorySizeReference(rmode_));
  uint32_t current_size_reference = wasm_memory_size_reference();
  uint32_t updated_size_reference =
      new_size + (current_size_reference - old_size);
323 324
  unchecked_update_wasm_size(isolate, updated_size_reference,
                             icache_flush_mode);
325 326 327
}

void RelocInfo::update_wasm_global_reference(
328 329
    Isolate* isolate, Address old_base, Address new_base,
    ICacheFlushMode icache_flush_mode) {
330 331
  DCHECK(IsWasmGlobalReference(rmode_));
  Address updated_reference;
332
  DCHECK_LE(old_base, wasm_global_reference());
333
  updated_reference = new_base + (wasm_global_reference() - old_base);
334
  DCHECK_LE(new_base, updated_reference);
335 336
  unchecked_update_wasm_memory_reference(isolate, updated_reference,
                                         icache_flush_mode);
337
}
338

339
void RelocInfo::update_wasm_function_table_size_reference(
340 341
    Isolate* isolate, uint32_t old_size, uint32_t new_size,
    ICacheFlushMode icache_flush_mode) {
342 343 344 345
  DCHECK(IsWasmFunctionTableSizeReference(rmode_));
  uint32_t current_size_reference = wasm_function_table_size_reference();
  uint32_t updated_size_reference =
      new_size + (current_size_reference - old_size);
346 347
  unchecked_update_wasm_size(isolate, updated_size_reference,
                             icache_flush_mode);
348 349
}

350
void RelocInfo::set_target_address(Isolate* isolate, Address target,
351 352 353
                                   WriteBarrierMode write_barrier_mode,
                                   ICacheFlushMode icache_flush_mode) {
  DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
354
  Assembler::set_target_address_at(isolate, pc_, host_, target,
355 356 357
                                   icache_flush_mode);
  if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL &&
      IsCodeTarget(rmode_)) {
358 359 360
    Code* target_code = Code::GetCodeFromTargetAddress(target);
    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
                                                                  target_code);
361 362 363
  }
}

364
uint32_t RelocInfoWriter::WriteLongPCJump(uint32_t pc_delta) {
365 366 367 368
  // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
  // Otherwise write a variable length PC jump for the bits that do
  // not fit in the kSmallPCDeltaBits bits.
  if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
369
  WriteMode(RelocInfo::PC_JUMP);
370
  uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
371
  DCHECK(pc_jump > 0);
372 373 374 375 376 377 378 379 380 381 382 383
  // Write kChunkBits size chunks of the pc_jump.
  for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
    byte b = pc_jump & kChunkMask;
    *--pos_ = b << kLastChunkTagBits;
  }
  // Tag the last chunk so it can be identified.
  *pos_ = *pos_ | kLastChunkTag;
  // Return the remaining kSmallPCDeltaBits of the pc_delta.
  return pc_delta & kSmallPCDeltaMask;
}


384 385 386
void RelocInfoWriter::WriteShortTaggedPC(uint32_t pc_delta, int tag) {
  // Write a byte of tagged pc-delta, possibly preceded by an explicit pc-jump.
  pc_delta = WriteLongPCJump(pc_delta);
387 388 389
  *--pos_ = pc_delta << kTagBits | tag;
}

390 391
void RelocInfoWriter::WriteShortData(intptr_t data_delta) {
  *--pos_ = static_cast<byte>(data_delta);
392 393 394
}


395 396 397
void RelocInfoWriter::WriteMode(RelocInfo::Mode rmode) {
  STATIC_ASSERT(RelocInfo::NUMBER_OF_MODES <= (1 << kLongTagBits));
  *--pos_ = static_cast<int>((rmode << kTagBits) | kDefaultTag);
398 399 400
}


401
void RelocInfoWriter::WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode) {
402
  // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
403 404
  pc_delta = WriteLongPCJump(pc_delta);
  WriteMode(rmode);
405 406 407 408
  *--pos_ = pc_delta;
}


409
void RelocInfoWriter::WriteIntData(int number) {
410
  for (int i = 0; i < kIntSize; i++) {
411
    *--pos_ = static_cast<byte>(number);
412
    // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
413
    number = number >> kBitsPerByte;
414 415 416
  }
}

417

418
void RelocInfoWriter::WriteData(intptr_t data_delta) {
419
  for (int i = 0; i < kIntptrSize; i++) {
420
    *--pos_ = static_cast<byte>(data_delta);
421
    // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
422
    data_delta = data_delta >> kBitsPerByte;
423 424 425 426 427
  }
}


void RelocInfoWriter::Write(const RelocInfo* rinfo) {
428
  RelocInfo::Mode rmode = rinfo->rmode();
429 430 431
#ifdef DEBUG
  byte* begin_pos = pos_;
#endif
432 433
  DCHECK(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES);
  DCHECK(rinfo->pc() - last_pc_ >= 0);
434
  // Use unsigned delta-encoding for pc.
435
  uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
436 437

  // The two most common modes are given small tags, and usually fit in a byte.
438
  if (rmode == RelocInfo::EMBEDDED_OBJECT) {
439
    WriteShortTaggedPC(pc_delta, kEmbeddedObjectTag);
440
  } else if (rmode == RelocInfo::CODE_TARGET) {
441
    WriteShortTaggedPC(pc_delta, kCodeTargetTag);
442
    DCHECK(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
443
  } else if (rmode == RelocInfo::DEOPT_REASON) {
444
    DCHECK(rinfo->data() < (1 << kBitsPerByte));
445
    WriteShortTaggedPC(pc_delta, kLocatableTag);
446
    WriteShortData(rinfo->data());
447
  } else {
448 449 450 451
    WriteModeAndPC(pc_delta, rmode);
    if (RelocInfo::IsComment(rmode)) {
      WriteData(rinfo->data());
    } else if (RelocInfo::IsConstPool(rmode) ||
452
               RelocInfo::IsVeneerPool(rmode) || RelocInfo::IsDeoptId(rmode) ||
453 454
               RelocInfo::IsDeoptPosition(rmode) ||
               RelocInfo::IsWasmProtectedLanding(rmode)) {
455
      WriteIntData(static_cast<int>(rinfo->data()));
456
    }
457 458
  }
  last_pc_ = rinfo->pc();
459
  last_mode_ = rmode;
460
#ifdef DEBUG
461
  DCHECK(begin_pos - pos_ <= kMaxSize);
462 463 464 465 466 467 468 469 470
#endif
}


inline int RelocIterator::AdvanceGetTag() {
  return *--pos_ & kTagMask;
}


471 472 473
inline RelocInfo::Mode RelocIterator::GetMode() {
  return static_cast<RelocInfo::Mode>((*pos_ >> kTagBits) &
                                      ((1 << kLongTagBits) - 1));
474 475 476
}


477
inline void RelocIterator::ReadShortTaggedPC() {
478 479 480 481 482 483 484 485 486
  rinfo_.pc_ += *pos_ >> kTagBits;
}


inline void RelocIterator::AdvanceReadPC() {
  rinfo_.pc_ += *--pos_;
}


487
void RelocIterator::AdvanceReadInt() {
488 489 490 491 492 493 494 495
  int x = 0;
  for (int i = 0; i < kIntSize; i++) {
    x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
  }
  rinfo_.data_ = x;
}


496
void RelocIterator::AdvanceReadData() {
497 498 499
  intptr_t x = 0;
  for (int i = 0; i < kIntptrSize; i++) {
    x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
500
  }
501
  rinfo_.data_ = x;
502 503 504
}


505
void RelocIterator::AdvanceReadLongPCJump() {
506 507 508 509 510 511 512 513 514 515 516 517 518 519
  // Read the 32-kSmallPCDeltaBits most significant bits of the
  // pc jump in kChunkBits bit chunks and shift them into place.
  // Stop when the last chunk is encountered.
  uint32_t pc_jump = 0;
  for (int i = 0; i < kIntSize; i++) {
    byte pc_jump_part = *--pos_;
    pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
    if ((pc_jump_part & kLastChunkTagMask) == 1) break;
  }
  // The least significant kSmallPCDeltaBits bits will be added
  // later.
  rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
}

520
inline void RelocIterator::ReadShortData() {
521
  uint8_t unsigned_b = *pos_;
522
  rinfo_.data_ = unsigned_b;
523 524 525 526
}


void RelocIterator::next() {
527
  DCHECK(!done());
528 529 530 531 532 533 534 535
  // Basically, do the opposite of RelocInfoWriter::Write.
  // Reading of data is as far as possible avoided for unwanted modes,
  // but we must always update the pc.
  //
  // We exit this loop by returning when we find a mode we want.
  while (pos_ > end_) {
    int tag = AdvanceGetTag();
    if (tag == kEmbeddedObjectTag) {
536
      ReadShortTaggedPC();
537
      if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
538
    } else if (tag == kCodeTargetTag) {
539
      ReadShortTaggedPC();
540
      if (SetMode(RelocInfo::CODE_TARGET)) return;
541
    } else if (tag == kLocatableTag) {
542
      ReadShortTaggedPC();
543
      Advance();
544 545 546
      if (SetMode(RelocInfo::DEOPT_REASON)) {
        ReadShortData();
        return;
547 548
      }
    } else {
549
      DCHECK(tag == kDefaultTag);
550 551 552 553 554
      RelocInfo::Mode rmode = GetMode();
      if (rmode == RelocInfo::PC_JUMP) {
        AdvanceReadLongPCJump();
      } else {
        AdvanceReadPC();
555
        if (RelocInfo::IsComment(rmode)) {
556 557 558 559 560 561
          if (SetMode(rmode)) {
            AdvanceReadData();
            return;
          }
          Advance(kIntptrSize);
        } else if (RelocInfo::IsConstPool(rmode) ||
562
                   RelocInfo::IsVeneerPool(rmode) ||
563
                   RelocInfo::IsDeoptId(rmode) ||
564 565
                   RelocInfo::IsDeoptPosition(rmode) ||
                   RelocInfo::IsWasmProtectedLanding(rmode)) {
566
          if (SetMode(rmode)) {
567
            AdvanceReadInt();
568 569 570
            return;
          }
          Advance(kIntSize);
571
        } else if (SetMode(static_cast<RelocInfo::Mode>(rmode))) {
572 573
          return;
        }
574 575 576
      }
    }
  }
577 578 579 580 581 582 583 584 585
  if (code_age_sequence_ != NULL) {
    byte* old_code_age_sequence = code_age_sequence_;
    code_age_sequence_ = NULL;
    if (SetMode(RelocInfo::CODE_AGE_SEQUENCE)) {
      rinfo_.data_ = 0;
      rinfo_.pc_ = old_code_age_sequence;
      return;
    }
  }
586 587 588
  done_ = true;
}

589
RelocIterator::RelocIterator(Code* code, int mode_mask) {
590
  rinfo_.host_ = code;
591 592
  rinfo_.pc_ = code->instruction_start();
  rinfo_.data_ = 0;
593
  // Relocation info is read backwards.
594 595 596 597
  pos_ = code->relocation_start() + code->relocation_size();
  end_ = code->relocation_start();
  done_ = false;
  mode_mask_ = mode_mask;
598
  byte* sequence = code->FindCodeAgeSequence();
599 600 601 602
  // We get the isolate from the map, because at serialization time
  // the code pointer has been cloned and isn't really in heap space.
  Isolate* isolate = code->map()->GetIsolate();
  if (sequence != NULL && !Code::IsYoungSequence(isolate, sequence)) {
603 604 605 606
    code_age_sequence_ = sequence;
  } else {
    code_age_sequence_ = NULL;
  }
607 608 609 610
  if (mode_mask_ == 0) pos_ = end_;
  next();
}

611
RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
612 613
  rinfo_.pc_ = desc.buffer;
  rinfo_.data_ = 0;
614
  // Relocation info is read backwards.
615 616 617 618
  pos_ = desc.buffer + desc.buffer_size;
  end_ = pos_ - desc.reloc_size;
  done_ = false;
  mode_mask_ = mode_mask;
619
  code_age_sequence_ = NULL;
620 621 622 623 624 625 626 627
  if (mode_mask_ == 0) pos_ = end_;
  next();
}


// -----------------------------------------------------------------------------
// Implementation of RelocInfo

628 629 630
bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
  return DebugCodegen::DebugBreakSlotIsPatched(pc_);
}
631

632
#ifdef DEBUG
633
bool RelocInfo::RequiresRelocation(Isolate* isolate, const CodeDesc& desc) {
634 635 636 637 638 639 640 641 642 643 644 645
  // Ensure there are no code targets or embedded objects present in the
  // deoptimization entries, they would require relocation after code
  // generation.
  int mode_mask = RelocInfo::kCodeTargetMask |
                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                  RelocInfo::kApplyMask;
  RelocIterator it(desc, mode_mask);
  return !it.done();
}
#endif


646
#ifdef ENABLE_DISASSEMBLER
647
const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
648
  switch (rmode) {
649
    case NONE32:
650
      return "no reloc 32";
651
    case NONE64:
652
      return "no reloc 64";
653
    case EMBEDDED_OBJECT:
654
      return "embedded object";
655
    case CODE_TARGET:
656
      return "code target";
657
    case RUNTIME_ENTRY:
658
      return "runtime entry";
659
    case COMMENT:
660
      return "comment";
661
    case EXTERNAL_REFERENCE:
662
      return "external reference";
663
    case INTERNAL_REFERENCE:
664
      return "internal reference";
665
    case INTERNAL_REFERENCE_ENCODED:
666
      return "encoded internal reference";
667 668 669 670
    case DEOPT_SCRIPT_OFFSET:
      return "deopt script offset";
    case DEOPT_INLINING_ID:
      return "deopt inlining id";
671
    case DEOPT_REASON:
672
      return "deopt reason";
673
    case DEOPT_ID:
674
      return "deopt index";
675
    case CONST_POOL:
676
      return "constant pool";
677
    case VENEER_POOL:
678
      return "veneer pool";
679 680
    case DEBUG_BREAK_SLOT_AT_POSITION:
      return "debug break slot at position";
681 682
    case DEBUG_BREAK_SLOT_AT_RETURN:
      return "debug break slot at return";
683 684
    case DEBUG_BREAK_SLOT_AT_CALL:
      return "debug break slot at call";
685 686
    case DEBUG_BREAK_SLOT_AT_TAIL_CALL:
      return "debug break slot at tail call";
687
    case CODE_AGE_SEQUENCE:
688
      return "code age sequence";
689 690
    case WASM_MEMORY_REFERENCE:
      return "wasm memory reference";
691 692
    case WASM_MEMORY_SIZE_REFERENCE:
      return "wasm memory size reference";
mtrofin's avatar
mtrofin committed
693 694
    case WASM_GLOBAL_REFERENCE:
      return "wasm global value reference";
695 696
    case WASM_FUNCTION_TABLE_SIZE_REFERENCE:
      return "wasm function table size reference";
697 698
    case WASM_PROTECTED_INSTRUCTION_LANDING:
      return "wasm protected instruction landing";
699 700
    case NUMBER_OF_MODES:
    case PC_JUMP:
701 702 703 704 705 706
      UNREACHABLE();
  }
  return "unknown relocation type";
}


707 708
void RelocInfo::Print(Isolate* isolate, std::ostream& os) {  // NOLINT
  os << static_cast<const void*>(pc_) << "  " << RelocModeName(rmode_);
709
  if (IsComment(rmode_)) {
710
    os << "  (" << reinterpret_cast<char*>(data_) << ")";
711
  } else if (rmode_ == DEOPT_SCRIPT_OFFSET || rmode_ == DEOPT_INLINING_ID) {
712
    os << "  (" << data() << ")";
713
  } else if (rmode_ == DEOPT_REASON) {
714 715
    os << "  ("
       << DeoptimizeReasonToString(static_cast<DeoptimizeReason>(data_)) << ")";
716
  } else if (rmode_ == EMBEDDED_OBJECT) {
717
    os << "  (" << Brief(target_object()) << ")";
718
  } else if (rmode_ == EXTERNAL_REFERENCE) {
719
    ExternalReferenceEncoder ref_encoder(isolate);
720 721
    os << " ("
       << ref_encoder.NameOfAddress(isolate, target_external_reference())
722 723
       << ")  (" << static_cast<const void*>(target_external_reference())
       << ")";
724
  } else if (IsCodeTarget(rmode_)) {
725
    Code* code = Code::GetCodeFromTargetAddress(target_address());
726 727
    os << " (" << Code::Kind2String(code->kind()) << ")  ("
       << static_cast<const void*>(target_address()) << ")";
728
  } else if (IsRuntimeEntry(rmode_) &&
729
             isolate->deoptimizer_data() != NULL) {
730 731
    // Depotimization bailouts are stored as runtime entries.
    int id = Deoptimizer::GetDeoptimizationId(
732
        isolate, target_address(), Deoptimizer::EAGER);
733
    if (id != Deoptimizer::kNotDeoptimizationEntry) {
734
      os << "  (deoptimization bailout " << id << ")";
735
    }
736 737
  } else if (IsConstPool(rmode_)) {
    os << " (size " << static_cast<int>(data_) << ")";
738 739
  }

740
  os << "\n";
741
}
742
#endif  // ENABLE_DISASSEMBLER
743 744


745
#ifdef VERIFY_HEAP
746
void RelocInfo::Verify(Isolate* isolate) {
747
  switch (rmode_) {
748
    case EMBEDDED_OBJECT:
749 750
      Object::VerifyPointer(target_object());
      break;
751
    case CODE_TARGET: {
752 753
      // convert inline target address to code object
      Address addr = target_address();
754
      CHECK(addr != NULL);
755
      // Check that we can find the right code object.
756
      Code* code = Code::GetCodeFromTargetAddress(addr);
757
      Object* found = isolate->FindCodeObject(addr);
758 759
      CHECK(found->IsCode());
      CHECK(code->address() == HeapObject::cast(found)->address());
760 761
      break;
    }
762 763 764 765 766 767 768 769 770
    case INTERNAL_REFERENCE:
    case INTERNAL_REFERENCE_ENCODED: {
      Address target = target_internal_reference();
      Address pc = target_internal_reference_address();
      Code* code = Code::cast(isolate->FindCodeObject(pc));
      CHECK(target >= code->instruction_start());
      CHECK(target <= code->instruction_end());
      break;
    }
771 772 773
    case RUNTIME_ENTRY:
    case COMMENT:
    case EXTERNAL_REFERENCE:
774 775
    case DEOPT_SCRIPT_OFFSET:
    case DEOPT_INLINING_ID:
776
    case DEOPT_REASON:
777
    case DEOPT_ID:
778
    case CONST_POOL:
779
    case VENEER_POOL:
780
    case DEBUG_BREAK_SLOT_AT_POSITION:
781
    case DEBUG_BREAK_SLOT_AT_RETURN:
782
    case DEBUG_BREAK_SLOT_AT_CALL:
783
    case DEBUG_BREAK_SLOT_AT_TAIL_CALL:
784
    case WASM_MEMORY_REFERENCE:
785
    case WASM_MEMORY_SIZE_REFERENCE:
mtrofin's avatar
mtrofin committed
786
    case WASM_GLOBAL_REFERENCE:
787
    case WASM_FUNCTION_TABLE_SIZE_REFERENCE:
788 789
    case WASM_PROTECTED_INSTRUCTION_LANDING:
    // TODO(eholk): make sure the protected instruction is in range.
790
    case NONE32:
791
    case NONE64:
792
      break;
793
    case NUMBER_OF_MODES:
794
    case PC_JUMP:
795 796
      UNREACHABLE();
      break;
797
    case CODE_AGE_SEQUENCE:
798
      DCHECK(Code::IsYoungSequence(isolate, pc_) || code_age_stub()->IsCode());
799
      break;
800 801
  }
}
802
#endif  // VERIFY_HEAP
803 804 805 806


// Implementation of ExternalReference

mbrandy's avatar
mbrandy committed
807 808 809 810 811 812 813 814 815 816 817 818 819
static ExternalReference::Type BuiltinCallTypeForResultSize(int result_size) {
  switch (result_size) {
    case 1:
      return ExternalReference::BUILTIN_CALL;
    case 2:
      return ExternalReference::BUILTIN_CALL_PAIR;
    case 3:
      return ExternalReference::BUILTIN_CALL_TRIPLE;
  }
  UNREACHABLE();
}


820 821 822
void ExternalReference::SetUp() {
  double_constants.min_int = kMinInt;
  double_constants.one_half = 0.5;
823
  double_constants.minus_one_half = -0.5;
824
  double_constants.the_hole_nan = kHoleNanInt64;
825
  double_constants.negative_infinity = -V8_INFINITY;
826 827
  double_constants.uint32_bias =
    static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
828 829
}

830 831
ExternalReference::ExternalReference(Address address, Isolate* isolate)
    : address_(Redirect(isolate, address)) {}
832

833
ExternalReference::ExternalReference(
834 835 836 837
    ApiFunction* fun,
    Type type = ExternalReference::BUILTIN_CALL,
    Isolate* isolate = NULL)
  : address_(Redirect(isolate, fun->address(), type)) {}
838 839


840 841
ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
  : address_(isolate->builtins()->builtin_address(name)) {}
842 843


844
ExternalReference::ExternalReference(Runtime::FunctionId id, Isolate* isolate)
845
    : ExternalReference(Runtime::FunctionForId(id), isolate) {}
846 847


848 849
ExternalReference::ExternalReference(const Runtime::Function* f,
                                     Isolate* isolate)
mbrandy's avatar
mbrandy committed
850 851
    : address_(Redirect(isolate, f->entry,
                        BuiltinCallTypeForResultSize(f->result_size))) {}
852 853


854 855
ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
  return ExternalReference(isolate);
856 857
}

858 859 860 861
ExternalReference ExternalReference::interpreter_dispatch_table_address(
    Isolate* isolate) {
  return ExternalReference(isolate->interpreter()->dispatch_table_address());
}
862

863 864 865
ExternalReference ExternalReference::interpreter_dispatch_counters(
    Isolate* isolate) {
  return ExternalReference(
866
      isolate->interpreter()->bytecode_dispatch_counters_table());
867 868
}

869 870 871
ExternalReference::ExternalReference(StatsCounter* counter)
  : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}

872 873
ExternalReference::ExternalReference(IsolateAddressId id, Isolate* isolate)
    : address_(isolate->get_address_from_id(id)) {}
874 875 876 877 878

ExternalReference::ExternalReference(const SCTableReference& table_ref)
  : address_(table_ref.address()) {}


879 880 881 882 883 884 885
ExternalReference ExternalReference::
    incremental_marking_record_write_function(Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate,
      FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode)));
}

886 887
ExternalReference ExternalReference::store_buffer_overflow_function(
    Isolate* isolate) {
888 889 890 891 892 893
  return ExternalReference(Redirect(
      isolate,
      FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow)));
}


894 895 896 897 898
ExternalReference ExternalReference::delete_handle_scope_extensions(
    Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate,
      FUNCTION_ADDR(HandleScope::DeleteExtensions)));
899 900 901
}


902 903 904 905 906 907
ExternalReference ExternalReference::get_date_field_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField)));
}


908 909 910 911 912 913 914
ExternalReference ExternalReference::get_make_code_young_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(Code::MakeCodeAgeSequenceYoung)));
}


915 916 917 918 919 920 921
ExternalReference ExternalReference::get_mark_code_as_executed_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(Code::MarkCodeAsExecuted)));
}


922 923 924 925
ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
  return ExternalReference(isolate->date_cache()->stamp_address());
}

926 927 928 929 930 931 932
void ExternalReference::set_redirector(
    Isolate* isolate, ExternalReferenceRedirector* redirector) {
  // We can't stack them.
  DCHECK(isolate->external_reference_redirector() == NULL);
  isolate->set_external_reference_redirector(
      reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
}
933

934 935 936 937 938
ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) {
  return ExternalReference(isolate->stress_deopt_count_address());
}


939 940
ExternalReference ExternalReference::new_deoptimizer_function(
    Isolate* isolate) {
941
  return ExternalReference(
942
      Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
943 944 945
}


946 947
ExternalReference ExternalReference::compute_output_frames_function(
    Isolate* isolate) {
948
  return ExternalReference(
949
      Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
950 951
}

952 953 954
ExternalReference ExternalReference::wasm_f32_trunc(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f32_trunc_wrapper)));
955
}
956 957 958
ExternalReference ExternalReference::wasm_f32_floor(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f32_floor_wrapper)));
959
}
960 961 962
ExternalReference ExternalReference::wasm_f32_ceil(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f32_ceil_wrapper)));
963
}
964 965 966
ExternalReference ExternalReference::wasm_f32_nearest_int(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f32_nearest_int_wrapper)));
967 968
}

969
ExternalReference ExternalReference::wasm_f64_trunc(Isolate* isolate) {
970
  return ExternalReference(
971
      Redirect(isolate, FUNCTION_ADDR(wasm::f64_trunc_wrapper)));
972 973
}

974 975 976
ExternalReference ExternalReference::wasm_f64_floor(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f64_floor_wrapper)));
977 978
}

979 980 981 982
ExternalReference ExternalReference::wasm_f64_ceil(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f64_ceil_wrapper)));
}
983

984 985 986
ExternalReference ExternalReference::wasm_f64_nearest_int(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::f64_nearest_int_wrapper)));
987 988
}

989 990 991 992
ExternalReference ExternalReference::wasm_int64_to_float32(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::int64_to_float32_wrapper)));
}
993

994 995 996
ExternalReference ExternalReference::wasm_uint64_to_float32(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::uint64_to_float32_wrapper)));
997 998
}

999 1000 1001
ExternalReference ExternalReference::wasm_int64_to_float64(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::int64_to_float64_wrapper)));
1002 1003
}

1004
ExternalReference ExternalReference::wasm_uint64_to_float64(Isolate* isolate) {
1005
  return ExternalReference(
1006
      Redirect(isolate, FUNCTION_ADDR(wasm::uint64_to_float64_wrapper)));
1007
}
1008

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
ExternalReference ExternalReference::wasm_float32_to_int64(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::float32_to_int64_wrapper)));
}

ExternalReference ExternalReference::wasm_float32_to_uint64(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::float32_to_uint64_wrapper)));
}

ExternalReference ExternalReference::wasm_float64_to_int64(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::float64_to_int64_wrapper)));
}

ExternalReference ExternalReference::wasm_float64_to_uint64(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::float64_to_uint64_wrapper)));
}

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
ExternalReference ExternalReference::wasm_int64_div(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::int64_div_wrapper)));
}

ExternalReference ExternalReference::wasm_int64_mod(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::int64_mod_wrapper)));
}

ExternalReference ExternalReference::wasm_uint64_div(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::uint64_div_wrapper)));
}

ExternalReference ExternalReference::wasm_uint64_mod(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::uint64_mod_wrapper)));
}

1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
ExternalReference ExternalReference::wasm_word32_ctz(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::word32_ctz_wrapper)));
}

ExternalReference ExternalReference::wasm_word64_ctz(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::word64_ctz_wrapper)));
}

ExternalReference ExternalReference::wasm_word32_popcnt(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::word32_popcnt_wrapper)));
}

ExternalReference ExternalReference::wasm_word64_popcnt(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::word64_popcnt_wrapper)));
}

1069
static void f64_acos_wrapper(double* param) {
1070
  WriteDoubleValue(param, base::ieee754::acos(ReadDoubleValue(param)));
1071
}
1072 1073 1074 1075 1076 1077

ExternalReference ExternalReference::f64_acos_wrapper_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_acos_wrapper)));
}

1078
static void f64_asin_wrapper(double* param) {
1079
  WriteDoubleValue(param, base::ieee754::asin(ReadDoubleValue(param)));
1080
}
1081 1082 1083 1084 1085 1086

ExternalReference ExternalReference::f64_asin_wrapper_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_asin_wrapper)));
}

1087 1088 1089 1090 1091
ExternalReference ExternalReference::wasm_float64_pow(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::float64_pow_wrapper)));
}

1092
static void f64_mod_wrapper(double* param0, double* param1) {
1093 1094
  WriteDoubleValue(param0,
                   modulo(ReadDoubleValue(param0), ReadDoubleValue(param1)));
1095 1096 1097 1098 1099 1100 1101
}

ExternalReference ExternalReference::f64_mod_wrapper_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_mod_wrapper)));
}

1102 1103 1104 1105 1106 1107
ExternalReference ExternalReference::wasm_call_trap_callback_for_testing(
    Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(wasm::call_trap_callback_for_testing)));
}

1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
ExternalReference ExternalReference::log_enter_external_function(
    Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(Logger::EnterExternal)));
}


ExternalReference ExternalReference::log_leave_external_function(
    Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(Logger::LeaveExternal)));
}

1121 1122
ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
  return ExternalReference(isolate->heap()->roots_array_start());
1123 1124 1125
}


1126 1127 1128 1129 1130 1131
ExternalReference ExternalReference::allocation_sites_list_address(
    Isolate* isolate) {
  return ExternalReference(isolate->heap()->allocation_sites_list_address());
}


1132 1133
ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
  return ExternalReference(isolate->stack_guard()->address_of_jslimit());
1134 1135 1136
}


1137 1138 1139
ExternalReference ExternalReference::address_of_real_stack_limit(
    Isolate* isolate) {
  return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
1140 1141 1142
}


1143 1144 1145
ExternalReference ExternalReference::address_of_regexp_stack_limit(
    Isolate* isolate) {
  return ExternalReference(isolate->regexp_stack()->limit_address());
1146 1147
}

1148 1149 1150 1151 1152
ExternalReference ExternalReference::address_of_regexp_dotall_flag(
    Isolate* isolate) {
  return ExternalReference(&FLAG_harmony_regexp_dotall);
}

1153
ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
1154
  return ExternalReference(isolate->heap()->store_buffer_top_address());
1155 1156 1157
}


1158 1159 1160
ExternalReference ExternalReference::new_space_allocation_top_address(
    Isolate* isolate) {
  return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
1161 1162
}

1163

1164 1165 1166
ExternalReference ExternalReference::new_space_allocation_limit_address(
    Isolate* isolate) {
  return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
1167 1168
}

1169

1170
ExternalReference ExternalReference::old_space_allocation_top_address(
1171
    Isolate* isolate) {
1172
  return ExternalReference(isolate->heap()->OldSpaceAllocationTopAddress());
1173 1174 1175
}


1176
ExternalReference ExternalReference::old_space_allocation_limit_address(
1177
    Isolate* isolate) {
1178
  return ExternalReference(isolate->heap()->OldSpaceAllocationLimitAddress());
1179 1180 1181
}


1182 1183 1184
ExternalReference ExternalReference::handle_scope_level_address(
    Isolate* isolate) {
  return ExternalReference(HandleScope::current_level_address(isolate));
1185 1186 1187
}


1188 1189 1190
ExternalReference ExternalReference::handle_scope_next_address(
    Isolate* isolate) {
  return ExternalReference(HandleScope::current_next_address(isolate));
1191 1192 1193
}


1194 1195 1196
ExternalReference ExternalReference::handle_scope_limit_address(
    Isolate* isolate) {
  return ExternalReference(HandleScope::current_limit_address(isolate));
1197 1198 1199
}


1200 1201 1202
ExternalReference ExternalReference::scheduled_exception_address(
    Isolate* isolate) {
  return ExternalReference(isolate->scheduled_exception_address());
1203 1204 1205
}


1206 1207 1208 1209 1210 1211
ExternalReference ExternalReference::address_of_pending_message_obj(
    Isolate* isolate) {
  return ExternalReference(isolate->pending_message_obj_address());
}


1212
ExternalReference ExternalReference::address_of_min_int() {
1213
  return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int));
1214 1215 1216 1217
}


ExternalReference ExternalReference::address_of_one_half() {
1218
  return ExternalReference(reinterpret_cast<void*>(&double_constants.one_half));
1219 1220 1221
}


1222 1223 1224 1225 1226 1227
ExternalReference ExternalReference::address_of_minus_one_half() {
  return ExternalReference(
      reinterpret_cast<void*>(&double_constants.minus_one_half));
}


1228
ExternalReference ExternalReference::address_of_negative_infinity() {
1229 1230
  return ExternalReference(
      reinterpret_cast<void*>(&double_constants.negative_infinity));
1231 1232 1233
}


1234
ExternalReference ExternalReference::address_of_the_hole_nan() {
1235 1236
  return ExternalReference(
      reinterpret_cast<void*>(&double_constants.the_hole_nan));
1237 1238 1239
}


1240 1241 1242 1243 1244 1245
ExternalReference ExternalReference::address_of_uint32_bias() {
  return ExternalReference(
      reinterpret_cast<void*>(&double_constants.uint32_bias));
}


1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
ExternalReference ExternalReference::address_of_float_abs_constant() {
  return ExternalReference(reinterpret_cast<void*>(&float_absolute_constant));
}


ExternalReference ExternalReference::address_of_float_neg_constant() {
  return ExternalReference(reinterpret_cast<void*>(&float_negate_constant));
}


ExternalReference ExternalReference::address_of_double_abs_constant() {
  return ExternalReference(reinterpret_cast<void*>(&double_absolute_constant));
}


ExternalReference ExternalReference::address_of_double_neg_constant() {
  return ExternalReference(reinterpret_cast<void*>(&double_negate_constant));
}


1266
ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
1267
  return ExternalReference(isolate->is_profiling_address());
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
}


ExternalReference ExternalReference::invoke_function_callback(
    Isolate* isolate) {
  Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
  ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
  ApiFunction thunk_fun(thunk_address);
  return ExternalReference(&thunk_fun, thunk_type, isolate);
}


ExternalReference ExternalReference::invoke_accessor_getter_callback(
    Isolate* isolate) {
  Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
  ExternalReference::Type thunk_type =
      ExternalReference::PROFILING_GETTER_CALL;
  ApiFunction thunk_fun(thunk_address);
  return ExternalReference(&thunk_fun, thunk_type, isolate);
}


1290
#ifndef V8_INTERPRETED_REGEXP
lrn@chromium.org's avatar
lrn@chromium.org committed
1291

1292 1293
ExternalReference ExternalReference::re_check_stack_guard_state(
    Isolate* isolate) {
lrn@chromium.org's avatar
lrn@chromium.org committed
1294
  Address function;
1295
#if V8_TARGET_ARCH_X64
lrn@chromium.org's avatar
lrn@chromium.org committed
1296 1297 1298
  function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
#elif V8_TARGET_ARCH_IA32
  function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
1299 1300
#elif V8_TARGET_ARCH_ARM64
  function = FUNCTION_ADDR(RegExpMacroAssemblerARM64::CheckStackGuardState);
lrn@chromium.org's avatar
lrn@chromium.org committed
1301 1302
#elif V8_TARGET_ARCH_ARM
  function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
1303 1304
#elif V8_TARGET_ARCH_PPC
  function = FUNCTION_ADDR(RegExpMacroAssemblerPPC::CheckStackGuardState);
1305 1306
#elif V8_TARGET_ARCH_MIPS
  function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1307 1308
#elif V8_TARGET_ARCH_MIPS64
  function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
1309 1310
#elif V8_TARGET_ARCH_S390
  function = FUNCTION_ADDR(RegExpMacroAssemblerS390::CheckStackGuardState);
lrn@chromium.org's avatar
lrn@chromium.org committed
1311
#else
1312
  UNREACHABLE();
lrn@chromium.org's avatar
lrn@chromium.org committed
1313
#endif
1314
  return ExternalReference(Redirect(isolate, function));
lrn@chromium.org's avatar
lrn@chromium.org committed
1315 1316
}

1317

1318
ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
lrn@chromium.org's avatar
lrn@chromium.org committed
1319
  return ExternalReference(
1320
      Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
lrn@chromium.org's avatar
lrn@chromium.org committed
1321 1322
}

1323 1324
ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
    Isolate* isolate) {
lrn@chromium.org's avatar
lrn@chromium.org committed
1325
  return ExternalReference(Redirect(
1326
      isolate,
lrn@chromium.org's avatar
lrn@chromium.org committed
1327 1328 1329
      FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
}

1330

1331 1332 1333 1334
ExternalReference ExternalReference::re_word_character_map() {
  return ExternalReference(
      NativeRegExpMacroAssembler::word_character_map_address());
}
1335

1336 1337 1338
ExternalReference ExternalReference::address_of_static_offsets_vector(
    Isolate* isolate) {
  return ExternalReference(
1339
      reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector()));
1340 1341
}

1342 1343
ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
    Isolate* isolate) {
1344
  return ExternalReference(
1345
      isolate->regexp_stack()->memory_address());
1346 1347
}

1348 1349 1350
ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
    Isolate* isolate) {
  return ExternalReference(isolate->regexp_stack()->memory_size_address());
1351 1352
}

1353
#endif  // V8_INTERPRETED_REGEXP
lrn@chromium.org's avatar
lrn@chromium.org committed
1354

1355
ExternalReference ExternalReference::ieee754_acos_function(Isolate* isolate) {
1356
  return ExternalReference(
1357
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::acos), BUILTIN_FP_CALL));
1358 1359
}

1360
ExternalReference ExternalReference::ieee754_acosh_function(Isolate* isolate) {
1361
  return ExternalReference(Redirect(
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
      isolate, FUNCTION_ADDR(base::ieee754::acosh), BUILTIN_FP_FP_CALL));
}

ExternalReference ExternalReference::ieee754_asin_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::asin), BUILTIN_FP_CALL));
}

ExternalReference ExternalReference::ieee754_asinh_function(Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(base::ieee754::asinh), BUILTIN_FP_FP_CALL));
}

ExternalReference ExternalReference::ieee754_atan_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::atan), BUILTIN_FP_CALL));
1378 1379
}

1380 1381 1382 1383 1384
ExternalReference ExternalReference::ieee754_atanh_function(Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(base::ieee754::atanh), BUILTIN_FP_FP_CALL));
}

1385 1386 1387 1388 1389
ExternalReference ExternalReference::ieee754_atan2_function(Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(base::ieee754::atan2), BUILTIN_FP_FP_CALL));
}

1390 1391 1392 1393 1394
ExternalReference ExternalReference::ieee754_cbrt_function(Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(base::ieee754::cbrt),
                                    BUILTIN_FP_FP_CALL));
}

1395 1396 1397 1398 1399
ExternalReference ExternalReference::ieee754_cos_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::cos), BUILTIN_FP_CALL));
}

1400 1401 1402 1403 1404
ExternalReference ExternalReference::ieee754_cosh_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::cosh), BUILTIN_FP_CALL));
}

1405 1406 1407 1408 1409
ExternalReference ExternalReference::ieee754_exp_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
}

1410 1411 1412 1413 1414
ExternalReference ExternalReference::ieee754_expm1_function(Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(base::ieee754::expm1), BUILTIN_FP_FP_CALL));
}

1415 1416 1417
ExternalReference ExternalReference::ieee754_log_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
1418 1419
}

1420 1421 1422 1423
ExternalReference ExternalReference::ieee754_log1p_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log1p), BUILTIN_FP_CALL));
}
1424

1425 1426 1427 1428 1429
ExternalReference ExternalReference::ieee754_log10_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log10), BUILTIN_FP_CALL));
}

1430 1431 1432
ExternalReference ExternalReference::ieee754_log2_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log2), BUILTIN_FP_CALL));
1433 1434
}

1435 1436 1437 1438 1439
ExternalReference ExternalReference::ieee754_sin_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::sin), BUILTIN_FP_CALL));
}

1440 1441 1442 1443 1444
ExternalReference ExternalReference::ieee754_sinh_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::sinh), BUILTIN_FP_CALL));
}

1445 1446 1447 1448 1449
ExternalReference ExternalReference::ieee754_tan_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::tan), BUILTIN_FP_CALL));
}

1450 1451 1452 1453 1454
ExternalReference ExternalReference::ieee754_tanh_function(Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(base::ieee754::tanh), BUILTIN_FP_CALL));
}

1455 1456 1457 1458 1459 1460 1461 1462
void* libc_memchr(void* string, int character, size_t search_length) {
  return memchr(string, character, search_length);
}

ExternalReference ExternalReference::libc_memchr_function(Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memchr)));
}

1463 1464 1465 1466 1467 1468 1469 1470
void* libc_memcpy(void* dest, const void* src, size_t n) {
  return memcpy(dest, src, n);
}

ExternalReference ExternalReference::libc_memcpy_function(Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memcpy)));
}

1471 1472 1473 1474 1475 1476 1477 1478
void* libc_memmove(void* dest, const void* src, size_t n) {
  return memmove(dest, src, n);
}

ExternalReference ExternalReference::libc_memmove_function(Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memmove)));
}

1479 1480 1481
void* libc_memset(void* dest, int byte, size_t n) {
  DCHECK_EQ(static_cast<char>(byte), byte);
  return memset(dest, byte, n);
1482 1483 1484 1485 1486 1487
}

ExternalReference ExternalReference::libc_memset_function(Isolate* isolate) {
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memset)));
}

1488 1489 1490 1491 1492 1493
template <typename SubjectChar, typename PatternChar>
ExternalReference ExternalReference::search_string_raw(Isolate* isolate) {
  auto f = SearchStringRaw<SubjectChar, PatternChar>;
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
}

1494 1495 1496
ExternalReference ExternalReference::orderedhashmap_gethash_raw(
    Isolate* isolate) {
  auto f = OrderedHashMap::GetHash;
1497 1498 1499
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
}

1500 1501 1502 1503 1504 1505 1506
template <typename CollectionType, int entrysize>
ExternalReference ExternalReference::orderedhashtable_has_raw(
    Isolate* isolate) {
  auto f = OrderedHashTable<CollectionType, entrysize>::HasKey;
  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
}

1507 1508 1509 1510 1511 1512
ExternalReference ExternalReference::try_internalize_string_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(
      isolate, FUNCTION_ADDR(StringTable::LookupStringIfExists_NoAllocate)));
}

1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526
#ifdef V8_INTL_SUPPORT
ExternalReference ExternalReference::intl_convert_one_byte_to_lower(
    Isolate* isolate) {
  return ExternalReference(
      Redirect(isolate, FUNCTION_ADDR(ConvertOneByteToLower)));
}

ExternalReference ExternalReference::intl_to_latin1_lower_table(
    Isolate* isolate) {
  uint8_t* ptr = const_cast<uint8_t*>(ToLatin1LowerTable());
  return ExternalReference(reinterpret_cast<Address>(ptr));
}
#endif  // V8_INTL_SUPPORT

1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
// Explicit instantiations for all combinations of 1- and 2-byte strings.
template ExternalReference
ExternalReference::search_string_raw<const uint8_t, const uint8_t>(Isolate*);
template ExternalReference
ExternalReference::search_string_raw<const uint8_t, const uc16>(Isolate*);
template ExternalReference
ExternalReference::search_string_raw<const uc16, const uint8_t>(Isolate*);
template ExternalReference
ExternalReference::search_string_raw<const uc16, const uc16>(Isolate*);

1537 1538 1539 1540 1541
template ExternalReference
ExternalReference::orderedhashtable_has_raw<OrderedHashMap, 2>(Isolate*);
template ExternalReference
ExternalReference::orderedhashtable_has_raw<OrderedHashSet, 1>(Isolate*);

1542 1543 1544 1545 1546 1547
ExternalReference ExternalReference::page_flags(Page* page) {
  return ExternalReference(reinterpret_cast<Address>(page) +
                           MemoryChunk::kFlagsOffset);
}


1548 1549 1550 1551 1552
ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
  return ExternalReference(entry);
}


1553
ExternalReference ExternalReference::cpu_features() {
1554
  DCHECK(CpuFeatures::initialized_);
1555 1556 1557
  return ExternalReference(&CpuFeatures::supported_);
}

1558 1559 1560
ExternalReference ExternalReference::promise_hook_or_debug_is_active_address(
    Isolate* isolate) {
  return ExternalReference(isolate->promise_hook_or_debug_is_active_address());
1561 1562
}

1563 1564 1565 1566 1567
ExternalReference ExternalReference::debug_is_active_address(
    Isolate* isolate) {
  return ExternalReference(isolate->debug()->is_active_address());
}

1568 1569 1570 1571
ExternalReference ExternalReference::debug_hook_on_function_call_address(
    Isolate* isolate) {
  return ExternalReference(isolate->debug()->hook_on_function_call_address());
}
1572

1573 1574 1575 1576 1577 1578 1579
ExternalReference ExternalReference::runtime_function_table_address(
    Isolate* isolate) {
  return ExternalReference(
      const_cast<Runtime::Function*>(Runtime::RuntimeFunctionTable(isolate)));
}


1580
double power_helper(Isolate* isolate, double x, double y) {
1581 1582 1583 1584 1585
  int y_int = static_cast<int>(y);
  if (y == y_int) {
    return power_double_int(x, y_int);  // Returns 1 if exponent is 0.
  }
  if (y == 0.5) {
1586
    lazily_initialize_fast_sqrt(isolate);
1587
    return (std::isinf(x)) ? V8_INFINITY
1588
                           : fast_sqrt(x + 0.0, isolate);  // Convert -0 to +0.
1589 1590
  }
  if (y == -0.5) {
1591 1592 1593
    lazily_initialize_fast_sqrt(isolate);
    return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0,
                                                 isolate);  // Convert -0 to +0.
1594 1595 1596 1597 1598
  }
  return power_double_double(x, y);
}


1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
// Helper function to compute x^y, where y is known to be an
// integer. Uses binary decomposition to limit the number of
// multiplications; see the discussion in "Hacker's Delight" by Henry
// S. Warren, Jr., figure 11-6, page 213.
double power_double_int(double x, int y) {
  double m = (y < 0) ? 1 / x : x;
  unsigned n = (y < 0) ? -y : y;
  double p = 1;
  while (n != 0) {
    if ((n & 1) != 0) p *= m;
    m *= m;
    if ((n & 2) != 0) p *= m;
    m *= m;
    n >>= 2;
  }
  return p;
}


double power_double_double(double x, double y) {
1619 1620
  // The checks for special cases can be dropped in ia32 because it has already
  // been done in generated code before bailing out here.
1621
  if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
1622
    return std::numeric_limits<double>::quiet_NaN();
1623
  }
1624
  return Pow(x, y);
1625 1626 1627
}


1628 1629 1630 1631
ExternalReference ExternalReference::power_double_double_function(
    Isolate* isolate) {
  return ExternalReference(Redirect(isolate,
                                    FUNCTION_ADDR(power_double_double),
1632
                                    BUILTIN_FP_FP_CALL));
1633 1634 1635
}


1636 1637
ExternalReference ExternalReference::mod_two_doubles_operation(
    Isolate* isolate) {
1638
  return ExternalReference(Redirect(isolate,
1639
                                    FUNCTION_ADDR(modulo),
1640
                                    BUILTIN_FP_FP_CALL));
1641 1642
}

1643
ExternalReference ExternalReference::debug_last_step_action_address(
1644
    Isolate* isolate) {
1645
  return ExternalReference(isolate->debug()->last_step_action_address());
1646 1647
}

1648 1649 1650 1651
ExternalReference ExternalReference::debug_suspended_generator_address(
    Isolate* isolate) {
  return ExternalReference(isolate->debug()->suspended_generator_address());
}
1652

1653 1654 1655 1656 1657
ExternalReference ExternalReference::debug_restart_fp_address(
    Isolate* isolate) {
  return ExternalReference(isolate->debug()->restart_fp_address());
}

1658 1659 1660 1661 1662 1663
ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
  return ExternalReference(reinterpret_cast<void*>(
      FixedTypedArrayBase::kDataOffset - kHeapObjectTag));
}


1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
bool operator==(ExternalReference lhs, ExternalReference rhs) {
  return lhs.address() == rhs.address();
}


bool operator!=(ExternalReference lhs, ExternalReference rhs) {
  return !(lhs == rhs);
}


size_t hash_value(ExternalReference reference) {
  return base::hash<Address>()(reference.address());
}


std::ostream& operator<<(std::ostream& os, ExternalReference reference) {
  os << static_cast<const void*>(reference.address());
  const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address());
  if (fn) os << "<" << fn->name << ".entry>";
  return os;
}

1686

1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
ConstantPoolBuilder::ConstantPoolBuilder(int ptr_reach_bits,
                                         int double_reach_bits) {
  info_[ConstantPoolEntry::INTPTR].entries.reserve(64);
  info_[ConstantPoolEntry::INTPTR].regular_reach_bits = ptr_reach_bits;
  info_[ConstantPoolEntry::DOUBLE].regular_reach_bits = double_reach_bits;
}


ConstantPoolEntry::Access ConstantPoolBuilder::NextAccess(
    ConstantPoolEntry::Type type) const {
  const PerTypeEntryInfo& info = info_[type];

  if (info.overflow()) return ConstantPoolEntry::OVERFLOWED;

  int dbl_count = info_[ConstantPoolEntry::DOUBLE].regular_count;
  int dbl_offset = dbl_count * kDoubleSize;
  int ptr_count = info_[ConstantPoolEntry::INTPTR].regular_count;
  int ptr_offset = ptr_count * kPointerSize + dbl_offset;

  if (type == ConstantPoolEntry::DOUBLE) {
    // Double overflow detection must take into account the reach for both types
    int ptr_reach_bits = info_[ConstantPoolEntry::INTPTR].regular_reach_bits;
    if (!is_uintn(dbl_offset, info.regular_reach_bits) ||
        (ptr_count > 0 &&
         !is_uintn(ptr_offset + kDoubleSize - kPointerSize, ptr_reach_bits))) {
      return ConstantPoolEntry::OVERFLOWED;
    }
  } else {
    DCHECK(type == ConstantPoolEntry::INTPTR);
    if (!is_uintn(ptr_offset, info.regular_reach_bits)) {
      return ConstantPoolEntry::OVERFLOWED;
    }
  }

  return ConstantPoolEntry::REGULAR;
}


ConstantPoolEntry::Access ConstantPoolBuilder::AddEntry(
    ConstantPoolEntry& entry, ConstantPoolEntry::Type type) {
  DCHECK(!emitted_label_.is_bound());
  PerTypeEntryInfo& info = info_[type];
  const int entry_size = ConstantPoolEntry::size(type);
  bool merged = false;

  if (entry.sharing_ok()) {
    // Try to merge entries
    std::vector<ConstantPoolEntry>::iterator it = info.shared_entries.begin();
    int end = static_cast<int>(info.shared_entries.size());
    for (int i = 0; i < end; i++, it++) {
      if ((entry_size == kPointerSize) ? entry.value() == it->value()
                                       : entry.value64() == it->value64()) {
        // Merge with found entry.
        entry.set_merged_index(i);
        merged = true;
        break;
      }
    }
  }

  // By definition, merged entries have regular access.
  DCHECK(!merged || entry.merged_index() < info.regular_count);
  ConstantPoolEntry::Access access =
      (merged ? ConstantPoolEntry::REGULAR : NextAccess(type));

  // Enforce an upper bound on search time by limiting the search to
  // unique sharable entries which fit in the regular section.
  if (entry.sharing_ok() && !merged && access == ConstantPoolEntry::REGULAR) {
    info.shared_entries.push_back(entry);
  } else {
    info.entries.push_back(entry);
  }

  // We're done if we found a match or have already triggered the
  // overflow state.
  if (merged || info.overflow()) return access;

  if (access == ConstantPoolEntry::REGULAR) {
    info.regular_count++;
  } else {
    info.overflow_start = static_cast<int>(info.entries.size()) - 1;
  }

  return access;
}


void ConstantPoolBuilder::EmitSharedEntries(Assembler* assm,
                                            ConstantPoolEntry::Type type) {
  PerTypeEntryInfo& info = info_[type];
  std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
  const int entry_size = ConstantPoolEntry::size(type);
  int base = emitted_label_.pos();
  DCHECK(base > 0);
  int shared_end = static_cast<int>(shared_entries.size());
  std::vector<ConstantPoolEntry>::iterator shared_it = shared_entries.begin();
  for (int i = 0; i < shared_end; i++, shared_it++) {
    int offset = assm->pc_offset() - base;
    shared_it->set_offset(offset);  // Save offset for merged entries.
    if (entry_size == kPointerSize) {
      assm->dp(shared_it->value());
    } else {
      assm->dq(shared_it->value64());
    }
    DCHECK(is_uintn(offset, info.regular_reach_bits));

    // Patch load sequence with correct offset.
    assm->PatchConstantPoolAccessInstruction(shared_it->position(), offset,
                                             ConstantPoolEntry::REGULAR, type);
  }
}


void ConstantPoolBuilder::EmitGroup(Assembler* assm,
                                    ConstantPoolEntry::Access access,
                                    ConstantPoolEntry::Type type) {
  PerTypeEntryInfo& info = info_[type];
  const bool overflow = info.overflow();
  std::vector<ConstantPoolEntry>& entries = info.entries;
  std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
  const int entry_size = ConstantPoolEntry::size(type);
  int base = emitted_label_.pos();
  DCHECK(base > 0);
  int begin;
  int end;

  if (access == ConstantPoolEntry::REGULAR) {
    // Emit any shared entries first
    EmitSharedEntries(assm, type);
  }

  if (access == ConstantPoolEntry::REGULAR) {
    begin = 0;
    end = overflow ? info.overflow_start : static_cast<int>(entries.size());
  } else {
    DCHECK(access == ConstantPoolEntry::OVERFLOWED);
    if (!overflow) return;
    begin = info.overflow_start;
    end = static_cast<int>(entries.size());
  }

  std::vector<ConstantPoolEntry>::iterator it = entries.begin();
  if (begin > 0) std::advance(it, begin);
  for (int i = begin; i < end; i++, it++) {
    // Update constant pool if necessary and get the entry's offset.
    int offset;
    ConstantPoolEntry::Access entry_access;
    if (!it->is_merged()) {
      // Emit new entry
      offset = assm->pc_offset() - base;
      entry_access = access;
      if (entry_size == kPointerSize) {
        assm->dp(it->value());
      } else {
        assm->dq(it->value64());
      }
    } else {
      // Retrieve offset from shared entry.
      offset = shared_entries[it->merged_index()].offset();
      entry_access = ConstantPoolEntry::REGULAR;
    }

    DCHECK(entry_access == ConstantPoolEntry::OVERFLOWED ||
           is_uintn(offset, info.regular_reach_bits));

    // Patch load sequence with correct offset.
    assm->PatchConstantPoolAccessInstruction(it->position(), offset,
                                             entry_access, type);
  }
}


// Emit and return position of pool.  Zero implies no constant pool.
int ConstantPoolBuilder::Emit(Assembler* assm) {
  bool emitted = emitted_label_.is_bound();
  bool empty = IsEmpty();

  if (!emitted) {
    // Mark start of constant pool.  Align if necessary.
1866
    if (!empty) assm->DataAlign(kDoubleSize);
1867 1868 1869 1870 1871 1872 1873
    assm->bind(&emitted_label_);
    if (!empty) {
      // Emit in groups based on access and type.
      // Emit doubles first for alignment purposes.
      EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::DOUBLE);
      EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::INTPTR);
      if (info_[ConstantPoolEntry::DOUBLE].overflow()) {
1874
        assm->DataAlign(kDoubleSize);
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
        EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
                  ConstantPoolEntry::DOUBLE);
      }
      if (info_[ConstantPoolEntry::INTPTR].overflow()) {
        EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
                  ConstantPoolEntry::INTPTR);
      }
    }
  }

  return !empty ? emitted_label_.pos() : 0;
}

1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
    : kind_(kHeapNumber), offset_(offset) {
  value_.heap_number = heap_number;
  DCHECK(!IsSmiDouble(value_.heap_number));
}

HeapObjectRequest::HeapObjectRequest(CodeStub* code_stub, int offset)
    : kind_(kCodeStub), offset_(offset) {
  value_.code_stub = code_stub;
  DCHECK_NOT_NULL(value_.code_stub);
}
1899

1900 1901
// Platform specific but identical code for all the platforms.

1902 1903
void Assembler::RecordDeoptReason(DeoptimizeReason reason,
                                  SourcePosition position, int id) {
1904 1905 1906 1907 1908
  EnsureSpace ensure_space(this);
  RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
  RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
  RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
  RecordRelocInfo(RelocInfo::DEOPT_ID, id);
1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919
}


void Assembler::RecordComment(const char* msg) {
  if (FLAG_code_comments) {
    EnsureSpace ensure_space(this);
    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
  }
}


1920
void Assembler::RecordDebugBreakSlot(RelocInfo::Mode mode) {
1921
  EnsureSpace ensure_space(this);
1922
  DCHECK(RelocInfo::IsDebugBreakSlot(mode));
1923
  RecordRelocInfo(mode);
1924
}
1925 1926 1927


void Assembler::DataAlign(int m) {
1928
  DCHECK(m >= 2 && base::bits::IsPowerOfTwo(m));
1929 1930 1931 1932
  while ((pc_offset() & (m - 1)) != 0) {
    db(0);
  }
}
1933

1934 1935 1936 1937 1938
void Assembler::RequestHeapObject(HeapObjectRequest request) {
  request.set_offset(pc_offset());
  heap_object_requests_.push_front(request);
}

1939 1940
}  // namespace internal
}  // namespace v8