blob: db9e2ef7b10f95e01cfce86773eed94bd6a6ce32 [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// Copyright 2010 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27//
28// Review notes:
29//
ager@chromium.org32912102009-01-16 10:38:43 +000030// - The use of macros in these inline functions may seem superfluous
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000031// but it is absolutely needed to make sure gcc generates optimal
32// code. gcc is not happy when attempting to inline too deep.
33//
34
35#ifndef V8_OBJECTS_INL_H_
36#define V8_OBJECTS_INL_H_
37
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000038#include "objects.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#include "contexts.h"
40#include "conversions-inl.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000041#include "heap.h"
42#include "memory.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043#include "property.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000044#include "spaces.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
kasperl@chromium.org71affb52009-05-26 05:44:31 +000046namespace v8 {
47namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000048
49PropertyDetails::PropertyDetails(Smi* smi) {
50 value_ = smi->value();
51}
52
53
54Smi* PropertyDetails::AsSmi() {
55 return Smi::FromInt(value_);
56}
57
58
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000059PropertyDetails PropertyDetails::AsDeleted() {
ager@chromium.org378b34e2011-01-28 08:04:38 +000060 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000061 return PropertyDetails(smi);
62}
63
64
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065#define CAST_ACCESSOR(type) \
66 type* type::cast(Object* object) { \
67 ASSERT(object->Is##type()); \
68 return reinterpret_cast<type*>(object); \
69 }
70
71
72#define INT_ACCESSORS(holder, name, offset) \
73 int holder::name() { return READ_INT_FIELD(this, offset); } \
74 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
75
76
77#define ACCESSORS(holder, name, type, offset) \
78 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000079 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000081 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082 }
83
84
85#define SMI_ACCESSORS(holder, name, offset) \
86 int holder::name() { \
87 Object* value = READ_FIELD(this, offset); \
88 return Smi::cast(value)->value(); \
89 } \
90 void holder::set_##name(int value) { \
91 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
92 }
93
94
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000095#define BOOL_GETTER(holder, field, name, offset) \
96 bool holder::name() { \
97 return BooleanBit::get(field(), offset); \
98 } \
99
100
101#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102 bool holder::name() { \
103 return BooleanBit::get(field(), offset); \
104 } \
105 void holder::set_##name(bool value) { \
106 set_##field(BooleanBit::set(field(), offset, value)); \
107 }
108
109
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000110bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
111 // There is a constraint on the object; check.
112 if (!this->IsJSObject()) return false;
113 // Fetch the constructor function of the object.
114 Object* cons_obj = JSObject::cast(this)->map()->constructor();
115 if (!cons_obj->IsJSFunction()) return false;
116 JSFunction* fun = JSFunction::cast(cons_obj);
117 // Iterate through the chain of inheriting function templates to
118 // see if the required one occurs.
119 for (Object* type = fun->shared()->function_data();
120 type->IsFunctionTemplateInfo();
121 type = FunctionTemplateInfo::cast(type)->parent_template()) {
122 if (type == expected) return true;
123 }
124 // Didn't find the required type in the inheritance chain.
125 return false;
126}
127
128
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129bool Object::IsSmi() {
130 return HAS_SMI_TAG(this);
131}
132
133
134bool Object::IsHeapObject() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000135 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136}
137
138
139bool Object::IsHeapNumber() {
140 return Object::IsHeapObject()
141 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
142}
143
144
145bool Object::IsString() {
146 return Object::IsHeapObject()
147 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
148}
149
150
ager@chromium.org870a0b62008-11-04 11:43:05 +0000151bool Object::IsSymbol() {
152 if (!this->IsHeapObject()) return false;
153 uint32_t type = HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000154 // Because the symbol tag is non-zero and no non-string types have the
155 // symbol bit set we can test for symbols with a very simple test
156 // operation.
157 ASSERT(kSymbolTag != 0);
158 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
159 return (type & kIsSymbolMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000160}
161
162
163bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000164 if (!this->IsHeapObject()) return false;
165 uint32_t type = HeapObject::cast(this)->map()->instance_type();
166 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
167 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000168}
169
170
ager@chromium.org870a0b62008-11-04 11:43:05 +0000171bool Object::IsSeqString() {
172 if (!IsString()) return false;
173 return StringShape(String::cast(this)).IsSequential();
174}
175
176
177bool Object::IsSeqAsciiString() {
178 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000179 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000180 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000181}
182
183
184bool Object::IsSeqTwoByteString() {
185 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000186 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000187 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188}
189
190
191bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000192 if (!IsString()) return false;
193 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194}
195
196
197bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000198 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000199 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000200 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201}
202
203
204bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000205 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000206 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000207 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208}
209
210
ager@chromium.org870a0b62008-11-04 11:43:05 +0000211StringShape::StringShape(String* str)
212 : type_(str->map()->instance_type()) {
213 set_valid();
214 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000215}
216
217
ager@chromium.org870a0b62008-11-04 11:43:05 +0000218StringShape::StringShape(Map* map)
219 : type_(map->instance_type()) {
220 set_valid();
221 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222}
223
224
ager@chromium.org870a0b62008-11-04 11:43:05 +0000225StringShape::StringShape(InstanceType t)
226 : type_(static_cast<uint32_t>(t)) {
227 set_valid();
228 ASSERT((type_ & kIsNotStringMask) == kStringTag);
229}
230
231
232bool StringShape::IsSymbol() {
233 ASSERT(valid());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000234 ASSERT(kSymbolTag != 0);
235 return (type_ & kIsSymbolMask) != 0;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000236}
237
238
ager@chromium.org5ec48922009-05-05 07:25:34 +0000239bool String::IsAsciiRepresentation() {
240 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000241 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000242}
243
244
ager@chromium.org5ec48922009-05-05 07:25:34 +0000245bool String::IsTwoByteRepresentation() {
246 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000247 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000248}
249
250
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000251bool String::HasOnlyAsciiChars() {
252 uint32_t type = map()->instance_type();
253 return (type & kStringEncodingMask) == kAsciiStringTag ||
254 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000255}
256
257
ager@chromium.org870a0b62008-11-04 11:43:05 +0000258bool StringShape::IsCons() {
259 return (type_ & kStringRepresentationMask) == kConsStringTag;
260}
261
262
ager@chromium.org870a0b62008-11-04 11:43:05 +0000263bool StringShape::IsExternal() {
264 return (type_ & kStringRepresentationMask) == kExternalStringTag;
265}
266
267
268bool StringShape::IsSequential() {
269 return (type_ & kStringRepresentationMask) == kSeqStringTag;
270}
271
272
273StringRepresentationTag StringShape::representation_tag() {
274 uint32_t tag = (type_ & kStringRepresentationMask);
275 return static_cast<StringRepresentationTag>(tag);
276}
277
278
279uint32_t StringShape::full_representation_tag() {
280 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
281}
282
283
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000284STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
285 Internals::kFullStringRepresentationMask);
286
287
ager@chromium.org870a0b62008-11-04 11:43:05 +0000288bool StringShape::IsSequentialAscii() {
289 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
290}
291
292
293bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000294 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000295}
296
297
298bool StringShape::IsExternalAscii() {
299 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
300}
301
302
303bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000304 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305}
306
307
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000308STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
309 Internals::kExternalTwoByteRepresentationTag);
310
311
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000312uc32 FlatStringReader::Get(int index) {
313 ASSERT(0 <= index && index <= length_);
314 if (is_ascii_) {
315 return static_cast<const byte*>(start_)[index];
316 } else {
317 return static_cast<const uc16*>(start_)[index];
318 }
319}
320
321
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322bool Object::IsNumber() {
323 return IsSmi() || IsHeapNumber();
324}
325
326
327bool Object::IsByteArray() {
328 return Object::IsHeapObject()
329 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
330}
331
332
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000333bool Object::IsPixelArray() {
334 return Object::IsHeapObject() &&
335 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
336}
337
338
ager@chromium.org3811b432009-10-28 14:53:37 +0000339bool Object::IsExternalArray() {
340 if (!Object::IsHeapObject())
341 return false;
342 InstanceType instance_type =
343 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000344 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
345 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000346}
347
348
349bool Object::IsExternalByteArray() {
350 return Object::IsHeapObject() &&
351 HeapObject::cast(this)->map()->instance_type() ==
352 EXTERNAL_BYTE_ARRAY_TYPE;
353}
354
355
356bool Object::IsExternalUnsignedByteArray() {
357 return Object::IsHeapObject() &&
358 HeapObject::cast(this)->map()->instance_type() ==
359 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
360}
361
362
363bool Object::IsExternalShortArray() {
364 return Object::IsHeapObject() &&
365 HeapObject::cast(this)->map()->instance_type() ==
366 EXTERNAL_SHORT_ARRAY_TYPE;
367}
368
369
370bool Object::IsExternalUnsignedShortArray() {
371 return Object::IsHeapObject() &&
372 HeapObject::cast(this)->map()->instance_type() ==
373 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
374}
375
376
377bool Object::IsExternalIntArray() {
378 return Object::IsHeapObject() &&
379 HeapObject::cast(this)->map()->instance_type() ==
380 EXTERNAL_INT_ARRAY_TYPE;
381}
382
383
384bool Object::IsExternalUnsignedIntArray() {
385 return Object::IsHeapObject() &&
386 HeapObject::cast(this)->map()->instance_type() ==
387 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
388}
389
390
391bool Object::IsExternalFloatArray() {
392 return Object::IsHeapObject() &&
393 HeapObject::cast(this)->map()->instance_type() ==
394 EXTERNAL_FLOAT_ARRAY_TYPE;
395}
396
397
lrn@chromium.org303ada72010-10-27 09:33:13 +0000398bool MaybeObject::IsFailure() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399 return HAS_FAILURE_TAG(this);
400}
401
402
lrn@chromium.org303ada72010-10-27 09:33:13 +0000403bool MaybeObject::IsRetryAfterGC() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404 return HAS_FAILURE_TAG(this)
405 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
406}
407
408
lrn@chromium.org303ada72010-10-27 09:33:13 +0000409bool MaybeObject::IsOutOfMemory() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000410 return HAS_FAILURE_TAG(this)
411 && Failure::cast(this)->IsOutOfMemoryException();
412}
413
414
lrn@chromium.org303ada72010-10-27 09:33:13 +0000415bool MaybeObject::IsException() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416 return this == Failure::Exception();
417}
418
419
lrn@chromium.org303ada72010-10-27 09:33:13 +0000420bool MaybeObject::IsTheHole() {
421 return this == Heap::the_hole_value();
422}
423
424
425Failure* Failure::cast(MaybeObject* obj) {
426 ASSERT(HAS_FAILURE_TAG(obj));
427 return reinterpret_cast<Failure*>(obj);
428}
429
430
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431bool Object::IsJSObject() {
432 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000433 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000434}
435
436
ager@chromium.org32912102009-01-16 10:38:43 +0000437bool Object::IsJSContextExtensionObject() {
438 return IsHeapObject()
439 && (HeapObject::cast(this)->map()->instance_type() ==
440 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
441}
442
443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444bool Object::IsMap() {
445 return Object::IsHeapObject()
446 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
447}
448
449
450bool Object::IsFixedArray() {
451 return Object::IsHeapObject()
452 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
453}
454
455
456bool Object::IsDescriptorArray() {
457 return IsFixedArray();
458}
459
460
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000461bool Object::IsDeoptimizationInputData() {
462 // Must be a fixed array.
463 if (!IsFixedArray()) return false;
464
465 // There's no sure way to detect the difference between a fixed array and
466 // a deoptimization data array. Since this is used for asserts we can
467 // check that the length is zero or else the fixed size plus a multiple of
468 // the entry size.
469 int length = FixedArray::cast(this)->length();
470 if (length == 0) return true;
471
472 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
473 return length >= 0 &&
474 length % DeoptimizationInputData::kDeoptEntrySize == 0;
475}
476
477
478bool Object::IsDeoptimizationOutputData() {
479 if (!IsFixedArray()) return false;
480 // There's actually no way to see the difference between a fixed array and
481 // a deoptimization data array. Since this is used for asserts we can check
482 // that the length is plausible though.
483 if (FixedArray::cast(this)->length() % 2 != 0) return false;
484 return true;
485}
486
487
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488bool Object::IsContext() {
489 return Object::IsHeapObject()
490 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000491 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492 HeapObject::cast(this)->map() == Heap::global_context_map());
493}
494
495
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000496bool Object::IsCatchContext() {
497 return Object::IsHeapObject()
498 && HeapObject::cast(this)->map() == Heap::catch_context_map();
499}
500
501
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502bool Object::IsGlobalContext() {
503 return Object::IsHeapObject()
504 && HeapObject::cast(this)->map() == Heap::global_context_map();
505}
506
507
508bool Object::IsJSFunction() {
509 return Object::IsHeapObject()
510 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
511}
512
513
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000514template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515 return obj->IsJSFunction();
516}
517
518
519bool Object::IsCode() {
520 return Object::IsHeapObject()
521 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
522}
523
524
525bool Object::IsOddball() {
526 return Object::IsHeapObject()
527 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
528}
529
530
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000531bool Object::IsJSGlobalPropertyCell() {
532 return Object::IsHeapObject()
533 && HeapObject::cast(this)->map()->instance_type()
534 == JS_GLOBAL_PROPERTY_CELL_TYPE;
535}
536
537
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000538bool Object::IsSharedFunctionInfo() {
539 return Object::IsHeapObject() &&
540 (HeapObject::cast(this)->map()->instance_type() ==
541 SHARED_FUNCTION_INFO_TYPE);
542}
543
544
545bool Object::IsJSValue() {
546 return Object::IsHeapObject()
547 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
548}
549
550
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000551bool Object::IsStringWrapper() {
552 return IsJSValue() && JSValue::cast(this)->value()->IsString();
553}
554
555
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000556bool Object::IsProxy() {
557 return Object::IsHeapObject()
558 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
559}
560
561
562bool Object::IsBoolean() {
563 return IsTrue() || IsFalse();
564}
565
566
567bool Object::IsJSArray() {
568 return Object::IsHeapObject()
569 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
570}
571
572
ager@chromium.org236ad962008-09-25 09:45:57 +0000573bool Object::IsJSRegExp() {
574 return Object::IsHeapObject()
575 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
576}
577
578
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000579template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 return obj->IsJSArray();
581}
582
583
584bool Object::IsHashTable() {
585 return Object::IsHeapObject()
586 && HeapObject::cast(this)->map() == Heap::hash_table_map();
587}
588
589
590bool Object::IsDictionary() {
591 return IsHashTable() && this != Heap::symbol_table();
592}
593
594
595bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000596 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000597}
598
599
ager@chromium.orgac091b72010-05-05 07:34:42 +0000600bool Object::IsJSFunctionResultCache() {
601 if (!IsFixedArray()) return false;
602 FixedArray* self = FixedArray::cast(this);
603 int length = self->length();
604 if (length < JSFunctionResultCache::kEntriesIndex) return false;
605 if ((length - JSFunctionResultCache::kEntriesIndex)
606 % JSFunctionResultCache::kEntrySize != 0) {
607 return false;
608 }
609#ifdef DEBUG
610 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
611#endif
612 return true;
613}
614
615
ricow@chromium.org65fae842010-08-25 15:26:24 +0000616bool Object::IsNormalizedMapCache() {
617 if (!IsFixedArray()) return false;
618 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
619 return false;
620 }
621#ifdef DEBUG
622 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
623#endif
624 return true;
625}
626
627
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000628bool Object::IsCompilationCacheTable() {
629 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000630}
631
632
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000633bool Object::IsCodeCacheHashTable() {
634 return IsHashTable();
635}
636
637
ager@chromium.org236ad962008-09-25 09:45:57 +0000638bool Object::IsMapCache() {
639 return IsHashTable();
640}
641
642
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643bool Object::IsPrimitive() {
644 return IsOddball() || IsNumber() || IsString();
645}
646
647
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000648bool Object::IsJSGlobalProxy() {
649 bool result = IsHeapObject() &&
650 (HeapObject::cast(this)->map()->instance_type() ==
651 JS_GLOBAL_PROXY_TYPE);
652 ASSERT(!result || IsAccessCheckNeeded());
653 return result;
654}
655
656
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000657bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000658 if (!IsHeapObject()) return false;
659
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000660 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000661 return type == JS_GLOBAL_OBJECT_TYPE ||
662 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000663}
664
665
666bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667 return IsHeapObject() &&
668 (HeapObject::cast(this)->map()->instance_type() ==
669 JS_GLOBAL_OBJECT_TYPE);
670}
671
672
673bool Object::IsJSBuiltinsObject() {
674 return IsHeapObject() &&
675 (HeapObject::cast(this)->map()->instance_type() ==
676 JS_BUILTINS_OBJECT_TYPE);
677}
678
679
680bool Object::IsUndetectableObject() {
681 return IsHeapObject()
682 && HeapObject::cast(this)->map()->is_undetectable();
683}
684
685
686bool Object::IsAccessCheckNeeded() {
687 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000688 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689}
690
691
692bool Object::IsStruct() {
693 if (!IsHeapObject()) return false;
694 switch (HeapObject::cast(this)->map()->instance_type()) {
695#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
696 STRUCT_LIST(MAKE_STRUCT_CASE)
697#undef MAKE_STRUCT_CASE
698 default: return false;
699 }
700}
701
702
703#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
704 bool Object::Is##Name() { \
705 return Object::IsHeapObject() \
706 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
707 }
708 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
709#undef MAKE_STRUCT_PREDICATE
710
711
712bool Object::IsUndefined() {
713 return this == Heap::undefined_value();
714}
715
716
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717bool Object::IsNull() {
718 return this == Heap::null_value();
719}
720
721
722bool Object::IsTrue() {
723 return this == Heap::true_value();
724}
725
726
727bool Object::IsFalse() {
728 return this == Heap::false_value();
729}
730
731
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000732bool Object::IsArgumentsMarker() {
733 return this == Heap::arguments_marker();
734}
735
736
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737double Object::Number() {
738 ASSERT(IsNumber());
739 return IsSmi()
740 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
741 : reinterpret_cast<HeapNumber*>(this)->value();
742}
743
744
745
lrn@chromium.org303ada72010-10-27 09:33:13 +0000746MaybeObject* Object::ToSmi() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000747 if (IsSmi()) return this;
748 if (IsHeapNumber()) {
749 double value = HeapNumber::cast(this)->value();
750 int int_value = FastD2I(value);
751 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
752 return Smi::FromInt(int_value);
753 }
754 }
755 return Failure::Exception();
756}
757
758
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000759bool Object::HasSpecificClassOf(String* name) {
760 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
761}
762
763
lrn@chromium.org303ada72010-10-27 09:33:13 +0000764MaybeObject* Object::GetElement(uint32_t index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000765 return GetElementWithReceiver(this, index);
766}
767
768
lrn@chromium.org303ada72010-10-27 09:33:13 +0000769Object* Object::GetElementNoExceptionThrown(uint32_t index) {
770 MaybeObject* maybe = GetElementWithReceiver(this, index);
771 ASSERT(!maybe->IsFailure());
772 Object* result = NULL; // Initialization to please compiler.
773 maybe->ToObject(&result);
774 return result;
775}
776
777
778MaybeObject* Object::GetProperty(String* key) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000779 PropertyAttributes attributes;
780 return GetPropertyWithReceiver(this, key, &attributes);
781}
782
783
lrn@chromium.org303ada72010-10-27 09:33:13 +0000784MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000785 return GetPropertyWithReceiver(this, key, attributes);
786}
787
788
789#define FIELD_ADDR(p, offset) \
790 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
791
792#define READ_FIELD(p, offset) \
793 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
794
795#define WRITE_FIELD(p, offset, value) \
796 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
797
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000798
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799#define WRITE_BARRIER(object, offset) \
800 Heap::RecordWrite(object->address(), offset);
801
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000802// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000803// write due to the assert validating the written value.
804#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
805 if (mode == UPDATE_WRITE_BARRIER) { \
806 Heap::RecordWrite(object->address(), offset); \
807 } else { \
808 ASSERT(mode == SKIP_WRITE_BARRIER); \
809 ASSERT(Heap::InNewSpace(object) || \
kmillikin@chromium.orgb8dc8eb2010-04-01 07:13:38 +0000810 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000811 Page::FromAddress(object->address())-> \
812 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000813 }
814
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815#define READ_DOUBLE_FIELD(p, offset) \
816 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
817
818#define WRITE_DOUBLE_FIELD(p, offset, value) \
819 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
820
821#define READ_INT_FIELD(p, offset) \
822 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
823
824#define WRITE_INT_FIELD(p, offset, value) \
825 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
826
ager@chromium.org3e875802009-06-29 08:26:34 +0000827#define READ_INTPTR_FIELD(p, offset) \
828 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
829
830#define WRITE_INTPTR_FIELD(p, offset, value) \
831 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
832
ager@chromium.org7c537e22008-10-16 08:43:32 +0000833#define READ_UINT32_FIELD(p, offset) \
834 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
835
836#define WRITE_UINT32_FIELD(p, offset, value) \
837 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
838
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839#define READ_SHORT_FIELD(p, offset) \
840 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
841
842#define WRITE_SHORT_FIELD(p, offset, value) \
843 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
844
845#define READ_BYTE_FIELD(p, offset) \
846 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
847
848#define WRITE_BYTE_FIELD(p, offset, value) \
849 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
850
851
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000852Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
853 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000854}
855
856
857int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000858 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000859}
860
861
862Smi* Smi::FromInt(int value) {
863 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000864 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000865 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000866 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000867 return reinterpret_cast<Smi*>(tagged_value);
868}
869
870
871Smi* Smi::FromIntptr(intptr_t value) {
872 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000873 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
874 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875}
876
877
878Failure::Type Failure::type() const {
879 return static_cast<Type>(value() & kFailureTypeTagMask);
880}
881
882
883bool Failure::IsInternalError() const {
884 return type() == INTERNAL_ERROR;
885}
886
887
888bool Failure::IsOutOfMemoryException() const {
889 return type() == OUT_OF_MEMORY_EXCEPTION;
890}
891
892
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893AllocationSpace Failure::allocation_space() const {
894 ASSERT_EQ(RETRY_AFTER_GC, type());
895 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
896 & kSpaceTagMask);
897}
898
899
900Failure* Failure::InternalError() {
901 return Construct(INTERNAL_ERROR);
902}
903
904
905Failure* Failure::Exception() {
906 return Construct(EXCEPTION);
907}
908
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000909
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910Failure* Failure::OutOfMemoryException() {
911 return Construct(OUT_OF_MEMORY_EXCEPTION);
912}
913
914
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000915intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000916 return static_cast<intptr_t>(
917 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918}
919
920
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000921Failure* Failure::RetryAfterGC() {
922 return RetryAfterGC(NEW_SPACE);
923}
924
925
926Failure* Failure::RetryAfterGC(AllocationSpace space) {
927 ASSERT((space & ~kSpaceTagMask) == 0);
928 return Construct(RETRY_AFTER_GC, space);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000929}
930
931
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000932Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000933 uintptr_t info =
934 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000935 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000936 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000937}
938
939
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000940bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000941#ifdef DEBUG
942 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
943#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000944
945#ifdef V8_TARGET_ARCH_X64
946 // To be representable as a long smi, the value must be a 32-bit integer.
947 bool result = (value == static_cast<int32_t>(value));
948#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000949 // To be representable as an tagged small integer, the two
950 // most-significant bits of 'value' must be either 00 or 11 due to
951 // sign-extension. To check this we add 01 to the two
952 // most-significant bits, and check if the most-significant bit is 0
953 //
954 // CAUTION: The original code below:
955 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
956 // may lead to incorrect results according to the C language spec, and
957 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
958 // compiler may produce undefined results in case of signed integer
959 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000960 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000961#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000962 ASSERT(result == in_range);
963 return result;
964}
965
966
kasper.lund7276f142008-07-30 08:49:36 +0000967MapWord MapWord::FromMap(Map* map) {
968 return MapWord(reinterpret_cast<uintptr_t>(map));
969}
970
971
972Map* MapWord::ToMap() {
973 return reinterpret_cast<Map*>(value_);
974}
975
976
977bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000978 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000979}
980
981
982MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000983 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
984 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000985}
986
987
988HeapObject* MapWord::ToForwardingAddress() {
989 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000990 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000991}
992
993
994bool MapWord::IsMarked() {
995 return (value_ & kMarkingMask) == 0;
996}
997
998
999void MapWord::SetMark() {
1000 value_ &= ~kMarkingMask;
1001}
1002
1003
1004void MapWord::ClearMark() {
1005 value_ |= kMarkingMask;
1006}
1007
1008
1009bool MapWord::IsOverflowed() {
1010 return (value_ & kOverflowMask) != 0;
1011}
1012
1013
1014void MapWord::SetOverflow() {
1015 value_ |= kOverflowMask;
1016}
1017
1018
1019void MapWord::ClearOverflow() {
1020 value_ &= ~kOverflowMask;
1021}
1022
1023
1024MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1025 // Offset is the distance in live bytes from the first live object in the
1026 // same page. The offset between two objects in the same page should not
1027 // exceed the object area size of a page.
1028 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1029
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001030 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001031 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1032
1033 Page* map_page = Page::FromAddress(map_address);
1034 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1035
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001036 uintptr_t map_page_offset =
1037 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001038
1039 uintptr_t encoding =
1040 (compact_offset << kForwardingOffsetShift) |
1041 (map_page_offset << kMapPageOffsetShift) |
1042 (map_page->mc_page_index << kMapPageIndexShift);
1043 return MapWord(encoding);
1044}
1045
1046
1047Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001048 int map_page_index =
1049 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001050 ASSERT_MAP_PAGE_INDEX(map_page_index);
1051
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001052 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001053 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1054 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001055
1056 return (map_space->PageAddress(map_page_index) + map_page_offset);
1057}
1058
1059
1060int MapWord::DecodeOffset() {
1061 // The offset field is represented in the kForwardingOffsetBits
1062 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001063 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1064 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1065 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001066}
1067
1068
1069MapWord MapWord::FromEncodedAddress(Address address) {
1070 return MapWord(reinterpret_cast<uintptr_t>(address));
1071}
1072
1073
1074Address MapWord::ToEncodedAddress() {
1075 return reinterpret_cast<Address>(value_);
1076}
1077
1078
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001079#ifdef DEBUG
1080void HeapObject::VerifyObjectField(int offset) {
1081 VerifyPointer(READ_FIELD(this, offset));
1082}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001083
1084void HeapObject::VerifySmiField(int offset) {
1085 ASSERT(READ_FIELD(this, offset)->IsSmi());
1086}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001087#endif
1088
1089
1090Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001091 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001092}
1093
1094
1095void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001096 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001097}
1098
1099
kasper.lund7276f142008-07-30 08:49:36 +00001100MapWord HeapObject::map_word() {
1101 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1102}
1103
1104
1105void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001106 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001107 // here.
1108 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1109}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001110
1111
1112HeapObject* HeapObject::FromAddress(Address address) {
1113 ASSERT_TAG_ALIGNED(address);
1114 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1115}
1116
1117
1118Address HeapObject::address() {
1119 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1120}
1121
1122
1123int HeapObject::Size() {
1124 return SizeFromMap(map());
1125}
1126
1127
1128void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1129 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1130 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1131}
1132
1133
1134void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1135 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1136}
1137
1138
kasper.lund7276f142008-07-30 08:49:36 +00001139bool HeapObject::IsMarked() {
1140 return map_word().IsMarked();
1141}
1142
1143
1144void HeapObject::SetMark() {
1145 ASSERT(!IsMarked());
1146 MapWord first_word = map_word();
1147 first_word.SetMark();
1148 set_map_word(first_word);
1149}
1150
1151
1152void HeapObject::ClearMark() {
1153 ASSERT(IsMarked());
1154 MapWord first_word = map_word();
1155 first_word.ClearMark();
1156 set_map_word(first_word);
1157}
1158
1159
1160bool HeapObject::IsOverflowed() {
1161 return map_word().IsOverflowed();
1162}
1163
1164
1165void HeapObject::SetOverflow() {
1166 MapWord first_word = map_word();
1167 first_word.SetOverflow();
1168 set_map_word(first_word);
1169}
1170
1171
1172void HeapObject::ClearOverflow() {
1173 ASSERT(IsOverflowed());
1174 MapWord first_word = map_word();
1175 first_word.ClearOverflow();
1176 set_map_word(first_word);
1177}
1178
1179
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001180double HeapNumber::value() {
1181 return READ_DOUBLE_FIELD(this, kValueOffset);
1182}
1183
1184
1185void HeapNumber::set_value(double value) {
1186 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1187}
1188
1189
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001190int HeapNumber::get_exponent() {
1191 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1192 kExponentShift) - kExponentBias;
1193}
1194
1195
1196int HeapNumber::get_sign() {
1197 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1198}
1199
1200
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001201ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001202
1203
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001204HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001205 Object* array = READ_FIELD(this, kElementsOffset);
1206 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001207 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1208 array->IsExternalArray());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001209 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001210}
1211
1212
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001213void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001214 ASSERT(map()->has_fast_elements() ==
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001215 (value->map() == Heap::fixed_array_map() ||
1216 value->map() == Heap::fixed_cow_array_map()));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001217 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001218 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1219 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001220 WRITE_FIELD(this, kElementsOffset, value);
1221 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1222}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223
1224
1225void JSObject::initialize_properties() {
1226 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1227 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1228}
1229
1230
1231void JSObject::initialize_elements() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001232 ASSERT(map()->has_fast_elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001233 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1234 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1235}
1236
1237
lrn@chromium.org303ada72010-10-27 09:33:13 +00001238MaybeObject* JSObject::ResetElements() {
1239 Object* obj;
1240 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1241 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1242 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001243 set_map(Map::cast(obj));
1244 initialize_elements();
1245 return this;
1246}
1247
1248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249ACCESSORS(Oddball, to_string, String, kToStringOffset)
1250ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1251
1252
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001253Object* JSGlobalPropertyCell::value() {
1254 return READ_FIELD(this, kValueOffset);
1255}
1256
1257
1258void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1259 // The write barrier is not used for global property cells.
1260 ASSERT(!val->IsJSGlobalPropertyCell());
1261 WRITE_FIELD(this, kValueOffset, val);
1262}
1263
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001264
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001265int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001266 InstanceType type = map()->instance_type();
1267 // Check for the most common kind of JavaScript object before
1268 // falling into the generic switch. This speeds up the internal
1269 // field operations considerably on average.
1270 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1271 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001272 case JS_GLOBAL_PROXY_TYPE:
1273 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001274 case JS_GLOBAL_OBJECT_TYPE:
1275 return JSGlobalObject::kSize;
1276 case JS_BUILTINS_OBJECT_TYPE:
1277 return JSBuiltinsObject::kSize;
1278 case JS_FUNCTION_TYPE:
1279 return JSFunction::kSize;
1280 case JS_VALUE_TYPE:
1281 return JSValue::kSize;
1282 case JS_ARRAY_TYPE:
1283 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001284 case JS_REGEXP_TYPE:
1285 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001286 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001287 return JSObject::kHeaderSize;
1288 default:
1289 UNREACHABLE();
1290 return 0;
1291 }
1292}
1293
1294
1295int JSObject::GetInternalFieldCount() {
1296 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001297 // Make sure to adjust for the number of in-object properties. These
1298 // properties do contribute to the size, but are not internal fields.
1299 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1300 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001301}
1302
1303
1304Object* JSObject::GetInternalField(int index) {
1305 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001306 // Internal objects do follow immediately after the header, whereas in-object
1307 // properties are at the end of the object. Therefore there is no need
1308 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1310}
1311
1312
1313void JSObject::SetInternalField(int index, Object* value) {
1314 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001315 // Internal objects do follow immediately after the header, whereas in-object
1316 // properties are at the end of the object. Therefore there is no need
1317 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001318 int offset = GetHeaderSize() + (kPointerSize * index);
1319 WRITE_FIELD(this, offset, value);
1320 WRITE_BARRIER(this, offset);
1321}
1322
1323
ager@chromium.org7c537e22008-10-16 08:43:32 +00001324// Access fast-case object properties at index. The use of these routines
1325// is needed to correctly distinguish between properties stored in-object and
1326// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001327Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001328 // Adjust for the number of properties stored in the object.
1329 index -= map()->inobject_properties();
1330 if (index < 0) {
1331 int offset = map()->instance_size() + (index * kPointerSize);
1332 return READ_FIELD(this, offset);
1333 } else {
1334 ASSERT(index < properties()->length());
1335 return properties()->get(index);
1336 }
1337}
1338
1339
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001340Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001341 // Adjust for the number of properties stored in the object.
1342 index -= map()->inobject_properties();
1343 if (index < 0) {
1344 int offset = map()->instance_size() + (index * kPointerSize);
1345 WRITE_FIELD(this, offset, value);
1346 WRITE_BARRIER(this, offset);
1347 } else {
1348 ASSERT(index < properties()->length());
1349 properties()->set(index, value);
1350 }
1351 return value;
1352}
1353
1354
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001355Object* JSObject::InObjectPropertyAt(int index) {
1356 // Adjust for the number of properties stored in the object.
1357 index -= map()->inobject_properties();
1358 ASSERT(index < 0);
1359 int offset = map()->instance_size() + (index * kPointerSize);
1360 return READ_FIELD(this, offset);
1361}
1362
1363
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001364Object* JSObject::InObjectPropertyAtPut(int index,
1365 Object* value,
1366 WriteBarrierMode mode) {
1367 // Adjust for the number of properties stored in the object.
1368 index -= map()->inobject_properties();
1369 ASSERT(index < 0);
1370 int offset = map()->instance_size() + (index * kPointerSize);
1371 WRITE_FIELD(this, offset, value);
1372 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1373 return value;
1374}
1375
1376
1377
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001378void JSObject::InitializeBody(int object_size, Object* value) {
1379 ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001381 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001382 }
1383}
1384
1385
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001386bool JSObject::HasFastProperties() {
1387 return !properties()->IsDictionary();
1388}
1389
1390
1391int JSObject::MaxFastProperties() {
1392 // Allow extra fast properties if the object has more than
1393 // kMaxFastProperties in-object properties. When this is the case,
1394 // it is very unlikely that the object is being used as a dictionary
1395 // and there is a good chance that allowing more map transitions
1396 // will be worth it.
1397 return Max(map()->inobject_properties(), kMaxFastProperties);
1398}
1399
1400
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001401void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001402 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001403 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001404 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405 }
1406}
1407
1408
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001409bool Object::ToArrayIndex(uint32_t* index) {
1410 if (IsSmi()) {
1411 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001412 if (value < 0) return false;
1413 *index = value;
1414 return true;
1415 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001416 if (IsHeapNumber()) {
1417 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001418 uint32_t uint_value = static_cast<uint32_t>(value);
1419 if (value == static_cast<double>(uint_value)) {
1420 *index = uint_value;
1421 return true;
1422 }
1423 }
1424 return false;
1425}
1426
1427
1428bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1429 if (!this->IsJSValue()) return false;
1430
1431 JSValue* js_value = JSValue::cast(this);
1432 if (!js_value->value()->IsString()) return false;
1433
1434 String* str = String::cast(js_value->value());
1435 if (index >= (uint32_t)str->length()) return false;
1436
1437 return true;
1438}
1439
1440
1441Object* FixedArray::get(int index) {
1442 ASSERT(index >= 0 && index < this->length());
1443 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1444}
1445
1446
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001447void FixedArray::set(int index, Smi* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001448 ASSERT(map() != Heap::fixed_cow_array_map());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001449 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1450 int offset = kHeaderSize + index * kPointerSize;
1451 WRITE_FIELD(this, offset, value);
1452}
1453
1454
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001455void FixedArray::set(int index, Object* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001456 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001457 ASSERT(index >= 0 && index < this->length());
1458 int offset = kHeaderSize + index * kPointerSize;
1459 WRITE_FIELD(this, offset, value);
1460 WRITE_BARRIER(this, offset);
1461}
1462
1463
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001464WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001465 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1466 return UPDATE_WRITE_BARRIER;
1467}
1468
1469
1470void FixedArray::set(int index,
1471 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001472 WriteBarrierMode mode) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001473 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474 ASSERT(index >= 0 && index < this->length());
1475 int offset = kHeaderSize + index * kPointerSize;
1476 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001477 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001478}
1479
1480
1481void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001482 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001483 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001484 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001485 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1486}
1487
1488
1489void FixedArray::set_undefined(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001490 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001491 ASSERT(index >= 0 && index < this->length());
1492 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1493 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1494 Heap::undefined_value());
1495}
1496
1497
ager@chromium.org236ad962008-09-25 09:45:57 +00001498void FixedArray::set_null(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001499 ASSERT(map() != Heap::fixed_cow_array_map());
ager@chromium.org236ad962008-09-25 09:45:57 +00001500 ASSERT(index >= 0 && index < this->length());
1501 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1502 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1503}
1504
1505
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001506void FixedArray::set_the_hole(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001507 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001508 ASSERT(index >= 0 && index < this->length());
1509 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1510 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1511}
1512
1513
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001514void FixedArray::set_unchecked(int index, Smi* value) {
1515 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1516 int offset = kHeaderSize + index * kPointerSize;
1517 WRITE_FIELD(this, offset, value);
1518}
1519
1520
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001521void FixedArray::set_unchecked(int index,
1522 Object* value,
1523 WriteBarrierMode mode) {
1524 int offset = kHeaderSize + index * kPointerSize;
1525 WRITE_FIELD(this, offset, value);
1526 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1527}
1528
1529
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001530void FixedArray::set_null_unchecked(int index) {
1531 ASSERT(index >= 0 && index < this->length());
1532 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1533 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1534}
1535
1536
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001537Object** FixedArray::data_start() {
1538 return HeapObject::RawField(this, kHeaderSize);
1539}
1540
1541
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001542bool DescriptorArray::IsEmpty() {
1543 ASSERT(this == Heap::empty_descriptor_array() ||
1544 this->length() > 2);
1545 return this == Heap::empty_descriptor_array();
1546}
1547
1548
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1550 Object* tmp = array->get(first);
1551 fast_set(array, first, array->get(second));
1552 fast_set(array, second, tmp);
1553}
1554
1555
1556int DescriptorArray::Search(String* name) {
1557 SLOW_ASSERT(IsSortedNoDuplicates());
1558
1559 // Check for empty descriptor array.
1560 int nof = number_of_descriptors();
1561 if (nof == 0) return kNotFound;
1562
1563 // Fast case: do linear search for small arrays.
1564 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001565 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001566 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001567 }
1568
1569 // Slow case: perform binary search.
1570 return BinarySearch(name, 0, nof - 1);
1571}
1572
1573
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001574int DescriptorArray::SearchWithCache(String* name) {
1575 int number = DescriptorLookupCache::Lookup(this, name);
1576 if (number == DescriptorLookupCache::kAbsent) {
1577 number = Search(name);
1578 DescriptorLookupCache::Update(this, name, number);
1579 }
1580 return number;
1581}
1582
1583
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001584String* DescriptorArray::GetKey(int descriptor_number) {
1585 ASSERT(descriptor_number < number_of_descriptors());
1586 return String::cast(get(ToKeyIndex(descriptor_number)));
1587}
1588
1589
1590Object* DescriptorArray::GetValue(int descriptor_number) {
1591 ASSERT(descriptor_number < number_of_descriptors());
1592 return GetContentArray()->get(ToValueIndex(descriptor_number));
1593}
1594
1595
1596Smi* DescriptorArray::GetDetails(int descriptor_number) {
1597 ASSERT(descriptor_number < number_of_descriptors());
1598 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1599}
1600
1601
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001602PropertyType DescriptorArray::GetType(int descriptor_number) {
1603 ASSERT(descriptor_number < number_of_descriptors());
1604 return PropertyDetails(GetDetails(descriptor_number)).type();
1605}
1606
1607
1608int DescriptorArray::GetFieldIndex(int descriptor_number) {
1609 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1610}
1611
1612
1613JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1614 return JSFunction::cast(GetValue(descriptor_number));
1615}
1616
1617
1618Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1619 ASSERT(GetType(descriptor_number) == CALLBACKS);
1620 return GetValue(descriptor_number);
1621}
1622
1623
1624AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1625 ASSERT(GetType(descriptor_number) == CALLBACKS);
1626 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1627 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1628}
1629
1630
1631bool DescriptorArray::IsProperty(int descriptor_number) {
1632 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1633}
1634
1635
1636bool DescriptorArray::IsTransition(int descriptor_number) {
1637 PropertyType t = GetType(descriptor_number);
1638 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1639}
1640
1641
1642bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1643 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1644}
1645
1646
1647bool DescriptorArray::IsDontEnum(int descriptor_number) {
1648 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1649}
1650
1651
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001652void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1653 desc->Init(GetKey(descriptor_number),
1654 GetValue(descriptor_number),
1655 GetDetails(descriptor_number));
1656}
1657
1658
1659void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1660 // Range check.
1661 ASSERT(descriptor_number < number_of_descriptors());
1662
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001663 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1665 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1666
1667 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1668 FixedArray* content_array = GetContentArray();
1669 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1670 fast_set(content_array, ToDetailsIndex(descriptor_number),
1671 desc->GetDetails().AsSmi());
1672}
1673
1674
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001675void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1676 Descriptor desc;
1677 src->Get(src_index, &desc);
1678 Set(index, &desc);
1679}
1680
1681
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001682void DescriptorArray::Swap(int first, int second) {
1683 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1684 FixedArray* content_array = GetContentArray();
1685 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1686 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1687}
1688
1689
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001690bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001691 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001692 if (!max_index_object->IsSmi()) return false;
1693 return 0 !=
1694 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1695}
1696
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001697uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001698 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001699 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001700 if (!max_index_object->IsSmi()) return 0;
1701 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1702 return value >> kRequiresSlowElementsTagSize;
1703}
1704
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001705void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001706 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001707}
1708
1709
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001710// ------------------------------------
1711// Cast operations
1712
1713
1714CAST_ACCESSOR(FixedArray)
1715CAST_ACCESSOR(DescriptorArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001716CAST_ACCESSOR(DeoptimizationInputData)
1717CAST_ACCESSOR(DeoptimizationOutputData)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001718CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001719CAST_ACCESSOR(JSFunctionResultCache)
ricow@chromium.org65fae842010-08-25 15:26:24 +00001720CAST_ACCESSOR(NormalizedMapCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001721CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001722CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001723CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001724CAST_ACCESSOR(String)
1725CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001726CAST_ACCESSOR(SeqAsciiString)
1727CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001728CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001729CAST_ACCESSOR(ExternalString)
1730CAST_ACCESSOR(ExternalAsciiString)
1731CAST_ACCESSOR(ExternalTwoByteString)
1732CAST_ACCESSOR(JSObject)
1733CAST_ACCESSOR(Smi)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001734CAST_ACCESSOR(HeapObject)
1735CAST_ACCESSOR(HeapNumber)
1736CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001737CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001738CAST_ACCESSOR(SharedFunctionInfo)
1739CAST_ACCESSOR(Map)
1740CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001741CAST_ACCESSOR(GlobalObject)
1742CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001743CAST_ACCESSOR(JSGlobalObject)
1744CAST_ACCESSOR(JSBuiltinsObject)
1745CAST_ACCESSOR(Code)
1746CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001747CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001748CAST_ACCESSOR(Proxy)
1749CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001750CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001751CAST_ACCESSOR(ExternalArray)
1752CAST_ACCESSOR(ExternalByteArray)
1753CAST_ACCESSOR(ExternalUnsignedByteArray)
1754CAST_ACCESSOR(ExternalShortArray)
1755CAST_ACCESSOR(ExternalUnsignedShortArray)
1756CAST_ACCESSOR(ExternalIntArray)
1757CAST_ACCESSOR(ExternalUnsignedIntArray)
1758CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001759CAST_ACCESSOR(Struct)
1760
1761
1762#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1763 STRUCT_LIST(MAKE_STRUCT_CAST)
1764#undef MAKE_STRUCT_CAST
1765
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001766
1767template <typename Shape, typename Key>
1768HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001769 ASSERT(obj->IsHashTable());
1770 return reinterpret_cast<HashTable*>(obj);
1771}
1772
1773
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001774SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1775SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1776
1777INT_ACCESSORS(PixelArray, length, kLengthOffset)
1778INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001779
1780
ager@chromium.orgac091b72010-05-05 07:34:42 +00001781SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001782
1783
1784uint32_t String::hash_field() {
1785 return READ_UINT32_FIELD(this, kHashFieldOffset);
1786}
1787
1788
1789void String::set_hash_field(uint32_t value) {
1790 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001791#if V8_HOST_ARCH_64_BIT
1792 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1793#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001794}
1795
1796
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001797bool String::Equals(String* other) {
1798 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001799 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1800 return false;
1801 }
1802 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001803}
1804
1805
lrn@chromium.org303ada72010-10-27 09:33:13 +00001806MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001807 if (!StringShape(this).IsCons()) return this;
1808 ConsString* cons = ConsString::cast(this);
1809 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001810 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001811}
1812
1813
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001814String* String::TryFlattenGetString(PretenureFlag pretenure) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001815 MaybeObject* flat = TryFlatten(pretenure);
1816 Object* successfully_flattened;
1817 if (flat->ToObject(&successfully_flattened)) {
1818 return String::cast(successfully_flattened);
1819 }
1820 return this;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001821}
1822
1823
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001824uint16_t String::Get(int index) {
1825 ASSERT(index >= 0 && index < length());
1826 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001827 case kSeqStringTag | kAsciiStringTag:
1828 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1829 case kSeqStringTag | kTwoByteStringTag:
1830 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1831 case kConsStringTag | kAsciiStringTag:
1832 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001833 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001834 case kExternalStringTag | kAsciiStringTag:
1835 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1836 case kExternalStringTag | kTwoByteStringTag:
1837 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001838 default:
1839 break;
1840 }
1841
1842 UNREACHABLE();
1843 return 0;
1844}
1845
1846
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001847void String::Set(int index, uint16_t value) {
1848 ASSERT(index >= 0 && index < length());
1849 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001850
ager@chromium.org5ec48922009-05-05 07:25:34 +00001851 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001852 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1853 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001854}
1855
1856
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001857bool String::IsFlat() {
1858 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001859 case kConsStringTag: {
1860 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001861 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001862 return second->length() == 0;
1863 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001864 default:
1865 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001866 }
1867}
1868
1869
ager@chromium.org7c537e22008-10-16 08:43:32 +00001870uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001871 ASSERT(index >= 0 && index < length());
1872 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1873}
1874
1875
ager@chromium.org7c537e22008-10-16 08:43:32 +00001876void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001877 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1878 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1879 static_cast<byte>(value));
1880}
1881
1882
ager@chromium.org7c537e22008-10-16 08:43:32 +00001883Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001884 return FIELD_ADDR(this, kHeaderSize);
1885}
1886
1887
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001888char* SeqAsciiString::GetChars() {
1889 return reinterpret_cast<char*>(GetCharsAddress());
1890}
1891
1892
ager@chromium.org7c537e22008-10-16 08:43:32 +00001893Address SeqTwoByteString::GetCharsAddress() {
1894 return FIELD_ADDR(this, kHeaderSize);
1895}
1896
1897
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001898uc16* SeqTwoByteString::GetChars() {
1899 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1900}
1901
1902
ager@chromium.org7c537e22008-10-16 08:43:32 +00001903uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001904 ASSERT(index >= 0 && index < length());
1905 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1906}
1907
1908
ager@chromium.org7c537e22008-10-16 08:43:32 +00001909void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001910 ASSERT(index >= 0 && index < length());
1911 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1912}
1913
1914
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001915int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001916 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001917}
1918
1919
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001920int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001921 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001922}
1923
1924
ager@chromium.org870a0b62008-11-04 11:43:05 +00001925String* ConsString::first() {
1926 return String::cast(READ_FIELD(this, kFirstOffset));
1927}
1928
1929
1930Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001931 return READ_FIELD(this, kFirstOffset);
1932}
1933
1934
ager@chromium.org870a0b62008-11-04 11:43:05 +00001935void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001936 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001937 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001938}
1939
1940
ager@chromium.org870a0b62008-11-04 11:43:05 +00001941String* ConsString::second() {
1942 return String::cast(READ_FIELD(this, kSecondOffset));
1943}
1944
1945
1946Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001947 return READ_FIELD(this, kSecondOffset);
1948}
1949
1950
ager@chromium.org870a0b62008-11-04 11:43:05 +00001951void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001952 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001953 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001954}
1955
1956
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001957ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1958 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1959}
1960
1961
1962void ExternalAsciiString::set_resource(
1963 ExternalAsciiString::Resource* resource) {
1964 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1965}
1966
1967
1968ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1969 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1970}
1971
1972
1973void ExternalTwoByteString::set_resource(
1974 ExternalTwoByteString::Resource* resource) {
1975 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1976}
1977
1978
ager@chromium.orgac091b72010-05-05 07:34:42 +00001979void JSFunctionResultCache::MakeZeroSize() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001980 set_finger_index(kEntriesIndex);
1981 set_size(kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001982}
1983
1984
1985void JSFunctionResultCache::Clear() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001986 int cache_size = size();
ager@chromium.orgac091b72010-05-05 07:34:42 +00001987 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001988 MemsetPointer(entries_start,
1989 Heap::the_hole_value(),
1990 cache_size - kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001991 MakeZeroSize();
1992}
1993
1994
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001995int JSFunctionResultCache::size() {
1996 return Smi::cast(get(kCacheSizeIndex))->value();
1997}
1998
1999
2000void JSFunctionResultCache::set_size(int size) {
2001 set(kCacheSizeIndex, Smi::FromInt(size));
2002}
2003
2004
2005int JSFunctionResultCache::finger_index() {
2006 return Smi::cast(get(kFingerIndex))->value();
2007}
2008
2009
2010void JSFunctionResultCache::set_finger_index(int finger_index) {
2011 set(kFingerIndex, Smi::FromInt(finger_index));
2012}
2013
2014
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002015byte ByteArray::get(int index) {
2016 ASSERT(index >= 0 && index < this->length());
2017 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2018}
2019
2020
2021void ByteArray::set(int index, byte value) {
2022 ASSERT(index >= 0 && index < this->length());
2023 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2024}
2025
2026
2027int ByteArray::get_int(int index) {
2028 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2029 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2030}
2031
2032
2033ByteArray* ByteArray::FromDataStartAddress(Address address) {
2034 ASSERT_TAG_ALIGNED(address);
2035 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2036}
2037
2038
2039Address ByteArray::GetDataStartAddress() {
2040 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2041}
2042
2043
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002044uint8_t* PixelArray::external_pointer() {
2045 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2046 return reinterpret_cast<uint8_t*>(ptr);
2047}
2048
2049
2050void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
2051 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2052 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2053}
2054
2055
2056uint8_t PixelArray::get(int index) {
2057 ASSERT((index >= 0) && (index < this->length()));
2058 uint8_t* ptr = external_pointer();
2059 return ptr[index];
2060}
2061
2062
2063void PixelArray::set(int index, uint8_t value) {
2064 ASSERT((index >= 0) && (index < this->length()));
2065 uint8_t* ptr = external_pointer();
2066 ptr[index] = value;
2067}
2068
2069
ager@chromium.org3811b432009-10-28 14:53:37 +00002070void* ExternalArray::external_pointer() {
2071 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2072 return reinterpret_cast<void*>(ptr);
2073}
2074
2075
2076void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2077 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2078 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2079}
2080
2081
2082int8_t ExternalByteArray::get(int index) {
2083 ASSERT((index >= 0) && (index < this->length()));
2084 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2085 return ptr[index];
2086}
2087
2088
2089void ExternalByteArray::set(int index, int8_t value) {
2090 ASSERT((index >= 0) && (index < this->length()));
2091 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2092 ptr[index] = value;
2093}
2094
2095
2096uint8_t ExternalUnsignedByteArray::get(int index) {
2097 ASSERT((index >= 0) && (index < this->length()));
2098 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2099 return ptr[index];
2100}
2101
2102
2103void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2104 ASSERT((index >= 0) && (index < this->length()));
2105 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2106 ptr[index] = value;
2107}
2108
2109
2110int16_t ExternalShortArray::get(int index) {
2111 ASSERT((index >= 0) && (index < this->length()));
2112 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2113 return ptr[index];
2114}
2115
2116
2117void ExternalShortArray::set(int index, int16_t value) {
2118 ASSERT((index >= 0) && (index < this->length()));
2119 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2120 ptr[index] = value;
2121}
2122
2123
2124uint16_t ExternalUnsignedShortArray::get(int index) {
2125 ASSERT((index >= 0) && (index < this->length()));
2126 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2127 return ptr[index];
2128}
2129
2130
2131void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2132 ASSERT((index >= 0) && (index < this->length()));
2133 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2134 ptr[index] = value;
2135}
2136
2137
2138int32_t ExternalIntArray::get(int index) {
2139 ASSERT((index >= 0) && (index < this->length()));
2140 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2141 return ptr[index];
2142}
2143
2144
2145void ExternalIntArray::set(int index, int32_t value) {
2146 ASSERT((index >= 0) && (index < this->length()));
2147 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2148 ptr[index] = value;
2149}
2150
2151
2152uint32_t ExternalUnsignedIntArray::get(int index) {
2153 ASSERT((index >= 0) && (index < this->length()));
2154 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2155 return ptr[index];
2156}
2157
2158
2159void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2160 ASSERT((index >= 0) && (index < this->length()));
2161 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2162 ptr[index] = value;
2163}
2164
2165
2166float ExternalFloatArray::get(int index) {
2167 ASSERT((index >= 0) && (index < this->length()));
2168 float* ptr = static_cast<float*>(external_pointer());
2169 return ptr[index];
2170}
2171
2172
2173void ExternalFloatArray::set(int index, float value) {
2174 ASSERT((index >= 0) && (index < this->length()));
2175 float* ptr = static_cast<float*>(external_pointer());
2176 ptr[index] = value;
2177}
2178
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002179
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00002180int Map::visitor_id() {
2181 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2182}
2183
2184
2185void Map::set_visitor_id(int id) {
2186 ASSERT(0 <= id && id < 256);
2187 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2188}
2189
ager@chromium.org3811b432009-10-28 14:53:37 +00002190
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002191int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002192 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2193}
2194
2195
2196int Map::inobject_properties() {
2197 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002198}
2199
2200
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002201int Map::pre_allocated_property_fields() {
2202 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2203}
2204
2205
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002206int HeapObject::SizeFromMap(Map* map) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002207 int instance_size = map->instance_size();
2208 if (instance_size != kVariableSizeSentinel) return instance_size;
2209 // We can ignore the "symbol" bit becase it is only set for symbols
2210 // and implies a string type.
2211 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002212 // Only inline the most frequent cases.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002213 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002214 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002215 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002216 if (instance_type == ASCII_STRING_TYPE) {
2217 return SeqAsciiString::SizeFor(
2218 reinterpret_cast<SeqAsciiString*>(this)->length());
2219 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002220 if (instance_type == BYTE_ARRAY_TYPE) {
2221 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2222 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002223 if (instance_type == STRING_TYPE) {
2224 return SeqTwoByteString::SizeFor(
2225 reinterpret_cast<SeqTwoByteString*>(this)->length());
2226 }
2227 ASSERT(instance_type == CODE_TYPE);
2228 return reinterpret_cast<Code*>(this)->CodeSize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002229}
2230
2231
2232void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002233 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002234 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002235 ASSERT(0 <= value && value < 256);
2236 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2237}
2238
2239
ager@chromium.org7c537e22008-10-16 08:43:32 +00002240void Map::set_inobject_properties(int value) {
2241 ASSERT(0 <= value && value < 256);
2242 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2243}
2244
2245
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002246void Map::set_pre_allocated_property_fields(int value) {
2247 ASSERT(0 <= value && value < 256);
2248 WRITE_BYTE_FIELD(this,
2249 kPreAllocatedPropertyFieldsOffset,
2250 static_cast<byte>(value));
2251}
2252
2253
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002254InstanceType Map::instance_type() {
2255 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2256}
2257
2258
2259void Map::set_instance_type(InstanceType value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002260 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2261}
2262
2263
2264int Map::unused_property_fields() {
2265 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2266}
2267
2268
2269void Map::set_unused_property_fields(int value) {
2270 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2271}
2272
2273
2274byte Map::bit_field() {
2275 return READ_BYTE_FIELD(this, kBitFieldOffset);
2276}
2277
2278
2279void Map::set_bit_field(byte value) {
2280 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2281}
2282
2283
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002284byte Map::bit_field2() {
2285 return READ_BYTE_FIELD(this, kBitField2Offset);
2286}
2287
2288
2289void Map::set_bit_field2(byte value) {
2290 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2291}
2292
2293
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002294void Map::set_non_instance_prototype(bool value) {
2295 if (value) {
2296 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2297 } else {
2298 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2299 }
2300}
2301
2302
2303bool Map::has_non_instance_prototype() {
2304 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2305}
2306
2307
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002308void Map::set_function_with_prototype(bool value) {
2309 if (value) {
2310 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2311 } else {
2312 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2313 }
2314}
2315
2316
2317bool Map::function_with_prototype() {
2318 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2319}
2320
2321
ager@chromium.org870a0b62008-11-04 11:43:05 +00002322void Map::set_is_access_check_needed(bool access_check_needed) {
2323 if (access_check_needed) {
2324 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2325 } else {
2326 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2327 }
2328}
2329
2330
2331bool Map::is_access_check_needed() {
2332 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2333}
2334
2335
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002336void Map::set_is_extensible(bool value) {
2337 if (value) {
2338 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2339 } else {
2340 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2341 }
2342}
2343
2344bool Map::is_extensible() {
2345 return ((1 << kIsExtensible) & bit_field2()) != 0;
2346}
2347
2348
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002349void Map::set_attached_to_shared_function_info(bool value) {
2350 if (value) {
2351 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2352 } else {
2353 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2354 }
2355}
2356
2357bool Map::attached_to_shared_function_info() {
2358 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2359}
2360
2361
2362void Map::set_is_shared(bool value) {
2363 if (value) {
2364 set_bit_field2(bit_field2() | (1 << kIsShared));
2365 } else {
2366 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2367 }
2368}
2369
2370bool Map::is_shared() {
2371 return ((1 << kIsShared) & bit_field2()) != 0;
2372}
2373
2374
2375JSFunction* Map::unchecked_constructor() {
2376 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2377}
2378
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002379
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002380Code::Flags Code::flags() {
2381 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2382}
2383
2384
2385void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002386 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002387 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002388 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2389 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002390 ExtractArgumentsCountFromFlags(flags) >= 0);
2391 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2392}
2393
2394
2395Code::Kind Code::kind() {
2396 return ExtractKindFromFlags(flags());
2397}
2398
2399
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002400InLoopFlag Code::ic_in_loop() {
2401 return ExtractICInLoopFromFlags(flags());
2402}
2403
2404
kasper.lund7276f142008-07-30 08:49:36 +00002405InlineCacheState Code::ic_state() {
2406 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002407 // Only allow uninitialized or debugger states for non-IC code
2408 // objects. This is used in the debugger to determine whether or not
2409 // a call to code object has been replaced with a debug break call.
2410 ASSERT(is_inline_cache_stub() ||
2411 result == UNINITIALIZED ||
2412 result == DEBUG_BREAK ||
2413 result == DEBUG_PREPARE_STEP_IN);
2414 return result;
2415}
2416
2417
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002418Code::ExtraICState Code::extra_ic_state() {
2419 ASSERT(is_inline_cache_stub());
2420 return ExtractExtraICStateFromFlags(flags());
2421}
2422
2423
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002424PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002425 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002426 return ExtractTypeFromFlags(flags());
2427}
2428
2429
2430int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002431 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002432 return ExtractArgumentsCountFromFlags(flags());
2433}
2434
2435
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002436int Code::major_key() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002437 ASSERT(kind() == STUB ||
2438 kind() == BINARY_OP_IC ||
2439 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2440 kind() == COMPARE_IC);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002441 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
kasper.lund7276f142008-07-30 08:49:36 +00002442}
2443
2444
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002445void Code::set_major_key(int major) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002446 ASSERT(kind() == STUB ||
2447 kind() == BINARY_OP_IC ||
2448 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2449 kind() == COMPARE_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002450 ASSERT(0 <= major && major < 256);
2451 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002452}
2453
2454
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002455bool Code::optimizable() {
2456 ASSERT(kind() == FUNCTION);
2457 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2458}
2459
2460
2461void Code::set_optimizable(bool value) {
2462 ASSERT(kind() == FUNCTION);
2463 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2464}
2465
2466
2467bool Code::has_deoptimization_support() {
2468 ASSERT(kind() == FUNCTION);
2469 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2470}
2471
2472
2473void Code::set_has_deoptimization_support(bool value) {
2474 ASSERT(kind() == FUNCTION);
2475 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2476}
2477
2478
2479int Code::allow_osr_at_loop_nesting_level() {
2480 ASSERT(kind() == FUNCTION);
2481 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2482}
2483
2484
2485void Code::set_allow_osr_at_loop_nesting_level(int level) {
2486 ASSERT(kind() == FUNCTION);
2487 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2488 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2489}
2490
2491
2492unsigned Code::stack_slots() {
2493 ASSERT(kind() == OPTIMIZED_FUNCTION);
2494 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2495}
2496
2497
2498void Code::set_stack_slots(unsigned slots) {
2499 ASSERT(kind() == OPTIMIZED_FUNCTION);
2500 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2501}
2502
2503
2504unsigned Code::safepoint_table_start() {
2505 ASSERT(kind() == OPTIMIZED_FUNCTION);
2506 return READ_UINT32_FIELD(this, kSafepointTableStartOffset);
2507}
2508
2509
2510void Code::set_safepoint_table_start(unsigned offset) {
2511 ASSERT(kind() == OPTIMIZED_FUNCTION);
2512 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2513 WRITE_UINT32_FIELD(this, kSafepointTableStartOffset, offset);
2514}
2515
2516
2517unsigned Code::stack_check_table_start() {
2518 ASSERT(kind() == FUNCTION);
2519 return READ_UINT32_FIELD(this, kStackCheckTableStartOffset);
2520}
2521
2522
2523void Code::set_stack_check_table_start(unsigned offset) {
2524 ASSERT(kind() == FUNCTION);
2525 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2526 WRITE_UINT32_FIELD(this, kStackCheckTableStartOffset, offset);
2527}
2528
2529
2530CheckType Code::check_type() {
2531 ASSERT(is_call_stub() || is_keyed_call_stub());
2532 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2533 return static_cast<CheckType>(type);
2534}
2535
2536
2537void Code::set_check_type(CheckType value) {
2538 ASSERT(is_call_stub() || is_keyed_call_stub());
2539 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2540}
2541
2542
2543byte Code::binary_op_type() {
2544 ASSERT(is_binary_op_stub());
2545 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2546}
2547
2548
2549void Code::set_binary_op_type(byte value) {
2550 ASSERT(is_binary_op_stub());
2551 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2552}
2553
2554
2555byte Code::type_recording_binary_op_type() {
2556 ASSERT(is_type_recording_binary_op_stub());
2557 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2558}
2559
2560
2561void Code::set_type_recording_binary_op_type(byte value) {
2562 ASSERT(is_type_recording_binary_op_stub());
2563 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2564}
2565
2566
2567byte Code::type_recording_binary_op_result_type() {
2568 ASSERT(is_type_recording_binary_op_stub());
2569 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2570}
2571
2572
2573void Code::set_type_recording_binary_op_result_type(byte value) {
2574 ASSERT(is_type_recording_binary_op_stub());
2575 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2576}
2577
2578
2579byte Code::compare_state() {
2580 ASSERT(is_compare_ic_stub());
2581 return READ_BYTE_FIELD(this, kCompareStateOffset);
2582}
2583
2584
2585void Code::set_compare_state(byte value) {
2586 ASSERT(is_compare_ic_stub());
2587 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2588}
2589
2590
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002591bool Code::is_inline_cache_stub() {
2592 Kind kind = this->kind();
2593 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2594}
2595
2596
2597Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002598 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002599 InlineCacheState ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002600 ExtraICState extra_ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002601 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002602 int argc,
2603 InlineCacheHolderFlag holder) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002604 // Extra IC state is only allowed for monomorphic call IC stubs.
2605 ASSERT(extra_ic_state == kNoExtraICState ||
2606 (kind == CALL_IC && (ic_state == MONOMORPHIC ||
2607 ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002608 // Compute the bit mask.
2609 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002610 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002611 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002612 bits |= type << kFlagsTypeShift;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002613 bits |= extra_ic_state << kFlagsExtraICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002614 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002615 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002616 // Cast to flags and validate result before returning it.
2617 Flags result = static_cast<Flags>(bits);
2618 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002619 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002620 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002621 ASSERT(ExtractTypeFromFlags(result) == type);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002622 ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002623 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2624 return result;
2625}
2626
2627
2628Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2629 PropertyType type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002630 ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002631 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002632 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002633 int argc) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002634 return ComputeFlags(
2635 kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002636}
2637
2638
2639Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2640 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2641 return static_cast<Kind>(bits);
2642}
2643
2644
kasper.lund7276f142008-07-30 08:49:36 +00002645InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2646 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002647 return static_cast<InlineCacheState>(bits);
2648}
2649
2650
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002651Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
2652 int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
2653 return static_cast<ExtraICState>(bits);
2654}
2655
2656
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002657InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2658 int bits = (flags & kFlagsICInLoopMask);
2659 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2660}
2661
2662
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002663PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2664 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2665 return static_cast<PropertyType>(bits);
2666}
2667
2668
2669int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2670 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2671}
2672
2673
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002674InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2675 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2676 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2677}
2678
2679
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002680Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2681 int bits = flags & ~kFlagsTypeMask;
2682 return static_cast<Flags>(bits);
2683}
2684
2685
ager@chromium.org8bb60582008-12-11 12:02:20 +00002686Code* Code::GetCodeFromTargetAddress(Address address) {
2687 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2688 // GetCodeFromTargetAddress might be called when marking objects during mark
2689 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2690 // Code::cast. Code::cast does not work when the object's map is
2691 // marked.
2692 Code* result = reinterpret_cast<Code*>(code);
2693 return result;
2694}
2695
2696
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002697Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2698 return HeapObject::
2699 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2700}
2701
2702
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002703Object* Map::prototype() {
2704 return READ_FIELD(this, kPrototypeOffset);
2705}
2706
2707
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002708void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002709 ASSERT(value->IsNull() || value->IsJSObject());
2710 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002711 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002712}
2713
2714
lrn@chromium.org303ada72010-10-27 09:33:13 +00002715MaybeObject* Map::GetFastElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002716 if (has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002717 Object* obj;
2718 { MaybeObject* maybe_obj = CopyDropTransitions();
2719 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2720 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002721 Map* new_map = Map::cast(obj);
2722 new_map->set_has_fast_elements(true);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002723 Counters::map_slow_to_fast_elements.Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002724 return new_map;
2725}
2726
2727
lrn@chromium.org303ada72010-10-27 09:33:13 +00002728MaybeObject* Map::GetSlowElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002729 if (!has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002730 Object* obj;
2731 { MaybeObject* maybe_obj = CopyDropTransitions();
2732 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2733 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002734 Map* new_map = Map::cast(obj);
2735 new_map->set_has_fast_elements(false);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002736 Counters::map_fast_to_slow_elements.Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002737 return new_map;
2738}
2739
2740
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002741ACCESSORS(Map, instance_descriptors, DescriptorArray,
2742 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002743ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002744ACCESSORS(Map, constructor, Object, kConstructorOffset)
2745
2746ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2747ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002748ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002749
2750ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2751ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002752ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002753
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002754ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002755
2756ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2757ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2758ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2759ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2760ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2761
2762ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2763ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2764ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2765
2766ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2767ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2768ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2769ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2770ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2771ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2772
2773ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2774ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2775
2776ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2777ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2778
2779ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2780ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2782 kPropertyAccessorsOffset)
2783ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2784 kPrototypeTemplateOffset)
2785ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2786ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2787 kNamedPropertyHandlerOffset)
2788ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2789 kIndexedPropertyHandlerOffset)
2790ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2791 kInstanceTemplateOffset)
2792ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2793ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002794ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2795 kInstanceCallHandlerOffset)
2796ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2797 kAccessCheckInfoOffset)
2798ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2799
2800ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002801ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2802 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002803
2804ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2805ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2806
2807ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2808
2809ACCESSORS(Script, source, Object, kSourceOffset)
2810ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002811ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002812ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2813ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002814ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002815ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002816ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2817ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002818ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002819ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002820ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002821ACCESSORS(Script, eval_from_instructions_offset, Smi,
2822 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002823
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002824#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002825ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2826ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2827ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2828ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2829
2830ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2831ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2832ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2833ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002834#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002835
2836ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002837ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002838ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002839ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2840 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002841ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002842ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2843ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002844ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002845ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2846 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002847
2848BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2849 kHiddenPrototypeBit)
2850BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2851BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2852 kNeedsAccessCheckBit)
2853BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2854 kIsExpressionBit)
2855BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2856 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002857BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002858 has_only_simple_this_property_assignments,
2859 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002860BOOL_ACCESSORS(SharedFunctionInfo,
2861 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002862 try_full_codegen,
2863 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002864BOOL_ACCESSORS(SharedFunctionInfo,
2865 compiler_hints,
2866 allows_lazy_compilation,
2867 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002868
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002869
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002870#if V8_HOST_ARCH_32_BIT
2871SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2872SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002873 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002874SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002875 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002876SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2877SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002878 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002879SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2880SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002881 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002882SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002883 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002884SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002885 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002886SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002887#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002888
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002889#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002890 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002891 int holder::name() { \
2892 int value = READ_INT_FIELD(this, offset); \
2893 ASSERT(kHeapObjectTag == 1); \
2894 ASSERT((value & kHeapObjectTag) == 0); \
2895 return value >> 1; \
2896 } \
2897 void holder::set_##name(int value) { \
2898 ASSERT(kHeapObjectTag == 1); \
2899 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2900 (value & 0xC0000000) == 0x000000000); \
2901 WRITE_INT_FIELD(this, \
2902 offset, \
2903 (value << 1) & ~kHeapObjectTag); \
2904 }
2905
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002906#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2907 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002908 INT_ACCESSORS(holder, name, offset)
2909
2910
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002911PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002912PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2913 formal_parameter_count,
2914 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002915
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002916PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2917 expected_nof_properties,
2918 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002919PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2920
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002921PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
2922PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2923 start_position_and_type,
2924 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002925
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002926PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2927 function_token_position,
2928 kFunctionTokenPositionOffset)
2929PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2930 compiler_hints,
2931 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002932
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002933PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2934 this_property_assignments_count,
2935 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002936PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002937#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002938
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002939
2940int SharedFunctionInfo::construction_count() {
2941 return READ_BYTE_FIELD(this, kConstructionCountOffset);
2942}
2943
2944
2945void SharedFunctionInfo::set_construction_count(int value) {
2946 ASSERT(0 <= value && value < 256);
2947 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
2948}
2949
2950
2951bool SharedFunctionInfo::live_objects_may_exist() {
2952 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
2953}
2954
2955
2956void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
2957 if (value) {
2958 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
2959 } else {
2960 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
2961 }
2962}
2963
2964
2965bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
2966 return initial_map() != Heap::undefined_value();
2967}
2968
2969
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002970bool SharedFunctionInfo::optimization_disabled() {
2971 return BooleanBit::get(compiler_hints(), kOptimizationDisabled);
2972}
2973
2974
2975void SharedFunctionInfo::set_optimization_disabled(bool disable) {
2976 set_compiler_hints(BooleanBit::set(compiler_hints(),
2977 kOptimizationDisabled,
2978 disable));
2979 // If disabling optimizations we reflect that in the code object so
2980 // it will not be counted as optimizable code.
2981 if ((code()->kind() == Code::FUNCTION) && disable) {
2982 code()->set_optimizable(false);
2983 }
2984}
2985
2986
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002987ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2988ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2989
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002990bool Script::HasValidSource() {
2991 Object* src = this->source();
2992 if (!src->IsString()) return true;
2993 String* src_str = String::cast(src);
2994 if (!StringShape(src_str).IsExternal()) return true;
2995 if (src_str->IsAsciiRepresentation()) {
2996 return ExternalAsciiString::cast(src)->resource() != NULL;
2997 } else if (src_str->IsTwoByteRepresentation()) {
2998 return ExternalTwoByteString::cast(src)->resource() != NULL;
2999 }
3000 return true;
3001}
3002
3003
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003004void SharedFunctionInfo::DontAdaptArguments() {
3005 ASSERT(code()->kind() == Code::BUILTIN);
3006 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3007}
3008
3009
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003010int SharedFunctionInfo::start_position() {
3011 return start_position_and_type() >> kStartPositionShift;
3012}
3013
3014
3015void SharedFunctionInfo::set_start_position(int start_position) {
3016 set_start_position_and_type((start_position << kStartPositionShift)
3017 | (start_position_and_type() & ~kStartPositionMask));
3018}
3019
3020
3021Code* SharedFunctionInfo::code() {
3022 return Code::cast(READ_FIELD(this, kCodeOffset));
3023}
3024
3025
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003026Code* SharedFunctionInfo::unchecked_code() {
3027 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3028}
3029
3030
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003031void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003032 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003033 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003034}
3035
3036
ager@chromium.orgb5737492010-07-15 09:29:43 +00003037SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3038 return reinterpret_cast<SerializedScopeInfo*>(
3039 READ_FIELD(this, kScopeInfoOffset));
3040}
3041
3042
3043void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3044 WriteBarrierMode mode) {
3045 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3046 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
3047}
3048
3049
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003050Smi* SharedFunctionInfo::deopt_counter() {
3051 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3052}
3053
3054
3055void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3056 WRITE_FIELD(this, kDeoptCounterOffset, value);
3057}
3058
3059
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003060bool SharedFunctionInfo::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003061 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003062}
3063
3064
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003065bool SharedFunctionInfo::IsApiFunction() {
3066 return function_data()->IsFunctionTemplateInfo();
3067}
3068
3069
3070FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3071 ASSERT(IsApiFunction());
3072 return FunctionTemplateInfo::cast(function_data());
3073}
3074
3075
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003076bool SharedFunctionInfo::HasBuiltinFunctionId() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003077 return function_data()->IsSmi();
3078}
3079
3080
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003081BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3082 ASSERT(HasBuiltinFunctionId());
3083 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003084}
3085
3086
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003087int SharedFunctionInfo::code_age() {
3088 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3089}
3090
3091
3092void SharedFunctionInfo::set_code_age(int code_age) {
3093 set_compiler_hints(compiler_hints() |
3094 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3095}
3096
3097
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003098bool SharedFunctionInfo::has_deoptimization_support() {
3099 Code* code = this->code();
3100 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3101}
3102
3103
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003104bool JSFunction::IsBuiltin() {
3105 return context()->global()->IsJSBuiltinsObject();
3106}
3107
3108
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003109bool JSFunction::NeedsArgumentsAdaption() {
3110 return shared()->formal_parameter_count() !=
3111 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3112}
3113
3114
3115bool JSFunction::IsOptimized() {
3116 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3117}
3118
3119
3120bool JSFunction::IsMarkedForLazyRecompilation() {
3121 return code() == Builtins::builtin(Builtins::LazyRecompile);
3122}
3123
3124
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003125Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003126 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003127}
3128
3129
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003130Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003131 return reinterpret_cast<Code*>(
3132 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003133}
3134
3135
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003136void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003137 // Skip the write barrier because code is never in new space.
3138 ASSERT(!Heap::InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003139 Address entry = value->entry();
3140 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003141}
3142
3143
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003144void JSFunction::ReplaceCode(Code* code) {
3145 bool was_optimized = IsOptimized();
3146 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3147
3148 set_code(code);
3149
3150 // Add/remove the function from the list of optimized functions for this
3151 // context based on the state change.
3152 if (!was_optimized && is_optimized) {
3153 context()->global_context()->AddOptimizedFunction(this);
3154 }
3155 if (was_optimized && !is_optimized) {
3156 context()->global_context()->RemoveOptimizedFunction(this);
3157 }
3158}
3159
3160
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003161Context* JSFunction::context() {
3162 return Context::cast(READ_FIELD(this, kContextOffset));
3163}
3164
3165
3166Object* JSFunction::unchecked_context() {
3167 return READ_FIELD(this, kContextOffset);
3168}
3169
3170
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003171SharedFunctionInfo* JSFunction::unchecked_shared() {
3172 return reinterpret_cast<SharedFunctionInfo*>(
3173 READ_FIELD(this, kSharedFunctionInfoOffset));
3174}
3175
3176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003177void JSFunction::set_context(Object* value) {
3178 ASSERT(value == Heap::undefined_value() || value->IsContext());
3179 WRITE_FIELD(this, kContextOffset, value);
3180 WRITE_BARRIER(this, kContextOffset);
3181}
3182
3183ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3184 kPrototypeOrInitialMapOffset)
3185
3186
3187Map* JSFunction::initial_map() {
3188 return Map::cast(prototype_or_initial_map());
3189}
3190
3191
3192void JSFunction::set_initial_map(Map* value) {
3193 set_prototype_or_initial_map(value);
3194}
3195
3196
3197bool JSFunction::has_initial_map() {
3198 return prototype_or_initial_map()->IsMap();
3199}
3200
3201
3202bool JSFunction::has_instance_prototype() {
3203 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3204}
3205
3206
3207bool JSFunction::has_prototype() {
3208 return map()->has_non_instance_prototype() || has_instance_prototype();
3209}
3210
3211
3212Object* JSFunction::instance_prototype() {
3213 ASSERT(has_instance_prototype());
3214 if (has_initial_map()) return initial_map()->prototype();
3215 // When there is no initial map and the prototype is a JSObject, the
3216 // initial map field is used for the prototype field.
3217 return prototype_or_initial_map();
3218}
3219
3220
3221Object* JSFunction::prototype() {
3222 ASSERT(has_prototype());
3223 // If the function's prototype property has been set to a non-JSObject
3224 // value, that value is stored in the constructor field of the map.
3225 if (map()->has_non_instance_prototype()) return map()->constructor();
3226 return instance_prototype();
3227}
3228
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003229bool JSFunction::should_have_prototype() {
3230 return map()->function_with_prototype();
3231}
3232
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003233
3234bool JSFunction::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003235 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003236}
3237
3238
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003239int JSFunction::NumberOfLiterals() {
3240 return literals()->length();
3241}
3242
3243
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003244Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003245 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003246 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003247}
3248
3249
3250void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3251 Object* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003252 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003253 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3254 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3255}
3256
3257
3258Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003259 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003260 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3261}
3262
3263
3264void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3265 Code* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003266 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003267 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3268 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003269}
3270
3271
3272Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00003273 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003274}
3275
3276
3277void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00003278 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003279}
3280
3281
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003282ACCESSORS(JSValue, value, Object, kValueOffset)
3283
3284
3285JSValue* JSValue::cast(Object* obj) {
3286 ASSERT(obj->IsJSValue());
3287 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3288 return reinterpret_cast<JSValue*>(obj);
3289}
3290
3291
3292INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003293ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003294ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003295
3296
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003297byte* Code::instruction_start() {
3298 return FIELD_ADDR(this, kHeaderSize);
3299}
3300
3301
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003302byte* Code::instruction_end() {
3303 return instruction_start() + instruction_size();
3304}
3305
3306
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003307int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003308 return RoundUp(instruction_size(), kObjectAlignment);
3309}
3310
3311
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003312FixedArray* Code::unchecked_deoptimization_data() {
3313 return reinterpret_cast<FixedArray*>(
3314 READ_FIELD(this, kDeoptimizationDataOffset));
3315}
3316
3317
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003318ByteArray* Code::unchecked_relocation_info() {
3319 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003320}
3321
3322
3323byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003324 return unchecked_relocation_info()->GetDataStartAddress();
3325}
3326
3327
3328int Code::relocation_size() {
3329 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003330}
3331
3332
3333byte* Code::entry() {
3334 return instruction_start();
3335}
3336
3337
3338bool Code::contains(byte* pc) {
3339 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003340 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003341}
3342
3343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003344ACCESSORS(JSArray, length, Object, kLengthOffset)
3345
3346
ager@chromium.org236ad962008-09-25 09:45:57 +00003347ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003348
3349
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003350JSRegExp::Type JSRegExp::TypeTag() {
3351 Object* data = this->data();
3352 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3353 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3354 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003355}
3356
3357
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003358int JSRegExp::CaptureCount() {
3359 switch (TypeTag()) {
3360 case ATOM:
3361 return 0;
3362 case IRREGEXP:
3363 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3364 default:
3365 UNREACHABLE();
3366 return -1;
3367 }
3368}
3369
3370
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003371JSRegExp::Flags JSRegExp::GetFlags() {
3372 ASSERT(this->data()->IsFixedArray());
3373 Object* data = this->data();
3374 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3375 return Flags(smi->value());
3376}
3377
3378
3379String* JSRegExp::Pattern() {
3380 ASSERT(this->data()->IsFixedArray());
3381 Object* data = this->data();
3382 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3383 return pattern;
3384}
3385
3386
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003387Object* JSRegExp::DataAt(int index) {
3388 ASSERT(TypeTag() != NOT_COMPILED);
3389 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003390}
3391
3392
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003393void JSRegExp::SetDataAt(int index, Object* value) {
3394 ASSERT(TypeTag() != NOT_COMPILED);
3395 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3396 FixedArray::cast(data())->set(index, value);
3397}
3398
3399
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003400JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003401 if (map()->has_fast_elements()) {
3402 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3403 elements()->map() == Heap::fixed_cow_array_map());
3404 return FAST_ELEMENTS;
3405 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003406 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003407 if (array->IsFixedArray()) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003408 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3409 // FixedArray, but FAST_ELEMENTS is already handled above.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003410 ASSERT(array->IsDictionary());
3411 return DICTIONARY_ELEMENTS;
3412 }
ager@chromium.org3811b432009-10-28 14:53:37 +00003413 if (array->IsExternalArray()) {
3414 switch (array->map()->instance_type()) {
3415 case EXTERNAL_BYTE_ARRAY_TYPE:
3416 return EXTERNAL_BYTE_ELEMENTS;
3417 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3418 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3419 case EXTERNAL_SHORT_ARRAY_TYPE:
3420 return EXTERNAL_SHORT_ELEMENTS;
3421 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3422 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3423 case EXTERNAL_INT_ARRAY_TYPE:
3424 return EXTERNAL_INT_ELEMENTS;
3425 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3426 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3427 default:
3428 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3429 return EXTERNAL_FLOAT_ELEMENTS;
3430 }
3431 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003432 ASSERT(array->IsPixelArray());
3433 return PIXEL_ELEMENTS;
3434}
3435
3436
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003437bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003438 return GetElementsKind() == FAST_ELEMENTS;
3439}
3440
3441
3442bool JSObject::HasDictionaryElements() {
3443 return GetElementsKind() == DICTIONARY_ELEMENTS;
3444}
3445
3446
3447bool JSObject::HasPixelElements() {
3448 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003449}
3450
3451
ager@chromium.org3811b432009-10-28 14:53:37 +00003452bool JSObject::HasExternalArrayElements() {
3453 return (HasExternalByteElements() ||
3454 HasExternalUnsignedByteElements() ||
3455 HasExternalShortElements() ||
3456 HasExternalUnsignedShortElements() ||
3457 HasExternalIntElements() ||
3458 HasExternalUnsignedIntElements() ||
3459 HasExternalFloatElements());
3460}
3461
3462
3463bool JSObject::HasExternalByteElements() {
3464 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3465}
3466
3467
3468bool JSObject::HasExternalUnsignedByteElements() {
3469 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3470}
3471
3472
3473bool JSObject::HasExternalShortElements() {
3474 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3475}
3476
3477
3478bool JSObject::HasExternalUnsignedShortElements() {
3479 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3480}
3481
3482
3483bool JSObject::HasExternalIntElements() {
3484 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3485}
3486
3487
3488bool JSObject::HasExternalUnsignedIntElements() {
3489 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3490}
3491
3492
3493bool JSObject::HasExternalFloatElements() {
3494 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3495}
3496
3497
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003498bool JSObject::HasNamedInterceptor() {
3499 return map()->has_named_interceptor();
3500}
3501
3502
3503bool JSObject::HasIndexedInterceptor() {
3504 return map()->has_indexed_interceptor();
3505}
3506
3507
ager@chromium.org5c838252010-02-19 08:53:10 +00003508bool JSObject::AllowsSetElementsLength() {
3509 bool result = elements()->IsFixedArray();
3510 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3511 return result;
3512}
3513
3514
lrn@chromium.org303ada72010-10-27 09:33:13 +00003515MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003516 ASSERT(HasFastElements());
3517 FixedArray* elems = FixedArray::cast(elements());
3518 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003519 Object* writable_elems;
3520 { MaybeObject* maybe_writable_elems =
3521 Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
3522 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3523 return maybe_writable_elems;
3524 }
3525 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003526 set_elements(FixedArray::cast(writable_elems));
3527 Counters::cow_arrays_converted.Increment();
3528 return writable_elems;
3529}
3530
3531
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003532StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003533 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003534 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003535}
3536
3537
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003538NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003539 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003540 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003541}
3542
3543
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003544bool String::IsHashFieldComputed(uint32_t field) {
3545 return (field & kHashNotComputedMask) == 0;
3546}
3547
3548
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003549bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003550 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003551}
3552
3553
3554uint32_t String::Hash() {
3555 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003556 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003557 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003558 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003559 return ComputeAndSetHash();
3560}
3561
3562
ager@chromium.org7c537e22008-10-16 08:43:32 +00003563StringHasher::StringHasher(int length)
3564 : length_(length),
3565 raw_running_hash_(0),
3566 array_index_(0),
3567 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3568 is_first_char_(true),
3569 is_valid_(true) { }
3570
3571
3572bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003573 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003574}
3575
3576
3577void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003578 // Use the Jenkins one-at-a-time hash function to update the hash
3579 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003580 raw_running_hash_ += c;
3581 raw_running_hash_ += (raw_running_hash_ << 10);
3582 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003583 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003584 if (is_array_index_) {
3585 if (c < '0' || c > '9') {
3586 is_array_index_ = false;
3587 } else {
3588 int d = c - '0';
3589 if (is_first_char_) {
3590 is_first_char_ = false;
3591 if (c == '0' && length_ > 1) {
3592 is_array_index_ = false;
3593 return;
3594 }
3595 }
3596 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3597 is_array_index_ = false;
3598 } else {
3599 array_index_ = array_index_ * 10 + d;
3600 }
3601 }
3602 }
3603}
3604
3605
3606void StringHasher::AddCharacterNoIndex(uc32 c) {
3607 ASSERT(!is_array_index());
3608 raw_running_hash_ += c;
3609 raw_running_hash_ += (raw_running_hash_ << 10);
3610 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3611}
3612
3613
3614uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003615 // Get the calculated raw hash value and do some more bit ops to distribute
3616 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003617 uint32_t result = raw_running_hash_;
3618 result += (result << 3);
3619 result ^= (result >> 11);
3620 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003621 if (result == 0) {
3622 result = 27;
3623 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003624 return result;
3625}
3626
3627
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003628bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003629 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003630 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3631 return false;
3632 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003633 return SlowAsArrayIndex(index);
3634}
3635
3636
3637Object* JSObject::GetPrototype() {
3638 return JSObject::cast(this)->map()->prototype();
3639}
3640
3641
3642PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3643 return GetPropertyAttributeWithReceiver(this, key);
3644}
3645
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003646// TODO(504): this may be useful in other places too where JSGlobalProxy
3647// is used.
3648Object* JSObject::BypassGlobalProxy() {
3649 if (IsJSGlobalProxy()) {
3650 Object* proto = GetPrototype();
3651 if (proto->IsNull()) return Heap::undefined_value();
3652 ASSERT(proto->IsJSGlobalObject());
3653 return proto;
3654 }
3655 return this;
3656}
3657
3658
3659bool JSObject::HasHiddenPropertiesObject() {
3660 ASSERT(!IsJSGlobalProxy());
3661 return GetPropertyAttributePostInterceptor(this,
3662 Heap::hidden_symbol(),
3663 false) != ABSENT;
3664}
3665
3666
3667Object* JSObject::GetHiddenPropertiesObject() {
3668 ASSERT(!IsJSGlobalProxy());
3669 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003670 // You can't install a getter on a property indexed by the hidden symbol,
3671 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3672 // object.
3673 Object* result =
3674 GetLocalPropertyPostInterceptor(this,
3675 Heap::hidden_symbol(),
3676 &attributes)->ToObjectUnchecked();
3677 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003678}
3679
3680
lrn@chromium.org303ada72010-10-27 09:33:13 +00003681MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003682 ASSERT(!IsJSGlobalProxy());
3683 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3684 hidden_obj,
3685 DONT_ENUM);
3686}
3687
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003688
3689bool JSObject::HasElement(uint32_t index) {
3690 return HasElementWithReceiver(this, index);
3691}
3692
3693
3694bool AccessorInfo::all_can_read() {
3695 return BooleanBit::get(flag(), kAllCanReadBit);
3696}
3697
3698
3699void AccessorInfo::set_all_can_read(bool value) {
3700 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3701}
3702
3703
3704bool AccessorInfo::all_can_write() {
3705 return BooleanBit::get(flag(), kAllCanWriteBit);
3706}
3707
3708
3709void AccessorInfo::set_all_can_write(bool value) {
3710 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3711}
3712
3713
ager@chromium.org870a0b62008-11-04 11:43:05 +00003714bool AccessorInfo::prohibits_overwriting() {
3715 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3716}
3717
3718
3719void AccessorInfo::set_prohibits_overwriting(bool value) {
3720 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3721}
3722
3723
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003724PropertyAttributes AccessorInfo::property_attributes() {
3725 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3726}
3727
3728
3729void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3730 ASSERT(AttributesField::is_valid(attributes));
3731 int rest_value = flag()->value() & ~AttributesField::mask();
3732 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3733}
3734
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003735template<typename Shape, typename Key>
3736void Dictionary<Shape, Key>::SetEntry(int entry,
3737 Object* key,
3738 Object* value,
3739 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003740 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003741 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003742 AssertNoAllocation no_gc;
3743 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003744 FixedArray::set(index, key, mode);
3745 FixedArray::set(index+1, value, mode);
3746 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003747}
3748
3749
3750void Map::ClearCodeCache() {
3751 // No write barrier is needed since empty_fixed_array is not in new space.
3752 // Please note this function is used during marking:
3753 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003754 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3755 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003756}
3757
3758
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003759void JSArray::EnsureSize(int required_size) {
3760 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003761 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003762 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3763 if (elts->length() < required_size) {
3764 // Doubling in size would be overkill, but leave some slack to avoid
3765 // constantly growing.
3766 Expand(required_size + (required_size >> 3));
3767 // It's a performance benefit to keep a frequently used array in new-space.
3768 } else if (!Heap::new_space()->Contains(elts) &&
3769 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3770 // Expand will allocate a new backing store in new space even if the size
3771 // we asked for isn't larger than what we had before.
3772 Expand(required_size);
3773 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003774}
3775
3776
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003777void JSArray::set_length(Smi* length) {
3778 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3779}
3780
3781
ager@chromium.org7c537e22008-10-16 08:43:32 +00003782void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003783 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003784 set_elements(storage);
3785}
3786
3787
lrn@chromium.org303ada72010-10-27 09:33:13 +00003788MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003789 if (length() == 0) return this;
3790 return Heap::CopyFixedArray(this);
3791}
3792
3793
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003794int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3795 return map->instance_size();
3796}
3797
3798
3799void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3800 v->VisitExternalReference(
3801 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3802}
3803
3804
3805template<typename StaticVisitor>
3806void Proxy::ProxyIterateBody() {
3807 StaticVisitor::VisitExternalReference(
3808 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3809}
3810
3811
3812void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3813 typedef v8::String::ExternalAsciiStringResource Resource;
3814 v->VisitExternalAsciiString(
3815 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3816}
3817
3818
3819template<typename StaticVisitor>
3820void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3821 typedef v8::String::ExternalAsciiStringResource Resource;
3822 StaticVisitor::VisitExternalAsciiString(
3823 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3824}
3825
3826
3827void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3828 typedef v8::String::ExternalStringResource Resource;
3829 v->VisitExternalTwoByteString(
3830 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3831}
3832
3833
3834template<typename StaticVisitor>
3835void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3836 typedef v8::String::ExternalStringResource Resource;
3837 StaticVisitor::VisitExternalTwoByteString(
3838 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3839}
3840
3841#define SLOT_ADDR(obj, offset) \
3842 reinterpret_cast<Object**>((obj)->address() + offset)
3843
3844template<int start_offset, int end_offset, int size>
3845void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3846 HeapObject* obj,
3847 ObjectVisitor* v) {
3848 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3849}
3850
3851
3852template<int start_offset>
3853void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3854 int object_size,
3855 ObjectVisitor* v) {
3856 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3857}
3858
3859#undef SLOT_ADDR
3860
3861
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003862#undef CAST_ACCESSOR
3863#undef INT_ACCESSORS
3864#undef SMI_ACCESSORS
3865#undef ACCESSORS
3866#undef FIELD_ADDR
3867#undef READ_FIELD
3868#undef WRITE_FIELD
3869#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003870#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003871#undef READ_MEMADDR_FIELD
3872#undef WRITE_MEMADDR_FIELD
3873#undef READ_DOUBLE_FIELD
3874#undef WRITE_DOUBLE_FIELD
3875#undef READ_INT_FIELD
3876#undef WRITE_INT_FIELD
3877#undef READ_SHORT_FIELD
3878#undef WRITE_SHORT_FIELD
3879#undef READ_BYTE_FIELD
3880#undef WRITE_BYTE_FIELD
3881
3882
3883} } // namespace v8::internal
3884
3885#endif // V8_OBJECTS_INL_H_