blob: 2a54062f0a00019247f92d25b25ff85326e4e764 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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
Kristian Monsen80d68ea2010-09-08 11:05:35 +010038#include "objects.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "contexts.h"
40#include "conversions-inl.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010041#include "heap.h"
42#include "memory.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043#include "property.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010044#include "spaces.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000045
46namespace v8 {
47namespace internal {
48
49PropertyDetails::PropertyDetails(Smi* smi) {
50 value_ = smi->value();
51}
52
53
54Smi* PropertyDetails::AsSmi() {
55 return Smi::FromInt(value_);
56}
57
58
59PropertyDetails PropertyDetails::AsDeleted() {
60 PropertyDetails d(DONT_ENUM, NORMAL);
61 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
62 return PropertyDetails(smi);
63}
64
65
66#define CAST_ACCESSOR(type) \
67 type* type::cast(Object* object) { \
68 ASSERT(object->Is##type()); \
69 return reinterpret_cast<type*>(object); \
70 }
71
72
73#define INT_ACCESSORS(holder, name, offset) \
74 int holder::name() { return READ_INT_FIELD(this, offset); } \
75 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
76
77
78#define ACCESSORS(holder, name, type, offset) \
79 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
80 void holder::set_##name(type* value, WriteBarrierMode mode) { \
81 WRITE_FIELD(this, offset, value); \
82 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
83 }
84
85
86
87#define SMI_ACCESSORS(holder, name, offset) \
88 int holder::name() { \
89 Object* value = READ_FIELD(this, offset); \
90 return Smi::cast(value)->value(); \
91 } \
92 void holder::set_##name(int value) { \
93 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
94 }
95
96
97#define BOOL_GETTER(holder, field, name, offset) \
98 bool holder::name() { \
99 return BooleanBit::get(field(), offset); \
100 } \
101
102
103#define BOOL_ACCESSORS(holder, field, name, offset) \
104 bool holder::name() { \
105 return BooleanBit::get(field(), offset); \
106 } \
107 void holder::set_##name(bool value) { \
108 set_##field(BooleanBit::set(field(), offset, value)); \
109 }
110
111
112bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
113 // There is a constraint on the object; check.
114 if (!this->IsJSObject()) return false;
115 // Fetch the constructor function of the object.
116 Object* cons_obj = JSObject::cast(this)->map()->constructor();
117 if (!cons_obj->IsJSFunction()) return false;
118 JSFunction* fun = JSFunction::cast(cons_obj);
119 // Iterate through the chain of inheriting function templates to
120 // see if the required one occurs.
121 for (Object* type = fun->shared()->function_data();
122 type->IsFunctionTemplateInfo();
123 type = FunctionTemplateInfo::cast(type)->parent_template()) {
124 if (type == expected) return true;
125 }
126 // Didn't find the required type in the inheritance chain.
127 return false;
128}
129
130
131bool Object::IsSmi() {
132 return HAS_SMI_TAG(this);
133}
134
135
136bool Object::IsHeapObject() {
137 return Internals::HasHeapObjectTag(this);
138}
139
140
141bool Object::IsHeapNumber() {
142 return Object::IsHeapObject()
143 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
144}
145
146
147bool Object::IsString() {
148 return Object::IsHeapObject()
149 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
150}
151
152
153bool Object::IsSymbol() {
154 if (!this->IsHeapObject()) return false;
155 uint32_t type = HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000156 // Because the symbol tag is non-zero and no non-string types have the
157 // symbol bit set we can test for symbols with a very simple test
158 // operation.
159 ASSERT(kSymbolTag != 0);
160 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
161 return (type & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000162}
163
164
165bool Object::IsConsString() {
166 if (!this->IsHeapObject()) return false;
167 uint32_t type = HeapObject::cast(this)->map()->instance_type();
168 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
169 (kStringTag | kConsStringTag);
170}
171
172
Steve Blocka7e24c12009-10-30 11:49:00 +0000173bool Object::IsSeqString() {
174 if (!IsString()) return false;
175 return StringShape(String::cast(this)).IsSequential();
176}
177
178
179bool Object::IsSeqAsciiString() {
180 if (!IsString()) return false;
181 return StringShape(String::cast(this)).IsSequential() &&
182 String::cast(this)->IsAsciiRepresentation();
183}
184
185
186bool Object::IsSeqTwoByteString() {
187 if (!IsString()) return false;
188 return StringShape(String::cast(this)).IsSequential() &&
189 String::cast(this)->IsTwoByteRepresentation();
190}
191
192
193bool Object::IsExternalString() {
194 if (!IsString()) return false;
195 return StringShape(String::cast(this)).IsExternal();
196}
197
198
199bool Object::IsExternalAsciiString() {
200 if (!IsString()) return false;
201 return StringShape(String::cast(this)).IsExternal() &&
202 String::cast(this)->IsAsciiRepresentation();
203}
204
205
206bool Object::IsExternalTwoByteString() {
207 if (!IsString()) return false;
208 return StringShape(String::cast(this)).IsExternal() &&
209 String::cast(this)->IsTwoByteRepresentation();
210}
211
212
Steve Blocka7e24c12009-10-30 11:49:00 +0000213StringShape::StringShape(String* str)
214 : type_(str->map()->instance_type()) {
215 set_valid();
216 ASSERT((type_ & kIsNotStringMask) == kStringTag);
217}
218
219
220StringShape::StringShape(Map* map)
221 : type_(map->instance_type()) {
222 set_valid();
223 ASSERT((type_ & kIsNotStringMask) == kStringTag);
224}
225
226
227StringShape::StringShape(InstanceType t)
228 : type_(static_cast<uint32_t>(t)) {
229 set_valid();
230 ASSERT((type_ & kIsNotStringMask) == kStringTag);
231}
232
233
234bool StringShape::IsSymbol() {
235 ASSERT(valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000236 ASSERT(kSymbolTag != 0);
237 return (type_ & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000238}
239
240
241bool String::IsAsciiRepresentation() {
242 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 return (type & kStringEncodingMask) == kAsciiStringTag;
244}
245
246
247bool String::IsTwoByteRepresentation() {
248 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000249 return (type & kStringEncodingMask) == kTwoByteStringTag;
250}
251
252
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100253bool String::HasOnlyAsciiChars() {
254 uint32_t type = map()->instance_type();
255 return (type & kStringEncodingMask) == kAsciiStringTag ||
256 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
Steve Block6ded16b2010-05-10 14:33:55 +0100257}
258
259
Steve Blocka7e24c12009-10-30 11:49:00 +0000260bool StringShape::IsCons() {
261 return (type_ & kStringRepresentationMask) == kConsStringTag;
262}
263
264
Steve Blocka7e24c12009-10-30 11:49:00 +0000265bool StringShape::IsExternal() {
266 return (type_ & kStringRepresentationMask) == kExternalStringTag;
267}
268
269
270bool StringShape::IsSequential() {
271 return (type_ & kStringRepresentationMask) == kSeqStringTag;
272}
273
274
275StringRepresentationTag StringShape::representation_tag() {
276 uint32_t tag = (type_ & kStringRepresentationMask);
277 return static_cast<StringRepresentationTag>(tag);
278}
279
280
281uint32_t StringShape::full_representation_tag() {
282 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
283}
284
285
286STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
287 Internals::kFullStringRepresentationMask);
288
289
Steve Blocka7e24c12009-10-30 11:49:00 +0000290bool StringShape::IsSequentialAscii() {
291 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
292}
293
294
295bool StringShape::IsSequentialTwoByte() {
296 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
297}
298
299
300bool StringShape::IsExternalAscii() {
301 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
302}
303
304
305bool StringShape::IsExternalTwoByte() {
306 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
307}
308
309
310STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
311 Internals::kExternalTwoByteRepresentationTag);
312
313
314uc32 FlatStringReader::Get(int index) {
315 ASSERT(0 <= index && index <= length_);
316 if (is_ascii_) {
317 return static_cast<const byte*>(start_)[index];
318 } else {
319 return static_cast<const uc16*>(start_)[index];
320 }
321}
322
323
324bool Object::IsNumber() {
325 return IsSmi() || IsHeapNumber();
326}
327
328
329bool Object::IsByteArray() {
330 return Object::IsHeapObject()
331 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
332}
333
334
335bool Object::IsPixelArray() {
336 return Object::IsHeapObject() &&
337 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
338}
339
340
Steve Block3ce2e202009-11-05 08:53:23 +0000341bool Object::IsExternalArray() {
342 if (!Object::IsHeapObject())
343 return false;
344 InstanceType instance_type =
345 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000346 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
347 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000348}
349
350
351bool Object::IsExternalByteArray() {
352 return Object::IsHeapObject() &&
353 HeapObject::cast(this)->map()->instance_type() ==
354 EXTERNAL_BYTE_ARRAY_TYPE;
355}
356
357
358bool Object::IsExternalUnsignedByteArray() {
359 return Object::IsHeapObject() &&
360 HeapObject::cast(this)->map()->instance_type() ==
361 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
362}
363
364
365bool Object::IsExternalShortArray() {
366 return Object::IsHeapObject() &&
367 HeapObject::cast(this)->map()->instance_type() ==
368 EXTERNAL_SHORT_ARRAY_TYPE;
369}
370
371
372bool Object::IsExternalUnsignedShortArray() {
373 return Object::IsHeapObject() &&
374 HeapObject::cast(this)->map()->instance_type() ==
375 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
376}
377
378
379bool Object::IsExternalIntArray() {
380 return Object::IsHeapObject() &&
381 HeapObject::cast(this)->map()->instance_type() ==
382 EXTERNAL_INT_ARRAY_TYPE;
383}
384
385
386bool Object::IsExternalUnsignedIntArray() {
387 return Object::IsHeapObject() &&
388 HeapObject::cast(this)->map()->instance_type() ==
389 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
390}
391
392
393bool Object::IsExternalFloatArray() {
394 return Object::IsHeapObject() &&
395 HeapObject::cast(this)->map()->instance_type() ==
396 EXTERNAL_FLOAT_ARRAY_TYPE;
397}
398
399
Steve Blocka7e24c12009-10-30 11:49:00 +0000400bool Object::IsFailure() {
401 return HAS_FAILURE_TAG(this);
402}
403
404
405bool Object::IsRetryAfterGC() {
406 return HAS_FAILURE_TAG(this)
407 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
408}
409
410
411bool Object::IsOutOfMemoryFailure() {
412 return HAS_FAILURE_TAG(this)
413 && Failure::cast(this)->IsOutOfMemoryException();
414}
415
416
417bool Object::IsException() {
418 return this == Failure::Exception();
419}
420
421
422bool Object::IsJSObject() {
423 return IsHeapObject()
424 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
425}
426
427
428bool Object::IsJSContextExtensionObject() {
429 return IsHeapObject()
430 && (HeapObject::cast(this)->map()->instance_type() ==
431 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
432}
433
434
435bool Object::IsMap() {
436 return Object::IsHeapObject()
437 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
438}
439
440
441bool Object::IsFixedArray() {
442 return Object::IsHeapObject()
443 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
444}
445
446
447bool Object::IsDescriptorArray() {
448 return IsFixedArray();
449}
450
451
452bool Object::IsContext() {
453 return Object::IsHeapObject()
454 && (HeapObject::cast(this)->map() == Heap::context_map() ||
455 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
456 HeapObject::cast(this)->map() == Heap::global_context_map());
457}
458
459
460bool Object::IsCatchContext() {
461 return Object::IsHeapObject()
462 && HeapObject::cast(this)->map() == Heap::catch_context_map();
463}
464
465
466bool Object::IsGlobalContext() {
467 return Object::IsHeapObject()
468 && HeapObject::cast(this)->map() == Heap::global_context_map();
469}
470
471
472bool Object::IsJSFunction() {
473 return Object::IsHeapObject()
474 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
475}
476
477
478template <> inline bool Is<JSFunction>(Object* obj) {
479 return obj->IsJSFunction();
480}
481
482
483bool Object::IsCode() {
484 return Object::IsHeapObject()
485 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
486}
487
488
489bool Object::IsOddball() {
490 return Object::IsHeapObject()
491 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
492}
493
494
495bool Object::IsJSGlobalPropertyCell() {
496 return Object::IsHeapObject()
497 && HeapObject::cast(this)->map()->instance_type()
498 == JS_GLOBAL_PROPERTY_CELL_TYPE;
499}
500
501
502bool Object::IsSharedFunctionInfo() {
503 return Object::IsHeapObject() &&
504 (HeapObject::cast(this)->map()->instance_type() ==
505 SHARED_FUNCTION_INFO_TYPE);
506}
507
508
509bool Object::IsJSValue() {
510 return Object::IsHeapObject()
511 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
512}
513
514
515bool Object::IsStringWrapper() {
516 return IsJSValue() && JSValue::cast(this)->value()->IsString();
517}
518
519
520bool Object::IsProxy() {
521 return Object::IsHeapObject()
522 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
523}
524
525
526bool Object::IsBoolean() {
527 return IsTrue() || IsFalse();
528}
529
530
531bool Object::IsJSArray() {
532 return Object::IsHeapObject()
533 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
534}
535
536
537bool Object::IsJSRegExp() {
538 return Object::IsHeapObject()
539 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
540}
541
542
543template <> inline bool Is<JSArray>(Object* obj) {
544 return obj->IsJSArray();
545}
546
547
548bool Object::IsHashTable() {
549 return Object::IsHeapObject()
550 && HeapObject::cast(this)->map() == Heap::hash_table_map();
551}
552
553
554bool Object::IsDictionary() {
555 return IsHashTable() && this != Heap::symbol_table();
556}
557
558
559bool Object::IsSymbolTable() {
560 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
561}
562
563
Steve Block6ded16b2010-05-10 14:33:55 +0100564bool Object::IsJSFunctionResultCache() {
565 if (!IsFixedArray()) return false;
566 FixedArray* self = FixedArray::cast(this);
567 int length = self->length();
568 if (length < JSFunctionResultCache::kEntriesIndex) return false;
569 if ((length - JSFunctionResultCache::kEntriesIndex)
570 % JSFunctionResultCache::kEntrySize != 0) {
571 return false;
572 }
573#ifdef DEBUG
574 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
575#endif
576 return true;
577}
578
579
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100580bool Object::IsNormalizedMapCache() {
581 if (!IsFixedArray()) return false;
582 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
583 return false;
584 }
585#ifdef DEBUG
586 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
587#endif
588 return true;
589}
590
591
Steve Blocka7e24c12009-10-30 11:49:00 +0000592bool Object::IsCompilationCacheTable() {
593 return IsHashTable();
594}
595
596
Steve Block6ded16b2010-05-10 14:33:55 +0100597bool Object::IsCodeCacheHashTable() {
598 return IsHashTable();
599}
600
601
Steve Blocka7e24c12009-10-30 11:49:00 +0000602bool Object::IsMapCache() {
603 return IsHashTable();
604}
605
606
607bool Object::IsPrimitive() {
608 return IsOddball() || IsNumber() || IsString();
609}
610
611
612bool Object::IsJSGlobalProxy() {
613 bool result = IsHeapObject() &&
614 (HeapObject::cast(this)->map()->instance_type() ==
615 JS_GLOBAL_PROXY_TYPE);
616 ASSERT(!result || IsAccessCheckNeeded());
617 return result;
618}
619
620
621bool Object::IsGlobalObject() {
622 if (!IsHeapObject()) return false;
623
624 InstanceType type = HeapObject::cast(this)->map()->instance_type();
625 return type == JS_GLOBAL_OBJECT_TYPE ||
626 type == JS_BUILTINS_OBJECT_TYPE;
627}
628
629
630bool Object::IsJSGlobalObject() {
631 return IsHeapObject() &&
632 (HeapObject::cast(this)->map()->instance_type() ==
633 JS_GLOBAL_OBJECT_TYPE);
634}
635
636
637bool Object::IsJSBuiltinsObject() {
638 return IsHeapObject() &&
639 (HeapObject::cast(this)->map()->instance_type() ==
640 JS_BUILTINS_OBJECT_TYPE);
641}
642
643
644bool Object::IsUndetectableObject() {
645 return IsHeapObject()
646 && HeapObject::cast(this)->map()->is_undetectable();
647}
648
649
650bool Object::IsAccessCheckNeeded() {
651 return IsHeapObject()
652 && HeapObject::cast(this)->map()->is_access_check_needed();
653}
654
655
656bool Object::IsStruct() {
657 if (!IsHeapObject()) return false;
658 switch (HeapObject::cast(this)->map()->instance_type()) {
659#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
660 STRUCT_LIST(MAKE_STRUCT_CASE)
661#undef MAKE_STRUCT_CASE
662 default: return false;
663 }
664}
665
666
667#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
668 bool Object::Is##Name() { \
669 return Object::IsHeapObject() \
670 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
671 }
672 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
673#undef MAKE_STRUCT_PREDICATE
674
675
676bool Object::IsUndefined() {
677 return this == Heap::undefined_value();
678}
679
680
681bool Object::IsTheHole() {
682 return this == Heap::the_hole_value();
683}
684
685
686bool Object::IsNull() {
687 return this == Heap::null_value();
688}
689
690
691bool Object::IsTrue() {
692 return this == Heap::true_value();
693}
694
695
696bool Object::IsFalse() {
697 return this == Heap::false_value();
698}
699
700
701double Object::Number() {
702 ASSERT(IsNumber());
703 return IsSmi()
704 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
705 : reinterpret_cast<HeapNumber*>(this)->value();
706}
707
708
709
710Object* Object::ToSmi() {
711 if (IsSmi()) return this;
712 if (IsHeapNumber()) {
713 double value = HeapNumber::cast(this)->value();
714 int int_value = FastD2I(value);
715 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
716 return Smi::FromInt(int_value);
717 }
718 }
719 return Failure::Exception();
720}
721
722
723bool Object::HasSpecificClassOf(String* name) {
724 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
725}
726
727
728Object* Object::GetElement(uint32_t index) {
729 return GetElementWithReceiver(this, index);
730}
731
732
733Object* Object::GetProperty(String* key) {
734 PropertyAttributes attributes;
735 return GetPropertyWithReceiver(this, key, &attributes);
736}
737
738
739Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
740 return GetPropertyWithReceiver(this, key, attributes);
741}
742
743
744#define FIELD_ADDR(p, offset) \
745 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
746
747#define READ_FIELD(p, offset) \
748 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
749
750#define WRITE_FIELD(p, offset, value) \
751 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
752
753
754#define WRITE_BARRIER(object, offset) \
755 Heap::RecordWrite(object->address(), offset);
756
757// CONDITIONAL_WRITE_BARRIER must be issued after the actual
758// write due to the assert validating the written value.
759#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
760 if (mode == UPDATE_WRITE_BARRIER) { \
761 Heap::RecordWrite(object->address(), offset); \
762 } else { \
763 ASSERT(mode == SKIP_WRITE_BARRIER); \
764 ASSERT(Heap::InNewSpace(object) || \
Steve Block6ded16b2010-05-10 14:33:55 +0100765 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100766 Page::FromAddress(object->address())-> \
767 IsRegionDirty(object->address() + offset)); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000768 }
769
770#define READ_DOUBLE_FIELD(p, offset) \
771 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
772
773#define WRITE_DOUBLE_FIELD(p, offset, value) \
774 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
775
776#define READ_INT_FIELD(p, offset) \
777 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
778
779#define WRITE_INT_FIELD(p, offset, value) \
780 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
781
782#define READ_INTPTR_FIELD(p, offset) \
783 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
784
785#define WRITE_INTPTR_FIELD(p, offset, value) \
786 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
787
788#define READ_UINT32_FIELD(p, offset) \
789 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
790
791#define WRITE_UINT32_FIELD(p, offset, value) \
792 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
793
794#define READ_SHORT_FIELD(p, offset) \
795 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
796
797#define WRITE_SHORT_FIELD(p, offset, value) \
798 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
799
800#define READ_BYTE_FIELD(p, offset) \
801 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
802
803#define WRITE_BYTE_FIELD(p, offset, value) \
804 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
805
806
807Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
808 return &READ_FIELD(obj, byte_offset);
809}
810
811
812int Smi::value() {
813 return Internals::SmiValue(this);
814}
815
816
817Smi* Smi::FromInt(int value) {
818 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000819 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000820 intptr_t tagged_value =
Steve Block3ce2e202009-11-05 08:53:23 +0000821 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000822 return reinterpret_cast<Smi*>(tagged_value);
823}
824
825
826Smi* Smi::FromIntptr(intptr_t value) {
827 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000828 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
829 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000830}
831
832
833Failure::Type Failure::type() const {
834 return static_cast<Type>(value() & kFailureTypeTagMask);
835}
836
837
838bool Failure::IsInternalError() const {
839 return type() == INTERNAL_ERROR;
840}
841
842
843bool Failure::IsOutOfMemoryException() const {
844 return type() == OUT_OF_MEMORY_EXCEPTION;
845}
846
847
848int Failure::requested() const {
849 const int kShiftBits =
850 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
851 STATIC_ASSERT(kShiftBits >= 0);
852 ASSERT(type() == RETRY_AFTER_GC);
Steve Block3ce2e202009-11-05 08:53:23 +0000853 return static_cast<int>(value() >> kShiftBits);
Steve Blocka7e24c12009-10-30 11:49:00 +0000854}
855
856
857AllocationSpace Failure::allocation_space() const {
858 ASSERT_EQ(RETRY_AFTER_GC, type());
859 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
860 & kSpaceTagMask);
861}
862
863
864Failure* Failure::InternalError() {
865 return Construct(INTERNAL_ERROR);
866}
867
868
869Failure* Failure::Exception() {
870 return Construct(EXCEPTION);
871}
872
873
874Failure* Failure::OutOfMemoryException() {
875 return Construct(OUT_OF_MEMORY_EXCEPTION);
876}
877
878
Steve Block3ce2e202009-11-05 08:53:23 +0000879intptr_t Failure::value() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100880 return static_cast<intptr_t>(
881 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000882}
883
884
885Failure* Failure::RetryAfterGC(int requested_bytes) {
886 // Assert that the space encoding fits in the three bytes allotted for it.
887 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
Steve Block6ded16b2010-05-10 14:33:55 +0100888 uintptr_t requested =
889 static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
890 int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
Steve Block3ce2e202009-11-05 08:53:23 +0000891 if (((requested << tag_bits) >> tag_bits) != requested) {
892 // No room for entire requested size in the bits. Round down to
893 // maximally representable size.
894 requested = static_cast<intptr_t>(
895 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
896 }
Steve Blockd0582a62009-12-15 09:54:21 +0000897 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000898 return Construct(RETRY_AFTER_GC, value);
899}
900
901
Steve Block3ce2e202009-11-05 08:53:23 +0000902Failure* Failure::Construct(Type type, intptr_t value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100903 uintptr_t info =
904 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
Steve Block3ce2e202009-11-05 08:53:23 +0000906 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000907}
908
909
910bool Smi::IsValid(intptr_t value) {
911#ifdef DEBUG
912 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
913#endif
Steve Block3ce2e202009-11-05 08:53:23 +0000914
915#ifdef V8_TARGET_ARCH_X64
916 // To be representable as a long smi, the value must be a 32-bit integer.
917 bool result = (value == static_cast<int32_t>(value));
918#else
Steve Blocka7e24c12009-10-30 11:49:00 +0000919 // To be representable as an tagged small integer, the two
920 // most-significant bits of 'value' must be either 00 or 11 due to
921 // sign-extension. To check this we add 01 to the two
922 // most-significant bits, and check if the most-significant bit is 0
923 //
924 // CAUTION: The original code below:
925 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
926 // may lead to incorrect results according to the C language spec, and
927 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
928 // compiler may produce undefined results in case of signed integer
929 // overflow. The computation must be done w/ unsigned ints.
Steve Block3ce2e202009-11-05 08:53:23 +0000930 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
Steve Blocka7e24c12009-10-30 11:49:00 +0000931#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 ASSERT(result == in_range);
933 return result;
934}
935
936
937MapWord MapWord::FromMap(Map* map) {
938 return MapWord(reinterpret_cast<uintptr_t>(map));
939}
940
941
942Map* MapWord::ToMap() {
943 return reinterpret_cast<Map*>(value_);
944}
945
946
947bool MapWord::IsForwardingAddress() {
948 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
949}
950
951
952MapWord MapWord::FromForwardingAddress(HeapObject* object) {
953 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
954 return MapWord(reinterpret_cast<uintptr_t>(raw));
955}
956
957
958HeapObject* MapWord::ToForwardingAddress() {
959 ASSERT(IsForwardingAddress());
960 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
961}
962
963
964bool MapWord::IsMarked() {
965 return (value_ & kMarkingMask) == 0;
966}
967
968
969void MapWord::SetMark() {
970 value_ &= ~kMarkingMask;
971}
972
973
974void MapWord::ClearMark() {
975 value_ |= kMarkingMask;
976}
977
978
979bool MapWord::IsOverflowed() {
980 return (value_ & kOverflowMask) != 0;
981}
982
983
984void MapWord::SetOverflow() {
985 value_ |= kOverflowMask;
986}
987
988
989void MapWord::ClearOverflow() {
990 value_ &= ~kOverflowMask;
991}
992
993
994MapWord MapWord::EncodeAddress(Address map_address, int offset) {
995 // Offset is the distance in live bytes from the first live object in the
996 // same page. The offset between two objects in the same page should not
997 // exceed the object area size of a page.
998 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
999
Leon Clarkee46be812010-01-19 14:06:41 +00001000 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1002
1003 Page* map_page = Page::FromAddress(map_address);
1004 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1005
Leon Clarkee46be812010-01-19 14:06:41 +00001006 uintptr_t map_page_offset =
1007 map_page->Offset(map_address) >> kMapAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +00001008
1009 uintptr_t encoding =
1010 (compact_offset << kForwardingOffsetShift) |
1011 (map_page_offset << kMapPageOffsetShift) |
1012 (map_page->mc_page_index << kMapPageIndexShift);
1013 return MapWord(encoding);
1014}
1015
1016
1017Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1018 int map_page_index =
1019 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1020 ASSERT_MAP_PAGE_INDEX(map_page_index);
1021
1022 int map_page_offset = static_cast<int>(
Leon Clarkee46be812010-01-19 14:06:41 +00001023 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1024 kMapAlignmentBits);
Steve Blocka7e24c12009-10-30 11:49:00 +00001025
1026 return (map_space->PageAddress(map_page_index) + map_page_offset);
1027}
1028
1029
1030int MapWord::DecodeOffset() {
1031 // The offset field is represented in the kForwardingOffsetBits
1032 // most-significant bits.
Steve Blockd0582a62009-12-15 09:54:21 +00001033 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1034 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1035 return static_cast<int>(offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001036}
1037
1038
1039MapWord MapWord::FromEncodedAddress(Address address) {
1040 return MapWord(reinterpret_cast<uintptr_t>(address));
1041}
1042
1043
1044Address MapWord::ToEncodedAddress() {
1045 return reinterpret_cast<Address>(value_);
1046}
1047
1048
1049#ifdef DEBUG
1050void HeapObject::VerifyObjectField(int offset) {
1051 VerifyPointer(READ_FIELD(this, offset));
1052}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001053
1054void HeapObject::VerifySmiField(int offset) {
1055 ASSERT(READ_FIELD(this, offset)->IsSmi());
1056}
Steve Blocka7e24c12009-10-30 11:49:00 +00001057#endif
1058
1059
1060Map* HeapObject::map() {
1061 return map_word().ToMap();
1062}
1063
1064
1065void HeapObject::set_map(Map* value) {
1066 set_map_word(MapWord::FromMap(value));
1067}
1068
1069
1070MapWord HeapObject::map_word() {
1071 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1072}
1073
1074
1075void HeapObject::set_map_word(MapWord map_word) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001076 // WRITE_FIELD does not invoke write barrier, but there is no need
Steve Blocka7e24c12009-10-30 11:49:00 +00001077 // here.
1078 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1079}
1080
1081
1082HeapObject* HeapObject::FromAddress(Address address) {
1083 ASSERT_TAG_ALIGNED(address);
1084 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1085}
1086
1087
1088Address HeapObject::address() {
1089 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1090}
1091
1092
1093int HeapObject::Size() {
1094 return SizeFromMap(map());
1095}
1096
1097
1098void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1099 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1100 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1101}
1102
1103
1104void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1105 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1106}
1107
1108
1109bool HeapObject::IsMarked() {
1110 return map_word().IsMarked();
1111}
1112
1113
1114void HeapObject::SetMark() {
1115 ASSERT(!IsMarked());
1116 MapWord first_word = map_word();
1117 first_word.SetMark();
1118 set_map_word(first_word);
1119}
1120
1121
1122void HeapObject::ClearMark() {
1123 ASSERT(IsMarked());
1124 MapWord first_word = map_word();
1125 first_word.ClearMark();
1126 set_map_word(first_word);
1127}
1128
1129
1130bool HeapObject::IsOverflowed() {
1131 return map_word().IsOverflowed();
1132}
1133
1134
1135void HeapObject::SetOverflow() {
1136 MapWord first_word = map_word();
1137 first_word.SetOverflow();
1138 set_map_word(first_word);
1139}
1140
1141
1142void HeapObject::ClearOverflow() {
1143 ASSERT(IsOverflowed());
1144 MapWord first_word = map_word();
1145 first_word.ClearOverflow();
1146 set_map_word(first_word);
1147}
1148
1149
1150double HeapNumber::value() {
1151 return READ_DOUBLE_FIELD(this, kValueOffset);
1152}
1153
1154
1155void HeapNumber::set_value(double value) {
1156 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1157}
1158
1159
Steve Block6ded16b2010-05-10 14:33:55 +01001160int HeapNumber::get_exponent() {
1161 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1162 kExponentShift) - kExponentBias;
1163}
1164
1165
1166int HeapNumber::get_sign() {
1167 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1168}
1169
1170
Steve Blocka7e24c12009-10-30 11:49:00 +00001171ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1172
1173
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001174HeapObject* JSObject::elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 Object* array = READ_FIELD(this, kElementsOffset);
1176 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001177 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1178 array->IsExternalArray());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001179 return reinterpret_cast<HeapObject*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001180}
1181
1182
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001183void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
Steve Block8defd9f2010-07-08 12:39:36 +01001184 ASSERT(map()->has_fast_elements() ==
Iain Merrick75681382010-08-19 15:07:18 +01001185 (value->map() == Heap::fixed_array_map() ||
1186 value->map() == Heap::fixed_cow_array_map()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001187 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001188 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1189 value->IsExternalArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 WRITE_FIELD(this, kElementsOffset, value);
1191 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1192}
1193
1194
1195void JSObject::initialize_properties() {
1196 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1197 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1198}
1199
1200
1201void JSObject::initialize_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01001202 ASSERT(map()->has_fast_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00001203 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1204 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1205}
1206
1207
Steve Block8defd9f2010-07-08 12:39:36 +01001208Object* JSObject::ResetElements() {
1209 Object* obj = map()->GetFastElementsMap();
1210 if (obj->IsFailure()) return obj;
1211 set_map(Map::cast(obj));
1212 initialize_elements();
1213 return this;
1214}
1215
1216
Steve Blocka7e24c12009-10-30 11:49:00 +00001217ACCESSORS(Oddball, to_string, String, kToStringOffset)
1218ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1219
1220
1221Object* JSGlobalPropertyCell::value() {
1222 return READ_FIELD(this, kValueOffset);
1223}
1224
1225
1226void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1227 // The write barrier is not used for global property cells.
1228 ASSERT(!val->IsJSGlobalPropertyCell());
1229 WRITE_FIELD(this, kValueOffset, val);
1230}
1231
1232
1233int JSObject::GetHeaderSize() {
1234 InstanceType type = map()->instance_type();
1235 // Check for the most common kind of JavaScript object before
1236 // falling into the generic switch. This speeds up the internal
1237 // field operations considerably on average.
1238 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1239 switch (type) {
1240 case JS_GLOBAL_PROXY_TYPE:
1241 return JSGlobalProxy::kSize;
1242 case JS_GLOBAL_OBJECT_TYPE:
1243 return JSGlobalObject::kSize;
1244 case JS_BUILTINS_OBJECT_TYPE:
1245 return JSBuiltinsObject::kSize;
1246 case JS_FUNCTION_TYPE:
1247 return JSFunction::kSize;
1248 case JS_VALUE_TYPE:
1249 return JSValue::kSize;
1250 case JS_ARRAY_TYPE:
1251 return JSValue::kSize;
1252 case JS_REGEXP_TYPE:
1253 return JSValue::kSize;
1254 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1255 return JSObject::kHeaderSize;
1256 default:
1257 UNREACHABLE();
1258 return 0;
1259 }
1260}
1261
1262
1263int JSObject::GetInternalFieldCount() {
1264 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1265 // Make sure to adjust for the number of in-object properties. These
1266 // properties do contribute to the size, but are not internal fields.
1267 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1268 map()->inobject_properties();
1269}
1270
1271
1272Object* JSObject::GetInternalField(int index) {
1273 ASSERT(index < GetInternalFieldCount() && index >= 0);
1274 // Internal objects do follow immediately after the header, whereas in-object
1275 // properties are at the end of the object. Therefore there is no need
1276 // to adjust the index here.
1277 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1278}
1279
1280
1281void JSObject::SetInternalField(int index, Object* value) {
1282 ASSERT(index < GetInternalFieldCount() && index >= 0);
1283 // Internal objects do follow immediately after the header, whereas in-object
1284 // properties are at the end of the object. Therefore there is no need
1285 // to adjust the index here.
1286 int offset = GetHeaderSize() + (kPointerSize * index);
1287 WRITE_FIELD(this, offset, value);
1288 WRITE_BARRIER(this, offset);
1289}
1290
1291
1292// Access fast-case object properties at index. The use of these routines
1293// is needed to correctly distinguish between properties stored in-object and
1294// properties stored in the properties array.
1295Object* JSObject::FastPropertyAt(int index) {
1296 // Adjust for the number of properties stored in the object.
1297 index -= map()->inobject_properties();
1298 if (index < 0) {
1299 int offset = map()->instance_size() + (index * kPointerSize);
1300 return READ_FIELD(this, offset);
1301 } else {
1302 ASSERT(index < properties()->length());
1303 return properties()->get(index);
1304 }
1305}
1306
1307
1308Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1309 // Adjust for the number of properties stored in the object.
1310 index -= map()->inobject_properties();
1311 if (index < 0) {
1312 int offset = map()->instance_size() + (index * kPointerSize);
1313 WRITE_FIELD(this, offset, value);
1314 WRITE_BARRIER(this, offset);
1315 } else {
1316 ASSERT(index < properties()->length());
1317 properties()->set(index, value);
1318 }
1319 return value;
1320}
1321
1322
1323Object* JSObject::InObjectPropertyAt(int index) {
1324 // Adjust for the number of properties stored in the object.
1325 index -= map()->inobject_properties();
1326 ASSERT(index < 0);
1327 int offset = map()->instance_size() + (index * kPointerSize);
1328 return READ_FIELD(this, offset);
1329}
1330
1331
1332Object* JSObject::InObjectPropertyAtPut(int index,
1333 Object* value,
1334 WriteBarrierMode mode) {
1335 // Adjust for the number of properties stored in the object.
1336 index -= map()->inobject_properties();
1337 ASSERT(index < 0);
1338 int offset = map()->instance_size() + (index * kPointerSize);
1339 WRITE_FIELD(this, offset, value);
1340 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1341 return value;
1342}
1343
1344
1345
1346void JSObject::InitializeBody(int object_size) {
1347 Object* value = Heap::undefined_value();
1348 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1349 WRITE_FIELD(this, offset, value);
1350 }
1351}
1352
1353
Steve Block8defd9f2010-07-08 12:39:36 +01001354bool JSObject::HasFastProperties() {
1355 return !properties()->IsDictionary();
1356}
1357
1358
1359int JSObject::MaxFastProperties() {
1360 // Allow extra fast properties if the object has more than
1361 // kMaxFastProperties in-object properties. When this is the case,
1362 // it is very unlikely that the object is being used as a dictionary
1363 // and there is a good chance that allowing more map transitions
1364 // will be worth it.
1365 return Max(map()->inobject_properties(), kMaxFastProperties);
1366}
1367
1368
Steve Blocka7e24c12009-10-30 11:49:00 +00001369void Struct::InitializeBody(int object_size) {
1370 Object* value = Heap::undefined_value();
1371 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1372 WRITE_FIELD(this, offset, value);
1373 }
1374}
1375
1376
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001377bool Object::ToArrayIndex(uint32_t* index) {
1378 if (IsSmi()) {
1379 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001380 if (value < 0) return false;
1381 *index = value;
1382 return true;
1383 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001384 if (IsHeapNumber()) {
1385 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001386 uint32_t uint_value = static_cast<uint32_t>(value);
1387 if (value == static_cast<double>(uint_value)) {
1388 *index = uint_value;
1389 return true;
1390 }
1391 }
1392 return false;
1393}
1394
1395
1396bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1397 if (!this->IsJSValue()) return false;
1398
1399 JSValue* js_value = JSValue::cast(this);
1400 if (!js_value->value()->IsString()) return false;
1401
1402 String* str = String::cast(js_value->value());
1403 if (index >= (uint32_t)str->length()) return false;
1404
1405 return true;
1406}
1407
1408
1409Object* FixedArray::get(int index) {
1410 ASSERT(index >= 0 && index < this->length());
1411 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1412}
1413
1414
1415void FixedArray::set(int index, Smi* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001416 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001417 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1418 int offset = kHeaderSize + index * kPointerSize;
1419 WRITE_FIELD(this, offset, value);
1420}
1421
1422
1423void FixedArray::set(int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001424 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001425 ASSERT(index >= 0 && index < this->length());
1426 int offset = kHeaderSize + index * kPointerSize;
1427 WRITE_FIELD(this, offset, value);
1428 WRITE_BARRIER(this, offset);
1429}
1430
1431
Leon Clarke4515c472010-02-03 11:58:03 +00001432WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001433 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1434 return UPDATE_WRITE_BARRIER;
1435}
1436
1437
1438void FixedArray::set(int index,
1439 Object* value,
1440 WriteBarrierMode mode) {
Iain Merrick75681382010-08-19 15:07:18 +01001441 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001442 ASSERT(index >= 0 && index < this->length());
1443 int offset = kHeaderSize + index * kPointerSize;
1444 WRITE_FIELD(this, offset, value);
1445 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1446}
1447
1448
1449void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001450 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001451 ASSERT(index >= 0 && index < array->length());
Leon Clarke4515c472010-02-03 11:58:03 +00001452 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1454}
1455
1456
1457void FixedArray::set_undefined(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001458 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001459 ASSERT(index >= 0 && index < this->length());
1460 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1461 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1462 Heap::undefined_value());
1463}
1464
1465
1466void FixedArray::set_null(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001467 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001468 ASSERT(index >= 0 && index < this->length());
1469 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1470 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1471}
1472
1473
1474void FixedArray::set_the_hole(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001475 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001476 ASSERT(index >= 0 && index < this->length());
1477 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1478 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1479}
1480
1481
Iain Merrick75681382010-08-19 15:07:18 +01001482void FixedArray::set_unchecked(int index, Smi* value) {
1483 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1484 int offset = kHeaderSize + index * kPointerSize;
1485 WRITE_FIELD(this, offset, value);
1486}
1487
1488
1489void FixedArray::set_null_unchecked(int index) {
1490 ASSERT(index >= 0 && index < this->length());
1491 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1492 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1493}
1494
1495
Steve Block6ded16b2010-05-10 14:33:55 +01001496Object** FixedArray::data_start() {
1497 return HeapObject::RawField(this, kHeaderSize);
1498}
1499
1500
Steve Blocka7e24c12009-10-30 11:49:00 +00001501bool DescriptorArray::IsEmpty() {
1502 ASSERT(this == Heap::empty_descriptor_array() ||
1503 this->length() > 2);
1504 return this == Heap::empty_descriptor_array();
1505}
1506
1507
1508void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1509 Object* tmp = array->get(first);
1510 fast_set(array, first, array->get(second));
1511 fast_set(array, second, tmp);
1512}
1513
1514
1515int DescriptorArray::Search(String* name) {
1516 SLOW_ASSERT(IsSortedNoDuplicates());
1517
1518 // Check for empty descriptor array.
1519 int nof = number_of_descriptors();
1520 if (nof == 0) return kNotFound;
1521
1522 // Fast case: do linear search for small arrays.
1523 const int kMaxElementsForLinearSearch = 8;
1524 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1525 return LinearSearch(name, nof);
1526 }
1527
1528 // Slow case: perform binary search.
1529 return BinarySearch(name, 0, nof - 1);
1530}
1531
1532
Iain Merrick75681382010-08-19 15:07:18 +01001533int DescriptorArray::SearchWithCache(String* name) {
1534 int number = DescriptorLookupCache::Lookup(this, name);
1535 if (number == DescriptorLookupCache::kAbsent) {
1536 number = Search(name);
1537 DescriptorLookupCache::Update(this, name, number);
1538 }
1539 return number;
1540}
1541
1542
Steve Blocka7e24c12009-10-30 11:49:00 +00001543String* DescriptorArray::GetKey(int descriptor_number) {
1544 ASSERT(descriptor_number < number_of_descriptors());
1545 return String::cast(get(ToKeyIndex(descriptor_number)));
1546}
1547
1548
1549Object* DescriptorArray::GetValue(int descriptor_number) {
1550 ASSERT(descriptor_number < number_of_descriptors());
1551 return GetContentArray()->get(ToValueIndex(descriptor_number));
1552}
1553
1554
1555Smi* DescriptorArray::GetDetails(int descriptor_number) {
1556 ASSERT(descriptor_number < number_of_descriptors());
1557 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1558}
1559
1560
1561PropertyType DescriptorArray::GetType(int descriptor_number) {
1562 ASSERT(descriptor_number < number_of_descriptors());
1563 return PropertyDetails(GetDetails(descriptor_number)).type();
1564}
1565
1566
1567int DescriptorArray::GetFieldIndex(int descriptor_number) {
1568 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1569}
1570
1571
1572JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1573 return JSFunction::cast(GetValue(descriptor_number));
1574}
1575
1576
1577Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1578 ASSERT(GetType(descriptor_number) == CALLBACKS);
1579 return GetValue(descriptor_number);
1580}
1581
1582
1583AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1584 ASSERT(GetType(descriptor_number) == CALLBACKS);
1585 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1586 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1587}
1588
1589
1590bool DescriptorArray::IsProperty(int descriptor_number) {
1591 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1592}
1593
1594
1595bool DescriptorArray::IsTransition(int descriptor_number) {
1596 PropertyType t = GetType(descriptor_number);
1597 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1598}
1599
1600
1601bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1602 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1603}
1604
1605
1606bool DescriptorArray::IsDontEnum(int descriptor_number) {
1607 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1608}
1609
1610
1611void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1612 desc->Init(GetKey(descriptor_number),
1613 GetValue(descriptor_number),
1614 GetDetails(descriptor_number));
1615}
1616
1617
1618void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1619 // Range check.
1620 ASSERT(descriptor_number < number_of_descriptors());
1621
Leon Clarkee46be812010-01-19 14:06:41 +00001622 // Make sure none of the elements in desc are in new space.
Steve Blocka7e24c12009-10-30 11:49:00 +00001623 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1624 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1625
1626 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1627 FixedArray* content_array = GetContentArray();
1628 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1629 fast_set(content_array, ToDetailsIndex(descriptor_number),
1630 desc->GetDetails().AsSmi());
1631}
1632
1633
1634void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1635 Descriptor desc;
1636 src->Get(src_index, &desc);
1637 Set(index, &desc);
1638}
1639
1640
1641void DescriptorArray::Swap(int first, int second) {
1642 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1643 FixedArray* content_array = GetContentArray();
1644 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1645 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1646}
1647
1648
1649bool NumberDictionary::requires_slow_elements() {
1650 Object* max_index_object = get(kMaxNumberKeyIndex);
1651 if (!max_index_object->IsSmi()) return false;
1652 return 0 !=
1653 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1654}
1655
1656uint32_t NumberDictionary::max_number_key() {
1657 ASSERT(!requires_slow_elements());
1658 Object* max_index_object = get(kMaxNumberKeyIndex);
1659 if (!max_index_object->IsSmi()) return 0;
1660 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1661 return value >> kRequiresSlowElementsTagSize;
1662}
1663
1664void NumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00001665 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00001666}
1667
1668
1669// ------------------------------------
1670// Cast operations
1671
1672
1673CAST_ACCESSOR(FixedArray)
1674CAST_ACCESSOR(DescriptorArray)
1675CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001676CAST_ACCESSOR(JSFunctionResultCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001677CAST_ACCESSOR(NormalizedMapCache)
Steve Blocka7e24c12009-10-30 11:49:00 +00001678CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001679CAST_ACCESSOR(CodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00001680CAST_ACCESSOR(MapCache)
1681CAST_ACCESSOR(String)
1682CAST_ACCESSOR(SeqString)
1683CAST_ACCESSOR(SeqAsciiString)
1684CAST_ACCESSOR(SeqTwoByteString)
1685CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00001686CAST_ACCESSOR(ExternalString)
1687CAST_ACCESSOR(ExternalAsciiString)
1688CAST_ACCESSOR(ExternalTwoByteString)
1689CAST_ACCESSOR(JSObject)
1690CAST_ACCESSOR(Smi)
1691CAST_ACCESSOR(Failure)
1692CAST_ACCESSOR(HeapObject)
1693CAST_ACCESSOR(HeapNumber)
1694CAST_ACCESSOR(Oddball)
1695CAST_ACCESSOR(JSGlobalPropertyCell)
1696CAST_ACCESSOR(SharedFunctionInfo)
1697CAST_ACCESSOR(Map)
1698CAST_ACCESSOR(JSFunction)
1699CAST_ACCESSOR(GlobalObject)
1700CAST_ACCESSOR(JSGlobalProxy)
1701CAST_ACCESSOR(JSGlobalObject)
1702CAST_ACCESSOR(JSBuiltinsObject)
1703CAST_ACCESSOR(Code)
1704CAST_ACCESSOR(JSArray)
1705CAST_ACCESSOR(JSRegExp)
1706CAST_ACCESSOR(Proxy)
1707CAST_ACCESSOR(ByteArray)
1708CAST_ACCESSOR(PixelArray)
Steve Block3ce2e202009-11-05 08:53:23 +00001709CAST_ACCESSOR(ExternalArray)
1710CAST_ACCESSOR(ExternalByteArray)
1711CAST_ACCESSOR(ExternalUnsignedByteArray)
1712CAST_ACCESSOR(ExternalShortArray)
1713CAST_ACCESSOR(ExternalUnsignedShortArray)
1714CAST_ACCESSOR(ExternalIntArray)
1715CAST_ACCESSOR(ExternalUnsignedIntArray)
1716CAST_ACCESSOR(ExternalFloatArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00001717CAST_ACCESSOR(Struct)
1718
1719
1720#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1721 STRUCT_LIST(MAKE_STRUCT_CAST)
1722#undef MAKE_STRUCT_CAST
1723
1724
1725template <typename Shape, typename Key>
1726HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1727 ASSERT(obj->IsHashTable());
1728 return reinterpret_cast<HashTable*>(obj);
1729}
1730
1731
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001732SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1733SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1734
1735INT_ACCESSORS(PixelArray, length, kLengthOffset)
1736INT_ACCESSORS(ExternalArray, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00001737
1738
Steve Block6ded16b2010-05-10 14:33:55 +01001739SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00001740
1741
1742uint32_t String::hash_field() {
1743 return READ_UINT32_FIELD(this, kHashFieldOffset);
1744}
1745
1746
1747void String::set_hash_field(uint32_t value) {
1748 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001749#if V8_HOST_ARCH_64_BIT
1750 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1751#endif
Steve Blockd0582a62009-12-15 09:54:21 +00001752}
1753
1754
Steve Blocka7e24c12009-10-30 11:49:00 +00001755bool String::Equals(String* other) {
1756 if (other == this) return true;
1757 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1758 return false;
1759 }
1760 return SlowEquals(other);
1761}
1762
1763
Steve Block6ded16b2010-05-10 14:33:55 +01001764Object* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001765 if (!StringShape(this).IsCons()) return this;
1766 ConsString* cons = ConsString::cast(this);
1767 if (cons->second()->length() == 0) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01001768 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00001769}
1770
1771
Leon Clarkef7060e22010-06-03 12:02:55 +01001772String* String::TryFlattenGetString(PretenureFlag pretenure) {
1773 Object* flat = TryFlatten(pretenure);
1774 return flat->IsFailure() ? this : String::cast(flat);
1775}
1776
1777
Steve Blocka7e24c12009-10-30 11:49:00 +00001778uint16_t String::Get(int index) {
1779 ASSERT(index >= 0 && index < length());
1780 switch (StringShape(this).full_representation_tag()) {
1781 case kSeqStringTag | kAsciiStringTag:
1782 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1783 case kSeqStringTag | kTwoByteStringTag:
1784 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1785 case kConsStringTag | kAsciiStringTag:
1786 case kConsStringTag | kTwoByteStringTag:
1787 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001788 case kExternalStringTag | kAsciiStringTag:
1789 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1790 case kExternalStringTag | kTwoByteStringTag:
1791 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1792 default:
1793 break;
1794 }
1795
1796 UNREACHABLE();
1797 return 0;
1798}
1799
1800
1801void String::Set(int index, uint16_t value) {
1802 ASSERT(index >= 0 && index < length());
1803 ASSERT(StringShape(this).IsSequential());
1804
1805 return this->IsAsciiRepresentation()
1806 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1807 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1808}
1809
1810
1811bool String::IsFlat() {
1812 switch (StringShape(this).representation_tag()) {
1813 case kConsStringTag: {
1814 String* second = ConsString::cast(this)->second();
1815 // Only flattened strings have second part empty.
1816 return second->length() == 0;
1817 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001818 default:
1819 return true;
1820 }
1821}
1822
1823
1824uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1825 ASSERT(index >= 0 && index < length());
1826 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1827}
1828
1829
1830void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1831 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1832 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1833 static_cast<byte>(value));
1834}
1835
1836
1837Address SeqAsciiString::GetCharsAddress() {
1838 return FIELD_ADDR(this, kHeaderSize);
1839}
1840
1841
1842char* SeqAsciiString::GetChars() {
1843 return reinterpret_cast<char*>(GetCharsAddress());
1844}
1845
1846
1847Address SeqTwoByteString::GetCharsAddress() {
1848 return FIELD_ADDR(this, kHeaderSize);
1849}
1850
1851
1852uc16* SeqTwoByteString::GetChars() {
1853 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1854}
1855
1856
1857uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1858 ASSERT(index >= 0 && index < length());
1859 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1860}
1861
1862
1863void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1864 ASSERT(index >= 0 && index < length());
1865 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1866}
1867
1868
1869int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001870 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001871}
1872
1873
1874int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001875 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001876}
1877
1878
1879String* ConsString::first() {
1880 return String::cast(READ_FIELD(this, kFirstOffset));
1881}
1882
1883
1884Object* ConsString::unchecked_first() {
1885 return READ_FIELD(this, kFirstOffset);
1886}
1887
1888
1889void ConsString::set_first(String* value, WriteBarrierMode mode) {
1890 WRITE_FIELD(this, kFirstOffset, value);
1891 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1892}
1893
1894
1895String* ConsString::second() {
1896 return String::cast(READ_FIELD(this, kSecondOffset));
1897}
1898
1899
1900Object* ConsString::unchecked_second() {
1901 return READ_FIELD(this, kSecondOffset);
1902}
1903
1904
1905void ConsString::set_second(String* value, WriteBarrierMode mode) {
1906 WRITE_FIELD(this, kSecondOffset, value);
1907 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1908}
1909
1910
Steve Blocka7e24c12009-10-30 11:49:00 +00001911ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1912 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1913}
1914
1915
1916void ExternalAsciiString::set_resource(
1917 ExternalAsciiString::Resource* resource) {
1918 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1919}
1920
1921
Steve Blocka7e24c12009-10-30 11:49:00 +00001922ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1923 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1924}
1925
1926
1927void ExternalTwoByteString::set_resource(
1928 ExternalTwoByteString::Resource* resource) {
1929 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1930}
1931
1932
Steve Block6ded16b2010-05-10 14:33:55 +01001933void JSFunctionResultCache::MakeZeroSize() {
1934 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1935 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1936}
1937
1938
1939void JSFunctionResultCache::Clear() {
1940 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1941 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1942 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1943 MakeZeroSize();
1944}
1945
1946
Steve Blocka7e24c12009-10-30 11:49:00 +00001947byte ByteArray::get(int index) {
1948 ASSERT(index >= 0 && index < this->length());
1949 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1950}
1951
1952
1953void ByteArray::set(int index, byte value) {
1954 ASSERT(index >= 0 && index < this->length());
1955 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1956}
1957
1958
1959int ByteArray::get_int(int index) {
1960 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1961 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1962}
1963
1964
1965ByteArray* ByteArray::FromDataStartAddress(Address address) {
1966 ASSERT_TAG_ALIGNED(address);
1967 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1968}
1969
1970
1971Address ByteArray::GetDataStartAddress() {
1972 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1973}
1974
1975
1976uint8_t* PixelArray::external_pointer() {
1977 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1978 return reinterpret_cast<uint8_t*>(ptr);
1979}
1980
1981
1982void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1983 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1984 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1985}
1986
1987
1988uint8_t PixelArray::get(int index) {
1989 ASSERT((index >= 0) && (index < this->length()));
1990 uint8_t* ptr = external_pointer();
1991 return ptr[index];
1992}
1993
1994
1995void PixelArray::set(int index, uint8_t value) {
1996 ASSERT((index >= 0) && (index < this->length()));
1997 uint8_t* ptr = external_pointer();
1998 ptr[index] = value;
1999}
2000
2001
Steve Block3ce2e202009-11-05 08:53:23 +00002002void* ExternalArray::external_pointer() {
2003 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2004 return reinterpret_cast<void*>(ptr);
2005}
2006
2007
2008void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2009 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2010 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2011}
2012
2013
2014int8_t ExternalByteArray::get(int index) {
2015 ASSERT((index >= 0) && (index < this->length()));
2016 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2017 return ptr[index];
2018}
2019
2020
2021void ExternalByteArray::set(int index, int8_t value) {
2022 ASSERT((index >= 0) && (index < this->length()));
2023 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2024 ptr[index] = value;
2025}
2026
2027
2028uint8_t ExternalUnsignedByteArray::get(int index) {
2029 ASSERT((index >= 0) && (index < this->length()));
2030 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2031 return ptr[index];
2032}
2033
2034
2035void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2036 ASSERT((index >= 0) && (index < this->length()));
2037 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2038 ptr[index] = value;
2039}
2040
2041
2042int16_t ExternalShortArray::get(int index) {
2043 ASSERT((index >= 0) && (index < this->length()));
2044 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2045 return ptr[index];
2046}
2047
2048
2049void ExternalShortArray::set(int index, int16_t value) {
2050 ASSERT((index >= 0) && (index < this->length()));
2051 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2052 ptr[index] = value;
2053}
2054
2055
2056uint16_t ExternalUnsignedShortArray::get(int index) {
2057 ASSERT((index >= 0) && (index < this->length()));
2058 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2059 return ptr[index];
2060}
2061
2062
2063void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2064 ASSERT((index >= 0) && (index < this->length()));
2065 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2066 ptr[index] = value;
2067}
2068
2069
2070int32_t ExternalIntArray::get(int index) {
2071 ASSERT((index >= 0) && (index < this->length()));
2072 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2073 return ptr[index];
2074}
2075
2076
2077void ExternalIntArray::set(int index, int32_t value) {
2078 ASSERT((index >= 0) && (index < this->length()));
2079 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2080 ptr[index] = value;
2081}
2082
2083
2084uint32_t ExternalUnsignedIntArray::get(int index) {
2085 ASSERT((index >= 0) && (index < this->length()));
2086 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2087 return ptr[index];
2088}
2089
2090
2091void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2092 ASSERT((index >= 0) && (index < this->length()));
2093 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2094 ptr[index] = value;
2095}
2096
2097
2098float ExternalFloatArray::get(int index) {
2099 ASSERT((index >= 0) && (index < this->length()));
2100 float* ptr = static_cast<float*>(external_pointer());
2101 return ptr[index];
2102}
2103
2104
2105void ExternalFloatArray::set(int index, float value) {
2106 ASSERT((index >= 0) && (index < this->length()));
2107 float* ptr = static_cast<float*>(external_pointer());
2108 ptr[index] = value;
2109}
2110
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002111
Iain Merrick75681382010-08-19 15:07:18 +01002112INT_ACCESSORS(Map, visitor_id, kScavengerCallbackOffset)
Steve Block3ce2e202009-11-05 08:53:23 +00002113
Steve Blocka7e24c12009-10-30 11:49:00 +00002114int Map::instance_size() {
2115 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2116}
2117
2118
2119int Map::inobject_properties() {
2120 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2121}
2122
2123
2124int Map::pre_allocated_property_fields() {
2125 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2126}
2127
2128
2129int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01002130 int instance_size = map->instance_size();
2131 if (instance_size != kVariableSizeSentinel) return instance_size;
2132 // We can ignore the "symbol" bit becase it is only set for symbols
2133 // and implies a string type.
2134 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002135 // Only inline the most frequent cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00002136 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002137 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002138 }
Steve Block791712a2010-08-27 10:21:07 +01002139 if (instance_type == ASCII_STRING_TYPE) {
2140 return SeqAsciiString::SizeFor(
2141 reinterpret_cast<SeqAsciiString*>(this)->length());
2142 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002143 if (instance_type == BYTE_ARRAY_TYPE) {
2144 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2145 }
Steve Block791712a2010-08-27 10:21:07 +01002146 if (instance_type == STRING_TYPE) {
2147 return SeqTwoByteString::SizeFor(
2148 reinterpret_cast<SeqTwoByteString*>(this)->length());
2149 }
2150 ASSERT(instance_type == CODE_TYPE);
2151 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00002152}
2153
2154
2155void Map::set_instance_size(int value) {
2156 ASSERT_EQ(0, value & (kPointerSize - 1));
2157 value >>= kPointerSizeLog2;
2158 ASSERT(0 <= value && value < 256);
2159 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2160}
2161
2162
2163void Map::set_inobject_properties(int value) {
2164 ASSERT(0 <= value && value < 256);
2165 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2166}
2167
2168
2169void Map::set_pre_allocated_property_fields(int value) {
2170 ASSERT(0 <= value && value < 256);
2171 WRITE_BYTE_FIELD(this,
2172 kPreAllocatedPropertyFieldsOffset,
2173 static_cast<byte>(value));
2174}
2175
2176
2177InstanceType Map::instance_type() {
2178 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2179}
2180
2181
2182void Map::set_instance_type(InstanceType value) {
2183 ASSERT(0 <= value && value < 256);
2184 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2185}
2186
2187
2188int Map::unused_property_fields() {
2189 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2190}
2191
2192
2193void Map::set_unused_property_fields(int value) {
2194 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2195}
2196
2197
2198byte Map::bit_field() {
2199 return READ_BYTE_FIELD(this, kBitFieldOffset);
2200}
2201
2202
2203void Map::set_bit_field(byte value) {
2204 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2205}
2206
2207
2208byte Map::bit_field2() {
2209 return READ_BYTE_FIELD(this, kBitField2Offset);
2210}
2211
2212
2213void Map::set_bit_field2(byte value) {
2214 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2215}
2216
2217
2218void Map::set_non_instance_prototype(bool value) {
2219 if (value) {
2220 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2221 } else {
2222 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2223 }
2224}
2225
2226
2227bool Map::has_non_instance_prototype() {
2228 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2229}
2230
2231
Steve Block6ded16b2010-05-10 14:33:55 +01002232void Map::set_function_with_prototype(bool value) {
2233 if (value) {
2234 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2235 } else {
2236 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2237 }
2238}
2239
2240
2241bool Map::function_with_prototype() {
2242 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2243}
2244
2245
Steve Blocka7e24c12009-10-30 11:49:00 +00002246void Map::set_is_access_check_needed(bool access_check_needed) {
2247 if (access_check_needed) {
2248 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2249 } else {
2250 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2251 }
2252}
2253
2254
2255bool Map::is_access_check_needed() {
2256 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2257}
2258
2259
Steve Block8defd9f2010-07-08 12:39:36 +01002260void Map::set_is_extensible(bool value) {
2261 if (value) {
2262 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2263 } else {
2264 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2265 }
2266}
2267
2268bool Map::is_extensible() {
2269 return ((1 << kIsExtensible) & bit_field2()) != 0;
2270}
2271
2272
2273
Steve Blocka7e24c12009-10-30 11:49:00 +00002274Code::Flags Code::flags() {
2275 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2276}
2277
2278
2279void Code::set_flags(Code::Flags flags) {
2280 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2281 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002282 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2283 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002284 ExtractArgumentsCountFromFlags(flags) >= 0);
2285 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2286}
2287
2288
2289Code::Kind Code::kind() {
2290 return ExtractKindFromFlags(flags());
2291}
2292
2293
2294InLoopFlag Code::ic_in_loop() {
2295 return ExtractICInLoopFromFlags(flags());
2296}
2297
2298
2299InlineCacheState Code::ic_state() {
2300 InlineCacheState result = ExtractICStateFromFlags(flags());
2301 // Only allow uninitialized or debugger states for non-IC code
2302 // objects. This is used in the debugger to determine whether or not
2303 // a call to code object has been replaced with a debug break call.
2304 ASSERT(is_inline_cache_stub() ||
2305 result == UNINITIALIZED ||
2306 result == DEBUG_BREAK ||
2307 result == DEBUG_PREPARE_STEP_IN);
2308 return result;
2309}
2310
2311
2312PropertyType Code::type() {
2313 ASSERT(ic_state() == MONOMORPHIC);
2314 return ExtractTypeFromFlags(flags());
2315}
2316
2317
2318int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002319 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002320 return ExtractArgumentsCountFromFlags(flags());
2321}
2322
2323
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002324int Code::major_key() {
Steve Block6ded16b2010-05-10 14:33:55 +01002325 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002326 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00002327}
2328
2329
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002330void Code::set_major_key(int major) {
Steve Block6ded16b2010-05-10 14:33:55 +01002331 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002332 ASSERT(0 <= major && major < 256);
2333 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2334}
2335
2336
2337bool Code::is_inline_cache_stub() {
2338 Kind kind = this->kind();
2339 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2340}
2341
2342
2343Code::Flags Code::ComputeFlags(Kind kind,
2344 InLoopFlag in_loop,
2345 InlineCacheState ic_state,
2346 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002347 int argc,
2348 InlineCacheHolderFlag holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002349 // Compute the bit mask.
2350 int bits = kind << kFlagsKindShift;
2351 if (in_loop) bits |= kFlagsICInLoopMask;
2352 bits |= ic_state << kFlagsICStateShift;
2353 bits |= type << kFlagsTypeShift;
2354 bits |= argc << kFlagsArgumentsCountShift;
Steve Block8defd9f2010-07-08 12:39:36 +01002355 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002356 // Cast to flags and validate result before returning it.
2357 Flags result = static_cast<Flags>(bits);
2358 ASSERT(ExtractKindFromFlags(result) == kind);
2359 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2360 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2361 ASSERT(ExtractTypeFromFlags(result) == type);
2362 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2363 return result;
2364}
2365
2366
2367Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2368 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002369 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00002370 InLoopFlag in_loop,
2371 int argc) {
Steve Block8defd9f2010-07-08 12:39:36 +01002372 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00002373}
2374
2375
2376Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2377 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2378 return static_cast<Kind>(bits);
2379}
2380
2381
2382InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2383 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2384 return static_cast<InlineCacheState>(bits);
2385}
2386
2387
2388InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2389 int bits = (flags & kFlagsICInLoopMask);
2390 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2391}
2392
2393
2394PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2395 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2396 return static_cast<PropertyType>(bits);
2397}
2398
2399
2400int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2401 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2402}
2403
2404
Steve Block8defd9f2010-07-08 12:39:36 +01002405InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2406 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2407 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2408}
2409
2410
Steve Blocka7e24c12009-10-30 11:49:00 +00002411Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2412 int bits = flags & ~kFlagsTypeMask;
2413 return static_cast<Flags>(bits);
2414}
2415
2416
2417Code* Code::GetCodeFromTargetAddress(Address address) {
2418 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2419 // GetCodeFromTargetAddress might be called when marking objects during mark
2420 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2421 // Code::cast. Code::cast does not work when the object's map is
2422 // marked.
2423 Code* result = reinterpret_cast<Code*>(code);
2424 return result;
2425}
2426
2427
Steve Block791712a2010-08-27 10:21:07 +01002428Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2429 return HeapObject::
2430 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2431}
2432
2433
Steve Blocka7e24c12009-10-30 11:49:00 +00002434Object* Map::prototype() {
2435 return READ_FIELD(this, kPrototypeOffset);
2436}
2437
2438
2439void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2440 ASSERT(value->IsNull() || value->IsJSObject());
2441 WRITE_FIELD(this, kPrototypeOffset, value);
2442 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2443}
2444
2445
Steve Block8defd9f2010-07-08 12:39:36 +01002446Object* Map::GetFastElementsMap() {
2447 if (has_fast_elements()) return this;
2448 Object* obj = CopyDropTransitions();
2449 if (obj->IsFailure()) return obj;
2450 Map* new_map = Map::cast(obj);
2451 new_map->set_has_fast_elements(true);
Iain Merrick75681382010-08-19 15:07:18 +01002452 Counters::map_slow_to_fast_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002453 return new_map;
2454}
2455
2456
2457Object* Map::GetSlowElementsMap() {
2458 if (!has_fast_elements()) return this;
2459 Object* obj = CopyDropTransitions();
2460 if (obj->IsFailure()) return obj;
2461 Map* new_map = Map::cast(obj);
2462 new_map->set_has_fast_elements(false);
Iain Merrick75681382010-08-19 15:07:18 +01002463 Counters::map_fast_to_slow_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002464 return new_map;
2465}
2466
2467
Steve Blocka7e24c12009-10-30 11:49:00 +00002468ACCESSORS(Map, instance_descriptors, DescriptorArray,
2469 kInstanceDescriptorsOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002470ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002471ACCESSORS(Map, constructor, Object, kConstructorOffset)
2472
2473ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2474ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2475
2476ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2477ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2478ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2479
2480ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2481
2482ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2483ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2484ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2485ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2486ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002487ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002488
2489ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2490ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2491ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2492
2493ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2494ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2495ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2496ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2497ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2498ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2499
2500ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2501ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2502
2503ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2504ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2505
2506ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2507ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2508ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2509 kPropertyAccessorsOffset)
2510ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2511 kPrototypeTemplateOffset)
2512ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2513ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2514 kNamedPropertyHandlerOffset)
2515ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2516 kIndexedPropertyHandlerOffset)
2517ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2518 kInstanceTemplateOffset)
2519ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2520ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2521ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2522 kInstanceCallHandlerOffset)
2523ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2524 kAccessCheckInfoOffset)
2525ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2526
2527ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2528ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2529 kInternalFieldCountOffset)
2530
2531ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2532ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2533
2534ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2535
2536ACCESSORS(Script, source, Object, kSourceOffset)
2537ACCESSORS(Script, name, Object, kNameOffset)
2538ACCESSORS(Script, id, Object, kIdOffset)
2539ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2540ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2541ACCESSORS(Script, data, Object, kDataOffset)
2542ACCESSORS(Script, context_data, Object, kContextOffset)
2543ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2544ACCESSORS(Script, type, Smi, kTypeOffset)
2545ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2546ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002547ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002548ACCESSORS(Script, eval_from_instructions_offset, Smi,
2549 kEvalFrominstructionsOffsetOffset)
2550
2551#ifdef ENABLE_DEBUGGER_SUPPORT
2552ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2553ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2554ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2555ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2556
2557ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2558ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2559ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2560ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2561#endif
2562
Steve Blocka7e24c12009-10-30 11:49:00 +00002563ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002564ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002565ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2566 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002567ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002568ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2569ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2570ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2571ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2572 kThisPropertyAssignmentsOffset)
2573
2574BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2575 kHiddenPrototypeBit)
2576BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2577BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2578 kNeedsAccessCheckBit)
2579BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2580 kIsExpressionBit)
2581BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2582 kIsTopLevelBit)
2583BOOL_GETTER(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002584 has_only_simple_this_property_assignments,
2585 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00002586BOOL_ACCESSORS(SharedFunctionInfo,
2587 compiler_hints,
Leon Clarked91b9f72010-01-27 17:25:45 +00002588 try_full_codegen,
2589 kTryFullCodegen)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002590BOOL_ACCESSORS(SharedFunctionInfo,
2591 compiler_hints,
2592 allows_lazy_compilation,
2593 kAllowLazyCompilation)
Steve Blocka7e24c12009-10-30 11:49:00 +00002594
Iain Merrick75681382010-08-19 15:07:18 +01002595
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002596#if V8_HOST_ARCH_32_BIT
2597SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2598SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002599 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002600SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00002601 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002602SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2603SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00002604 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002605SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2606SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00002607 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002608SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002609 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002610SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002611 kThisPropertyAssignmentsCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002612#else
Steve Blocka7e24c12009-10-30 11:49:00 +00002613
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002614#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2615 int holder::name() { \
2616 int value = READ_INT_FIELD(this, offset); \
2617 ASSERT(kHeapObjectTag == 1); \
2618 ASSERT((value & kHeapObjectTag) == 0); \
2619 return value >> 1; \
2620 } \
2621 void holder::set_##name(int value) { \
2622 ASSERT(kHeapObjectTag == 1); \
2623 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2624 (value & 0xC0000000) == 0x000000000); \
2625 WRITE_INT_FIELD(this, \
2626 offset, \
2627 (value << 1) & ~kHeapObjectTag); \
2628 }
2629
2630#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2631 INT_ACCESSORS(holder, name, offset)
2632
2633
2634
2635PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2636PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2637 kFormalParameterCountOffset)
2638
2639PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2640 kExpectedNofPropertiesOffset)
2641PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2642
2643PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2644 kStartPositionAndTypeOffset)
2645PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2646
2647PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2648 kFunctionTokenPositionOffset)
2649PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2650 kCompilerHintsOffset)
2651
2652PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2653 kThisPropertyAssignmentsCountOffset)
2654#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002655
Steve Block6ded16b2010-05-10 14:33:55 +01002656ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2657ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2658
Steve Block3ce2e202009-11-05 08:53:23 +00002659bool Script::HasValidSource() {
2660 Object* src = this->source();
2661 if (!src->IsString()) return true;
2662 String* src_str = String::cast(src);
2663 if (!StringShape(src_str).IsExternal()) return true;
2664 if (src_str->IsAsciiRepresentation()) {
2665 return ExternalAsciiString::cast(src)->resource() != NULL;
2666 } else if (src_str->IsTwoByteRepresentation()) {
2667 return ExternalTwoByteString::cast(src)->resource() != NULL;
2668 }
2669 return true;
2670}
2671
2672
Steve Blocka7e24c12009-10-30 11:49:00 +00002673void SharedFunctionInfo::DontAdaptArguments() {
2674 ASSERT(code()->kind() == Code::BUILTIN);
2675 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2676}
2677
2678
2679int SharedFunctionInfo::start_position() {
2680 return start_position_and_type() >> kStartPositionShift;
2681}
2682
2683
2684void SharedFunctionInfo::set_start_position(int start_position) {
2685 set_start_position_and_type((start_position << kStartPositionShift)
2686 | (start_position_and_type() & ~kStartPositionMask));
2687}
2688
2689
2690Code* SharedFunctionInfo::code() {
2691 return Code::cast(READ_FIELD(this, kCodeOffset));
2692}
2693
2694
Iain Merrick75681382010-08-19 15:07:18 +01002695Code* SharedFunctionInfo::unchecked_code() {
2696 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2697}
2698
2699
Steve Blocka7e24c12009-10-30 11:49:00 +00002700void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2701 WRITE_FIELD(this, kCodeOffset, value);
2702 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2703}
2704
2705
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002706SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2707 return reinterpret_cast<SerializedScopeInfo*>(
2708 READ_FIELD(this, kScopeInfoOffset));
2709}
2710
2711
2712void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2713 WriteBarrierMode mode) {
2714 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2715 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2716}
2717
2718
Steve Blocka7e24c12009-10-30 11:49:00 +00002719bool SharedFunctionInfo::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01002720 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00002721}
2722
2723
Steve Block6ded16b2010-05-10 14:33:55 +01002724bool SharedFunctionInfo::IsApiFunction() {
2725 return function_data()->IsFunctionTemplateInfo();
2726}
2727
2728
2729FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2730 ASSERT(IsApiFunction());
2731 return FunctionTemplateInfo::cast(function_data());
2732}
2733
2734
2735bool SharedFunctionInfo::HasCustomCallGenerator() {
Kristian Monsen25f61362010-05-21 11:50:48 +01002736 return function_data()->IsSmi();
2737}
2738
2739
2740int SharedFunctionInfo::custom_call_generator_id() {
2741 ASSERT(HasCustomCallGenerator());
2742 return Smi::cast(function_data())->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002743}
2744
2745
Iain Merrick75681382010-08-19 15:07:18 +01002746int SharedFunctionInfo::code_age() {
2747 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
2748}
2749
2750
2751void SharedFunctionInfo::set_code_age(int code_age) {
2752 set_compiler_hints(compiler_hints() |
2753 ((code_age & kCodeAgeMask) << kCodeAgeShift));
2754}
2755
2756
Steve Blocka7e24c12009-10-30 11:49:00 +00002757bool JSFunction::IsBuiltin() {
2758 return context()->global()->IsJSBuiltinsObject();
2759}
2760
2761
Steve Blocka7e24c12009-10-30 11:49:00 +00002762Code* JSFunction::code() {
Steve Block791712a2010-08-27 10:21:07 +01002763 return Code::cast(unchecked_code());
Iain Merrick75681382010-08-19 15:07:18 +01002764}
2765
2766
2767Code* JSFunction::unchecked_code() {
Steve Block791712a2010-08-27 10:21:07 +01002768 return reinterpret_cast<Code*>(
2769 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002770}
2771
2772
2773void JSFunction::set_code(Code* value) {
Iain Merrick75681382010-08-19 15:07:18 +01002774 // Skip the write barrier because code is never in new space.
2775 ASSERT(!Heap::InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01002776 Address entry = value->entry();
2777 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Steve Blocka7e24c12009-10-30 11:49:00 +00002778}
2779
2780
2781Context* JSFunction::context() {
2782 return Context::cast(READ_FIELD(this, kContextOffset));
2783}
2784
2785
2786Object* JSFunction::unchecked_context() {
2787 return READ_FIELD(this, kContextOffset);
2788}
2789
2790
Iain Merrick75681382010-08-19 15:07:18 +01002791SharedFunctionInfo* JSFunction::unchecked_shared() {
2792 return reinterpret_cast<SharedFunctionInfo*>(
2793 READ_FIELD(this, kSharedFunctionInfoOffset));
2794}
2795
2796
Steve Blocka7e24c12009-10-30 11:49:00 +00002797void JSFunction::set_context(Object* value) {
2798 ASSERT(value == Heap::undefined_value() || value->IsContext());
2799 WRITE_FIELD(this, kContextOffset, value);
2800 WRITE_BARRIER(this, kContextOffset);
2801}
2802
2803ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2804 kPrototypeOrInitialMapOffset)
2805
2806
2807Map* JSFunction::initial_map() {
2808 return Map::cast(prototype_or_initial_map());
2809}
2810
2811
2812void JSFunction::set_initial_map(Map* value) {
2813 set_prototype_or_initial_map(value);
2814}
2815
2816
2817bool JSFunction::has_initial_map() {
2818 return prototype_or_initial_map()->IsMap();
2819}
2820
2821
2822bool JSFunction::has_instance_prototype() {
2823 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2824}
2825
2826
2827bool JSFunction::has_prototype() {
2828 return map()->has_non_instance_prototype() || has_instance_prototype();
2829}
2830
2831
2832Object* JSFunction::instance_prototype() {
2833 ASSERT(has_instance_prototype());
2834 if (has_initial_map()) return initial_map()->prototype();
2835 // When there is no initial map and the prototype is a JSObject, the
2836 // initial map field is used for the prototype field.
2837 return prototype_or_initial_map();
2838}
2839
2840
2841Object* JSFunction::prototype() {
2842 ASSERT(has_prototype());
2843 // If the function's prototype property has been set to a non-JSObject
2844 // value, that value is stored in the constructor field of the map.
2845 if (map()->has_non_instance_prototype()) return map()->constructor();
2846 return instance_prototype();
2847}
2848
Steve Block6ded16b2010-05-10 14:33:55 +01002849bool JSFunction::should_have_prototype() {
2850 return map()->function_with_prototype();
2851}
2852
Steve Blocka7e24c12009-10-30 11:49:00 +00002853
2854bool JSFunction::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01002855 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00002856}
2857
2858
2859int JSFunction::NumberOfLiterals() {
2860 return literals()->length();
2861}
2862
2863
2864Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2865 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002866 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00002867}
2868
2869
2870void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2871 Object* value) {
2872 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002873 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2874 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2875}
2876
2877
2878Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2879 ASSERT(0 <= id && id < kJSBuiltinsCount);
2880 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2881}
2882
2883
2884void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2885 Code* value) {
2886 ASSERT(0 <= id && id < kJSBuiltinsCount);
2887 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2888 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002889}
2890
2891
2892Address Proxy::proxy() {
2893 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2894}
2895
2896
2897void Proxy::set_proxy(Address value) {
2898 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2899}
2900
2901
Steve Blocka7e24c12009-10-30 11:49:00 +00002902ACCESSORS(JSValue, value, Object, kValueOffset)
2903
2904
2905JSValue* JSValue::cast(Object* obj) {
2906 ASSERT(obj->IsJSValue());
2907 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2908 return reinterpret_cast<JSValue*>(obj);
2909}
2910
2911
2912INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01002913ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002914
2915
2916byte* Code::instruction_start() {
2917 return FIELD_ADDR(this, kHeaderSize);
2918}
2919
2920
Leon Clarkeac952652010-07-15 11:15:24 +01002921byte* Code::instruction_end() {
2922 return instruction_start() + instruction_size();
2923}
2924
2925
Steve Blocka7e24c12009-10-30 11:49:00 +00002926int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01002927 return RoundUp(instruction_size(), kObjectAlignment);
2928}
2929
2930
2931ByteArray* Code::unchecked_relocation_info() {
2932 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002933}
2934
2935
2936byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01002937 return unchecked_relocation_info()->GetDataStartAddress();
2938}
2939
2940
2941int Code::relocation_size() {
2942 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00002943}
2944
2945
2946byte* Code::entry() {
2947 return instruction_start();
2948}
2949
2950
2951bool Code::contains(byte* pc) {
2952 return (instruction_start() <= pc) &&
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002953 (pc <= instruction_start() + instruction_size());
Steve Blocka7e24c12009-10-30 11:49:00 +00002954}
2955
2956
Steve Blocka7e24c12009-10-30 11:49:00 +00002957ACCESSORS(JSArray, length, Object, kLengthOffset)
2958
2959
2960ACCESSORS(JSRegExp, data, Object, kDataOffset)
2961
2962
2963JSRegExp::Type JSRegExp::TypeTag() {
2964 Object* data = this->data();
2965 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2966 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2967 return static_cast<JSRegExp::Type>(smi->value());
2968}
2969
2970
2971int JSRegExp::CaptureCount() {
2972 switch (TypeTag()) {
2973 case ATOM:
2974 return 0;
2975 case IRREGEXP:
2976 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2977 default:
2978 UNREACHABLE();
2979 return -1;
2980 }
2981}
2982
2983
2984JSRegExp::Flags JSRegExp::GetFlags() {
2985 ASSERT(this->data()->IsFixedArray());
2986 Object* data = this->data();
2987 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2988 return Flags(smi->value());
2989}
2990
2991
2992String* JSRegExp::Pattern() {
2993 ASSERT(this->data()->IsFixedArray());
2994 Object* data = this->data();
2995 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2996 return pattern;
2997}
2998
2999
3000Object* JSRegExp::DataAt(int index) {
3001 ASSERT(TypeTag() != NOT_COMPILED);
3002 return FixedArray::cast(data())->get(index);
3003}
3004
3005
3006void JSRegExp::SetDataAt(int index, Object* value) {
3007 ASSERT(TypeTag() != NOT_COMPILED);
3008 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3009 FixedArray::cast(data())->set(index, value);
3010}
3011
3012
3013JSObject::ElementsKind JSObject::GetElementsKind() {
Iain Merrick75681382010-08-19 15:07:18 +01003014 if (map()->has_fast_elements()) {
3015 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3016 elements()->map() == Heap::fixed_cow_array_map());
3017 return FAST_ELEMENTS;
3018 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003019 HeapObject* array = elements();
Steve Blocka7e24c12009-10-30 11:49:00 +00003020 if (array->IsFixedArray()) {
Iain Merrick75681382010-08-19 15:07:18 +01003021 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3022 // FixedArray, but FAST_ELEMENTS is already handled above.
Steve Blocka7e24c12009-10-30 11:49:00 +00003023 ASSERT(array->IsDictionary());
3024 return DICTIONARY_ELEMENTS;
3025 }
Steve Block3ce2e202009-11-05 08:53:23 +00003026 if (array->IsExternalArray()) {
3027 switch (array->map()->instance_type()) {
3028 case EXTERNAL_BYTE_ARRAY_TYPE:
3029 return EXTERNAL_BYTE_ELEMENTS;
3030 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3031 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3032 case EXTERNAL_SHORT_ARRAY_TYPE:
3033 return EXTERNAL_SHORT_ELEMENTS;
3034 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3035 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3036 case EXTERNAL_INT_ARRAY_TYPE:
3037 return EXTERNAL_INT_ELEMENTS;
3038 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3039 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3040 default:
3041 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3042 return EXTERNAL_FLOAT_ELEMENTS;
3043 }
3044 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003045 ASSERT(array->IsPixelArray());
3046 return PIXEL_ELEMENTS;
3047}
3048
3049
3050bool JSObject::HasFastElements() {
3051 return GetElementsKind() == FAST_ELEMENTS;
3052}
3053
3054
3055bool JSObject::HasDictionaryElements() {
3056 return GetElementsKind() == DICTIONARY_ELEMENTS;
3057}
3058
3059
3060bool JSObject::HasPixelElements() {
3061 return GetElementsKind() == PIXEL_ELEMENTS;
3062}
3063
3064
Steve Block3ce2e202009-11-05 08:53:23 +00003065bool JSObject::HasExternalArrayElements() {
3066 return (HasExternalByteElements() ||
3067 HasExternalUnsignedByteElements() ||
3068 HasExternalShortElements() ||
3069 HasExternalUnsignedShortElements() ||
3070 HasExternalIntElements() ||
3071 HasExternalUnsignedIntElements() ||
3072 HasExternalFloatElements());
3073}
3074
3075
3076bool JSObject::HasExternalByteElements() {
3077 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3078}
3079
3080
3081bool JSObject::HasExternalUnsignedByteElements() {
3082 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3083}
3084
3085
3086bool JSObject::HasExternalShortElements() {
3087 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3088}
3089
3090
3091bool JSObject::HasExternalUnsignedShortElements() {
3092 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3093}
3094
3095
3096bool JSObject::HasExternalIntElements() {
3097 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3098}
3099
3100
3101bool JSObject::HasExternalUnsignedIntElements() {
3102 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3103}
3104
3105
3106bool JSObject::HasExternalFloatElements() {
3107 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3108}
3109
3110
Steve Blocka7e24c12009-10-30 11:49:00 +00003111bool JSObject::HasNamedInterceptor() {
3112 return map()->has_named_interceptor();
3113}
3114
3115
3116bool JSObject::HasIndexedInterceptor() {
3117 return map()->has_indexed_interceptor();
3118}
3119
3120
Steve Block6ded16b2010-05-10 14:33:55 +01003121bool JSObject::AllowsSetElementsLength() {
3122 bool result = elements()->IsFixedArray();
3123 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3124 return result;
3125}
3126
3127
Iain Merrick75681382010-08-19 15:07:18 +01003128Object* JSObject::EnsureWritableFastElements() {
3129 ASSERT(HasFastElements());
3130 FixedArray* elems = FixedArray::cast(elements());
3131 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
3132 Object* writable_elems = Heap::CopyFixedArray(elems);
3133 if (writable_elems->IsFailure()) return writable_elems;
3134 FixedArray::cast(writable_elems)->set_map(Heap::fixed_array_map());
3135 set_elements(FixedArray::cast(writable_elems));
3136 Counters::cow_arrays_converted.Increment();
3137 return writable_elems;
3138}
3139
3140
Steve Blocka7e24c12009-10-30 11:49:00 +00003141StringDictionary* JSObject::property_dictionary() {
3142 ASSERT(!HasFastProperties());
3143 return StringDictionary::cast(properties());
3144}
3145
3146
3147NumberDictionary* JSObject::element_dictionary() {
3148 ASSERT(HasDictionaryElements());
3149 return NumberDictionary::cast(elements());
3150}
3151
3152
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003153bool String::IsHashFieldComputed(uint32_t field) {
3154 return (field & kHashNotComputedMask) == 0;
3155}
3156
3157
Steve Blocka7e24c12009-10-30 11:49:00 +00003158bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003159 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00003160}
3161
3162
3163uint32_t String::Hash() {
3164 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00003165 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003166 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003167 // Slow case: compute hash code and set it.
3168 return ComputeAndSetHash();
3169}
3170
3171
3172StringHasher::StringHasher(int length)
3173 : length_(length),
3174 raw_running_hash_(0),
3175 array_index_(0),
3176 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3177 is_first_char_(true),
3178 is_valid_(true) { }
3179
3180
3181bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00003182 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00003183}
3184
3185
3186void StringHasher::AddCharacter(uc32 c) {
3187 // Use the Jenkins one-at-a-time hash function to update the hash
3188 // for the given character.
3189 raw_running_hash_ += c;
3190 raw_running_hash_ += (raw_running_hash_ << 10);
3191 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3192 // Incremental array index computation.
3193 if (is_array_index_) {
3194 if (c < '0' || c > '9') {
3195 is_array_index_ = false;
3196 } else {
3197 int d = c - '0';
3198 if (is_first_char_) {
3199 is_first_char_ = false;
3200 if (c == '0' && length_ > 1) {
3201 is_array_index_ = false;
3202 return;
3203 }
3204 }
3205 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3206 is_array_index_ = false;
3207 } else {
3208 array_index_ = array_index_ * 10 + d;
3209 }
3210 }
3211 }
3212}
3213
3214
3215void StringHasher::AddCharacterNoIndex(uc32 c) {
3216 ASSERT(!is_array_index());
3217 raw_running_hash_ += c;
3218 raw_running_hash_ += (raw_running_hash_ << 10);
3219 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3220}
3221
3222
3223uint32_t StringHasher::GetHash() {
3224 // Get the calculated raw hash value and do some more bit ops to distribute
3225 // the hash further. Ensure that we never return zero as the hash value.
3226 uint32_t result = raw_running_hash_;
3227 result += (result << 3);
3228 result ^= (result >> 11);
3229 result += (result << 15);
3230 if (result == 0) {
3231 result = 27;
3232 }
3233 return result;
3234}
3235
3236
3237bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00003238 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003239 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3240 return false;
3241 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003242 return SlowAsArrayIndex(index);
3243}
3244
3245
3246Object* JSObject::GetPrototype() {
3247 return JSObject::cast(this)->map()->prototype();
3248}
3249
3250
3251PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3252 return GetPropertyAttributeWithReceiver(this, key);
3253}
3254
Steve Blockd0582a62009-12-15 09:54:21 +00003255// TODO(504): this may be useful in other places too where JSGlobalProxy
3256// is used.
3257Object* JSObject::BypassGlobalProxy() {
3258 if (IsJSGlobalProxy()) {
3259 Object* proto = GetPrototype();
3260 if (proto->IsNull()) return Heap::undefined_value();
3261 ASSERT(proto->IsJSGlobalObject());
3262 return proto;
3263 }
3264 return this;
3265}
3266
3267
3268bool JSObject::HasHiddenPropertiesObject() {
3269 ASSERT(!IsJSGlobalProxy());
3270 return GetPropertyAttributePostInterceptor(this,
3271 Heap::hidden_symbol(),
3272 false) != ABSENT;
3273}
3274
3275
3276Object* JSObject::GetHiddenPropertiesObject() {
3277 ASSERT(!IsJSGlobalProxy());
3278 PropertyAttributes attributes;
3279 return GetLocalPropertyPostInterceptor(this,
3280 Heap::hidden_symbol(),
3281 &attributes);
3282}
3283
3284
3285Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3286 ASSERT(!IsJSGlobalProxy());
3287 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3288 hidden_obj,
3289 DONT_ENUM);
3290}
3291
Steve Blocka7e24c12009-10-30 11:49:00 +00003292
3293bool JSObject::HasElement(uint32_t index) {
3294 return HasElementWithReceiver(this, index);
3295}
3296
3297
3298bool AccessorInfo::all_can_read() {
3299 return BooleanBit::get(flag(), kAllCanReadBit);
3300}
3301
3302
3303void AccessorInfo::set_all_can_read(bool value) {
3304 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3305}
3306
3307
3308bool AccessorInfo::all_can_write() {
3309 return BooleanBit::get(flag(), kAllCanWriteBit);
3310}
3311
3312
3313void AccessorInfo::set_all_can_write(bool value) {
3314 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3315}
3316
3317
3318bool AccessorInfo::prohibits_overwriting() {
3319 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3320}
3321
3322
3323void AccessorInfo::set_prohibits_overwriting(bool value) {
3324 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3325}
3326
3327
3328PropertyAttributes AccessorInfo::property_attributes() {
3329 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3330}
3331
3332
3333void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3334 ASSERT(AttributesField::is_valid(attributes));
3335 int rest_value = flag()->value() & ~AttributesField::mask();
3336 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3337}
3338
3339template<typename Shape, typename Key>
3340void Dictionary<Shape, Key>::SetEntry(int entry,
3341 Object* key,
3342 Object* value,
3343 PropertyDetails details) {
3344 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3345 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00003346 AssertNoAllocation no_gc;
3347 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00003348 FixedArray::set(index, key, mode);
3349 FixedArray::set(index+1, value, mode);
3350 FixedArray::fast_set(this, index+2, details.AsSmi());
3351}
3352
3353
3354void Map::ClearCodeCache() {
3355 // No write barrier is needed since empty_fixed_array is not in new space.
3356 // Please note this function is used during marking:
3357 // - MarkCompactCollector::MarkUnmarkedObject
3358 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3359 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3360}
3361
3362
3363void JSArray::EnsureSize(int required_size) {
3364 ASSERT(HasFastElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003365 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00003366 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3367 if (elts->length() < required_size) {
3368 // Doubling in size would be overkill, but leave some slack to avoid
3369 // constantly growing.
3370 Expand(required_size + (required_size >> 3));
3371 // It's a performance benefit to keep a frequently used array in new-space.
3372 } else if (!Heap::new_space()->Contains(elts) &&
3373 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3374 // Expand will allocate a new backing store in new space even if the size
3375 // we asked for isn't larger than what we had before.
3376 Expand(required_size);
3377 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003378}
3379
3380
Leon Clarke4515c472010-02-03 11:58:03 +00003381void JSArray::set_length(Smi* length) {
3382 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3383}
3384
3385
Steve Blocka7e24c12009-10-30 11:49:00 +00003386void JSArray::SetContent(FixedArray* storage) {
Leon Clarke4515c472010-02-03 11:58:03 +00003387 set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00003388 set_elements(storage);
3389}
3390
3391
3392Object* FixedArray::Copy() {
3393 if (length() == 0) return this;
3394 return Heap::CopyFixedArray(this);
3395}
3396
3397
Iain Merrick75681382010-08-19 15:07:18 +01003398int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3399 return map->instance_size();
3400}
3401
3402
3403void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3404 v->VisitExternalReference(
3405 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3406}
3407
3408
3409template<typename StaticVisitor>
3410void Proxy::ProxyIterateBody() {
3411 StaticVisitor::VisitExternalReference(
3412 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3413}
3414
3415
3416void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3417 typedef v8::String::ExternalAsciiStringResource Resource;
3418 v->VisitExternalAsciiString(
3419 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3420}
3421
3422
3423template<typename StaticVisitor>
3424void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3425 typedef v8::String::ExternalAsciiStringResource Resource;
3426 StaticVisitor::VisitExternalAsciiString(
3427 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3428}
3429
3430
3431void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3432 typedef v8::String::ExternalStringResource Resource;
3433 v->VisitExternalTwoByteString(
3434 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3435}
3436
3437
3438template<typename StaticVisitor>
3439void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3440 typedef v8::String::ExternalStringResource Resource;
3441 StaticVisitor::VisitExternalTwoByteString(
3442 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3443}
3444
3445#define SLOT_ADDR(obj, offset) \
3446 reinterpret_cast<Object**>((obj)->address() + offset)
3447
3448template<int start_offset, int end_offset, int size>
3449void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3450 HeapObject* obj,
3451 ObjectVisitor* v) {
3452 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3453}
3454
3455
3456template<int start_offset>
3457void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3458 int object_size,
3459 ObjectVisitor* v) {
3460 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3461}
3462
3463#undef SLOT_ADDR
3464
3465
Steve Blocka7e24c12009-10-30 11:49:00 +00003466#undef CAST_ACCESSOR
3467#undef INT_ACCESSORS
3468#undef SMI_ACCESSORS
3469#undef ACCESSORS
3470#undef FIELD_ADDR
3471#undef READ_FIELD
3472#undef WRITE_FIELD
3473#undef WRITE_BARRIER
3474#undef CONDITIONAL_WRITE_BARRIER
3475#undef READ_MEMADDR_FIELD
3476#undef WRITE_MEMADDR_FIELD
3477#undef READ_DOUBLE_FIELD
3478#undef WRITE_DOUBLE_FIELD
3479#undef READ_INT_FIELD
3480#undef WRITE_INT_FIELD
3481#undef READ_SHORT_FIELD
3482#undef WRITE_SHORT_FIELD
3483#undef READ_BYTE_FIELD
3484#undef WRITE_BYTE_FIELD
3485
3486
3487} } // namespace v8::internal
3488
3489#endif // V8_OBJECTS_INL_H_