blob: 77c7b68c4f799bd1417e7dd5ad838f4a6090e2b1 [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.
danno@chromium.org160a7b02011-04-18 15:51:38 +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// -----------------------------------------------------------------------------
77// Implementation of Label
78
79int Label::pos() const {
80 if (pos_ < 0) return -pos_ - 1;
81 if (pos_ > 0) return pos_ - 1;
82 UNREACHABLE();
83 return 0;
84}
85
86
87// -----------------------------------------------------------------------------
88// Implementation of RelocInfoWriter and RelocIterator
89//
danno@chromium.org160a7b02011-04-18 15:51:38 +000090// Relocation information is written backwards in memory, from high addresses
91// towards low addresses, byte by byte. Therefore, in the encodings listed
92// below, the first byte listed it at the highest address, and successive
93// bytes in the record are at progressively lower addresses.
94//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095// Encoding
96//
97// The most common modes are given single-byte encodings. Also, it is
98// easy to identify the type of reloc info and skip unwanted modes in
99// an iteration.
100//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000101// The encoding relies on the fact that there are fewer than 14
102// different non-compactly encoded relocation modes.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000104// The first byte of a relocation record has a tag in its low 2 bits:
105// Here are the record schemes, depending on the low tag and optional higher
106// tags.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000108// Low tag:
109// 00: embedded_object: [6-bit pc delta] 00
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000110//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000111// 01: code_target: [6-bit pc delta] 01
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000113// 10: short_data_record: [6-bit pc delta] 10 followed by
114// [6-bit data delta] [2-bit data type tag]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000116// 11: long_record [2-bit high tag][4 bit middle_tag] 11
117// followed by variable data depending on type.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000119// 2-bit data type tags, used in short_data_record and data_jump long_record:
120// code_target_with_id: 00
121// position: 01
122// statement_position: 10
123// comment: 11 (not used in short_data_record)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000125// Long record format:
126// 4-bit middle_tag:
127// 0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2
128// (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM,
129// and is between 0000 and 1100)
130// The format is:
131// 00 [4 bit middle_tag] 11 followed by
132// 00 [6 bit pc delta]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000133//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000134// 1101: not used (would allow one more relocation mode to be added)
135// 1110: long_data_record
136// The format is: [2-bit data_type_tag] 1110 11
137// signed intptr_t, lowest byte written first
138// (except data_type code_target_with_id, which
139// is followed by a signed int, not intptr_t.)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140//
danno@chromium.org160a7b02011-04-18 15:51:38 +0000141// 1111: long_pc_jump
142// The format is:
143// pc-jump: 00 1111 11,
144// 00 [6 bits pc delta]
145// or
146// pc-jump (variable length):
147// 01 1111 11,
148// [7 bits data] 0
149// ...
150// [7 bits data] 1
151// (Bits 6..31 of pc delta, with leading zeroes
152// dropped, and last non-zero chunk tagged with 1.)
153
154
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155const int kMaxRelocModes = 14;
156
157const int kTagBits = 2;
158const int kTagMask = (1 << kTagBits) - 1;
159const int kExtraTagBits = 4;
danno@chromium.org160a7b02011-04-18 15:51:38 +0000160const int kLocatableTypeTagBits = 2;
161const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162
163const int kEmbeddedObjectTag = 0;
164const int kCodeTargetTag = 1;
danno@chromium.org160a7b02011-04-18 15:51:38 +0000165const int kLocatableTag = 2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166const int kDefaultTag = 3;
167
danno@chromium.org160a7b02011-04-18 15:51:38 +0000168const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169
170const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
171const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000172const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173
174const int kVariableLengthPCJumpTopTag = 1;
175const int kChunkBits = 7;
176const int kChunkMask = (1 << kChunkBits) - 1;
177const int kLastChunkTagBits = 1;
178const int kLastChunkTagMask = 1;
179const int kLastChunkTag = 1;
180
181
danno@chromium.org160a7b02011-04-18 15:51:38 +0000182const int kDataJumpExtraTag = kPCJumpExtraTag - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183
danno@chromium.org160a7b02011-04-18 15:51:38 +0000184const int kCodeWithIdTag = 0;
185const int kNonstatementPositionTag = 1;
186const int kStatementPositionTag = 2;
187const int kCommentTag = 3;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
189
190uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
191 // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
192 // Otherwise write a variable length PC jump for the bits that do
193 // not fit in the kSmallPCDeltaBits bits.
194 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
danno@chromium.org160a7b02011-04-18 15:51:38 +0000195 WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
197 ASSERT(pc_jump > 0);
198 // Write kChunkBits size chunks of the pc_jump.
199 for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
200 byte b = pc_jump & kChunkMask;
201 *--pos_ = b << kLastChunkTagBits;
202 }
203 // Tag the last chunk so it can be identified.
204 *pos_ = *pos_ | kLastChunkTag;
205 // Return the remaining kSmallPCDeltaBits of the pc_delta.
206 return pc_delta & kSmallPCDeltaMask;
207}
208
209
210void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
211 // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
212 pc_delta = WriteVariableLengthPCJump(pc_delta);
213 *--pos_ = pc_delta << kTagBits | tag;
214}
215
216
ager@chromium.orge2902be2009-06-08 12:21:35 +0000217void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
danno@chromium.org160a7b02011-04-18 15:51:38 +0000218 *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219}
220
221
222void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000223 *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
224 extra_tag << kTagBits |
225 kDefaultTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226}
227
228
229void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
230 // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
231 pc_delta = WriteVariableLengthPCJump(pc_delta);
232 WriteExtraTag(extra_tag, 0);
233 *--pos_ = pc_delta;
234}
235
236
danno@chromium.org160a7b02011-04-18 15:51:38 +0000237void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
238 WriteExtraTag(kDataJumpExtraTag, top_tag);
239 for (int i = 0; i < kIntSize; i++) {
240 *--pos_ = static_cast<byte>(data_delta);
241 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
242 data_delta = data_delta >> kBitsPerByte;
243 }
244}
245
ager@chromium.orge2902be2009-06-08 12:21:35 +0000246void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
danno@chromium.org160a7b02011-04-18 15:51:38 +0000247 WriteExtraTag(kDataJumpExtraTag, top_tag);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000248 for (int i = 0; i < kIntptrSize; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000249 *--pos_ = static_cast<byte>(data_delta);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000250 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
ager@chromium.orge2902be2009-06-08 12:21:35 +0000251 data_delta = data_delta >> kBitsPerByte;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000252 }
253}
254
255
256void RelocInfoWriter::Write(const RelocInfo* rinfo) {
257#ifdef DEBUG
258 byte* begin_pos = pos_;
259#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000260 ASSERT(rinfo->pc() - last_pc_ >= 0);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000261 ASSERT(RelocInfo::NUMBER_OF_MODES - RelocInfo::LAST_COMPACT_ENUM <=
262 kMaxRelocModes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263 // Use unsigned delta-encoding for pc.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000264 uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
ager@chromium.org236ad962008-09-25 09:45:57 +0000265 RelocInfo::Mode rmode = rinfo->rmode();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000266
267 // The two most common modes are given small tags, and usually fit in a byte.
ager@chromium.org236ad962008-09-25 09:45:57 +0000268 if (rmode == RelocInfo::EMBEDDED_OBJECT) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269 WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
ager@chromium.org236ad962008-09-25 09:45:57 +0000270 } else if (rmode == RelocInfo::CODE_TARGET) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271 WriteTaggedPC(pc_delta, kCodeTargetTag);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000272 ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000273 } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
274 // Use signed delta-encoding for id.
275 ASSERT(static_cast<int>(rinfo->data()) == rinfo->data());
276 int id_delta = static_cast<int>(rinfo->data()) - last_id_;
277 // Check if delta is small enough to fit in a tagged byte.
278 if (is_intn(id_delta, kSmallDataBits)) {
279 WriteTaggedPC(pc_delta, kLocatableTag);
280 WriteTaggedData(id_delta, kCodeWithIdTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281 } else {
282 // Otherwise, use costly encoding.
danno@chromium.org160a7b02011-04-18 15:51:38 +0000283 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
284 WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000285 }
danno@chromium.org160a7b02011-04-18 15:51:38 +0000286 last_id_ = static_cast<int>(rinfo->data());
287 } else if (RelocInfo::IsPosition(rmode)) {
288 // Use signed delta-encoding for position.
289 ASSERT(static_cast<int>(rinfo->data()) == rinfo->data());
290 int pos_delta = static_cast<int>(rinfo->data()) - last_position_;
291 int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
292 : kStatementPositionTag;
293 // Check if delta is small enough to fit in a tagged byte.
294 if (is_intn(pos_delta, kSmallDataBits)) {
295 WriteTaggedPC(pc_delta, kLocatableTag);
296 WriteTaggedData(pos_delta, pos_type_tag);
297 } else {
298 // Otherwise, use costly encoding.
299 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
300 WriteExtraTaggedIntData(pos_delta, pos_type_tag);
301 }
302 last_position_ = static_cast<int>(rinfo->data());
ager@chromium.org236ad962008-09-25 09:45:57 +0000303 } else if (RelocInfo::IsComment(rmode)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000304 // Comments are normally not generated, so we use the costly encoding.
danno@chromium.org160a7b02011-04-18 15:51:38 +0000305 WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
306 WriteExtraTaggedData(rinfo->data(), kCommentTag);
ricow@chromium.org22334512011-02-25 07:28:50 +0000307 ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 } else {
danno@chromium.org160a7b02011-04-18 15:51:38 +0000309 ASSERT(rmode > RelocInfo::LAST_COMPACT_ENUM);
310 int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000311 // For all other modes we simply use the mode as the extra tag.
312 // None of these modes need a data component.
danno@chromium.org160a7b02011-04-18 15:51:38 +0000313 ASSERT(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag);
314 WriteExtraTaggedPC(pc_delta, saved_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315 }
316 last_pc_ = rinfo->pc();
317#ifdef DEBUG
318 ASSERT(begin_pos - pos_ <= kMaxSize);
319#endif
320}
321
322
323inline int RelocIterator::AdvanceGetTag() {
324 return *--pos_ & kTagMask;
325}
326
327
328inline int RelocIterator::GetExtraTag() {
329 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
330}
331
332
333inline int RelocIterator::GetTopTag() {
334 return *pos_ >> (kTagBits + kExtraTagBits);
335}
336
337
338inline void RelocIterator::ReadTaggedPC() {
339 rinfo_.pc_ += *pos_ >> kTagBits;
340}
341
342
343inline void RelocIterator::AdvanceReadPC() {
344 rinfo_.pc_ += *--pos_;
345}
346
347
danno@chromium.org160a7b02011-04-18 15:51:38 +0000348void RelocIterator::AdvanceReadId() {
349 int x = 0;
350 for (int i = 0; i < kIntSize; i++) {
351 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
352 }
353 last_id_ += x;
354 rinfo_.data_ = last_id_;
355}
356
357
358void RelocIterator::AdvanceReadPosition() {
359 int x = 0;
360 for (int i = 0; i < kIntSize; i++) {
361 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
362 }
363 last_position_ += x;
364 rinfo_.data_ = last_position_;
365}
366
367
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368void RelocIterator::AdvanceReadData() {
ager@chromium.orge2902be2009-06-08 12:21:35 +0000369 intptr_t x = 0;
370 for (int i = 0; i < kIntptrSize; i++) {
371 x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000372 }
danno@chromium.org160a7b02011-04-18 15:51:38 +0000373 rinfo_.data_ = x;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000374}
375
376
377void RelocIterator::AdvanceReadVariableLengthPCJump() {
378 // Read the 32-kSmallPCDeltaBits most significant bits of the
379 // pc jump in kChunkBits bit chunks and shift them into place.
380 // Stop when the last chunk is encountered.
381 uint32_t pc_jump = 0;
382 for (int i = 0; i < kIntSize; i++) {
383 byte pc_jump_part = *--pos_;
384 pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
385 if ((pc_jump_part & kLastChunkTagMask) == 1) break;
386 }
387 // The least significant kSmallPCDeltaBits bits will be added
388 // later.
389 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
390}
391
392
danno@chromium.org160a7b02011-04-18 15:51:38 +0000393inline int RelocIterator::GetLocatableTypeTag() {
394 return *pos_ & ((1 << kLocatableTypeTagBits) - 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000395}
396
397
danno@chromium.org160a7b02011-04-18 15:51:38 +0000398inline void RelocIterator::ReadTaggedId() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399 int8_t signed_b = *pos_;
ager@chromium.orge2902be2009-06-08 12:21:35 +0000400 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
danno@chromium.org160a7b02011-04-18 15:51:38 +0000401 last_id_ += signed_b >> kLocatableTypeTagBits;
402 rinfo_.data_ = last_id_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000403}
404
405
danno@chromium.org160a7b02011-04-18 15:51:38 +0000406inline void RelocIterator::ReadTaggedPosition() {
407 int8_t signed_b = *pos_;
408 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
409 last_position_ += signed_b >> kLocatableTypeTagBits;
410 rinfo_.data_ = last_position_;
411}
412
413
414static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
415 ASSERT(tag == kNonstatementPositionTag ||
416 tag == kStatementPositionTag);
417 return (tag == kNonstatementPositionTag) ?
418 RelocInfo::POSITION :
419 RelocInfo::STATEMENT_POSITION;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420}
421
422
423void RelocIterator::next() {
424 ASSERT(!done());
425 // Basically, do the opposite of RelocInfoWriter::Write.
426 // Reading of data is as far as possible avoided for unwanted modes,
427 // but we must always update the pc.
428 //
429 // We exit this loop by returning when we find a mode we want.
430 while (pos_ > end_) {
431 int tag = AdvanceGetTag();
432 if (tag == kEmbeddedObjectTag) {
433 ReadTaggedPC();
ager@chromium.org236ad962008-09-25 09:45:57 +0000434 if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000435 } else if (tag == kCodeTargetTag) {
436 ReadTaggedPC();
ager@chromium.org236ad962008-09-25 09:45:57 +0000437 if (SetMode(RelocInfo::CODE_TARGET)) return;
danno@chromium.org160a7b02011-04-18 15:51:38 +0000438 } else if (tag == kLocatableTag) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000439 ReadTaggedPC();
440 Advance();
danno@chromium.org160a7b02011-04-18 15:51:38 +0000441 int locatable_tag = GetLocatableTypeTag();
442 if (locatable_tag == kCodeWithIdTag) {
443 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
444 ReadTaggedId();
445 return;
446 }
447 } else {
448 // Compact encoding is never used for comments,
449 // so it must be a position.
450 ASSERT(locatable_tag == kNonstatementPositionTag ||
451 locatable_tag == kStatementPositionTag);
452 if (mode_mask_ & RelocInfo::kPositionMask) {
453 ReadTaggedPosition();
454 if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
455 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456 }
457 } else {
458 ASSERT(tag == kDefaultTag);
459 int extra_tag = GetExtraTag();
danno@chromium.org160a7b02011-04-18 15:51:38 +0000460 if (extra_tag == kPCJumpExtraTag) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461 int top_tag = GetTopTag();
462 if (top_tag == kVariableLengthPCJumpTopTag) {
463 AdvanceReadVariableLengthPCJump();
464 } else {
465 AdvanceReadPC();
466 }
danno@chromium.org160a7b02011-04-18 15:51:38 +0000467 } else if (extra_tag == kDataJumpExtraTag) {
468 int locatable_tag = GetTopTag();
469 if (locatable_tag == kCodeWithIdTag) {
470 if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
471 AdvanceReadId();
472 return;
473 }
474 Advance(kIntSize);
475 } else if (locatable_tag != kCommentTag) {
476 ASSERT(locatable_tag == kNonstatementPositionTag ||
477 locatable_tag == kStatementPositionTag);
478 if (mode_mask_ & RelocInfo::kPositionMask) {
479 AdvanceReadPosition();
480 if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
481 } else {
482 Advance(kIntSize);
483 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484 } else {
danno@chromium.org160a7b02011-04-18 15:51:38 +0000485 ASSERT(locatable_tag == kCommentTag);
486 if (SetMode(RelocInfo::COMMENT)) {
487 AdvanceReadData();
488 return;
489 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000490 Advance(kIntptrSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491 }
492 } else {
493 AdvanceReadPC();
danno@chromium.org160a7b02011-04-18 15:51:38 +0000494 int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM;
495 if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496 }
497 }
498 }
499 done_ = true;
500}
501
502
503RelocIterator::RelocIterator(Code* code, int mode_mask) {
504 rinfo_.pc_ = code->instruction_start();
505 rinfo_.data_ = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000506 // Relocation info is read backwards.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507 pos_ = code->relocation_start() + code->relocation_size();
508 end_ = code->relocation_start();
509 done_ = false;
510 mode_mask_ = mode_mask;
danno@chromium.org160a7b02011-04-18 15:51:38 +0000511 last_id_ = 0;
512 last_position_ = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513 if (mode_mask_ == 0) pos_ = end_;
514 next();
515}
516
517
518RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
519 rinfo_.pc_ = desc.buffer;
520 rinfo_.data_ = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000521 // Relocation info is read backwards.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522 pos_ = desc.buffer + desc.buffer_size;
523 end_ = pos_ - desc.reloc_size;
524 done_ = false;
525 mode_mask_ = mode_mask;
danno@chromium.org160a7b02011-04-18 15:51:38 +0000526 last_id_ = 0;
527 last_position_ = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 if (mode_mask_ == 0) pos_ = end_;
529 next();
530}
531
532
533// -----------------------------------------------------------------------------
534// Implementation of RelocInfo
535
536
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000537#ifdef ENABLE_DISASSEMBLER
ager@chromium.org236ad962008-09-25 09:45:57 +0000538const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539 switch (rmode) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000540 case RelocInfo::NONE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000541 return "no reloc";
ager@chromium.org236ad962008-09-25 09:45:57 +0000542 case RelocInfo::EMBEDDED_OBJECT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543 return "embedded object";
ager@chromium.org236ad962008-09-25 09:45:57 +0000544 case RelocInfo::CONSTRUCT_CALL:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545 return "code target (js construct call)";
ager@chromium.org236ad962008-09-25 09:45:57 +0000546 case RelocInfo::CODE_TARGET_CONTEXT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000547 return "code target (context)";
ager@chromium.org5c838252010-02-19 08:53:10 +0000548 case RelocInfo::DEBUG_BREAK:
549#ifndef ENABLE_DEBUGGER_SUPPORT
550 UNREACHABLE();
551#endif
552 return "debug break";
ager@chromium.org236ad962008-09-25 09:45:57 +0000553 case RelocInfo::CODE_TARGET:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554 return "code target";
danno@chromium.org160a7b02011-04-18 15:51:38 +0000555 case RelocInfo::CODE_TARGET_WITH_ID:
556 return "code target with id";
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000557 case RelocInfo::GLOBAL_PROPERTY_CELL:
558 return "global property cell";
ager@chromium.org236ad962008-09-25 09:45:57 +0000559 case RelocInfo::RUNTIME_ENTRY:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560 return "runtime entry";
ager@chromium.org236ad962008-09-25 09:45:57 +0000561 case RelocInfo::JS_RETURN:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562 return "js return";
ager@chromium.org236ad962008-09-25 09:45:57 +0000563 case RelocInfo::COMMENT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564 return "comment";
ager@chromium.org236ad962008-09-25 09:45:57 +0000565 case RelocInfo::POSITION:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566 return "position";
ager@chromium.org236ad962008-09-25 09:45:57 +0000567 case RelocInfo::STATEMENT_POSITION:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 return "statement position";
ager@chromium.org236ad962008-09-25 09:45:57 +0000569 case RelocInfo::EXTERNAL_REFERENCE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000570 return "external reference";
ager@chromium.org236ad962008-09-25 09:45:57 +0000571 case RelocInfo::INTERNAL_REFERENCE:
572 return "internal reference";
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000573 case RelocInfo::DEBUG_BREAK_SLOT:
574#ifndef ENABLE_DEBUGGER_SUPPORT
575 UNREACHABLE();
576#endif
577 return "debug break slot";
ager@chromium.org236ad962008-09-25 09:45:57 +0000578 case RelocInfo::NUMBER_OF_MODES:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579 UNREACHABLE();
ager@chromium.org236ad962008-09-25 09:45:57 +0000580 return "number_of_modes";
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581 }
582 return "unknown relocation type";
583}
584
585
whesse@chromium.org023421e2010-12-21 12:19:12 +0000586void RelocInfo::Print(FILE* out) {
587 PrintF(out, "%p %s", pc_, RelocModeName(rmode_));
ager@chromium.org236ad962008-09-25 09:45:57 +0000588 if (IsComment(rmode_)) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000589 PrintF(out, " (%s)", reinterpret_cast<char*>(data_));
ager@chromium.org236ad962008-09-25 09:45:57 +0000590 } else if (rmode_ == EMBEDDED_OBJECT) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000591 PrintF(out, " (");
592 target_object()->ShortPrint(out);
593 PrintF(out, ")");
ager@chromium.org236ad962008-09-25 09:45:57 +0000594 } else if (rmode_ == EXTERNAL_REFERENCE) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595 ExternalReferenceEncoder ref_encoder;
whesse@chromium.org023421e2010-12-21 12:19:12 +0000596 PrintF(out, " (%s) (%p)",
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000597 ref_encoder.NameOfAddress(*target_reference_address()),
598 *target_reference_address());
ager@chromium.org236ad962008-09-25 09:45:57 +0000599 } else if (IsCodeTarget(rmode_)) {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000600 Code* code = Code::GetCodeFromTargetAddress(target_address());
whesse@chromium.org023421e2010-12-21 12:19:12 +0000601 PrintF(out, " (%s) (%p)", Code::Kind2String(code->kind()),
602 target_address());
danno@chromium.org160a7b02011-04-18 15:51:38 +0000603 if (rmode_ == CODE_TARGET_WITH_ID) {
604 PrintF(" (id=%d)", static_cast<int>(data_));
605 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000606 } else if (IsPosition(rmode_)) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000607 PrintF(out, " (%" V8_PTR_PREFIX "d)", data());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000608 } else if (rmode_ == RelocInfo::RUNTIME_ENTRY &&
609 Isolate::Current()->deoptimizer_data() != NULL) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000610 // Depotimization bailouts are stored as runtime entries.
611 int id = Deoptimizer::GetDeoptimizationId(
612 target_address(), Deoptimizer::EAGER);
613 if (id != Deoptimizer::kNotDeoptimizationEntry) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000614 PrintF(out, " (deoptimization bailout %d)", id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000615 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616 }
617
whesse@chromium.org023421e2010-12-21 12:19:12 +0000618 PrintF(out, "\n");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619}
mads.s.ager31e71382008-08-13 09:32:07 +0000620#endif // ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621
622
mads.s.ager31e71382008-08-13 09:32:07 +0000623#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000624void RelocInfo::Verify() {
625 switch (rmode_) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000626 case EMBEDDED_OBJECT:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627 Object::VerifyPointer(target_object());
628 break;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000629 case GLOBAL_PROPERTY_CELL:
630 Object::VerifyPointer(target_cell());
631 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000632 case DEBUG_BREAK:
633#ifndef ENABLE_DEBUGGER_SUPPORT
634 UNREACHABLE();
635 break;
636#endif
ager@chromium.org236ad962008-09-25 09:45:57 +0000637 case CONSTRUCT_CALL:
638 case CODE_TARGET_CONTEXT:
danno@chromium.org160a7b02011-04-18 15:51:38 +0000639 case CODE_TARGET_WITH_ID:
ager@chromium.org236ad962008-09-25 09:45:57 +0000640 case CODE_TARGET: {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000641 // convert inline target address to code object
642 Address addr = target_address();
643 ASSERT(addr != NULL);
644 // Check that we can find the right code object.
ager@chromium.org4af710e2009-09-15 12:20:11 +0000645 Code* code = Code::GetCodeFromTargetAddress(addr);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000646 Object* found = HEAP->FindCodeObject(addr);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 ASSERT(found->IsCode());
648 ASSERT(code->address() == HeapObject::cast(found)->address());
649 break;
650 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000651 case RUNTIME_ENTRY:
652 case JS_RETURN:
653 case COMMENT:
654 case POSITION:
655 case STATEMENT_POSITION:
656 case EXTERNAL_REFERENCE:
657 case INTERNAL_REFERENCE:
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000658 case DEBUG_BREAK_SLOT:
ager@chromium.org236ad962008-09-25 09:45:57 +0000659 case NONE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660 break;
ager@chromium.org236ad962008-09-25 09:45:57 +0000661 case NUMBER_OF_MODES:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662 UNREACHABLE();
663 break;
664 }
665}
666#endif // DEBUG
667
668
669// -----------------------------------------------------------------------------
670// Implementation of ExternalReference
671
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000672ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
673 : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674
675
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000676ExternalReference::ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000677 ApiFunction* fun,
678 Type type = ExternalReference::BUILTIN_CALL,
679 Isolate* isolate = NULL)
680 : address_(Redirect(isolate, fun->address(), type)) {}
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000681
682
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000683ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
684 : address_(isolate->builtins()->builtin_address(name)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685
686
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000687ExternalReference::ExternalReference(Runtime::FunctionId id,
688 Isolate* isolate)
689 : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690
691
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000692ExternalReference::ExternalReference(const Runtime::Function* f,
693 Isolate* isolate)
694 : address_(Redirect(isolate, f->entry)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695
696
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000697ExternalReference ExternalReference::isolate_address() {
698 return ExternalReference(Isolate::Current());
699}
700
701
702ExternalReference::ExternalReference(const IC_Utility& ic_utility,
703 Isolate* isolate)
704 : address_(Redirect(isolate, ic_utility.address())) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000706#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000707ExternalReference::ExternalReference(const Debug_Address& debug_address,
708 Isolate* isolate)
709 : address_(debug_address.address(isolate)) {}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000710#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711
712ExternalReference::ExternalReference(StatsCounter* counter)
713 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
714
715
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000716ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
717 : address_(isolate->get_address_from_id(id)) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718
719
720ExternalReference::ExternalReference(const SCTableReference& table_ref)
721 : address_(table_ref.address()) {}
722
723
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000724ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
725 return ExternalReference(Redirect(isolate,
726 FUNCTION_ADDR(Runtime::PerformGC)));
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000727}
728
729
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000730ExternalReference ExternalReference::fill_heap_number_with_random_function(
731 Isolate* isolate) {
732 return ExternalReference(Redirect(
733 isolate,
734 FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
ager@chromium.org357bf652010-04-12 11:30:10 +0000735}
736
737
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000738ExternalReference ExternalReference::delete_handle_scope_extensions(
739 Isolate* isolate) {
740 return ExternalReference(Redirect(
741 isolate,
742 FUNCTION_ADDR(HandleScope::DeleteExtensions)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000743}
744
745
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000746ExternalReference ExternalReference::random_uint32_function(
747 Isolate* isolate) {
748 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000749}
750
751
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000752ExternalReference ExternalReference::transcendental_cache_array_address(
753 Isolate* isolate) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000754 return ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000755 isolate->transcendental_cache()->cache_array_address());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000756}
757
758
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000759ExternalReference ExternalReference::new_deoptimizer_function(
760 Isolate* isolate) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000761 return ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000762 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000763}
764
765
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000766ExternalReference ExternalReference::compute_output_frames_function(
767 Isolate* isolate) {
768 return ExternalReference(
769 Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000770}
771
772
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000773ExternalReference ExternalReference::global_contexts_list(Isolate* isolate) {
774 return ExternalReference(isolate->heap()->global_contexts_list_address());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000775}
776
777
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000778ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
779 return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000780}
781
782
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000783ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
784 Isolate* isolate) {
785 return ExternalReference(
786 isolate->keyed_lookup_cache()->field_offsets_address());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787}
788
789
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000790ExternalReference ExternalReference::the_hole_value_location(Isolate* isolate) {
791 return ExternalReference(isolate->factory()->the_hole_value().location());
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000792}
793
794
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000795ExternalReference ExternalReference::arguments_marker_location(
796 Isolate* isolate) {
797 return ExternalReference(isolate->factory()->arguments_marker().location());
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000798}
799
800
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000801ExternalReference ExternalReference::roots_address(Isolate* isolate) {
802 return ExternalReference(isolate->heap()->roots_address());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000803}
804
805
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000806ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
807 return ExternalReference(isolate->stack_guard()->address_of_jslimit());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000808}
809
810
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000811ExternalReference ExternalReference::address_of_real_stack_limit(
812 Isolate* isolate) {
813 return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
ager@chromium.org32912102009-01-16 10:38:43 +0000814}
815
816
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000817ExternalReference ExternalReference::address_of_regexp_stack_limit(
818 Isolate* isolate) {
819 return ExternalReference(isolate->regexp_stack()->limit_address());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000820}
821
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000822
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000823ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
824 return ExternalReference(isolate->heap()->NewSpaceStart());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000825}
826
827
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000828ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
829 Address mask = reinterpret_cast<Address>(isolate->heap()->NewSpaceMask());
830 return ExternalReference(mask);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000831}
832
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000833
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000834ExternalReference ExternalReference::new_space_allocation_top_address(
835 Isolate* isolate) {
836 return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000837}
838
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000839
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000840ExternalReference ExternalReference::heap_always_allocate_scope_depth(
841 Isolate* isolate) {
842 Heap* heap = isolate->heap();
843 return ExternalReference(heap->always_allocate_scope_depth_address());
844}
845
846
847ExternalReference ExternalReference::new_space_allocation_limit_address(
848 Isolate* isolate) {
849 return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850}
851
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000852
lrn@chromium.org303ada72010-10-27 09:33:13 +0000853ExternalReference ExternalReference::handle_scope_level_address() {
854 return ExternalReference(HandleScope::current_level_address());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000855}
856
857
858ExternalReference ExternalReference::handle_scope_next_address() {
859 return ExternalReference(HandleScope::current_next_address());
860}
861
862
863ExternalReference ExternalReference::handle_scope_limit_address() {
864 return ExternalReference(HandleScope::current_limit_address());
865}
866
867
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000868ExternalReference ExternalReference::scheduled_exception_address(
869 Isolate* isolate) {
870 return ExternalReference(isolate->scheduled_exception_address());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000871}
872
873
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000874ExternalReference ExternalReference::address_of_min_int() {
875 return ExternalReference(reinterpret_cast<void*>(
876 const_cast<double*>(&DoubleConstant::min_int)));
877}
878
879
880ExternalReference ExternalReference::address_of_one_half() {
881 return ExternalReference(reinterpret_cast<void*>(
882 const_cast<double*>(&DoubleConstant::one_half)));
883}
884
885
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000886ExternalReference ExternalReference::address_of_minus_zero() {
887 return ExternalReference(reinterpret_cast<void*>(
888 const_cast<double*>(&DoubleConstant::minus_zero)));
889}
890
891
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000892ExternalReference ExternalReference::address_of_negative_infinity() {
893 return ExternalReference(reinterpret_cast<void*>(
894 const_cast<double*>(&DoubleConstant::negative_infinity)));
895}
896
897
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000898ExternalReference ExternalReference::address_of_nan() {
899 return ExternalReference(reinterpret_cast<void*>(
900 const_cast<double*>(&DoubleConstant::nan)));
901}
902
903
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000904#ifndef V8_INTERPRETED_REGEXP
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000905
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000906ExternalReference ExternalReference::re_check_stack_guard_state(
907 Isolate* isolate) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000908 Address function;
909#ifdef V8_TARGET_ARCH_X64
910 function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
911#elif V8_TARGET_ARCH_IA32
912 function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
913#elif V8_TARGET_ARCH_ARM
914 function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000915#elif V8_TARGET_ARCH_MIPS
916 function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000917#else
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000918 UNREACHABLE();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000919#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000920 return ExternalReference(Redirect(isolate, function));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000921}
922
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000923ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000924 return ExternalReference(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000925 Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000926}
927
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000928ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
929 Isolate* isolate) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000930 return ExternalReference(Redirect(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000931 isolate,
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000932 FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
933}
934
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000935ExternalReference ExternalReference::re_word_character_map() {
936 return ExternalReference(
937 NativeRegExpMacroAssembler::word_character_map_address());
938}
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000939
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000940ExternalReference ExternalReference::address_of_static_offsets_vector(
941 Isolate* isolate) {
942 return ExternalReference(
943 OffsetsVector::static_offsets_vector_address(isolate));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000944}
945
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000946ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
947 Isolate* isolate) {
948 return ExternalReference(
949 isolate->regexp_stack()->memory_address());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000950}
951
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000952ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
953 Isolate* isolate) {
954 return ExternalReference(isolate->regexp_stack()->memory_size_address());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000955}
956
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000957#endif // V8_INTERPRETED_REGEXP
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000958
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000959
960static double add_two_doubles(double x, double y) {
961 return x + y;
962}
963
964
965static double sub_two_doubles(double x, double y) {
966 return x - y;
967}
968
969
970static double mul_two_doubles(double x, double y) {
971 return x * y;
972}
973
974
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000975static double div_two_doubles(double x, double y) {
976 return x / y;
977}
978
979
980static double mod_two_doubles(double x, double y) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000981 return modulo(x, y);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000982}
983
984
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000985static double math_sin_double(double x) {
986 return sin(x);
987}
988
989
990static double math_cos_double(double x) {
991 return cos(x);
992}
993
994
995static double math_log_double(double x) {
996 return log(x);
997}
998
999
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001000ExternalReference ExternalReference::math_sin_double_function(
1001 Isolate* isolate) {
1002 return ExternalReference(Redirect(isolate,
1003 FUNCTION_ADDR(math_sin_double),
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001004 FP_RETURN_CALL));
1005}
1006
1007
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001008ExternalReference ExternalReference::math_cos_double_function(
1009 Isolate* isolate) {
1010 return ExternalReference(Redirect(isolate,
1011 FUNCTION_ADDR(math_cos_double),
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001012 FP_RETURN_CALL));
1013}
1014
1015
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001016ExternalReference ExternalReference::math_log_double_function(
1017 Isolate* isolate) {
1018 return ExternalReference(Redirect(isolate,
1019 FUNCTION_ADDR(math_log_double),
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001020 FP_RETURN_CALL));
1021}
1022
1023
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001024// Helper function to compute x^y, where y is known to be an
1025// integer. Uses binary decomposition to limit the number of
1026// multiplications; see the discussion in "Hacker's Delight" by Henry
1027// S. Warren, Jr., figure 11-6, page 213.
1028double power_double_int(double x, int y) {
1029 double m = (y < 0) ? 1 / x : x;
1030 unsigned n = (y < 0) ? -y : y;
1031 double p = 1;
1032 while (n != 0) {
1033 if ((n & 1) != 0) p *= m;
1034 m *= m;
1035 if ((n & 2) != 0) p *= m;
1036 m *= m;
1037 n >>= 2;
1038 }
1039 return p;
1040}
1041
1042
1043double power_double_double(double x, double y) {
1044 int y_int = static_cast<int>(y);
1045 if (y == y_int) {
1046 return power_double_int(x, y_int); // Returns 1.0 for exponent 0.
1047 }
1048 if (!isinf(x)) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001049 if (y == 0.5) return sqrt(x + 0.0); // -0 must be converted to +0.
1050 if (y == -0.5) return 1.0 / sqrt(x + 0.0);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001051 }
1052 if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
1053 return OS::nan_value();
1054 }
1055 return pow(x, y);
1056}
1057
1058
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001059ExternalReference ExternalReference::power_double_double_function(
1060 Isolate* isolate) {
1061 return ExternalReference(Redirect(isolate,
1062 FUNCTION_ADDR(power_double_double),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001063 FP_RETURN_CALL));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001064}
1065
1066
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001067ExternalReference ExternalReference::power_double_int_function(
1068 Isolate* isolate) {
1069 return ExternalReference(Redirect(isolate,
1070 FUNCTION_ADDR(power_double_int),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001071 FP_RETURN_CALL));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001072}
1073
1074
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001075static int native_compare_doubles(double y, double x) {
1076 if (x == y) return EQUAL;
1077 return x < y ? LESS : GREATER;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001078}
1079
1080
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001081ExternalReference ExternalReference::double_fp_operation(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001082 Token::Value operation, Isolate* isolate) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001083 typedef double BinaryFPOperation(double x, double y);
1084 BinaryFPOperation* function = NULL;
1085 switch (operation) {
1086 case Token::ADD:
1087 function = &add_two_doubles;
1088 break;
1089 case Token::SUB:
1090 function = &sub_two_doubles;
1091 break;
1092 case Token::MUL:
1093 function = &mul_two_doubles;
1094 break;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001095 case Token::DIV:
1096 function = &div_two_doubles;
1097 break;
1098 case Token::MOD:
1099 function = &mod_two_doubles;
1100 break;
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001101 default:
1102 UNREACHABLE();
1103 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001104 // Passing true as 2nd parameter indicates that they return an fp value.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001105 return ExternalReference(Redirect(isolate,
1106 FUNCTION_ADDR(function),
1107 FP_RETURN_CALL));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001108}
1109
1110
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001111ExternalReference ExternalReference::compare_doubles(Isolate* isolate) {
1112 return ExternalReference(Redirect(isolate,
1113 FUNCTION_ADDR(native_compare_doubles),
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001114 BUILTIN_CALL));
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001115}
1116
1117
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001118#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001119ExternalReference ExternalReference::debug_break(Isolate* isolate) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001120 return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001121}
1122
1123
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001124ExternalReference ExternalReference::debug_step_in_fp_address(
1125 Isolate* isolate) {
1126 return ExternalReference(isolate->debug()->step_in_fp_addr());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001127}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001128#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001129
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001130
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001131void PositionsRecorder::RecordPosition(int pos) {
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001132 ASSERT(pos != RelocInfo::kNoPosition);
1133 ASSERT(pos >= 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001134 state_.current_position = pos;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001135#ifdef ENABLE_GDB_JIT_INTERFACE
1136 if (gdbjit_lineinfo_ != NULL) {
1137 gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
1138 }
1139#endif
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001140}
1141
1142
1143void PositionsRecorder::RecordStatementPosition(int pos) {
1144 ASSERT(pos != RelocInfo::kNoPosition);
1145 ASSERT(pos >= 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001146 state_.current_statement_position = pos;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001147#ifdef ENABLE_GDB_JIT_INTERFACE
1148 if (gdbjit_lineinfo_ != NULL) {
1149 gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
1150 }
1151#endif
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001152}
1153
1154
1155bool PositionsRecorder::WriteRecordedPositions() {
1156 bool written = false;
1157
1158 // Write the statement position if it is different from what was written last
1159 // time.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001160 if (state_.current_statement_position != state_.written_statement_position) {
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001161 EnsureSpace ensure_space(assembler_);
1162 assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001163 state_.current_statement_position);
1164 state_.written_statement_position = state_.current_statement_position;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001165 written = true;
1166 }
1167
1168 // Write the position if it is different from what was written last time and
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001169 // also different from the written statement position.
1170 if (state_.current_position != state_.written_position &&
1171 state_.current_position != state_.written_statement_position) {
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001172 EnsureSpace ensure_space(assembler_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001173 assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
1174 state_.written_position = state_.current_position;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001175 written = true;
1176 }
1177
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001178 // Return whether something was written.
1179 return written;
1180}
1181
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001182} } // namespace v8::internal