1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // 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 //
30 // - The use of macros in these inline functions may seem superfluous
31 // 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
38 #include "objects.h"
39 #include "contexts.h"
40 #include "conversions-inl.h"
41 #include "property.h"
42
43 namespace v8 {
44 namespace internal {
45
PropertyDetails(Smi * smi)46 PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48 }
49
50
AsSmi()51 Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53 }
54
55
AsDeleted()56 PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60 }
61
62
63 #define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70 #define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75 #define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
77 void holder::set_##name(type* value, WriteBarrierMode mode) { \
78 WRITE_FIELD(this, offset, value); \
79 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
80 }
81
82
83
84 #define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
94 #define BOOL_GETTER(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98
99
100 #define BOOL_ACCESSORS(holder, field, name, offset) \
101 bool holder::name() { \
102 return BooleanBit::get(field(), offset); \
103 } \
104 void holder::set_##name(bool value) { \
105 set_##field(BooleanBit::set(field(), offset, value)); \
106 }
107
108
IsInstanceOf(FunctionTemplateInfo * expected)109 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110 // There is a constraint on the object; check.
111 if (!this->IsJSObject()) return false;
112 // Fetch the constructor function of the object.
113 Object* cons_obj = JSObject::cast(this)->map()->constructor();
114 if (!cons_obj->IsJSFunction()) return false;
115 JSFunction* fun = JSFunction::cast(cons_obj);
116 // Iterate through the chain of inheriting function templates to
117 // see if the required one occurs.
118 for (Object* type = fun->shared()->function_data();
119 type->IsFunctionTemplateInfo();
120 type = FunctionTemplateInfo::cast(type)->parent_template()) {
121 if (type == expected) return true;
122 }
123 // Didn't find the required type in the inheritance chain.
124 return false;
125 }
126
127
IsSmi()128 bool Object::IsSmi() {
129 return HAS_SMI_TAG(this);
130 }
131
132
IsHeapObject()133 bool Object::IsHeapObject() {
134 return Internals::HasHeapObjectTag(this);
135 }
136
137
IsHeapNumber()138 bool Object::IsHeapNumber() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141 }
142
143
IsString()144 bool Object::IsString() {
145 return Object::IsHeapObject()
146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147 }
148
149
IsSymbol()150 bool Object::IsSymbol() {
151 if (!this->IsHeapObject()) return false;
152 uint32_t type = HeapObject::cast(this)->map()->instance_type();
153 // Because the symbol tag is non-zero and no non-string types have the
154 // symbol bit set we can test for symbols with a very simple test
155 // operation.
156 ASSERT(kSymbolTag != 0);
157 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
158 return (type & kIsSymbolMask) != 0;
159 }
160
161
IsConsString()162 bool Object::IsConsString() {
163 if (!this->IsHeapObject()) return false;
164 uint32_t type = HeapObject::cast(this)->map()->instance_type();
165 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
166 (kStringTag | kConsStringTag);
167 }
168
169
IsSeqString()170 bool Object::IsSeqString() {
171 if (!IsString()) return false;
172 return StringShape(String::cast(this)).IsSequential();
173 }
174
175
IsSeqAsciiString()176 bool Object::IsSeqAsciiString() {
177 if (!IsString()) return false;
178 return StringShape(String::cast(this)).IsSequential() &&
179 String::cast(this)->IsAsciiRepresentation();
180 }
181
182
IsSeqTwoByteString()183 bool Object::IsSeqTwoByteString() {
184 if (!IsString()) return false;
185 return StringShape(String::cast(this)).IsSequential() &&
186 String::cast(this)->IsTwoByteRepresentation();
187 }
188
189
IsExternalString()190 bool Object::IsExternalString() {
191 if (!IsString()) return false;
192 return StringShape(String::cast(this)).IsExternal();
193 }
194
195
IsExternalAsciiString()196 bool Object::IsExternalAsciiString() {
197 if (!IsString()) return false;
198 return StringShape(String::cast(this)).IsExternal() &&
199 String::cast(this)->IsAsciiRepresentation();
200 }
201
202
IsExternalTwoByteString()203 bool Object::IsExternalTwoByteString() {
204 if (!IsString()) return false;
205 return StringShape(String::cast(this)).IsExternal() &&
206 String::cast(this)->IsTwoByteRepresentation();
207 }
208
209
StringShape(String * str)210 StringShape::StringShape(String* str)
211 : type_(str->map()->instance_type()) {
212 set_valid();
213 ASSERT((type_ & kIsNotStringMask) == kStringTag);
214 }
215
216
StringShape(Map * map)217 StringShape::StringShape(Map* map)
218 : type_(map->instance_type()) {
219 set_valid();
220 ASSERT((type_ & kIsNotStringMask) == kStringTag);
221 }
222
223
StringShape(InstanceType t)224 StringShape::StringShape(InstanceType t)
225 : type_(static_cast<uint32_t>(t)) {
226 set_valid();
227 ASSERT((type_ & kIsNotStringMask) == kStringTag);
228 }
229
230
IsSymbol()231 bool StringShape::IsSymbol() {
232 ASSERT(valid());
233 ASSERT(kSymbolTag != 0);
234 return (type_ & kIsSymbolMask) != 0;
235 }
236
237
IsAsciiRepresentation()238 bool String::IsAsciiRepresentation() {
239 uint32_t type = map()->instance_type();
240 if ((type & kStringRepresentationMask) == kConsStringTag &&
241 ConsString::cast(this)->second()->length() == 0) {
242 return ConsString::cast(this)->first()->IsAsciiRepresentation();
243 }
244 return (type & kStringEncodingMask) == kAsciiStringTag;
245 }
246
247
IsTwoByteRepresentation()248 bool String::IsTwoByteRepresentation() {
249 uint32_t type = map()->instance_type();
250 if ((type & kStringRepresentationMask) == kConsStringTag &&
251 ConsString::cast(this)->second()->length() == 0) {
252 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
253 }
254 return (type & kStringEncodingMask) == kTwoByteStringTag;
255 }
256
257
IsCons()258 bool StringShape::IsCons() {
259 return (type_ & kStringRepresentationMask) == kConsStringTag;
260 }
261
262
IsExternal()263 bool StringShape::IsExternal() {
264 return (type_ & kStringRepresentationMask) == kExternalStringTag;
265 }
266
267
IsSequential()268 bool StringShape::IsSequential() {
269 return (type_ & kStringRepresentationMask) == kSeqStringTag;
270 }
271
272
representation_tag()273 StringRepresentationTag StringShape::representation_tag() {
274 uint32_t tag = (type_ & kStringRepresentationMask);
275 return static_cast<StringRepresentationTag>(tag);
276 }
277
278
full_representation_tag()279 uint32_t StringShape::full_representation_tag() {
280 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
281 }
282
283
284 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
285 Internals::kFullStringRepresentationMask);
286
287
IsSequentialAscii()288 bool StringShape::IsSequentialAscii() {
289 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
290 }
291
292
IsSequentialTwoByte()293 bool StringShape::IsSequentialTwoByte() {
294 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
295 }
296
297
IsExternalAscii()298 bool StringShape::IsExternalAscii() {
299 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
300 }
301
302
IsExternalTwoByte()303 bool StringShape::IsExternalTwoByte() {
304 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
305 }
306
307
308 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
309 Internals::kExternalTwoByteRepresentationTag);
310
311
Get(int index)312 uc32 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
IsNumber()322 bool Object::IsNumber() {
323 return IsSmi() || IsHeapNumber();
324 }
325
326
IsByteArray()327 bool Object::IsByteArray() {
328 return Object::IsHeapObject()
329 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
330 }
331
332
IsPixelArray()333 bool Object::IsPixelArray() {
334 return Object::IsHeapObject() &&
335 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
336 }
337
338
IsExternalArray()339 bool Object::IsExternalArray() {
340 if (!Object::IsHeapObject())
341 return false;
342 InstanceType instance_type =
343 HeapObject::cast(this)->map()->instance_type();
344 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
345 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
346 }
347
348
IsExternalByteArray()349 bool Object::IsExternalByteArray() {
350 return Object::IsHeapObject() &&
351 HeapObject::cast(this)->map()->instance_type() ==
352 EXTERNAL_BYTE_ARRAY_TYPE;
353 }
354
355
IsExternalUnsignedByteArray()356 bool Object::IsExternalUnsignedByteArray() {
357 return Object::IsHeapObject() &&
358 HeapObject::cast(this)->map()->instance_type() ==
359 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
360 }
361
362
IsExternalShortArray()363 bool Object::IsExternalShortArray() {
364 return Object::IsHeapObject() &&
365 HeapObject::cast(this)->map()->instance_type() ==
366 EXTERNAL_SHORT_ARRAY_TYPE;
367 }
368
369
IsExternalUnsignedShortArray()370 bool Object::IsExternalUnsignedShortArray() {
371 return Object::IsHeapObject() &&
372 HeapObject::cast(this)->map()->instance_type() ==
373 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
374 }
375
376
IsExternalIntArray()377 bool Object::IsExternalIntArray() {
378 return Object::IsHeapObject() &&
379 HeapObject::cast(this)->map()->instance_type() ==
380 EXTERNAL_INT_ARRAY_TYPE;
381 }
382
383
IsExternalUnsignedIntArray()384 bool Object::IsExternalUnsignedIntArray() {
385 return Object::IsHeapObject() &&
386 HeapObject::cast(this)->map()->instance_type() ==
387 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
388 }
389
390
IsExternalFloatArray()391 bool Object::IsExternalFloatArray() {
392 return Object::IsHeapObject() &&
393 HeapObject::cast(this)->map()->instance_type() ==
394 EXTERNAL_FLOAT_ARRAY_TYPE;
395 }
396
397
IsFailure()398 bool Object::IsFailure() {
399 return HAS_FAILURE_TAG(this);
400 }
401
402
IsRetryAfterGC()403 bool Object::IsRetryAfterGC() {
404 return HAS_FAILURE_TAG(this)
405 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
406 }
407
408
IsOutOfMemoryFailure()409 bool Object::IsOutOfMemoryFailure() {
410 return HAS_FAILURE_TAG(this)
411 && Failure::cast(this)->IsOutOfMemoryException();
412 }
413
414
IsException()415 bool Object::IsException() {
416 return this == Failure::Exception();
417 }
418
419
IsJSObject()420 bool Object::IsJSObject() {
421 return IsHeapObject()
422 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
423 }
424
425
IsJSContextExtensionObject()426 bool Object::IsJSContextExtensionObject() {
427 return IsHeapObject()
428 && (HeapObject::cast(this)->map()->instance_type() ==
429 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
430 }
431
432
IsMap()433 bool Object::IsMap() {
434 return Object::IsHeapObject()
435 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
436 }
437
438
IsFixedArray()439 bool Object::IsFixedArray() {
440 return Object::IsHeapObject()
441 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
442 }
443
444
IsDescriptorArray()445 bool Object::IsDescriptorArray() {
446 return IsFixedArray();
447 }
448
449
IsContext()450 bool Object::IsContext() {
451 return Object::IsHeapObject()
452 && (HeapObject::cast(this)->map() == Heap::context_map() ||
453 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
454 HeapObject::cast(this)->map() == Heap::global_context_map());
455 }
456
457
IsCatchContext()458 bool Object::IsCatchContext() {
459 return Object::IsHeapObject()
460 && HeapObject::cast(this)->map() == Heap::catch_context_map();
461 }
462
463
IsGlobalContext()464 bool Object::IsGlobalContext() {
465 return Object::IsHeapObject()
466 && HeapObject::cast(this)->map() == Heap::global_context_map();
467 }
468
469
IsJSFunction()470 bool Object::IsJSFunction() {
471 return Object::IsHeapObject()
472 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
473 }
474
475
476 template <> inline bool Is<JSFunction>(Object* obj) {
477 return obj->IsJSFunction();
478 }
479
480
IsCode()481 bool Object::IsCode() {
482 return Object::IsHeapObject()
483 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
484 }
485
486
IsOddball()487 bool Object::IsOddball() {
488 return Object::IsHeapObject()
489 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
490 }
491
492
IsJSGlobalPropertyCell()493 bool Object::IsJSGlobalPropertyCell() {
494 return Object::IsHeapObject()
495 && HeapObject::cast(this)->map()->instance_type()
496 == JS_GLOBAL_PROPERTY_CELL_TYPE;
497 }
498
499
IsSharedFunctionInfo()500 bool Object::IsSharedFunctionInfo() {
501 return Object::IsHeapObject() &&
502 (HeapObject::cast(this)->map()->instance_type() ==
503 SHARED_FUNCTION_INFO_TYPE);
504 }
505
506
IsJSValue()507 bool Object::IsJSValue() {
508 return Object::IsHeapObject()
509 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
510 }
511
512
IsStringWrapper()513 bool Object::IsStringWrapper() {
514 return IsJSValue() && JSValue::cast(this)->value()->IsString();
515 }
516
517
IsProxy()518 bool Object::IsProxy() {
519 return Object::IsHeapObject()
520 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
521 }
522
523
IsBoolean()524 bool Object::IsBoolean() {
525 return IsTrue() || IsFalse();
526 }
527
528
IsJSArray()529 bool Object::IsJSArray() {
530 return Object::IsHeapObject()
531 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
532 }
533
534
IsJSRegExp()535 bool Object::IsJSRegExp() {
536 return Object::IsHeapObject()
537 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
538 }
539
540
541 template <> inline bool Is<JSArray>(Object* obj) {
542 return obj->IsJSArray();
543 }
544
545
IsHashTable()546 bool Object::IsHashTable() {
547 return Object::IsHeapObject()
548 && HeapObject::cast(this)->map() == Heap::hash_table_map();
549 }
550
551
IsDictionary()552 bool Object::IsDictionary() {
553 return IsHashTable() && this != Heap::symbol_table();
554 }
555
556
IsSymbolTable()557 bool Object::IsSymbolTable() {
558 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
559 }
560
561
IsCompilationCacheTable()562 bool Object::IsCompilationCacheTable() {
563 return IsHashTable();
564 }
565
566
IsMapCache()567 bool Object::IsMapCache() {
568 return IsHashTable();
569 }
570
571
IsPrimitive()572 bool Object::IsPrimitive() {
573 return IsOddball() || IsNumber() || IsString();
574 }
575
576
IsJSGlobalProxy()577 bool Object::IsJSGlobalProxy() {
578 bool result = IsHeapObject() &&
579 (HeapObject::cast(this)->map()->instance_type() ==
580 JS_GLOBAL_PROXY_TYPE);
581 ASSERT(!result || IsAccessCheckNeeded());
582 return result;
583 }
584
585
IsGlobalObject()586 bool Object::IsGlobalObject() {
587 if (!IsHeapObject()) return false;
588
589 InstanceType type = HeapObject::cast(this)->map()->instance_type();
590 return type == JS_GLOBAL_OBJECT_TYPE ||
591 type == JS_BUILTINS_OBJECT_TYPE;
592 }
593
594
IsJSGlobalObject()595 bool Object::IsJSGlobalObject() {
596 return IsHeapObject() &&
597 (HeapObject::cast(this)->map()->instance_type() ==
598 JS_GLOBAL_OBJECT_TYPE);
599 }
600
601
IsJSBuiltinsObject()602 bool Object::IsJSBuiltinsObject() {
603 return IsHeapObject() &&
604 (HeapObject::cast(this)->map()->instance_type() ==
605 JS_BUILTINS_OBJECT_TYPE);
606 }
607
608
IsUndetectableObject()609 bool Object::IsUndetectableObject() {
610 return IsHeapObject()
611 && HeapObject::cast(this)->map()->is_undetectable();
612 }
613
614
IsAccessCheckNeeded()615 bool Object::IsAccessCheckNeeded() {
616 return IsHeapObject()
617 && HeapObject::cast(this)->map()->is_access_check_needed();
618 }
619
620
IsStruct()621 bool Object::IsStruct() {
622 if (!IsHeapObject()) return false;
623 switch (HeapObject::cast(this)->map()->instance_type()) {
624 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
625 STRUCT_LIST(MAKE_STRUCT_CASE)
626 #undef MAKE_STRUCT_CASE
627 default: return false;
628 }
629 }
630
631
632 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
633 bool Object::Is##Name() { \
634 return Object::IsHeapObject() \
635 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
636 }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)637 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
638 #undef MAKE_STRUCT_PREDICATE
639
640
641 bool Object::IsUndefined() {
642 return this == Heap::undefined_value();
643 }
644
645
IsTheHole()646 bool Object::IsTheHole() {
647 return this == Heap::the_hole_value();
648 }
649
650
IsNull()651 bool Object::IsNull() {
652 return this == Heap::null_value();
653 }
654
655
IsTrue()656 bool Object::IsTrue() {
657 return this == Heap::true_value();
658 }
659
660
IsFalse()661 bool Object::IsFalse() {
662 return this == Heap::false_value();
663 }
664
665
Number()666 double Object::Number() {
667 ASSERT(IsNumber());
668 return IsSmi()
669 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
670 : reinterpret_cast<HeapNumber*>(this)->value();
671 }
672
673
674
ToSmi()675 Object* Object::ToSmi() {
676 if (IsSmi()) return this;
677 if (IsHeapNumber()) {
678 double value = HeapNumber::cast(this)->value();
679 int int_value = FastD2I(value);
680 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
681 return Smi::FromInt(int_value);
682 }
683 }
684 return Failure::Exception();
685 }
686
687
HasSpecificClassOf(String * name)688 bool Object::HasSpecificClassOf(String* name) {
689 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
690 }
691
692
GetElement(uint32_t index)693 Object* Object::GetElement(uint32_t index) {
694 return GetElementWithReceiver(this, index);
695 }
696
697
GetProperty(String * key)698 Object* Object::GetProperty(String* key) {
699 PropertyAttributes attributes;
700 return GetPropertyWithReceiver(this, key, &attributes);
701 }
702
703
GetProperty(String * key,PropertyAttributes * attributes)704 Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
705 return GetPropertyWithReceiver(this, key, attributes);
706 }
707
708
709 #define FIELD_ADDR(p, offset) \
710 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
711
712 #define READ_FIELD(p, offset) \
713 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
714
715 #define WRITE_FIELD(p, offset, value) \
716 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
717
718
719 #define WRITE_BARRIER(object, offset) \
720 Heap::RecordWrite(object->address(), offset);
721
722 // CONDITIONAL_WRITE_BARRIER must be issued after the actual
723 // write due to the assert validating the written value.
724 #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
725 if (mode == UPDATE_WRITE_BARRIER) { \
726 Heap::RecordWrite(object->address(), offset); \
727 } else { \
728 ASSERT(mode == SKIP_WRITE_BARRIER); \
729 ASSERT(Heap::InNewSpace(object) || \
730 !Heap::InNewSpace(READ_FIELD(object, offset))); \
731 }
732
733 #define READ_DOUBLE_FIELD(p, offset) \
734 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
735
736 #define WRITE_DOUBLE_FIELD(p, offset, value) \
737 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
738
739 #define READ_INT_FIELD(p, offset) \
740 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
741
742 #define WRITE_INT_FIELD(p, offset, value) \
743 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
744
745 #define READ_INTPTR_FIELD(p, offset) \
746 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
747
748 #define WRITE_INTPTR_FIELD(p, offset, value) \
749 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
750
751 #define READ_UINT32_FIELD(p, offset) \
752 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
753
754 #define WRITE_UINT32_FIELD(p, offset, value) \
755 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
756
757 #define READ_SHORT_FIELD(p, offset) \
758 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
759
760 #define WRITE_SHORT_FIELD(p, offset, value) \
761 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
762
763 #define READ_BYTE_FIELD(p, offset) \
764 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
765
766 #define WRITE_BYTE_FIELD(p, offset, value) \
767 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
768
769
RawField(HeapObject * obj,int byte_offset)770 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
771 return &READ_FIELD(obj, byte_offset);
772 }
773
774
value()775 int Smi::value() {
776 return Internals::SmiValue(this);
777 }
778
779
FromInt(int value)780 Smi* Smi::FromInt(int value) {
781 ASSERT(Smi::IsValid(value));
782 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
783 intptr_t tagged_value =
784 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
785 return reinterpret_cast<Smi*>(tagged_value);
786 }
787
788
FromIntptr(intptr_t value)789 Smi* Smi::FromIntptr(intptr_t value) {
790 ASSERT(Smi::IsValid(value));
791 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
792 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
793 }
794
795
type()796 Failure::Type Failure::type() const {
797 return static_cast<Type>(value() & kFailureTypeTagMask);
798 }
799
800
IsInternalError()801 bool Failure::IsInternalError() const {
802 return type() == INTERNAL_ERROR;
803 }
804
805
IsOutOfMemoryException()806 bool Failure::IsOutOfMemoryException() const {
807 return type() == OUT_OF_MEMORY_EXCEPTION;
808 }
809
810
requested()811 int Failure::requested() const {
812 const int kShiftBits =
813 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
814 STATIC_ASSERT(kShiftBits >= 0);
815 ASSERT(type() == RETRY_AFTER_GC);
816 return static_cast<int>(value() >> kShiftBits);
817 }
818
819
allocation_space()820 AllocationSpace Failure::allocation_space() const {
821 ASSERT_EQ(RETRY_AFTER_GC, type());
822 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
823 & kSpaceTagMask);
824 }
825
826
InternalError()827 Failure* Failure::InternalError() {
828 return Construct(INTERNAL_ERROR);
829 }
830
831
Exception()832 Failure* Failure::Exception() {
833 return Construct(EXCEPTION);
834 }
835
836
OutOfMemoryException()837 Failure* Failure::OutOfMemoryException() {
838 return Construct(OUT_OF_MEMORY_EXCEPTION);
839 }
840
841
value()842 intptr_t Failure::value() const {
843 return reinterpret_cast<intptr_t>(this) >> kFailureTagSize;
844 }
845
846
RetryAfterGC(int requested_bytes)847 Failure* Failure::RetryAfterGC(int requested_bytes) {
848 // Assert that the space encoding fits in the three bytes allotted for it.
849 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
850 intptr_t requested = requested_bytes >> kObjectAlignmentBits;
851 int tag_bits = kSpaceTagSize + kFailureTypeTagSize;
852 if (((requested << tag_bits) >> tag_bits) != requested) {
853 // No room for entire requested size in the bits. Round down to
854 // maximally representable size.
855 requested = static_cast<intptr_t>(
856 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
857 }
858 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
859 return Construct(RETRY_AFTER_GC, value);
860 }
861
862
Construct(Type type,intptr_t value)863 Failure* Failure::Construct(Type type, intptr_t value) {
864 intptr_t info = (static_cast<intptr_t>(value) << kFailureTypeTagSize) | type;
865 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
866 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
867 }
868
869
IsValid(intptr_t value)870 bool Smi::IsValid(intptr_t value) {
871 #ifdef DEBUG
872 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
873 #endif
874
875 #ifdef V8_TARGET_ARCH_X64
876 // To be representable as a long smi, the value must be a 32-bit integer.
877 bool result = (value == static_cast<int32_t>(value));
878 #else
879 // To be representable as an tagged small integer, the two
880 // most-significant bits of 'value' must be either 00 or 11 due to
881 // sign-extension. To check this we add 01 to the two
882 // most-significant bits, and check if the most-significant bit is 0
883 //
884 // CAUTION: The original code below:
885 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
886 // may lead to incorrect results according to the C language spec, and
887 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
888 // compiler may produce undefined results in case of signed integer
889 // overflow. The computation must be done w/ unsigned ints.
890 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
891 #endif
892 ASSERT(result == in_range);
893 return result;
894 }
895
896
FromMap(Map * map)897 MapWord MapWord::FromMap(Map* map) {
898 return MapWord(reinterpret_cast<uintptr_t>(map));
899 }
900
901
ToMap()902 Map* MapWord::ToMap() {
903 return reinterpret_cast<Map*>(value_);
904 }
905
906
IsForwardingAddress()907 bool MapWord::IsForwardingAddress() {
908 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
909 }
910
911
FromForwardingAddress(HeapObject * object)912 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
913 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
914 return MapWord(reinterpret_cast<uintptr_t>(raw));
915 }
916
917
ToForwardingAddress()918 HeapObject* MapWord::ToForwardingAddress() {
919 ASSERT(IsForwardingAddress());
920 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
921 }
922
923
IsMarked()924 bool MapWord::IsMarked() {
925 return (value_ & kMarkingMask) == 0;
926 }
927
928
SetMark()929 void MapWord::SetMark() {
930 value_ &= ~kMarkingMask;
931 }
932
933
ClearMark()934 void MapWord::ClearMark() {
935 value_ |= kMarkingMask;
936 }
937
938
IsOverflowed()939 bool MapWord::IsOverflowed() {
940 return (value_ & kOverflowMask) != 0;
941 }
942
943
SetOverflow()944 void MapWord::SetOverflow() {
945 value_ |= kOverflowMask;
946 }
947
948
ClearOverflow()949 void MapWord::ClearOverflow() {
950 value_ &= ~kOverflowMask;
951 }
952
953
EncodeAddress(Address map_address,int offset)954 MapWord MapWord::EncodeAddress(Address map_address, int offset) {
955 // Offset is the distance in live bytes from the first live object in the
956 // same page. The offset between two objects in the same page should not
957 // exceed the object area size of a page.
958 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
959
960 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
961 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
962
963 Page* map_page = Page::FromAddress(map_address);
964 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
965
966 uintptr_t map_page_offset =
967 map_page->Offset(map_address) >> kMapAlignmentBits;
968
969 uintptr_t encoding =
970 (compact_offset << kForwardingOffsetShift) |
971 (map_page_offset << kMapPageOffsetShift) |
972 (map_page->mc_page_index << kMapPageIndexShift);
973 return MapWord(encoding);
974 }
975
976
DecodeMapAddress(MapSpace * map_space)977 Address MapWord::DecodeMapAddress(MapSpace* map_space) {
978 int map_page_index =
979 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
980 ASSERT_MAP_PAGE_INDEX(map_page_index);
981
982 int map_page_offset = static_cast<int>(
983 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
984 kMapAlignmentBits);
985
986 return (map_space->PageAddress(map_page_index) + map_page_offset);
987 }
988
989
DecodeOffset()990 int MapWord::DecodeOffset() {
991 // The offset field is represented in the kForwardingOffsetBits
992 // most-significant bits.
993 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
994 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
995 return static_cast<int>(offset);
996 }
997
998
FromEncodedAddress(Address address)999 MapWord MapWord::FromEncodedAddress(Address address) {
1000 return MapWord(reinterpret_cast<uintptr_t>(address));
1001 }
1002
1003
ToEncodedAddress()1004 Address MapWord::ToEncodedAddress() {
1005 return reinterpret_cast<Address>(value_);
1006 }
1007
1008
1009 #ifdef DEBUG
VerifyObjectField(int offset)1010 void HeapObject::VerifyObjectField(int offset) {
1011 VerifyPointer(READ_FIELD(this, offset));
1012 }
1013 #endif
1014
1015
map()1016 Map* HeapObject::map() {
1017 return map_word().ToMap();
1018 }
1019
1020
set_map(Map * value)1021 void HeapObject::set_map(Map* value) {
1022 set_map_word(MapWord::FromMap(value));
1023 }
1024
1025
map_word()1026 MapWord HeapObject::map_word() {
1027 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1028 }
1029
1030
set_map_word(MapWord map_word)1031 void HeapObject::set_map_word(MapWord map_word) {
1032 // WRITE_FIELD does not update the remembered set, but there is no need
1033 // here.
1034 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1035 }
1036
1037
FromAddress(Address address)1038 HeapObject* HeapObject::FromAddress(Address address) {
1039 ASSERT_TAG_ALIGNED(address);
1040 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1041 }
1042
1043
address()1044 Address HeapObject::address() {
1045 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1046 }
1047
1048
Size()1049 int HeapObject::Size() {
1050 return SizeFromMap(map());
1051 }
1052
1053
IteratePointers(ObjectVisitor * v,int start,int end)1054 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1055 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1056 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1057 }
1058
1059
IteratePointer(ObjectVisitor * v,int offset)1060 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1061 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1062 }
1063
1064
IsMarked()1065 bool HeapObject::IsMarked() {
1066 return map_word().IsMarked();
1067 }
1068
1069
SetMark()1070 void HeapObject::SetMark() {
1071 ASSERT(!IsMarked());
1072 MapWord first_word = map_word();
1073 first_word.SetMark();
1074 set_map_word(first_word);
1075 }
1076
1077
ClearMark()1078 void HeapObject::ClearMark() {
1079 ASSERT(IsMarked());
1080 MapWord first_word = map_word();
1081 first_word.ClearMark();
1082 set_map_word(first_word);
1083 }
1084
1085
IsOverflowed()1086 bool HeapObject::IsOverflowed() {
1087 return map_word().IsOverflowed();
1088 }
1089
1090
SetOverflow()1091 void HeapObject::SetOverflow() {
1092 MapWord first_word = map_word();
1093 first_word.SetOverflow();
1094 set_map_word(first_word);
1095 }
1096
1097
ClearOverflow()1098 void HeapObject::ClearOverflow() {
1099 ASSERT(IsOverflowed());
1100 MapWord first_word = map_word();
1101 first_word.ClearOverflow();
1102 set_map_word(first_word);
1103 }
1104
1105
value()1106 double HeapNumber::value() {
1107 return READ_DOUBLE_FIELD(this, kValueOffset);
1108 }
1109
1110
set_value(double value)1111 void HeapNumber::set_value(double value) {
1112 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1113 }
1114
1115
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1116 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1117
1118
1119 Array* JSObject::elements() {
1120 Object* array = READ_FIELD(this, kElementsOffset);
1121 // In the assert below Dictionary is covered under FixedArray.
1122 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1123 array->IsExternalArray());
1124 return reinterpret_cast<Array*>(array);
1125 }
1126
1127
set_elements(Array * value,WriteBarrierMode mode)1128 void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1129 // In the assert below Dictionary is covered under FixedArray.
1130 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1131 value->IsExternalArray());
1132 WRITE_FIELD(this, kElementsOffset, value);
1133 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1134 }
1135
1136
initialize_properties()1137 void JSObject::initialize_properties() {
1138 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1139 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1140 }
1141
1142
initialize_elements()1143 void JSObject::initialize_elements() {
1144 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1145 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1146 }
1147
1148
ACCESSORS(Oddball,to_string,String,kToStringOffset)1149 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1150 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1151
1152
1153 Object* JSGlobalPropertyCell::value() {
1154 return READ_FIELD(this, kValueOffset);
1155 }
1156
1157
set_value(Object * val,WriteBarrierMode ignored)1158 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1159 // The write barrier is not used for global property cells.
1160 ASSERT(!val->IsJSGlobalPropertyCell());
1161 WRITE_FIELD(this, kValueOffset, val);
1162 }
1163
1164
GetHeaderSize()1165 int JSObject::GetHeaderSize() {
1166 InstanceType type = map()->instance_type();
1167 // Check for the most common kind of JavaScript object before
1168 // falling into the generic switch. This speeds up the internal
1169 // field operations considerably on average.
1170 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1171 switch (type) {
1172 case JS_GLOBAL_PROXY_TYPE:
1173 return JSGlobalProxy::kSize;
1174 case JS_GLOBAL_OBJECT_TYPE:
1175 return JSGlobalObject::kSize;
1176 case JS_BUILTINS_OBJECT_TYPE:
1177 return JSBuiltinsObject::kSize;
1178 case JS_FUNCTION_TYPE:
1179 return JSFunction::kSize;
1180 case JS_VALUE_TYPE:
1181 return JSValue::kSize;
1182 case JS_ARRAY_TYPE:
1183 return JSValue::kSize;
1184 case JS_REGEXP_TYPE:
1185 return JSValue::kSize;
1186 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1187 return JSObject::kHeaderSize;
1188 default:
1189 UNREACHABLE();
1190 return 0;
1191 }
1192 }
1193
1194
GetInternalFieldCount()1195 int JSObject::GetInternalFieldCount() {
1196 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1197 // Make sure to adjust for the number of in-object properties. These
1198 // properties do contribute to the size, but are not internal fields.
1199 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1200 map()->inobject_properties();
1201 }
1202
1203
GetInternalField(int index)1204 Object* JSObject::GetInternalField(int index) {
1205 ASSERT(index < GetInternalFieldCount() && index >= 0);
1206 // Internal objects do follow immediately after the header, whereas in-object
1207 // properties are at the end of the object. Therefore there is no need
1208 // to adjust the index here.
1209 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1210 }
1211
1212
SetInternalField(int index,Object * value)1213 void JSObject::SetInternalField(int index, Object* value) {
1214 ASSERT(index < GetInternalFieldCount() && index >= 0);
1215 // Internal objects do follow immediately after the header, whereas in-object
1216 // properties are at the end of the object. Therefore there is no need
1217 // to adjust the index here.
1218 int offset = GetHeaderSize() + (kPointerSize * index);
1219 WRITE_FIELD(this, offset, value);
1220 WRITE_BARRIER(this, offset);
1221 }
1222
1223
1224 // Access fast-case object properties at index. The use of these routines
1225 // is needed to correctly distinguish between properties stored in-object and
1226 // properties stored in the properties array.
FastPropertyAt(int index)1227 Object* JSObject::FastPropertyAt(int index) {
1228 // Adjust for the number of properties stored in the object.
1229 index -= map()->inobject_properties();
1230 if (index < 0) {
1231 int offset = map()->instance_size() + (index * kPointerSize);
1232 return READ_FIELD(this, offset);
1233 } else {
1234 ASSERT(index < properties()->length());
1235 return properties()->get(index);
1236 }
1237 }
1238
1239
FastPropertyAtPut(int index,Object * value)1240 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1241 // Adjust for the number of properties stored in the object.
1242 index -= map()->inobject_properties();
1243 if (index < 0) {
1244 int offset = map()->instance_size() + (index * kPointerSize);
1245 WRITE_FIELD(this, offset, value);
1246 WRITE_BARRIER(this, offset);
1247 } else {
1248 ASSERT(index < properties()->length());
1249 properties()->set(index, value);
1250 }
1251 return value;
1252 }
1253
1254
InObjectPropertyAt(int index)1255 Object* JSObject::InObjectPropertyAt(int index) {
1256 // Adjust for the number of properties stored in the object.
1257 index -= map()->inobject_properties();
1258 ASSERT(index < 0);
1259 int offset = map()->instance_size() + (index * kPointerSize);
1260 return READ_FIELD(this, offset);
1261 }
1262
1263
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1264 Object* JSObject::InObjectPropertyAtPut(int index,
1265 Object* value,
1266 WriteBarrierMode mode) {
1267 // Adjust for the number of properties stored in the object.
1268 index -= map()->inobject_properties();
1269 ASSERT(index < 0);
1270 int offset = map()->instance_size() + (index * kPointerSize);
1271 WRITE_FIELD(this, offset, value);
1272 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1273 return value;
1274 }
1275
1276
1277
InitializeBody(int object_size)1278 void JSObject::InitializeBody(int object_size) {
1279 Object* value = Heap::undefined_value();
1280 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1281 WRITE_FIELD(this, offset, value);
1282 }
1283 }
1284
1285
InitializeBody(int object_size)1286 void Struct::InitializeBody(int object_size) {
1287 Object* value = Heap::undefined_value();
1288 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1289 WRITE_FIELD(this, offset, value);
1290 }
1291 }
1292
1293
HasFastProperties()1294 bool JSObject::HasFastProperties() {
1295 return !properties()->IsDictionary();
1296 }
1297
1298
IndexFromObject(Object * object,uint32_t * index)1299 bool Array::IndexFromObject(Object* object, uint32_t* index) {
1300 if (object->IsSmi()) {
1301 int value = Smi::cast(object)->value();
1302 if (value < 0) return false;
1303 *index = value;
1304 return true;
1305 }
1306 if (object->IsHeapNumber()) {
1307 double value = HeapNumber::cast(object)->value();
1308 uint32_t uint_value = static_cast<uint32_t>(value);
1309 if (value == static_cast<double>(uint_value)) {
1310 *index = uint_value;
1311 return true;
1312 }
1313 }
1314 return false;
1315 }
1316
1317
IsStringObjectWithCharacterAt(uint32_t index)1318 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1319 if (!this->IsJSValue()) return false;
1320
1321 JSValue* js_value = JSValue::cast(this);
1322 if (!js_value->value()->IsString()) return false;
1323
1324 String* str = String::cast(js_value->value());
1325 if (index >= (uint32_t)str->length()) return false;
1326
1327 return true;
1328 }
1329
1330
get(int index)1331 Object* FixedArray::get(int index) {
1332 ASSERT(index >= 0 && index < this->length());
1333 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1334 }
1335
1336
set(int index,Smi * value)1337 void FixedArray::set(int index, Smi* value) {
1338 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1339 int offset = kHeaderSize + index * kPointerSize;
1340 WRITE_FIELD(this, offset, value);
1341 }
1342
1343
set(int index,Object * value)1344 void FixedArray::set(int index, Object* value) {
1345 ASSERT(index >= 0 && index < this->length());
1346 int offset = kHeaderSize + index * kPointerSize;
1347 WRITE_FIELD(this, offset, value);
1348 WRITE_BARRIER(this, offset);
1349 }
1350
1351
GetWriteBarrierMode(const AssertNoAllocation &)1352 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1353 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1354 return UPDATE_WRITE_BARRIER;
1355 }
1356
1357
set(int index,Object * value,WriteBarrierMode mode)1358 void FixedArray::set(int index,
1359 Object* value,
1360 WriteBarrierMode mode) {
1361 ASSERT(index >= 0 && index < this->length());
1362 int offset = kHeaderSize + index * kPointerSize;
1363 WRITE_FIELD(this, offset, value);
1364 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1365 }
1366
1367
fast_set(FixedArray * array,int index,Object * value)1368 void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1369 ASSERT(index >= 0 && index < array->length());
1370 ASSERT(!Heap::InNewSpace(value));
1371 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1372 }
1373
1374
set_undefined(int index)1375 void FixedArray::set_undefined(int index) {
1376 ASSERT(index >= 0 && index < this->length());
1377 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1378 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1379 Heap::undefined_value());
1380 }
1381
1382
set_null(int index)1383 void FixedArray::set_null(int index) {
1384 ASSERT(index >= 0 && index < this->length());
1385 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1386 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1387 }
1388
1389
set_the_hole(int index)1390 void FixedArray::set_the_hole(int index) {
1391 ASSERT(index >= 0 && index < this->length());
1392 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1393 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1394 }
1395
1396
IsEmpty()1397 bool DescriptorArray::IsEmpty() {
1398 ASSERT(this == Heap::empty_descriptor_array() ||
1399 this->length() > 2);
1400 return this == Heap::empty_descriptor_array();
1401 }
1402
1403
fast_swap(FixedArray * array,int first,int second)1404 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1405 Object* tmp = array->get(first);
1406 fast_set(array, first, array->get(second));
1407 fast_set(array, second, tmp);
1408 }
1409
1410
Search(String * name)1411 int DescriptorArray::Search(String* name) {
1412 SLOW_ASSERT(IsSortedNoDuplicates());
1413
1414 // Check for empty descriptor array.
1415 int nof = number_of_descriptors();
1416 if (nof == 0) return kNotFound;
1417
1418 // Fast case: do linear search for small arrays.
1419 const int kMaxElementsForLinearSearch = 8;
1420 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1421 return LinearSearch(name, nof);
1422 }
1423
1424 // Slow case: perform binary search.
1425 return BinarySearch(name, 0, nof - 1);
1426 }
1427
1428
GetKey(int descriptor_number)1429 String* DescriptorArray::GetKey(int descriptor_number) {
1430 ASSERT(descriptor_number < number_of_descriptors());
1431 return String::cast(get(ToKeyIndex(descriptor_number)));
1432 }
1433
1434
GetValue(int descriptor_number)1435 Object* DescriptorArray::GetValue(int descriptor_number) {
1436 ASSERT(descriptor_number < number_of_descriptors());
1437 return GetContentArray()->get(ToValueIndex(descriptor_number));
1438 }
1439
1440
GetDetails(int descriptor_number)1441 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1442 ASSERT(descriptor_number < number_of_descriptors());
1443 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1444 }
1445
1446
GetType(int descriptor_number)1447 PropertyType DescriptorArray::GetType(int descriptor_number) {
1448 ASSERT(descriptor_number < number_of_descriptors());
1449 return PropertyDetails(GetDetails(descriptor_number)).type();
1450 }
1451
1452
GetFieldIndex(int descriptor_number)1453 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1454 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1455 }
1456
1457
GetConstantFunction(int descriptor_number)1458 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1459 return JSFunction::cast(GetValue(descriptor_number));
1460 }
1461
1462
GetCallbacksObject(int descriptor_number)1463 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1464 ASSERT(GetType(descriptor_number) == CALLBACKS);
1465 return GetValue(descriptor_number);
1466 }
1467
1468
GetCallbacks(int descriptor_number)1469 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1470 ASSERT(GetType(descriptor_number) == CALLBACKS);
1471 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1472 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1473 }
1474
1475
IsProperty(int descriptor_number)1476 bool DescriptorArray::IsProperty(int descriptor_number) {
1477 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1478 }
1479
1480
IsTransition(int descriptor_number)1481 bool DescriptorArray::IsTransition(int descriptor_number) {
1482 PropertyType t = GetType(descriptor_number);
1483 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1484 }
1485
1486
IsNullDescriptor(int descriptor_number)1487 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1488 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1489 }
1490
1491
IsDontEnum(int descriptor_number)1492 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1493 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1494 }
1495
1496
Get(int descriptor_number,Descriptor * desc)1497 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1498 desc->Init(GetKey(descriptor_number),
1499 GetValue(descriptor_number),
1500 GetDetails(descriptor_number));
1501 }
1502
1503
Set(int descriptor_number,Descriptor * desc)1504 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1505 // Range check.
1506 ASSERT(descriptor_number < number_of_descriptors());
1507
1508 // Make sure none of the elements in desc are in new space.
1509 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1510 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1511
1512 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1513 FixedArray* content_array = GetContentArray();
1514 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1515 fast_set(content_array, ToDetailsIndex(descriptor_number),
1516 desc->GetDetails().AsSmi());
1517 }
1518
1519
CopyFrom(int index,DescriptorArray * src,int src_index)1520 void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1521 Descriptor desc;
1522 src->Get(src_index, &desc);
1523 Set(index, &desc);
1524 }
1525
1526
Swap(int first,int second)1527 void DescriptorArray::Swap(int first, int second) {
1528 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1529 FixedArray* content_array = GetContentArray();
1530 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1531 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1532 }
1533
1534
requires_slow_elements()1535 bool NumberDictionary::requires_slow_elements() {
1536 Object* max_index_object = get(kMaxNumberKeyIndex);
1537 if (!max_index_object->IsSmi()) return false;
1538 return 0 !=
1539 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1540 }
1541
max_number_key()1542 uint32_t NumberDictionary::max_number_key() {
1543 ASSERT(!requires_slow_elements());
1544 Object* max_index_object = get(kMaxNumberKeyIndex);
1545 if (!max_index_object->IsSmi()) return 0;
1546 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1547 return value >> kRequiresSlowElementsTagSize;
1548 }
1549
set_requires_slow_elements()1550 void NumberDictionary::set_requires_slow_elements() {
1551 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
1552 }
1553
1554
1555 // ------------------------------------
1556 // Cast operations
1557
1558
1559 CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(DescriptorArray)1560 CAST_ACCESSOR(DescriptorArray)
1561 CAST_ACCESSOR(SymbolTable)
1562 CAST_ACCESSOR(CompilationCacheTable)
1563 CAST_ACCESSOR(MapCache)
1564 CAST_ACCESSOR(String)
1565 CAST_ACCESSOR(SeqString)
1566 CAST_ACCESSOR(SeqAsciiString)
1567 CAST_ACCESSOR(SeqTwoByteString)
1568 CAST_ACCESSOR(ConsString)
1569 CAST_ACCESSOR(ExternalString)
1570 CAST_ACCESSOR(ExternalAsciiString)
1571 CAST_ACCESSOR(ExternalTwoByteString)
1572 CAST_ACCESSOR(JSObject)
1573 CAST_ACCESSOR(Smi)
1574 CAST_ACCESSOR(Failure)
1575 CAST_ACCESSOR(HeapObject)
1576 CAST_ACCESSOR(HeapNumber)
1577 CAST_ACCESSOR(Oddball)
1578 CAST_ACCESSOR(JSGlobalPropertyCell)
1579 CAST_ACCESSOR(SharedFunctionInfo)
1580 CAST_ACCESSOR(Map)
1581 CAST_ACCESSOR(JSFunction)
1582 CAST_ACCESSOR(GlobalObject)
1583 CAST_ACCESSOR(JSGlobalProxy)
1584 CAST_ACCESSOR(JSGlobalObject)
1585 CAST_ACCESSOR(JSBuiltinsObject)
1586 CAST_ACCESSOR(Code)
1587 CAST_ACCESSOR(JSArray)
1588 CAST_ACCESSOR(JSRegExp)
1589 CAST_ACCESSOR(Proxy)
1590 CAST_ACCESSOR(ByteArray)
1591 CAST_ACCESSOR(PixelArray)
1592 CAST_ACCESSOR(ExternalArray)
1593 CAST_ACCESSOR(ExternalByteArray)
1594 CAST_ACCESSOR(ExternalUnsignedByteArray)
1595 CAST_ACCESSOR(ExternalShortArray)
1596 CAST_ACCESSOR(ExternalUnsignedShortArray)
1597 CAST_ACCESSOR(ExternalIntArray)
1598 CAST_ACCESSOR(ExternalUnsignedIntArray)
1599 CAST_ACCESSOR(ExternalFloatArray)
1600 CAST_ACCESSOR(Struct)
1601
1602
1603 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1604 STRUCT_LIST(MAKE_STRUCT_CAST)
1605 #undef MAKE_STRUCT_CAST
1606
1607
1608 template <typename Shape, typename Key>
1609 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1610 ASSERT(obj->IsHashTable());
1611 return reinterpret_cast<HashTable*>(obj);
1612 }
1613
1614
INT_ACCESSORS(Array,length,kLengthOffset)1615 INT_ACCESSORS(Array, length, kLengthOffset)
1616
1617
1618 INT_ACCESSORS(String, length, kLengthOffset)
1619
1620
1621 uint32_t String::hash_field() {
1622 return READ_UINT32_FIELD(this, kHashFieldOffset);
1623 }
1624
1625
set_hash_field(uint32_t value)1626 void String::set_hash_field(uint32_t value) {
1627 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1628 }
1629
1630
Equals(String * other)1631 bool String::Equals(String* other) {
1632 if (other == this) return true;
1633 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1634 return false;
1635 }
1636 return SlowEquals(other);
1637 }
1638
1639
TryFlattenIfNotFlat()1640 Object* String::TryFlattenIfNotFlat() {
1641 // We don't need to flatten strings that are already flat. Since this code
1642 // is inlined, it can be helpful in the flat case to not call out to Flatten.
1643 if (!IsFlat()) {
1644 return TryFlatten();
1645 }
1646 return this;
1647 }
1648
1649
Get(int index)1650 uint16_t String::Get(int index) {
1651 ASSERT(index >= 0 && index < length());
1652 switch (StringShape(this).full_representation_tag()) {
1653 case kSeqStringTag | kAsciiStringTag:
1654 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1655 case kSeqStringTag | kTwoByteStringTag:
1656 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1657 case kConsStringTag | kAsciiStringTag:
1658 case kConsStringTag | kTwoByteStringTag:
1659 return ConsString::cast(this)->ConsStringGet(index);
1660 case kExternalStringTag | kAsciiStringTag:
1661 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1662 case kExternalStringTag | kTwoByteStringTag:
1663 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1664 default:
1665 break;
1666 }
1667
1668 UNREACHABLE();
1669 return 0;
1670 }
1671
1672
Set(int index,uint16_t value)1673 void String::Set(int index, uint16_t value) {
1674 ASSERT(index >= 0 && index < length());
1675 ASSERT(StringShape(this).IsSequential());
1676
1677 return this->IsAsciiRepresentation()
1678 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1679 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1680 }
1681
1682
IsFlat()1683 bool String::IsFlat() {
1684 switch (StringShape(this).representation_tag()) {
1685 case kConsStringTag: {
1686 String* second = ConsString::cast(this)->second();
1687 // Only flattened strings have second part empty.
1688 return second->length() == 0;
1689 }
1690 default:
1691 return true;
1692 }
1693 }
1694
1695
SeqAsciiStringGet(int index)1696 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1697 ASSERT(index >= 0 && index < length());
1698 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1699 }
1700
1701
SeqAsciiStringSet(int index,uint16_t value)1702 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1703 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1704 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1705 static_cast<byte>(value));
1706 }
1707
1708
GetCharsAddress()1709 Address SeqAsciiString::GetCharsAddress() {
1710 return FIELD_ADDR(this, kHeaderSize);
1711 }
1712
1713
GetChars()1714 char* SeqAsciiString::GetChars() {
1715 return reinterpret_cast<char*>(GetCharsAddress());
1716 }
1717
1718
GetCharsAddress()1719 Address SeqTwoByteString::GetCharsAddress() {
1720 return FIELD_ADDR(this, kHeaderSize);
1721 }
1722
1723
GetChars()1724 uc16* SeqTwoByteString::GetChars() {
1725 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1726 }
1727
1728
SeqTwoByteStringGet(int index)1729 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1730 ASSERT(index >= 0 && index < length());
1731 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1732 }
1733
1734
SeqTwoByteStringSet(int index,uint16_t value)1735 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1736 ASSERT(index >= 0 && index < length());
1737 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1738 }
1739
1740
SeqTwoByteStringSize(InstanceType instance_type)1741 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
1742 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1743 return SizeFor(length);
1744 }
1745
1746
SeqAsciiStringSize(InstanceType instance_type)1747 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
1748 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1749 return SizeFor(length);
1750 }
1751
1752
first()1753 String* ConsString::first() {
1754 return String::cast(READ_FIELD(this, kFirstOffset));
1755 }
1756
1757
unchecked_first()1758 Object* ConsString::unchecked_first() {
1759 return READ_FIELD(this, kFirstOffset);
1760 }
1761
1762
set_first(String * value,WriteBarrierMode mode)1763 void ConsString::set_first(String* value, WriteBarrierMode mode) {
1764 WRITE_FIELD(this, kFirstOffset, value);
1765 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1766 }
1767
1768
second()1769 String* ConsString::second() {
1770 return String::cast(READ_FIELD(this, kSecondOffset));
1771 }
1772
1773
unchecked_second()1774 Object* ConsString::unchecked_second() {
1775 return READ_FIELD(this, kSecondOffset);
1776 }
1777
1778
set_second(String * value,WriteBarrierMode mode)1779 void ConsString::set_second(String* value, WriteBarrierMode mode) {
1780 WRITE_FIELD(this, kSecondOffset, value);
1781 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1782 }
1783
1784
resource()1785 ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1786 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1787 }
1788
1789
set_resource(ExternalAsciiString::Resource * resource)1790 void ExternalAsciiString::set_resource(
1791 ExternalAsciiString::Resource* resource) {
1792 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1793 }
1794
1795
resource()1796 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1797 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1798 }
1799
1800
set_resource(ExternalTwoByteString::Resource * resource)1801 void ExternalTwoByteString::set_resource(
1802 ExternalTwoByteString::Resource* resource) {
1803 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1804 }
1805
1806
get(int index)1807 byte ByteArray::get(int index) {
1808 ASSERT(index >= 0 && index < this->length());
1809 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1810 }
1811
1812
set(int index,byte value)1813 void ByteArray::set(int index, byte value) {
1814 ASSERT(index >= 0 && index < this->length());
1815 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1816 }
1817
1818
get_int(int index)1819 int ByteArray::get_int(int index) {
1820 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1821 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1822 }
1823
1824
FromDataStartAddress(Address address)1825 ByteArray* ByteArray::FromDataStartAddress(Address address) {
1826 ASSERT_TAG_ALIGNED(address);
1827 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1828 }
1829
1830
GetDataStartAddress()1831 Address ByteArray::GetDataStartAddress() {
1832 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1833 }
1834
1835
external_pointer()1836 uint8_t* PixelArray::external_pointer() {
1837 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1838 return reinterpret_cast<uint8_t*>(ptr);
1839 }
1840
1841
set_external_pointer(uint8_t * value,WriteBarrierMode mode)1842 void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1843 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1844 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1845 }
1846
1847
get(int index)1848 uint8_t PixelArray::get(int index) {
1849 ASSERT((index >= 0) && (index < this->length()));
1850 uint8_t* ptr = external_pointer();
1851 return ptr[index];
1852 }
1853
1854
set(int index,uint8_t value)1855 void PixelArray::set(int index, uint8_t value) {
1856 ASSERT((index >= 0) && (index < this->length()));
1857 uint8_t* ptr = external_pointer();
1858 ptr[index] = value;
1859 }
1860
1861
external_pointer()1862 void* ExternalArray::external_pointer() {
1863 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1864 return reinterpret_cast<void*>(ptr);
1865 }
1866
1867
set_external_pointer(void * value,WriteBarrierMode mode)1868 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1869 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1870 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1871 }
1872
1873
get(int index)1874 int8_t ExternalByteArray::get(int index) {
1875 ASSERT((index >= 0) && (index < this->length()));
1876 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1877 return ptr[index];
1878 }
1879
1880
set(int index,int8_t value)1881 void ExternalByteArray::set(int index, int8_t value) {
1882 ASSERT((index >= 0) && (index < this->length()));
1883 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1884 ptr[index] = value;
1885 }
1886
1887
get(int index)1888 uint8_t ExternalUnsignedByteArray::get(int index) {
1889 ASSERT((index >= 0) && (index < this->length()));
1890 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1891 return ptr[index];
1892 }
1893
1894
set(int index,uint8_t value)1895 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1896 ASSERT((index >= 0) && (index < this->length()));
1897 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1898 ptr[index] = value;
1899 }
1900
1901
get(int index)1902 int16_t ExternalShortArray::get(int index) {
1903 ASSERT((index >= 0) && (index < this->length()));
1904 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1905 return ptr[index];
1906 }
1907
1908
set(int index,int16_t value)1909 void ExternalShortArray::set(int index, int16_t value) {
1910 ASSERT((index >= 0) && (index < this->length()));
1911 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1912 ptr[index] = value;
1913 }
1914
1915
get(int index)1916 uint16_t ExternalUnsignedShortArray::get(int index) {
1917 ASSERT((index >= 0) && (index < this->length()));
1918 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1919 return ptr[index];
1920 }
1921
1922
set(int index,uint16_t value)1923 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1924 ASSERT((index >= 0) && (index < this->length()));
1925 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1926 ptr[index] = value;
1927 }
1928
1929
get(int index)1930 int32_t ExternalIntArray::get(int index) {
1931 ASSERT((index >= 0) && (index < this->length()));
1932 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1933 return ptr[index];
1934 }
1935
1936
set(int index,int32_t value)1937 void ExternalIntArray::set(int index, int32_t value) {
1938 ASSERT((index >= 0) && (index < this->length()));
1939 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1940 ptr[index] = value;
1941 }
1942
1943
get(int index)1944 uint32_t ExternalUnsignedIntArray::get(int index) {
1945 ASSERT((index >= 0) && (index < this->length()));
1946 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1947 return ptr[index];
1948 }
1949
1950
set(int index,uint32_t value)1951 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
1952 ASSERT((index >= 0) && (index < this->length()));
1953 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1954 ptr[index] = value;
1955 }
1956
1957
get(int index)1958 float ExternalFloatArray::get(int index) {
1959 ASSERT((index >= 0) && (index < this->length()));
1960 float* ptr = static_cast<float*>(external_pointer());
1961 return ptr[index];
1962 }
1963
1964
set(int index,float value)1965 void ExternalFloatArray::set(int index, float value) {
1966 ASSERT((index >= 0) && (index < this->length()));
1967 float* ptr = static_cast<float*>(external_pointer());
1968 ptr[index] = value;
1969 }
1970
1971
instance_size()1972 int Map::instance_size() {
1973 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1974 }
1975
1976
inobject_properties()1977 int Map::inobject_properties() {
1978 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
1979 }
1980
1981
pre_allocated_property_fields()1982 int Map::pre_allocated_property_fields() {
1983 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1984 }
1985
1986
SizeFromMap(Map * map)1987 int HeapObject::SizeFromMap(Map* map) {
1988 InstanceType instance_type = map->instance_type();
1989 // Only inline the most frequent cases.
1990 if (instance_type == JS_OBJECT_TYPE ||
1991 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1992 (kStringTag | kConsStringTag) ||
1993 instance_type == JS_ARRAY_TYPE) return map->instance_size();
1994 if (instance_type == FIXED_ARRAY_TYPE) {
1995 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1996 }
1997 if (instance_type == BYTE_ARRAY_TYPE) {
1998 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1999 }
2000 // Otherwise do the general size computation.
2001 return SlowSizeFromMap(map);
2002 }
2003
2004
set_instance_size(int value)2005 void Map::set_instance_size(int value) {
2006 ASSERT_EQ(0, value & (kPointerSize - 1));
2007 value >>= kPointerSizeLog2;
2008 ASSERT(0 <= value && value < 256);
2009 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2010 }
2011
2012
set_inobject_properties(int value)2013 void Map::set_inobject_properties(int value) {
2014 ASSERT(0 <= value && value < 256);
2015 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2016 }
2017
2018
set_pre_allocated_property_fields(int value)2019 void Map::set_pre_allocated_property_fields(int value) {
2020 ASSERT(0 <= value && value < 256);
2021 WRITE_BYTE_FIELD(this,
2022 kPreAllocatedPropertyFieldsOffset,
2023 static_cast<byte>(value));
2024 }
2025
2026
instance_type()2027 InstanceType Map::instance_type() {
2028 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2029 }
2030
2031
set_instance_type(InstanceType value)2032 void Map::set_instance_type(InstanceType value) {
2033 ASSERT(0 <= value && value < 256);
2034 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2035 }
2036
2037
unused_property_fields()2038 int Map::unused_property_fields() {
2039 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2040 }
2041
2042
set_unused_property_fields(int value)2043 void Map::set_unused_property_fields(int value) {
2044 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2045 }
2046
2047
bit_field()2048 byte Map::bit_field() {
2049 return READ_BYTE_FIELD(this, kBitFieldOffset);
2050 }
2051
2052
set_bit_field(byte value)2053 void Map::set_bit_field(byte value) {
2054 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2055 }
2056
2057
bit_field2()2058 byte Map::bit_field2() {
2059 return READ_BYTE_FIELD(this, kBitField2Offset);
2060 }
2061
2062
set_bit_field2(byte value)2063 void Map::set_bit_field2(byte value) {
2064 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2065 }
2066
2067
set_non_instance_prototype(bool value)2068 void Map::set_non_instance_prototype(bool value) {
2069 if (value) {
2070 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2071 } else {
2072 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2073 }
2074 }
2075
2076
has_non_instance_prototype()2077 bool Map::has_non_instance_prototype() {
2078 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2079 }
2080
2081
set_is_access_check_needed(bool access_check_needed)2082 void Map::set_is_access_check_needed(bool access_check_needed) {
2083 if (access_check_needed) {
2084 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2085 } else {
2086 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2087 }
2088 }
2089
2090
is_access_check_needed()2091 bool Map::is_access_check_needed() {
2092 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2093 }
2094
2095
flags()2096 Code::Flags Code::flags() {
2097 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2098 }
2099
2100
set_flags(Code::Flags flags)2101 void Code::set_flags(Code::Flags flags) {
2102 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2103 // Make sure that all call stubs have an arguments count.
2104 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2105 ExtractArgumentsCountFromFlags(flags) >= 0);
2106 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2107 }
2108
2109
kind()2110 Code::Kind Code::kind() {
2111 return ExtractKindFromFlags(flags());
2112 }
2113
2114
ic_in_loop()2115 InLoopFlag Code::ic_in_loop() {
2116 return ExtractICInLoopFromFlags(flags());
2117 }
2118
2119
ic_state()2120 InlineCacheState Code::ic_state() {
2121 InlineCacheState result = ExtractICStateFromFlags(flags());
2122 // Only allow uninitialized or debugger states for non-IC code
2123 // objects. This is used in the debugger to determine whether or not
2124 // a call to code object has been replaced with a debug break call.
2125 ASSERT(is_inline_cache_stub() ||
2126 result == UNINITIALIZED ||
2127 result == DEBUG_BREAK ||
2128 result == DEBUG_PREPARE_STEP_IN);
2129 return result;
2130 }
2131
2132
type()2133 PropertyType Code::type() {
2134 ASSERT(ic_state() == MONOMORPHIC);
2135 return ExtractTypeFromFlags(flags());
2136 }
2137
2138
arguments_count()2139 int Code::arguments_count() {
2140 ASSERT(is_call_stub() || kind() == STUB);
2141 return ExtractArgumentsCountFromFlags(flags());
2142 }
2143
2144
major_key()2145 CodeStub::Major Code::major_key() {
2146 ASSERT(kind() == STUB);
2147 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2148 kStubMajorKeyOffset));
2149 }
2150
2151
set_major_key(CodeStub::Major major)2152 void Code::set_major_key(CodeStub::Major major) {
2153 ASSERT(kind() == STUB);
2154 ASSERT(0 <= major && major < 256);
2155 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2156 }
2157
2158
is_inline_cache_stub()2159 bool Code::is_inline_cache_stub() {
2160 Kind kind = this->kind();
2161 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2162 }
2163
2164
ComputeFlags(Kind kind,InLoopFlag in_loop,InlineCacheState ic_state,PropertyType type,int argc)2165 Code::Flags Code::ComputeFlags(Kind kind,
2166 InLoopFlag in_loop,
2167 InlineCacheState ic_state,
2168 PropertyType type,
2169 int argc) {
2170 // Compute the bit mask.
2171 int bits = kind << kFlagsKindShift;
2172 if (in_loop) bits |= kFlagsICInLoopMask;
2173 bits |= ic_state << kFlagsICStateShift;
2174 bits |= type << kFlagsTypeShift;
2175 bits |= argc << kFlagsArgumentsCountShift;
2176 // Cast to flags and validate result before returning it.
2177 Flags result = static_cast<Flags>(bits);
2178 ASSERT(ExtractKindFromFlags(result) == kind);
2179 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2180 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2181 ASSERT(ExtractTypeFromFlags(result) == type);
2182 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2183 return result;
2184 }
2185
2186
ComputeMonomorphicFlags(Kind kind,PropertyType type,InLoopFlag in_loop,int argc)2187 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2188 PropertyType type,
2189 InLoopFlag in_loop,
2190 int argc) {
2191 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
2192 }
2193
2194
ExtractKindFromFlags(Flags flags)2195 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2196 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2197 return static_cast<Kind>(bits);
2198 }
2199
2200
ExtractICStateFromFlags(Flags flags)2201 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2202 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2203 return static_cast<InlineCacheState>(bits);
2204 }
2205
2206
ExtractICInLoopFromFlags(Flags flags)2207 InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2208 int bits = (flags & kFlagsICInLoopMask);
2209 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2210 }
2211
2212
ExtractTypeFromFlags(Flags flags)2213 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2214 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2215 return static_cast<PropertyType>(bits);
2216 }
2217
2218
ExtractArgumentsCountFromFlags(Flags flags)2219 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2220 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2221 }
2222
2223
RemoveTypeFromFlags(Flags flags)2224 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2225 int bits = flags & ~kFlagsTypeMask;
2226 return static_cast<Flags>(bits);
2227 }
2228
2229
GetCodeFromTargetAddress(Address address)2230 Code* Code::GetCodeFromTargetAddress(Address address) {
2231 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2232 // GetCodeFromTargetAddress might be called when marking objects during mark
2233 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2234 // Code::cast. Code::cast does not work when the object's map is
2235 // marked.
2236 Code* result = reinterpret_cast<Code*>(code);
2237 return result;
2238 }
2239
2240
prototype()2241 Object* Map::prototype() {
2242 return READ_FIELD(this, kPrototypeOffset);
2243 }
2244
2245
set_prototype(Object * value,WriteBarrierMode mode)2246 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2247 ASSERT(value->IsNull() || value->IsJSObject());
2248 WRITE_FIELD(this, kPrototypeOffset, value);
2249 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2250 }
2251
2252
ACCESSORS(Map,instance_descriptors,DescriptorArray,kInstanceDescriptorsOffset)2253 ACCESSORS(Map, instance_descriptors, DescriptorArray,
2254 kInstanceDescriptorsOffset)
2255 ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2256 ACCESSORS(Map, constructor, Object, kConstructorOffset)
2257
2258 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2259 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2260
2261 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2262 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2263 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2264
2265 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2266
2267 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2268 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2269 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2270 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2271 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2272 ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
2273
2274 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2275 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2276 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2277
2278 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2279 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2280 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2281 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2282 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2283 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2284
2285 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2286 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2287
2288 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2289 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2290
2291 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2292 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2293 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2294 kPropertyAccessorsOffset)
2295 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2296 kPrototypeTemplateOffset)
2297 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2298 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2299 kNamedPropertyHandlerOffset)
2300 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2301 kIndexedPropertyHandlerOffset)
2302 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2303 kInstanceTemplateOffset)
2304 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2305 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2306 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2307 kInstanceCallHandlerOffset)
2308 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2309 kAccessCheckInfoOffset)
2310 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2311
2312 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2313 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2314 kInternalFieldCountOffset)
2315
2316 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2317 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2318
2319 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2320
2321 ACCESSORS(Script, source, Object, kSourceOffset)
2322 ACCESSORS(Script, name, Object, kNameOffset)
2323 ACCESSORS(Script, id, Object, kIdOffset)
2324 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2325 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2326 ACCESSORS(Script, data, Object, kDataOffset)
2327 ACCESSORS(Script, context_data, Object, kContextOffset)
2328 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2329 ACCESSORS(Script, type, Smi, kTypeOffset)
2330 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2331 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
2332 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
2333 ACCESSORS(Script, eval_from_instructions_offset, Smi,
2334 kEvalFrominstructionsOffsetOffset)
2335
2336 #ifdef ENABLE_DEBUGGER_SUPPORT
2337 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2338 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2339 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2340 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2341
2342 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2343 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2344 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2345 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2346 #endif
2347
2348 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2349 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2350 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2351 kInstanceClassNameOffset)
2352 ACCESSORS(SharedFunctionInfo, function_data, Object,
2353 kExternalReferenceDataOffset)
2354 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2355 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2356 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2357 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2358 kThisPropertyAssignmentsOffset)
2359
2360 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2361 kHiddenPrototypeBit)
2362 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2363 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2364 kNeedsAccessCheckBit)
2365 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2366 kIsExpressionBit)
2367 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2368 kIsTopLevelBit)
2369 BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2370 has_only_simple_this_property_assignments,
2371 kHasOnlySimpleThisPropertyAssignments)
2372 BOOL_ACCESSORS(SharedFunctionInfo,
2373 compiler_hints,
2374 try_full_codegen,
2375 kTryFullCodegen)
2376
2377 INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2378 INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2379 kFormalParameterCountOffset)
2380 INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2381 kExpectedNofPropertiesOffset)
2382 INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2383 kStartPositionAndTypeOffset)
2384 INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2385 INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2386 kFunctionTokenPositionOffset)
2387 INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2388 kCompilerHintsOffset)
2389 INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2390 kThisPropertyAssignmentsCountOffset)
2391
2392
2393 bool Script::HasValidSource() {
2394 Object* src = this->source();
2395 if (!src->IsString()) return true;
2396 String* src_str = String::cast(src);
2397 if (!StringShape(src_str).IsExternal()) return true;
2398 if (src_str->IsAsciiRepresentation()) {
2399 return ExternalAsciiString::cast(src)->resource() != NULL;
2400 } else if (src_str->IsTwoByteRepresentation()) {
2401 return ExternalTwoByteString::cast(src)->resource() != NULL;
2402 }
2403 return true;
2404 }
2405
2406
DontAdaptArguments()2407 void SharedFunctionInfo::DontAdaptArguments() {
2408 ASSERT(code()->kind() == Code::BUILTIN);
2409 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2410 }
2411
2412
start_position()2413 int SharedFunctionInfo::start_position() {
2414 return start_position_and_type() >> kStartPositionShift;
2415 }
2416
2417
set_start_position(int start_position)2418 void SharedFunctionInfo::set_start_position(int start_position) {
2419 set_start_position_and_type((start_position << kStartPositionShift)
2420 | (start_position_and_type() & ~kStartPositionMask));
2421 }
2422
2423
code()2424 Code* SharedFunctionInfo::code() {
2425 return Code::cast(READ_FIELD(this, kCodeOffset));
2426 }
2427
2428
set_code(Code * value,WriteBarrierMode mode)2429 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2430 WRITE_FIELD(this, kCodeOffset, value);
2431 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2432 }
2433
2434
is_compiled()2435 bool SharedFunctionInfo::is_compiled() {
2436 // TODO(1242782): Create a code kind for uncompiled code.
2437 return code()->kind() != Code::STUB;
2438 }
2439
2440
IsBoilerplate()2441 bool JSFunction::IsBoilerplate() {
2442 return map() == Heap::boilerplate_function_map();
2443 }
2444
2445
IsBuiltin()2446 bool JSFunction::IsBuiltin() {
2447 return context()->global()->IsJSBuiltinsObject();
2448 }
2449
2450
code()2451 Code* JSFunction::code() {
2452 return shared()->code();
2453 }
2454
2455
set_code(Code * value)2456 void JSFunction::set_code(Code* value) {
2457 shared()->set_code(value);
2458 }
2459
2460
context()2461 Context* JSFunction::context() {
2462 return Context::cast(READ_FIELD(this, kContextOffset));
2463 }
2464
2465
unchecked_context()2466 Object* JSFunction::unchecked_context() {
2467 return READ_FIELD(this, kContextOffset);
2468 }
2469
2470
set_context(Object * value)2471 void JSFunction::set_context(Object* value) {
2472 ASSERT(value == Heap::undefined_value() || value->IsContext());
2473 WRITE_FIELD(this, kContextOffset, value);
2474 WRITE_BARRIER(this, kContextOffset);
2475 }
2476
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)2477 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2478 kPrototypeOrInitialMapOffset)
2479
2480
2481 Map* JSFunction::initial_map() {
2482 return Map::cast(prototype_or_initial_map());
2483 }
2484
2485
set_initial_map(Map * value)2486 void JSFunction::set_initial_map(Map* value) {
2487 set_prototype_or_initial_map(value);
2488 }
2489
2490
has_initial_map()2491 bool JSFunction::has_initial_map() {
2492 return prototype_or_initial_map()->IsMap();
2493 }
2494
2495
has_instance_prototype()2496 bool JSFunction::has_instance_prototype() {
2497 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2498 }
2499
2500
has_prototype()2501 bool JSFunction::has_prototype() {
2502 return map()->has_non_instance_prototype() || has_instance_prototype();
2503 }
2504
2505
instance_prototype()2506 Object* JSFunction::instance_prototype() {
2507 ASSERT(has_instance_prototype());
2508 if (has_initial_map()) return initial_map()->prototype();
2509 // When there is no initial map and the prototype is a JSObject, the
2510 // initial map field is used for the prototype field.
2511 return prototype_or_initial_map();
2512 }
2513
2514
prototype()2515 Object* JSFunction::prototype() {
2516 ASSERT(has_prototype());
2517 // If the function's prototype property has been set to a non-JSObject
2518 // value, that value is stored in the constructor field of the map.
2519 if (map()->has_non_instance_prototype()) return map()->constructor();
2520 return instance_prototype();
2521 }
2522
2523
is_compiled()2524 bool JSFunction::is_compiled() {
2525 return shared()->is_compiled();
2526 }
2527
2528
NumberOfLiterals()2529 int JSFunction::NumberOfLiterals() {
2530 return literals()->length();
2531 }
2532
2533
javascript_builtin(Builtins::JavaScript id)2534 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2535 ASSERT(0 <= id && id < kJSBuiltinsCount);
2536 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2537 }
2538
2539
set_javascript_builtin(Builtins::JavaScript id,Object * value)2540 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2541 Object* value) {
2542 ASSERT(0 <= id && id < kJSBuiltinsCount);
2543 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2544 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2545 }
2546
2547
proxy()2548 Address Proxy::proxy() {
2549 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2550 }
2551
2552
set_proxy(Address value)2553 void Proxy::set_proxy(Address value) {
2554 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2555 }
2556
2557
ProxyIterateBody(ObjectVisitor * visitor)2558 void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2559 visitor->VisitExternalReference(
2560 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2561 }
2562
2563
ACCESSORS(JSValue,value,Object,kValueOffset)2564 ACCESSORS(JSValue, value, Object, kValueOffset)
2565
2566
2567 JSValue* JSValue::cast(Object* obj) {
2568 ASSERT(obj->IsJSValue());
2569 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2570 return reinterpret_cast<JSValue*>(obj);
2571 }
2572
2573
INT_ACCESSORS(Code,instruction_size,kInstructionSizeOffset)2574 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2575 INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2576 INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2577
2578
2579 byte* Code::instruction_start() {
2580 return FIELD_ADDR(this, kHeaderSize);
2581 }
2582
2583
body_size()2584 int Code::body_size() {
2585 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2586 }
2587
2588
relocation_start()2589 byte* Code::relocation_start() {
2590 return FIELD_ADDR(this, kHeaderSize + instruction_size());
2591 }
2592
2593
entry()2594 byte* Code::entry() {
2595 return instruction_start();
2596 }
2597
2598
contains(byte * pc)2599 bool Code::contains(byte* pc) {
2600 return (instruction_start() <= pc) &&
2601 (pc < instruction_start() + instruction_size());
2602 }
2603
2604
sinfo_start()2605 byte* Code::sinfo_start() {
2606 return FIELD_ADDR(this, kHeaderSize + body_size());
2607 }
2608
2609
ACCESSORS(JSArray,length,Object,kLengthOffset)2610 ACCESSORS(JSArray, length, Object, kLengthOffset)
2611
2612
2613 ACCESSORS(JSRegExp, data, Object, kDataOffset)
2614
2615
2616 JSRegExp::Type JSRegExp::TypeTag() {
2617 Object* data = this->data();
2618 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2619 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2620 return static_cast<JSRegExp::Type>(smi->value());
2621 }
2622
2623
CaptureCount()2624 int JSRegExp::CaptureCount() {
2625 switch (TypeTag()) {
2626 case ATOM:
2627 return 0;
2628 case IRREGEXP:
2629 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2630 default:
2631 UNREACHABLE();
2632 return -1;
2633 }
2634 }
2635
2636
GetFlags()2637 JSRegExp::Flags JSRegExp::GetFlags() {
2638 ASSERT(this->data()->IsFixedArray());
2639 Object* data = this->data();
2640 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2641 return Flags(smi->value());
2642 }
2643
2644
Pattern()2645 String* JSRegExp::Pattern() {
2646 ASSERT(this->data()->IsFixedArray());
2647 Object* data = this->data();
2648 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2649 return pattern;
2650 }
2651
2652
DataAt(int index)2653 Object* JSRegExp::DataAt(int index) {
2654 ASSERT(TypeTag() != NOT_COMPILED);
2655 return FixedArray::cast(data())->get(index);
2656 }
2657
2658
SetDataAt(int index,Object * value)2659 void JSRegExp::SetDataAt(int index, Object* value) {
2660 ASSERT(TypeTag() != NOT_COMPILED);
2661 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2662 FixedArray::cast(data())->set(index, value);
2663 }
2664
2665
GetElementsKind()2666 JSObject::ElementsKind JSObject::GetElementsKind() {
2667 Array* array = elements();
2668 if (array->IsFixedArray()) {
2669 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2670 if (array->map() == Heap::fixed_array_map()) {
2671 return FAST_ELEMENTS;
2672 }
2673 ASSERT(array->IsDictionary());
2674 return DICTIONARY_ELEMENTS;
2675 }
2676 if (array->IsExternalArray()) {
2677 switch (array->map()->instance_type()) {
2678 case EXTERNAL_BYTE_ARRAY_TYPE:
2679 return EXTERNAL_BYTE_ELEMENTS;
2680 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2681 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2682 case EXTERNAL_SHORT_ARRAY_TYPE:
2683 return EXTERNAL_SHORT_ELEMENTS;
2684 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2685 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2686 case EXTERNAL_INT_ARRAY_TYPE:
2687 return EXTERNAL_INT_ELEMENTS;
2688 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2689 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2690 default:
2691 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2692 return EXTERNAL_FLOAT_ELEMENTS;
2693 }
2694 }
2695 ASSERT(array->IsPixelArray());
2696 return PIXEL_ELEMENTS;
2697 }
2698
2699
HasFastElements()2700 bool JSObject::HasFastElements() {
2701 return GetElementsKind() == FAST_ELEMENTS;
2702 }
2703
2704
HasDictionaryElements()2705 bool JSObject::HasDictionaryElements() {
2706 return GetElementsKind() == DICTIONARY_ELEMENTS;
2707 }
2708
2709
HasPixelElements()2710 bool JSObject::HasPixelElements() {
2711 return GetElementsKind() == PIXEL_ELEMENTS;
2712 }
2713
2714
HasExternalArrayElements()2715 bool JSObject::HasExternalArrayElements() {
2716 return (HasExternalByteElements() ||
2717 HasExternalUnsignedByteElements() ||
2718 HasExternalShortElements() ||
2719 HasExternalUnsignedShortElements() ||
2720 HasExternalIntElements() ||
2721 HasExternalUnsignedIntElements() ||
2722 HasExternalFloatElements());
2723 }
2724
2725
HasExternalByteElements()2726 bool JSObject::HasExternalByteElements() {
2727 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2728 }
2729
2730
HasExternalUnsignedByteElements()2731 bool JSObject::HasExternalUnsignedByteElements() {
2732 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2733 }
2734
2735
HasExternalShortElements()2736 bool JSObject::HasExternalShortElements() {
2737 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2738 }
2739
2740
HasExternalUnsignedShortElements()2741 bool JSObject::HasExternalUnsignedShortElements() {
2742 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2743 }
2744
2745
HasExternalIntElements()2746 bool JSObject::HasExternalIntElements() {
2747 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2748 }
2749
2750
HasExternalUnsignedIntElements()2751 bool JSObject::HasExternalUnsignedIntElements() {
2752 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2753 }
2754
2755
HasExternalFloatElements()2756 bool JSObject::HasExternalFloatElements() {
2757 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2758 }
2759
2760
HasNamedInterceptor()2761 bool JSObject::HasNamedInterceptor() {
2762 return map()->has_named_interceptor();
2763 }
2764
2765
HasIndexedInterceptor()2766 bool JSObject::HasIndexedInterceptor() {
2767 return map()->has_indexed_interceptor();
2768 }
2769
2770
property_dictionary()2771 StringDictionary* JSObject::property_dictionary() {
2772 ASSERT(!HasFastProperties());
2773 return StringDictionary::cast(properties());
2774 }
2775
2776
element_dictionary()2777 NumberDictionary* JSObject::element_dictionary() {
2778 ASSERT(HasDictionaryElements());
2779 return NumberDictionary::cast(elements());
2780 }
2781
2782
HasHashCode()2783 bool String::HasHashCode() {
2784 return (hash_field() & kHashComputedMask) != 0;
2785 }
2786
2787
Hash()2788 uint32_t String::Hash() {
2789 // Fast case: has hash code already been computed?
2790 uint32_t field = hash_field();
2791 if (field & kHashComputedMask) return field >> kHashShift;
2792 // Slow case: compute hash code and set it.
2793 return ComputeAndSetHash();
2794 }
2795
2796
StringHasher(int length)2797 StringHasher::StringHasher(int length)
2798 : length_(length),
2799 raw_running_hash_(0),
2800 array_index_(0),
2801 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2802 is_first_char_(true),
2803 is_valid_(true) { }
2804
2805
has_trivial_hash()2806 bool StringHasher::has_trivial_hash() {
2807 return length_ > String::kMaxHashCalcLength;
2808 }
2809
2810
AddCharacter(uc32 c)2811 void StringHasher::AddCharacter(uc32 c) {
2812 // Use the Jenkins one-at-a-time hash function to update the hash
2813 // for the given character.
2814 raw_running_hash_ += c;
2815 raw_running_hash_ += (raw_running_hash_ << 10);
2816 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2817 // Incremental array index computation.
2818 if (is_array_index_) {
2819 if (c < '0' || c > '9') {
2820 is_array_index_ = false;
2821 } else {
2822 int d = c - '0';
2823 if (is_first_char_) {
2824 is_first_char_ = false;
2825 if (c == '0' && length_ > 1) {
2826 is_array_index_ = false;
2827 return;
2828 }
2829 }
2830 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2831 is_array_index_ = false;
2832 } else {
2833 array_index_ = array_index_ * 10 + d;
2834 }
2835 }
2836 }
2837 }
2838
2839
AddCharacterNoIndex(uc32 c)2840 void StringHasher::AddCharacterNoIndex(uc32 c) {
2841 ASSERT(!is_array_index());
2842 raw_running_hash_ += c;
2843 raw_running_hash_ += (raw_running_hash_ << 10);
2844 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2845 }
2846
2847
GetHash()2848 uint32_t StringHasher::GetHash() {
2849 // Get the calculated raw hash value and do some more bit ops to distribute
2850 // the hash further. Ensure that we never return zero as the hash value.
2851 uint32_t result = raw_running_hash_;
2852 result += (result << 3);
2853 result ^= (result >> 11);
2854 result += (result << 15);
2855 if (result == 0) {
2856 result = 27;
2857 }
2858 return result;
2859 }
2860
2861
AsArrayIndex(uint32_t * index)2862 bool String::AsArrayIndex(uint32_t* index) {
2863 uint32_t field = hash_field();
2864 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
2865 return SlowAsArrayIndex(index);
2866 }
2867
2868
GetPrototype()2869 Object* JSObject::GetPrototype() {
2870 return JSObject::cast(this)->map()->prototype();
2871 }
2872
2873
GetPropertyAttribute(String * key)2874 PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2875 return GetPropertyAttributeWithReceiver(this, key);
2876 }
2877
2878 // TODO(504): this may be useful in other places too where JSGlobalProxy
2879 // is used.
BypassGlobalProxy()2880 Object* JSObject::BypassGlobalProxy() {
2881 if (IsJSGlobalProxy()) {
2882 Object* proto = GetPrototype();
2883 if (proto->IsNull()) return Heap::undefined_value();
2884 ASSERT(proto->IsJSGlobalObject());
2885 return proto;
2886 }
2887 return this;
2888 }
2889
2890
HasHiddenPropertiesObject()2891 bool JSObject::HasHiddenPropertiesObject() {
2892 ASSERT(!IsJSGlobalProxy());
2893 return GetPropertyAttributePostInterceptor(this,
2894 Heap::hidden_symbol(),
2895 false) != ABSENT;
2896 }
2897
2898
GetHiddenPropertiesObject()2899 Object* JSObject::GetHiddenPropertiesObject() {
2900 ASSERT(!IsJSGlobalProxy());
2901 PropertyAttributes attributes;
2902 return GetLocalPropertyPostInterceptor(this,
2903 Heap::hidden_symbol(),
2904 &attributes);
2905 }
2906
2907
SetHiddenPropertiesObject(Object * hidden_obj)2908 Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
2909 ASSERT(!IsJSGlobalProxy());
2910 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
2911 hidden_obj,
2912 DONT_ENUM);
2913 }
2914
2915
HasElement(uint32_t index)2916 bool JSObject::HasElement(uint32_t index) {
2917 return HasElementWithReceiver(this, index);
2918 }
2919
2920
all_can_read()2921 bool AccessorInfo::all_can_read() {
2922 return BooleanBit::get(flag(), kAllCanReadBit);
2923 }
2924
2925
set_all_can_read(bool value)2926 void AccessorInfo::set_all_can_read(bool value) {
2927 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2928 }
2929
2930
all_can_write()2931 bool AccessorInfo::all_can_write() {
2932 return BooleanBit::get(flag(), kAllCanWriteBit);
2933 }
2934
2935
set_all_can_write(bool value)2936 void AccessorInfo::set_all_can_write(bool value) {
2937 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2938 }
2939
2940
prohibits_overwriting()2941 bool AccessorInfo::prohibits_overwriting() {
2942 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2943 }
2944
2945
set_prohibits_overwriting(bool value)2946 void AccessorInfo::set_prohibits_overwriting(bool value) {
2947 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2948 }
2949
2950
property_attributes()2951 PropertyAttributes AccessorInfo::property_attributes() {
2952 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2953 }
2954
2955
set_property_attributes(PropertyAttributes attributes)2956 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2957 ASSERT(AttributesField::is_valid(attributes));
2958 int rest_value = flag()->value() & ~AttributesField::mask();
2959 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2960 }
2961
2962 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)2963 void Dictionary<Shape, Key>::SetEntry(int entry,
2964 Object* key,
2965 Object* value,
2966 PropertyDetails details) {
2967 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
2968 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2969 AssertNoAllocation no_gc;
2970 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
2971 FixedArray::set(index, key, mode);
2972 FixedArray::set(index+1, value, mode);
2973 FixedArray::fast_set(this, index+2, details.AsSmi());
2974 }
2975
2976
ClearCodeCache()2977 void Map::ClearCodeCache() {
2978 // No write barrier is needed since empty_fixed_array is not in new space.
2979 // Please note this function is used during marking:
2980 // - MarkCompactCollector::MarkUnmarkedObject
2981 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2982 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
2983 }
2984
2985
EnsureSize(int required_size)2986 void JSArray::EnsureSize(int required_size) {
2987 ASSERT(HasFastElements());
2988 Array* elts = elements();
2989 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
2990 if (elts->length() < required_size) {
2991 // Doubling in size would be overkill, but leave some slack to avoid
2992 // constantly growing.
2993 Expand(required_size + (required_size >> 3));
2994 // It's a performance benefit to keep a frequently used array in new-space.
2995 } else if (!Heap::new_space()->Contains(elts) &&
2996 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
2997 // Expand will allocate a new backing store in new space even if the size
2998 // we asked for isn't larger than what we had before.
2999 Expand(required_size);
3000 }
3001 }
3002
3003
set_length(Smi * length)3004 void JSArray::set_length(Smi* length) {
3005 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3006 }
3007
3008
SetContent(FixedArray * storage)3009 void JSArray::SetContent(FixedArray* storage) {
3010 set_length(Smi::FromInt(storage->length()));
3011 set_elements(storage);
3012 }
3013
3014
Copy()3015 Object* FixedArray::Copy() {
3016 if (length() == 0) return this;
3017 return Heap::CopyFixedArray(this);
3018 }
3019
3020
3021 #undef CAST_ACCESSOR
3022 #undef INT_ACCESSORS
3023 #undef SMI_ACCESSORS
3024 #undef ACCESSORS
3025 #undef FIELD_ADDR
3026 #undef READ_FIELD
3027 #undef WRITE_FIELD
3028 #undef WRITE_BARRIER
3029 #undef CONDITIONAL_WRITE_BARRIER
3030 #undef READ_MEMADDR_FIELD
3031 #undef WRITE_MEMADDR_FIELD
3032 #undef READ_DOUBLE_FIELD
3033 #undef WRITE_DOUBLE_FIELD
3034 #undef READ_INT_FIELD
3035 #undef WRITE_INT_FIELD
3036 #undef READ_SHORT_FIELD
3037 #undef WRITE_SHORT_FIELD
3038 #undef READ_BYTE_FIELD
3039 #undef WRITE_BYTE_FIELD
3040
3041
3042 } } // namespace v8::internal
3043
3044 #endif // V8_OBJECTS_INL_H_
3045