blob: a75c94aa0d4570975be1367588806bad5043bf0d [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000033// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034
35#include "v8.h"
36
37#include "arguments.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "deoptimizer.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#include "execution.h"
40#include "ic-inl.h"
41#include "factory.h"
42#include "runtime.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000043#include "runtime-profiler.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044#include "serialize.h"
45#include "stub-cache.h"
ager@chromium.org32912102009-01-16 10:38:43 +000046#include "regexp-stack.h"
ager@chromium.org18ad94b2009-09-02 08:22:29 +000047#include "ast.h"
48#include "regexp-macro-assembler.h"
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000049#include "platform.h"
ager@chromium.org18ad94b2009-09-02 08:22:29 +000050// Include native regexp-macro-assembler.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000051#ifndef V8_INTERPRETED_REGEXP
ager@chromium.org18ad94b2009-09-02 08:22:29 +000052#if V8_TARGET_ARCH_IA32
53#include "ia32/regexp-macro-assembler-ia32.h"
54#elif V8_TARGET_ARCH_X64
55#include "x64/regexp-macro-assembler-x64.h"
56#elif V8_TARGET_ARCH_ARM
57#include "arm/regexp-macro-assembler-arm.h"
lrn@chromium.org7516f052011-03-30 08:52:27 +000058#elif V8_TARGET_ARCH_MIPS
59#include "mips/regexp-macro-assembler-mips.h"
ager@chromium.org18ad94b2009-09-02 08:22:29 +000060#else // Unknown architecture.
61#error "Unknown architecture."
62#endif // Target architecture.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000063#endif // V8_INTERPRETED_REGEXP
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000064
kasperl@chromium.org71affb52009-05-26 05:44:31 +000065namespace v8 {
66namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067
68
kasperl@chromium.orga5551262010-12-07 12:49:48 +000069const double DoubleConstant::min_int = kMinInt;
70const double DoubleConstant::one_half = 0.5;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000071const double DoubleConstant::minus_zero = -0.0;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000072const double DoubleConstant::nan = OS::nan_value();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000073const double DoubleConstant::negative_infinity = -V8_INFINITY;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000074const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000075
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076// -----------------------------------------------------------------------------
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000077// Implementation of AssemblerBase
78
79AssemblerBase::AssemblerBase(Isolate* isolate)
80 : isolate_(isolate),
81 jit_cookie_(0) {
82 if (FLAG_mask_constants_with_cookie && isolate != NULL) {
83 jit_cookie_ = V8::RandomPrivate(isolate);
84 }
85}
86
87
88// -----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089// Implementation of Label
90
91int Label::pos() const {
92 if (pos_ < 0) return -pos_ - 1;
93 if (pos_ > 0) return pos_ - 1;
94 UNREACHABLE();
95 return 0;
96}
97
98
99// -----------------------------------------------------------------------------
100// Implementation of RelocInfoWriter and RelocIterator
101//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000102// Relocation information is written backwards in memory, from high addresses
103// towards low addresses, byte by byte. Therefore, in the encodings listed
104// below, the first byte listed it at the highest address, and successive
105// bytes in the record are at progressively lower addresses.
106//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107// Encoding
108//
109// The most common modes are given single-byte encodings. Also, it is
110// easy to identify the type of reloc info and skip unwanted modes in
111// an iteration.
112//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000113// The encoding relies on the fact that there are fewer than 14
114// different non-compactly encoded relocation modes.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000116// The first byte of a relocation record has a tag in its low 2 bits:
117// Here are the record schemes, depending on the low tag and optional higher
118// tags.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000120// Low tag:
121// 00: embedded_object: [6-bit pc delta] 00
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000123// 01: code_target: [6-bit pc delta] 01
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000125// 10: short_data_record: [6-bit pc delta] 10 followed by
126// [6-bit data delta] [2-bit data type tag]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000127//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000128// 11: long_record [2-bit high tag][4 bit middle_tag] 11
129// followed by variable data depending on type.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000131// 2-bit data type tags, used in short_data_record and data_jump long_record:
132// code_target_with_id: 00
133// position: 01
134// statement_position: 10
135// comment: 11 (not used in short_data_record)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000137// Long record format:
138// 4-bit middle_tag:
139// 0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2
140// (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM,
141// and is between 0000 and 1100)
142// The format is:
143// 00 [4 bit middle_tag] 11 followed by
144// 00 [6 bit pc delta]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000145//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000146// 1101: not used (would allow one more relocation mode to be added)
147// 1110: long_data_record
148// The format is: [2-bit data_type_tag] 1110 11
149// signed intptr_t, lowest byte written first
150// (except data_type code_target_with_id, which
151// is followed by a signed int, not intptr_t.)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000152//
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000153// 1111: long_pc_jump
154// The format is:
155// pc-jump: 00 1111 11,
156// 00 [6 bits pc delta]
157// or
158// pc-jump (variable length):
159// 01 1111 11,
160// [7 bits data] 0
161// ...
162// [7 bits data] 1
163// (Bits 6..31 of pc delta, with leading zeroes
164// dropped, and last non-zero chunk tagged with 1.)
165
166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000167const int kMaxRelocModes = 14;
168
169const int kTagBits = 2;
170const int kTagMask = (1 << kTagBits) - 1;
171const int kExtraTagBits = 4;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000172const int kLocatableTypeTagBits = 2;
173const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174
175const int kEmbeddedObjectTag = 0;
176const int kCodeTargetTag = 1;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000177const int kLocatableTag = 2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178const int kDefaultTag = 3;
179
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000180const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181
182const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
183const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000184const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185
186const int kVariableLengthPCJumpTopTag = 1;
187const int kChunkBits = 7;
188const int kChunkMask = (1 << kChunkBits) - 1;
189const int kLastChunkTagBits = 1;
190const int kLastChunkTagMask = 1;
191const int kLastChunkTag = 1;
192
193
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000194const int kDataJumpExtraTag = kPCJumpExtraTag - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000196const int kCodeWithIdTag = 0;
197const int kNonstatementPositionTag = 1;
198const int kStatementPositionTag = 2;
199const int kCommentTag = 3;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200
201
202uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
203 // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
204 // Otherwise write a variable length PC jump for the bits that do
205 // not fit in the kSmallPCDeltaBits bits.
206 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000207 WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
209 ASSERT(pc_jump > 0);
210 // Write kChunkBits size chunks of the pc_jump.
211 for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
212 byte b = pc_jump & kChunkMask;
213 *--pos_ = b << kLastChunkTagBits;
214 }
215 // Tag the last chunk so it can be identified.
216 *pos_ = *pos_ | kLastChunkTag;
217 // Return the remaining kSmallPCDeltaBits of the pc_delta.
218 return pc_delta & kSmallPCDeltaMask;
219}
220
221
222void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
223 // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
224 pc_delta = WriteVariableLengthPCJump(pc_delta);
225 *--pos_ = pc_delta << kTagBits | tag;
226}
227
228
ager@chromium.orge2902be2009-06-08 12:21:35 +0000229void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000230 *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231}
232
233
234void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000235 *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
236 extra_tag << kTagBits |
237 kDefaultTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238}
239
240
241void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
242 // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
243 pc_delta = WriteVariableLengthPCJump(pc_delta);
244 WriteExtraTag(extra_tag, 0);
245 *--pos_ = pc_delta;
246}
247
248
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000249void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
250 WriteExtraTag(kDataJumpExtraTag, top_tag);
251 for (int i = 0; i < kIntSize; i++) {
252 *--pos_ = static_cast<byte>(data_delta);
253 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
254 data_delta = data_delta >> kBitsPerByte;
255 }
256}
257
ager@chromium.orge2902be2009-06-08 12:21:35 +0000258void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000259 WriteExtraTag(kDataJumpExtraTag, top_tag);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000260 for (int i = 0; i < kIntptrSize; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000261 *--pos_ = static_cast<byte>(data_delta);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000262 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
ager@chromium.orge2902be2009-06-08 12:21:35 +0000263 data_delta = data_delta >> kBitsPerByte;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000264 }
265}
266
267
268void RelocInfoWriter::Write(const RelocInfo* rinfo) {
269#ifdef DEBUG
270 byte* begin_pos = pos_;
271#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000272 ASSERT(rinfo->pc() - last_pc_ >= 0);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000273 ASSERT(RelocInfo::NUMBER_OF_MODES - RelocInfo::LAST_COMPACT_ENUM <=
274 kMaxRelocModes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275 // Use unsigned delta-encoding for pc.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000276 uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
ager@chromium.org236ad962008-09-25 09:45:57 +0000277 RelocInfo::Mode rmode = rinfo->rmode();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000278
279 // The two most common modes are given small tags, and usually fit in a byte.
ager@chromium.org236ad962008-09-25 09:45:57 +0000280 if (rmode == RelocInfo::EMBEDDED_OBJECT) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281 WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
ager@chromium.org236ad962008-09-25 09:45:57 +0000282 } else if (rmode == RelocInfo::CODE_TARGET) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000283 WriteTaggedPC(pc_delta, kCodeTargetTag);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000284 ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000285 } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
286 // Use signed delta-encoding for id.
287 ASSERT(static_cast<int>(rinfo->data()) == rinfo->data());
288 int id_delta = static_cast<int>(rinfo->data()) - last_id_;
289 // Check if delta is small enough to fit in a tagged byte.
290 if (is_intn(id_delta, kSmallDataBits)) {
291 WriteTaggedPC(pc_delta, kLocatableTag);
292 WriteTaggedData(id_delta, kCodeWithIdTag);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000293 } else {
294 // Otherwise, use costly encoding.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000295 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
296 WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000297 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000298 last_id_ = static_cast<int>(rinfo->data());
299 } else if (RelocInfo::IsPosition(rmode)) {
300 // Use signed delta-encoding for position.
301 ASSERT(static_cast<int>(rinfo->data()) == rinfo->data());
302 int pos_delta = static_cast<int>(rinfo->data()) - last_position_;
303 int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
304 : kStatementPositionTag;
305 // Check if delta is small enough to fit in a tagged byte.
306 if (is_intn(pos_delta, kSmallDataBits)) {
307 WriteTaggedPC(pc_delta, kLocatableTag);
308 WriteTaggedData(pos_delta, pos_type_tag);
309 } else {
310 // Otherwise, use costly encoding.
311 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
312 WriteExtraTaggedIntData(pos_delta, pos_type_tag);
313 }
314 last_position_ = static_cast<int>(rinfo->data());
ager@chromium.org236ad962008-09-25 09:45:57 +0000315 } else if (RelocInfo::IsComment(rmode)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316 // Comments are normally not generated, so we use the costly encoding.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000317 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
318 WriteExtraTaggedData(rinfo->data(), kCommentTag);
ricow@chromium.org22334512011-02-25 07:28:50 +0000319 ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320 } else {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000321 ASSERT(rmode > RelocInfo::LAST_COMPACT_ENUM);
322 int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000323 // For all other modes we simply use the mode as the extra tag.
324 // None of these modes need a data component.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000325 ASSERT(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag);
326 WriteExtraTaggedPC(pc_delta, saved_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000327 }
328 last_pc_ = rinfo->pc();
329#ifdef DEBUG
330 ASSERT(begin_pos - pos_ <= kMaxSize);
331#endif
332}
333
334
335inline int RelocIterator::AdvanceGetTag() {
336 return *--pos_ & kTagMask;
337}
338
339
340inline int RelocIterator::GetExtraTag() {
341 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
342}
343
344
345inline int RelocIterator::GetTopTag() {
346 return *pos_ >> (kTagBits + kExtraTagBits);
347}
348
349
350inline void RelocIterator::ReadTaggedPC() {
351 rinfo_.pc_ += *pos_ >> kTagBits;
352}
353
354
355inline void RelocIterator::AdvanceReadPC() {
356 rinfo_.pc_ += *--pos_;
357}
358
359
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000360void RelocIterator::AdvanceReadId() {
361 int x = 0;
362 for (int i = 0; i < kIntSize; i++) {
363 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
364 }
365 last_id_ += x;
366 rinfo_.data_ = last_id_;
367}
368
369
370void RelocIterator::AdvanceReadPosition() {
371 int x = 0;
372 for (int i = 0; i < kIntSize; i++) {
373 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
374 }
375 last_position_ += x;
376 rinfo_.data_ = last_position_;
377}
378
379
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380void RelocIterator::AdvanceReadData() {
ager@chromium.orge2902be2009-06-08 12:21:35 +0000381 intptr_t x = 0;
382 for (int i = 0; i < kIntptrSize; i++) {
383 x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000385 rinfo_.data_ = x;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000386}
387
388
389void RelocIterator::AdvanceReadVariableLengthPCJump() {
390 // Read the 32-kSmallPCDeltaBits most significant bits of the
391 // pc jump in kChunkBits bit chunks and shift them into place.
392 // Stop when the last chunk is encountered.
393 uint32_t pc_jump = 0;
394 for (int i = 0; i < kIntSize; i++) {
395 byte pc_jump_part = *--pos_;
396 pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
397 if ((pc_jump_part & kLastChunkTagMask) == 1) break;
398 }
399 // The least significant kSmallPCDeltaBits bits will be added
400 // later.
401 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
402}
403
404
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000405inline int RelocIterator::GetLocatableTypeTag() {
406 return *pos_ & ((1 << kLocatableTypeTagBits) - 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000407}
408
409
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000410inline void RelocIterator::ReadTaggedId() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000411 int8_t signed_b = *pos_;
ager@chromium.orge2902be2009-06-08 12:21:35 +0000412 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000413 last_id_ += signed_b >> kLocatableTypeTagBits;
414 rinfo_.data_ = last_id_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415}
416
417
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000418inline void RelocIterator::ReadTaggedPosition() {
419 int8_t signed_b = *pos_;
420 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
421 last_position_ += signed_b >> kLocatableTypeTagBits;
422 rinfo_.data_ = last_position_;
423}
424
425
426static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
427 ASSERT(tag == kNonstatementPositionTag ||
428 tag == kStatementPositionTag);
429 return (tag == kNonstatementPositionTag) ?
430 RelocInfo::POSITION :
431 RelocInfo::STATEMENT_POSITION;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432}
433
434
435void RelocIterator::next() {
436 ASSERT(!done());
437 // Basically, do the opposite of RelocInfoWriter::Write.
438 // Reading of data is as far as possible avoided for unwanted modes,
439 // but we must always update the pc.
440 //
441 // We exit this loop by returning when we find a mode we want.
442 while (pos_ > end_) {
443 int tag = AdvanceGetTag();
444 if (tag == kEmbeddedObjectTag) {
445 ReadTaggedPC();
ager@chromium.org236ad962008-09-25 09:45:57 +0000446 if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447 } else if (tag == kCodeTargetTag) {
448 ReadTaggedPC();
ager@chromium.org236ad962008-09-25 09:45:57 +0000449 if (SetMode(RelocInfo::CODE_TARGET)) return;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000450 } else if (tag == kLocatableTag) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451 ReadTaggedPC();
452 Advance();
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000453 int locatable_tag = GetLocatableTypeTag();
454 if (locatable_tag == kCodeWithIdTag) {
455 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
456 ReadTaggedId();
457 return;
458 }
459 } else {
460 // Compact encoding is never used for comments,
461 // so it must be a position.
462 ASSERT(locatable_tag == kNonstatementPositionTag ||
463 locatable_tag == kStatementPositionTag);
464 if (mode_mask_ & RelocInfo::kPositionMask) {
465 ReadTaggedPosition();
466 if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
467 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468 }
469 } else {
470 ASSERT(tag == kDefaultTag);
471 int extra_tag = GetExtraTag();
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000472 if (extra_tag == kPCJumpExtraTag) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473 int top_tag = GetTopTag();
474 if (top_tag == kVariableLengthPCJumpTopTag) {
475 AdvanceReadVariableLengthPCJump();
476 } else {
477 AdvanceReadPC();
478 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000479 } else if (extra_tag == kDataJumpExtraTag) {
480 int locatable_tag = GetTopTag();
481 if (locatable_tag == kCodeWithIdTag) {
482 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
483 AdvanceReadId();
484 return;
485 }
486 Advance(kIntSize);
487 } else if (locatable_tag != kCommentTag) {
488 ASSERT(locatable_tag == kNonstatementPositionTag ||
489 locatable_tag == kStatementPositionTag);
490 if (mode_mask_ & RelocInfo::kPositionMask) {
491 AdvanceReadPosition();
492 if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
493 } else {
494 Advance(kIntSize);
495 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496 } else {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000497 ASSERT(locatable_tag == kCommentTag);
498 if (SetMode(RelocInfo::COMMENT)) {
499 AdvanceReadData();
500 return;
501 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000502 Advance(kIntptrSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503 }
504 } else {
505 AdvanceReadPC();
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000506 int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM;
507 if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508 }
509 }
510 }
511 done_ = true;
512}
513
514
515RelocIterator::RelocIterator(Code* code, int mode_mask) {
516 rinfo_.pc_ = code->instruction_start();
517 rinfo_.data_ = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000518 // Relocation info is read backwards.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519 pos_ = code->relocation_start() + code->relocation_size();
520 end_ = code->relocation_start();
521 done_ = false;
522 mode_mask_ = mode_mask;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000523 last_id_ = 0;
524 last_position_ = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 if (mode_mask_ == 0) pos_ = end_;
526 next();
527}
528
529
530RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
531 rinfo_.pc_ = desc.buffer;
532 rinfo_.data_ = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533 // Relocation info is read backwards.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534 pos_ = desc.buffer + desc.buffer_size;
535 end_ = pos_ - desc.reloc_size;
536 done_ = false;
537 mode_mask_ = mode_mask;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000538 last_id_ = 0;
539 last_position_ = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540 if (mode_mask_ == 0) pos_ = end_;
541 next();
542}
543
544
545// -----------------------------------------------------------------------------
546// Implementation of RelocInfo
547
548
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000549#ifdef ENABLE_DISASSEMBLER
ager@chromium.org236ad962008-09-25 09:45:57 +0000550const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551 switch (rmode) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000552 case RelocInfo::NONE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553 return "no reloc";
ager@chromium.org236ad962008-09-25 09:45:57 +0000554 case RelocInfo::EMBEDDED_OBJECT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000555 return "embedded object";
ager@chromium.org236ad962008-09-25 09:45:57 +0000556 case RelocInfo::CONSTRUCT_CALL:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557 return "code target (js construct call)";
ager@chromium.org236ad962008-09-25 09:45:57 +0000558 case RelocInfo::CODE_TARGET_CONTEXT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559 return "code target (context)";
ager@chromium.org5c838252010-02-19 08:53:10 +0000560 case RelocInfo::DEBUG_BREAK:
561#ifndef ENABLE_DEBUGGER_SUPPORT
562 UNREACHABLE();
563#endif
564 return "debug break";
ager@chromium.org236ad962008-09-25 09:45:57 +0000565 case RelocInfo::CODE_TARGET:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566 return "code target";
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000567 case RelocInfo::CODE_TARGET_WITH_ID:
568 return "code target with id";
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000569 case RelocInfo::GLOBAL_PROPERTY_CELL:
570 return "global property cell";
ager@chromium.org236ad962008-09-25 09:45:57 +0000571 case RelocInfo::RUNTIME_ENTRY:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572 return "runtime entry";
ager@chromium.org236ad962008-09-25 09:45:57 +0000573 case RelocInfo::JS_RETURN:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574 return "js return";
ager@chromium.org236ad962008-09-25 09:45:57 +0000575 case RelocInfo::COMMENT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576 return "comment";
ager@chromium.org236ad962008-09-25 09:45:57 +0000577 case RelocInfo::POSITION:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000578 return "position";
ager@chromium.org236ad962008-09-25 09:45:57 +0000579 case RelocInfo::STATEMENT_POSITION:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 return "statement position";
ager@chromium.org236ad962008-09-25 09:45:57 +0000581 case RelocInfo::EXTERNAL_REFERENCE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000582 return "external reference";
ager@chromium.org236ad962008-09-25 09:45:57 +0000583 case RelocInfo::INTERNAL_REFERENCE:
584 return "internal reference";
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000585 case RelocInfo::DEBUG_BREAK_SLOT:
586#ifndef ENABLE_DEBUGGER_SUPPORT
587 UNREACHABLE();
588#endif
589 return "debug break slot";
ager@chromium.org236ad962008-09-25 09:45:57 +0000590 case RelocInfo::NUMBER_OF_MODES:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000591 UNREACHABLE();
ager@chromium.org236ad962008-09-25 09:45:57 +0000592 return "number_of_modes";
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000593 }
594 return "unknown relocation type";
595}
596
597
whesse@chromium.org023421e2010-12-21 12:19:12 +0000598void RelocInfo::Print(FILE* out) {
599 PrintF(out, "%p %s", pc_, RelocModeName(rmode_));
ager@chromium.org236ad962008-09-25 09:45:57 +0000600 if (IsComment(rmode_)) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000601 PrintF(out, " (%s)", reinterpret_cast<char*>(data_));
ager@chromium.org236ad962008-09-25 09:45:57 +0000602 } else if (rmode_ == EMBEDDED_OBJECT) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000603 PrintF(out, " (");
604 target_object()->ShortPrint(out);
605 PrintF(out, ")");
ager@chromium.org236ad962008-09-25 09:45:57 +0000606 } else if (rmode_ == EXTERNAL_REFERENCE) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607 ExternalReferenceEncoder ref_encoder;
whesse@chromium.org023421e2010-12-21 12:19:12 +0000608 PrintF(out, " (%s) (%p)",
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609 ref_encoder.NameOfAddress(*target_reference_address()),
610 *target_reference_address());
ager@chromium.org236ad962008-09-25 09:45:57 +0000611 } else if (IsCodeTarget(rmode_)) {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000612 Code* code = Code::GetCodeFromTargetAddress(target_address());
whesse@chromium.org023421e2010-12-21 12:19:12 +0000613 PrintF(out, " (%s) (%p)", Code::Kind2String(code->kind()),
614 target_address());
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000615 if (rmode_ == CODE_TARGET_WITH_ID) {
616 PrintF(" (id=%d)", static_cast<int>(data_));
617 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000618 } else if (IsPosition(rmode_)) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000619 PrintF(out, " (%" V8_PTR_PREFIX "d)", data());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000620 } else if (rmode_ == RelocInfo::RUNTIME_ENTRY &&
621 Isolate::Current()->deoptimizer_data() != NULL) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000622 // Depotimization bailouts are stored as runtime entries.
623 int id = Deoptimizer::GetDeoptimizationId(
624 target_address(), Deoptimizer::EAGER);
625 if (id != Deoptimizer::kNotDeoptimizationEntry) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000626 PrintF(out, " (deoptimization bailout %d)", id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000627 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000628 }
629
whesse@chromium.org023421e2010-12-21 12:19:12 +0000630 PrintF(out, "\n");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631}
mads.s.ager31e71382008-08-13 09:32:07 +0000632#endif // ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000633
634
mads.s.ager31e71382008-08-13 09:32:07 +0000635#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636void RelocInfo::Verify() {
637 switch (rmode_) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000638 case EMBEDDED_OBJECT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000639 Object::VerifyPointer(target_object());
640 break;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000641 case GLOBAL_PROPERTY_CELL:
642 Object::VerifyPointer(target_cell());
643 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000644 case DEBUG_BREAK:
645#ifndef ENABLE_DEBUGGER_SUPPORT
646 UNREACHABLE();
647 break;
648#endif
ager@chromium.org236ad962008-09-25 09:45:57 +0000649 case CONSTRUCT_CALL:
650 case CODE_TARGET_CONTEXT:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000651 case CODE_TARGET_WITH_ID:
ager@chromium.org236ad962008-09-25 09:45:57 +0000652 case CODE_TARGET: {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000653 // convert inline target address to code object
654 Address addr = target_address();
655 ASSERT(addr != NULL);
656 // Check that we can find the right code object.
ager@chromium.org4af710e2009-09-15 12:20:11 +0000657 Code* code = Code::GetCodeFromTargetAddress(addr);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000658 Object* found = HEAP->FindCodeObject(addr);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000659 ASSERT(found->IsCode());
660 ASSERT(code->address() == HeapObject::cast(found)->address());
661 break;
662 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000663 case RUNTIME_ENTRY:
664 case JS_RETURN:
665 case COMMENT:
666 case POSITION:
667 case STATEMENT_POSITION:
668 case EXTERNAL_REFERENCE:
669 case INTERNAL_REFERENCE:
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000670 case DEBUG_BREAK_SLOT:
ager@chromium.org236ad962008-09-25 09:45:57 +0000671 case NONE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000672 break;
ager@chromium.org236ad962008-09-25 09:45:57 +0000673 case NUMBER_OF_MODES:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 UNREACHABLE();
675 break;
676 }
677}
678#endif // DEBUG
679
680
681// -----------------------------------------------------------------------------
682// Implementation of ExternalReference
683
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000684ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
685 : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000686
687
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000688ExternalReference::ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000689 ApiFunction* fun,
690 Type type = ExternalReference::BUILTIN_CALL,
691 Isolate* isolate = NULL)
692 : address_(Redirect(isolate, fun->address(), type)) {}
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000693
694
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000695ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
696 : address_(isolate->builtins()->builtin_address(name)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000697
698
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000699ExternalReference::ExternalReference(Runtime::FunctionId id,
700 Isolate* isolate)
701 : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702
703
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000704ExternalReference::ExternalReference(const Runtime::Function* f,
705 Isolate* isolate)
706 : address_(Redirect(isolate, f->entry)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707
708
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000709ExternalReference ExternalReference::isolate_address() {
710 return ExternalReference(Isolate::Current());
711}
712
713
714ExternalReference::ExternalReference(const IC_Utility& ic_utility,
715 Isolate* isolate)
716 : address_(Redirect(isolate, ic_utility.address())) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000718#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000719ExternalReference::ExternalReference(const Debug_Address& debug_address,
720 Isolate* isolate)
721 : address_(debug_address.address(isolate)) {}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000722#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000723
724ExternalReference::ExternalReference(StatsCounter* counter)
725 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
726
727
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000728ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
729 : address_(isolate->get_address_from_id(id)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000730
731
732ExternalReference::ExternalReference(const SCTableReference& table_ref)
733 : address_(table_ref.address()) {}
734
735
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000736ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
737 return ExternalReference(Redirect(isolate,
738 FUNCTION_ADDR(Runtime::PerformGC)));
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000739}
740
741
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000742ExternalReference ExternalReference::fill_heap_number_with_random_function(
743 Isolate* isolate) {
744 return ExternalReference(Redirect(
745 isolate,
746 FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
ager@chromium.org357bf652010-04-12 11:30:10 +0000747}
748
749
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000750ExternalReference ExternalReference::delete_handle_scope_extensions(
751 Isolate* isolate) {
752 return ExternalReference(Redirect(
753 isolate,
754 FUNCTION_ADDR(HandleScope::DeleteExtensions)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000755}
756
757
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000758ExternalReference ExternalReference::random_uint32_function(
759 Isolate* isolate) {
760 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000761}
762
763
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000764ExternalReference ExternalReference::transcendental_cache_array_address(
765 Isolate* isolate) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000766 return ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000767 isolate->transcendental_cache()->cache_array_address());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000768}
769
770
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000771ExternalReference ExternalReference::new_deoptimizer_function(
772 Isolate* isolate) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000773 return ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000774 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000775}
776
777
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000778ExternalReference ExternalReference::compute_output_frames_function(
779 Isolate* isolate) {
780 return ExternalReference(
781 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000782}
783
784
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000785ExternalReference ExternalReference::global_contexts_list(Isolate* isolate) {
786 return ExternalReference(isolate->heap()->global_contexts_list_address());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000787}
788
789
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000790ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
791 return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000792}
793
794
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000795ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
796 Isolate* isolate) {
797 return ExternalReference(
798 isolate->keyed_lookup_cache()->field_offsets_address());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799}
800
801
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000802ExternalReference ExternalReference::the_hole_value_location(Isolate* isolate) {
803 return ExternalReference(isolate->factory()->the_hole_value().location());
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000804}
805
806
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000807ExternalReference ExternalReference::arguments_marker_location(
808 Isolate* isolate) {
809 return ExternalReference(isolate->factory()->arguments_marker().location());
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000810}
811
812
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000813ExternalReference ExternalReference::roots_address(Isolate* isolate) {
814 return ExternalReference(isolate->heap()->roots_address());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815}
816
817
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000818ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
819 return ExternalReference(isolate->stack_guard()->address_of_jslimit());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000820}
821
822
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000823ExternalReference ExternalReference::address_of_real_stack_limit(
824 Isolate* isolate) {
825 return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
ager@chromium.org32912102009-01-16 10:38:43 +0000826}
827
828
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000829ExternalReference ExternalReference::address_of_regexp_stack_limit(
830 Isolate* isolate) {
831 return ExternalReference(isolate->regexp_stack()->limit_address());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832}
833
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000834
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000835ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
836 return ExternalReference(isolate->heap()->NewSpaceStart());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000837}
838
839
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000840ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
841 Address mask = reinterpret_cast<Address>(isolate->heap()->NewSpaceMask());
842 return ExternalReference(mask);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843}
844
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000845
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000846ExternalReference ExternalReference::new_space_allocation_top_address(
847 Isolate* isolate) {
848 return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000849}
850
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000851
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000852ExternalReference ExternalReference::heap_always_allocate_scope_depth(
853 Isolate* isolate) {
854 Heap* heap = isolate->heap();
855 return ExternalReference(heap->always_allocate_scope_depth_address());
856}
857
858
859ExternalReference ExternalReference::new_space_allocation_limit_address(
860 Isolate* isolate) {
861 return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862}
863
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000864
lrn@chromium.org303ada72010-10-27 09:33:13 +0000865ExternalReference ExternalReference::handle_scope_level_address() {
866 return ExternalReference(HandleScope::current_level_address());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000867}
868
869
870ExternalReference ExternalReference::handle_scope_next_address() {
871 return ExternalReference(HandleScope::current_next_address());
872}
873
874
875ExternalReference ExternalReference::handle_scope_limit_address() {
876 return ExternalReference(HandleScope::current_limit_address());
877}
878
879
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000880ExternalReference ExternalReference::scheduled_exception_address(
881 Isolate* isolate) {
882 return ExternalReference(isolate->scheduled_exception_address());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000883}
884
885
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000886ExternalReference ExternalReference::address_of_min_int() {
887 return ExternalReference(reinterpret_cast<void*>(
888 const_cast<double*>(&DoubleConstant::min_int)));
889}
890
891
892ExternalReference ExternalReference::address_of_one_half() {
893 return ExternalReference(reinterpret_cast<void*>(
894 const_cast<double*>(&DoubleConstant::one_half)));
895}
896
897
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000898ExternalReference ExternalReference::address_of_minus_zero() {
899 return ExternalReference(reinterpret_cast<void*>(
900 const_cast<double*>(&DoubleConstant::minus_zero)));
901}
902
903
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000904ExternalReference ExternalReference::address_of_negative_infinity() {
905 return ExternalReference(reinterpret_cast<void*>(
906 const_cast<double*>(&DoubleConstant::negative_infinity)));
907}
908
909
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000910ExternalReference ExternalReference::address_of_nan() {
911 return ExternalReference(reinterpret_cast<void*>(
912 const_cast<double*>(&DoubleConstant::nan)));
913}
914
915
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000916#ifndef V8_INTERPRETED_REGEXP
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000917
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000918ExternalReference ExternalReference::re_check_stack_guard_state(
919 Isolate* isolate) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000920 Address function;
921#ifdef V8_TARGET_ARCH_X64
922 function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
923#elif V8_TARGET_ARCH_IA32
924 function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
925#elif V8_TARGET_ARCH_ARM
926 function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000927#elif V8_TARGET_ARCH_MIPS
928 function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000929#else
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000930 UNREACHABLE();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000931#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000932 return ExternalReference(Redirect(isolate, function));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000933}
934
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000935ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000936 return ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000937 Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000938}
939
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000940ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
941 Isolate* isolate) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000942 return ExternalReference(Redirect(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000943 isolate,
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000944 FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
945}
946
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000947ExternalReference ExternalReference::re_word_character_map() {
948 return ExternalReference(
949 NativeRegExpMacroAssembler::word_character_map_address());
950}
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000951
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000952ExternalReference ExternalReference::address_of_static_offsets_vector(
953 Isolate* isolate) {
954 return ExternalReference(
955 OffsetsVector::static_offsets_vector_address(isolate));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000956}
957
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000958ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
959 Isolate* isolate) {
960 return ExternalReference(
961 isolate->regexp_stack()->memory_address());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000962}
963
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000964ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
965 Isolate* isolate) {
966 return ExternalReference(isolate->regexp_stack()->memory_size_address());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000967}
968
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000969#endif // V8_INTERPRETED_REGEXP
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000970
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000971
972static double add_two_doubles(double x, double y) {
973 return x + y;
974}
975
976
977static double sub_two_doubles(double x, double y) {
978 return x - y;
979}
980
981
982static double mul_two_doubles(double x, double y) {
983 return x * y;
984}
985
986
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000987static double div_two_doubles(double x, double y) {
988 return x / y;
989}
990
991
992static double mod_two_doubles(double x, double y) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000993 return modulo(x, y);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000994}
995
996
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000997static double math_sin_double(double x) {
998 return sin(x);
999}
1000
1001
1002static double math_cos_double(double x) {
1003 return cos(x);
1004}
1005
1006
1007static double math_log_double(double x) {
1008 return log(x);
1009}
1010
1011
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001012ExternalReference ExternalReference::math_sin_double_function(
1013 Isolate* isolate) {
1014 return ExternalReference(Redirect(isolate,
1015 FUNCTION_ADDR(math_sin_double),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001016 BUILTIN_FP_CALL));
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001017}
1018
1019
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001020ExternalReference ExternalReference::math_cos_double_function(
1021 Isolate* isolate) {
1022 return ExternalReference(Redirect(isolate,
1023 FUNCTION_ADDR(math_cos_double),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001024 BUILTIN_FP_CALL));
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001025}
1026
1027
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001028ExternalReference ExternalReference::math_log_double_function(
1029 Isolate* isolate) {
1030 return ExternalReference(Redirect(isolate,
1031 FUNCTION_ADDR(math_log_double),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001032 BUILTIN_FP_CALL));
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001033}
1034
1035
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001036// Helper function to compute x^y, where y is known to be an
1037// integer. Uses binary decomposition to limit the number of
1038// multiplications; see the discussion in "Hacker's Delight" by Henry
1039// S. Warren, Jr., figure 11-6, page 213.
1040double power_double_int(double x, int y) {
1041 double m = (y < 0) ? 1 / x : x;
1042 unsigned n = (y < 0) ? -y : y;
1043 double p = 1;
1044 while (n != 0) {
1045 if ((n & 1) != 0) p *= m;
1046 m *= m;
1047 if ((n & 2) != 0) p *= m;
1048 m *= m;
1049 n >>= 2;
1050 }
1051 return p;
1052}
1053
1054
1055double power_double_double(double x, double y) {
1056 int y_int = static_cast<int>(y);
1057 if (y == y_int) {
1058 return power_double_int(x, y_int); // Returns 1.0 for exponent 0.
1059 }
1060 if (!isinf(x)) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001061 if (y == 0.5) return sqrt(x + 0.0); // -0 must be converted to +0.
1062 if (y == -0.5) return 1.0 / sqrt(x + 0.0);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001063 }
1064 if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
1065 return OS::nan_value();
1066 }
1067 return pow(x, y);
1068}
1069
1070
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001071ExternalReference ExternalReference::power_double_double_function(
1072 Isolate* isolate) {
1073 return ExternalReference(Redirect(isolate,
1074 FUNCTION_ADDR(power_double_double),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001075 BUILTIN_FP_FP_CALL));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001076}
1077
1078
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001079ExternalReference ExternalReference::power_double_int_function(
1080 Isolate* isolate) {
1081 return ExternalReference(Redirect(isolate,
1082 FUNCTION_ADDR(power_double_int),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001083 BUILTIN_FP_INT_CALL));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001084}
1085
1086
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001087static int native_compare_doubles(double y, double x) {
1088 if (x == y) return EQUAL;
1089 return x < y ? LESS : GREATER;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001090}
1091
1092
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001093ExternalReference ExternalReference::double_fp_operation(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001094 Token::Value operation, Isolate* isolate) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001095 typedef double BinaryFPOperation(double x, double y);
1096 BinaryFPOperation* function = NULL;
1097 switch (operation) {
1098 case Token::ADD:
1099 function = &add_two_doubles;
1100 break;
1101 case Token::SUB:
1102 function = &sub_two_doubles;
1103 break;
1104 case Token::MUL:
1105 function = &mul_two_doubles;
1106 break;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001107 case Token::DIV:
1108 function = &div_two_doubles;
1109 break;
1110 case Token::MOD:
1111 function = &mod_two_doubles;
1112 break;
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001113 default:
1114 UNREACHABLE();
1115 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001116 return ExternalReference(Redirect(isolate,
1117 FUNCTION_ADDR(function),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001118 BUILTIN_FP_FP_CALL));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001119}
1120
1121
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001122ExternalReference ExternalReference::compare_doubles(Isolate* isolate) {
1123 return ExternalReference(Redirect(isolate,
1124 FUNCTION_ADDR(native_compare_doubles),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001125 BUILTIN_COMPARE_CALL));
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001126}
1127
1128
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001129#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001130ExternalReference ExternalReference::debug_break(Isolate* isolate) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001131 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001132}
1133
1134
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001135ExternalReference ExternalReference::debug_step_in_fp_address(
1136 Isolate* isolate) {
1137 return ExternalReference(isolate->debug()->step_in_fp_addr());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001138}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001139#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001141
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001142void PositionsRecorder::RecordPosition(int pos) {
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001143 ASSERT(pos != RelocInfo::kNoPosition);
1144 ASSERT(pos >= 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001145 state_.current_position = pos;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001146#ifdef ENABLE_GDB_JIT_INTERFACE
1147 if (gdbjit_lineinfo_ != NULL) {
1148 gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
1149 }
1150#endif
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001151}
1152
1153
1154void PositionsRecorder::RecordStatementPosition(int pos) {
1155 ASSERT(pos != RelocInfo::kNoPosition);
1156 ASSERT(pos >= 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001157 state_.current_statement_position = pos;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001158#ifdef ENABLE_GDB_JIT_INTERFACE
1159 if (gdbjit_lineinfo_ != NULL) {
1160 gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
1161 }
1162#endif
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001163}
1164
1165
1166bool PositionsRecorder::WriteRecordedPositions() {
1167 bool written = false;
1168
1169 // Write the statement position if it is different from what was written last
1170 // time.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001171 if (state_.current_statement_position != state_.written_statement_position) {
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001172 EnsureSpace ensure_space(assembler_);
1173 assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001174 state_.current_statement_position);
1175 state_.written_statement_position = state_.current_statement_position;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001176 written = true;
1177 }
1178
1179 // Write the position if it is different from what was written last time and
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001180 // also different from the written statement position.
1181 if (state_.current_position != state_.written_position &&
1182 state_.current_position != state_.written_statement_position) {
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001183 EnsureSpace ensure_space(assembler_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001184 assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
1185 state_.written_position = state_.current_position;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001186 written = true;
1187 }
1188
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001189 // Return whether something was written.
1190 return written;
1191}
1192
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001193} } // namespace v8::internal