blob: f63d6725ec2981afdf13b294c8a7de8a76d51f31 [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
Steve Blocka7e24c12009-10-30 11:49:00 +000086#define SMI_ACCESSORS(holder, name, offset) \
87 int holder::name() { \
88 Object* value = READ_FIELD(this, offset); \
89 return Smi::cast(value)->value(); \
90 } \
91 void holder::set_##name(int value) { \
92 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
93 }
94
95
96#define BOOL_GETTER(holder, field, name, offset) \
97 bool holder::name() { \
98 return BooleanBit::get(field(), offset); \
99 } \
100
101
102#define BOOL_ACCESSORS(holder, field, name, offset) \
103 bool holder::name() { \
104 return BooleanBit::get(field(), offset); \
105 } \
106 void holder::set_##name(bool value) { \
107 set_##field(BooleanBit::set(field(), offset, value)); \
108 }
109
110
111bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
112 // There is a constraint on the object; check.
113 if (!this->IsJSObject()) return false;
114 // Fetch the constructor function of the object.
115 Object* cons_obj = JSObject::cast(this)->map()->constructor();
116 if (!cons_obj->IsJSFunction()) return false;
117 JSFunction* fun = JSFunction::cast(cons_obj);
118 // Iterate through the chain of inheriting function templates to
119 // see if the required one occurs.
120 for (Object* type = fun->shared()->function_data();
121 type->IsFunctionTemplateInfo();
122 type = FunctionTemplateInfo::cast(type)->parent_template()) {
123 if (type == expected) return true;
124 }
125 // Didn't find the required type in the inheritance chain.
126 return false;
127}
128
129
130bool Object::IsSmi() {
131 return HAS_SMI_TAG(this);
132}
133
134
135bool Object::IsHeapObject() {
136 return Internals::HasHeapObjectTag(this);
137}
138
139
140bool Object::IsHeapNumber() {
141 return Object::IsHeapObject()
142 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
143}
144
145
146bool Object::IsString() {
147 return Object::IsHeapObject()
148 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
149}
150
151
152bool Object::IsSymbol() {
153 if (!this->IsHeapObject()) return false;
154 uint32_t type = HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000155 // Because the symbol tag is non-zero and no non-string types have the
156 // symbol bit set we can test for symbols with a very simple test
157 // operation.
158 ASSERT(kSymbolTag != 0);
159 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
160 return (type & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000161}
162
163
164bool Object::IsConsString() {
165 if (!this->IsHeapObject()) return false;
166 uint32_t type = HeapObject::cast(this)->map()->instance_type();
167 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
168 (kStringTag | kConsStringTag);
169}
170
171
Steve Blocka7e24c12009-10-30 11:49:00 +0000172bool Object::IsSeqString() {
173 if (!IsString()) return false;
174 return StringShape(String::cast(this)).IsSequential();
175}
176
177
178bool Object::IsSeqAsciiString() {
179 if (!IsString()) return false;
180 return StringShape(String::cast(this)).IsSequential() &&
181 String::cast(this)->IsAsciiRepresentation();
182}
183
184
185bool Object::IsSeqTwoByteString() {
186 if (!IsString()) return false;
187 return StringShape(String::cast(this)).IsSequential() &&
188 String::cast(this)->IsTwoByteRepresentation();
189}
190
191
192bool Object::IsExternalString() {
193 if (!IsString()) return false;
194 return StringShape(String::cast(this)).IsExternal();
195}
196
197
198bool Object::IsExternalAsciiString() {
199 if (!IsString()) return false;
200 return StringShape(String::cast(this)).IsExternal() &&
201 String::cast(this)->IsAsciiRepresentation();
202}
203
204
205bool Object::IsExternalTwoByteString() {
206 if (!IsString()) return false;
207 return StringShape(String::cast(this)).IsExternal() &&
208 String::cast(this)->IsTwoByteRepresentation();
209}
210
211
Steve Blocka7e24c12009-10-30 11:49:00 +0000212StringShape::StringShape(String* str)
213 : type_(str->map()->instance_type()) {
214 set_valid();
215 ASSERT((type_ & kIsNotStringMask) == kStringTag);
216}
217
218
219StringShape::StringShape(Map* map)
220 : type_(map->instance_type()) {
221 set_valid();
222 ASSERT((type_ & kIsNotStringMask) == kStringTag);
223}
224
225
226StringShape::StringShape(InstanceType t)
227 : type_(static_cast<uint32_t>(t)) {
228 set_valid();
229 ASSERT((type_ & kIsNotStringMask) == kStringTag);
230}
231
232
233bool StringShape::IsSymbol() {
234 ASSERT(valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000235 ASSERT(kSymbolTag != 0);
236 return (type_ & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000237}
238
239
240bool String::IsAsciiRepresentation() {
241 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 return (type & kStringEncodingMask) == kAsciiStringTag;
243}
244
245
246bool String::IsTwoByteRepresentation() {
247 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000248 return (type & kStringEncodingMask) == kTwoByteStringTag;
249}
250
251
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100252bool String::HasOnlyAsciiChars() {
253 uint32_t type = map()->instance_type();
254 return (type & kStringEncodingMask) == kAsciiStringTag ||
255 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
Steve Block6ded16b2010-05-10 14:33:55 +0100256}
257
258
Steve Blocka7e24c12009-10-30 11:49:00 +0000259bool StringShape::IsCons() {
260 return (type_ & kStringRepresentationMask) == kConsStringTag;
261}
262
263
Steve Blocka7e24c12009-10-30 11:49:00 +0000264bool StringShape::IsExternal() {
265 return (type_ & kStringRepresentationMask) == kExternalStringTag;
266}
267
268
269bool StringShape::IsSequential() {
270 return (type_ & kStringRepresentationMask) == kSeqStringTag;
271}
272
273
274StringRepresentationTag StringShape::representation_tag() {
275 uint32_t tag = (type_ & kStringRepresentationMask);
276 return static_cast<StringRepresentationTag>(tag);
277}
278
279
280uint32_t StringShape::full_representation_tag() {
281 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
282}
283
284
285STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
286 Internals::kFullStringRepresentationMask);
287
288
Steve Blocka7e24c12009-10-30 11:49:00 +0000289bool StringShape::IsSequentialAscii() {
290 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
291}
292
293
294bool StringShape::IsSequentialTwoByte() {
295 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
296}
297
298
299bool StringShape::IsExternalAscii() {
300 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
301}
302
303
304bool StringShape::IsExternalTwoByte() {
305 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
306}
307
308
309STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
310 Internals::kExternalTwoByteRepresentationTag);
311
312
313uc32 FlatStringReader::Get(int index) {
314 ASSERT(0 <= index && index <= length_);
315 if (is_ascii_) {
316 return static_cast<const byte*>(start_)[index];
317 } else {
318 return static_cast<const uc16*>(start_)[index];
319 }
320}
321
322
323bool Object::IsNumber() {
324 return IsSmi() || IsHeapNumber();
325}
326
327
328bool Object::IsByteArray() {
329 return Object::IsHeapObject()
330 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
331}
332
333
334bool Object::IsPixelArray() {
335 return Object::IsHeapObject() &&
336 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
337}
338
339
Steve Block3ce2e202009-11-05 08:53:23 +0000340bool Object::IsExternalArray() {
341 if (!Object::IsHeapObject())
342 return false;
343 InstanceType instance_type =
344 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000345 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
346 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000347}
348
349
350bool Object::IsExternalByteArray() {
351 return Object::IsHeapObject() &&
352 HeapObject::cast(this)->map()->instance_type() ==
353 EXTERNAL_BYTE_ARRAY_TYPE;
354}
355
356
357bool Object::IsExternalUnsignedByteArray() {
358 return Object::IsHeapObject() &&
359 HeapObject::cast(this)->map()->instance_type() ==
360 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
361}
362
363
364bool Object::IsExternalShortArray() {
365 return Object::IsHeapObject() &&
366 HeapObject::cast(this)->map()->instance_type() ==
367 EXTERNAL_SHORT_ARRAY_TYPE;
368}
369
370
371bool Object::IsExternalUnsignedShortArray() {
372 return Object::IsHeapObject() &&
373 HeapObject::cast(this)->map()->instance_type() ==
374 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
375}
376
377
378bool Object::IsExternalIntArray() {
379 return Object::IsHeapObject() &&
380 HeapObject::cast(this)->map()->instance_type() ==
381 EXTERNAL_INT_ARRAY_TYPE;
382}
383
384
385bool Object::IsExternalUnsignedIntArray() {
386 return Object::IsHeapObject() &&
387 HeapObject::cast(this)->map()->instance_type() ==
388 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
389}
390
391
392bool Object::IsExternalFloatArray() {
393 return Object::IsHeapObject() &&
394 HeapObject::cast(this)->map()->instance_type() ==
395 EXTERNAL_FLOAT_ARRAY_TYPE;
396}
397
398
Steve Blocka7e24c12009-10-30 11:49:00 +0000399bool Object::IsFailure() {
400 return HAS_FAILURE_TAG(this);
401}
402
403
404bool Object::IsRetryAfterGC() {
405 return HAS_FAILURE_TAG(this)
406 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
407}
408
409
410bool Object::IsOutOfMemoryFailure() {
411 return HAS_FAILURE_TAG(this)
412 && Failure::cast(this)->IsOutOfMemoryException();
413}
414
415
416bool Object::IsException() {
417 return this == Failure::Exception();
418}
419
420
421bool Object::IsJSObject() {
422 return IsHeapObject()
423 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
424}
425
426
427bool Object::IsJSContextExtensionObject() {
428 return IsHeapObject()
429 && (HeapObject::cast(this)->map()->instance_type() ==
430 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
431}
432
433
434bool Object::IsMap() {
435 return Object::IsHeapObject()
436 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
437}
438
439
440bool Object::IsFixedArray() {
441 return Object::IsHeapObject()
442 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
443}
444
445
446bool Object::IsDescriptorArray() {
447 return IsFixedArray();
448}
449
450
451bool Object::IsContext() {
452 return Object::IsHeapObject()
453 && (HeapObject::cast(this)->map() == Heap::context_map() ||
454 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
455 HeapObject::cast(this)->map() == Heap::global_context_map());
456}
457
458
459bool Object::IsCatchContext() {
460 return Object::IsHeapObject()
461 && HeapObject::cast(this)->map() == Heap::catch_context_map();
462}
463
464
465bool Object::IsGlobalContext() {
466 return Object::IsHeapObject()
467 && HeapObject::cast(this)->map() == Heap::global_context_map();
468}
469
470
471bool Object::IsJSFunction() {
472 return Object::IsHeapObject()
473 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
474}
475
476
477template <> inline bool Is<JSFunction>(Object* obj) {
478 return obj->IsJSFunction();
479}
480
481
482bool Object::IsCode() {
483 return Object::IsHeapObject()
484 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
485}
486
487
488bool Object::IsOddball() {
489 return Object::IsHeapObject()
490 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
491}
492
493
494bool Object::IsJSGlobalPropertyCell() {
495 return Object::IsHeapObject()
496 && HeapObject::cast(this)->map()->instance_type()
497 == JS_GLOBAL_PROPERTY_CELL_TYPE;
498}
499
500
501bool Object::IsSharedFunctionInfo() {
502 return Object::IsHeapObject() &&
503 (HeapObject::cast(this)->map()->instance_type() ==
504 SHARED_FUNCTION_INFO_TYPE);
505}
506
507
508bool Object::IsJSValue() {
509 return Object::IsHeapObject()
510 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
511}
512
513
514bool Object::IsStringWrapper() {
515 return IsJSValue() && JSValue::cast(this)->value()->IsString();
516}
517
518
519bool Object::IsProxy() {
520 return Object::IsHeapObject()
521 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
522}
523
524
525bool Object::IsBoolean() {
526 return IsTrue() || IsFalse();
527}
528
529
530bool Object::IsJSArray() {
531 return Object::IsHeapObject()
532 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
533}
534
535
536bool Object::IsJSRegExp() {
537 return Object::IsHeapObject()
538 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
539}
540
541
542template <> inline bool Is<JSArray>(Object* obj) {
543 return obj->IsJSArray();
544}
545
546
547bool Object::IsHashTable() {
548 return Object::IsHeapObject()
549 && HeapObject::cast(this)->map() == Heap::hash_table_map();
550}
551
552
553bool Object::IsDictionary() {
554 return IsHashTable() && this != Heap::symbol_table();
555}
556
557
558bool Object::IsSymbolTable() {
559 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
560}
561
562
Steve Block6ded16b2010-05-10 14:33:55 +0100563bool Object::IsJSFunctionResultCache() {
564 if (!IsFixedArray()) return false;
565 FixedArray* self = FixedArray::cast(this);
566 int length = self->length();
567 if (length < JSFunctionResultCache::kEntriesIndex) return false;
568 if ((length - JSFunctionResultCache::kEntriesIndex)
569 % JSFunctionResultCache::kEntrySize != 0) {
570 return false;
571 }
572#ifdef DEBUG
573 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
574#endif
575 return true;
576}
577
578
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100579bool Object::IsNormalizedMapCache() {
580 if (!IsFixedArray()) return false;
581 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
582 return false;
583 }
584#ifdef DEBUG
585 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
586#endif
587 return true;
588}
589
590
Steve Blocka7e24c12009-10-30 11:49:00 +0000591bool Object::IsCompilationCacheTable() {
592 return IsHashTable();
593}
594
595
Steve Block6ded16b2010-05-10 14:33:55 +0100596bool Object::IsCodeCacheHashTable() {
597 return IsHashTable();
598}
599
600
Steve Blocka7e24c12009-10-30 11:49:00 +0000601bool Object::IsMapCache() {
602 return IsHashTable();
603}
604
605
606bool Object::IsPrimitive() {
607 return IsOddball() || IsNumber() || IsString();
608}
609
610
611bool Object::IsJSGlobalProxy() {
612 bool result = IsHeapObject() &&
613 (HeapObject::cast(this)->map()->instance_type() ==
614 JS_GLOBAL_PROXY_TYPE);
615 ASSERT(!result || IsAccessCheckNeeded());
616 return result;
617}
618
619
620bool Object::IsGlobalObject() {
621 if (!IsHeapObject()) return false;
622
623 InstanceType type = HeapObject::cast(this)->map()->instance_type();
624 return type == JS_GLOBAL_OBJECT_TYPE ||
625 type == JS_BUILTINS_OBJECT_TYPE;
626}
627
628
629bool Object::IsJSGlobalObject() {
630 return IsHeapObject() &&
631 (HeapObject::cast(this)->map()->instance_type() ==
632 JS_GLOBAL_OBJECT_TYPE);
633}
634
635
636bool Object::IsJSBuiltinsObject() {
637 return IsHeapObject() &&
638 (HeapObject::cast(this)->map()->instance_type() ==
639 JS_BUILTINS_OBJECT_TYPE);
640}
641
642
643bool Object::IsUndetectableObject() {
644 return IsHeapObject()
645 && HeapObject::cast(this)->map()->is_undetectable();
646}
647
648
649bool Object::IsAccessCheckNeeded() {
650 return IsHeapObject()
651 && HeapObject::cast(this)->map()->is_access_check_needed();
652}
653
654
655bool Object::IsStruct() {
656 if (!IsHeapObject()) return false;
657 switch (HeapObject::cast(this)->map()->instance_type()) {
658#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
659 STRUCT_LIST(MAKE_STRUCT_CASE)
660#undef MAKE_STRUCT_CASE
661 default: return false;
662 }
663}
664
665
666#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
667 bool Object::Is##Name() { \
668 return Object::IsHeapObject() \
669 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
670 }
671 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
672#undef MAKE_STRUCT_PREDICATE
673
674
675bool Object::IsUndefined() {
676 return this == Heap::undefined_value();
677}
678
679
680bool Object::IsTheHole() {
681 return this == Heap::the_hole_value();
682}
683
684
685bool Object::IsNull() {
686 return this == Heap::null_value();
687}
688
689
690bool Object::IsTrue() {
691 return this == Heap::true_value();
692}
693
694
695bool Object::IsFalse() {
696 return this == Heap::false_value();
697}
698
699
700double Object::Number() {
701 ASSERT(IsNumber());
702 return IsSmi()
703 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
704 : reinterpret_cast<HeapNumber*>(this)->value();
705}
706
707
708
709Object* Object::ToSmi() {
710 if (IsSmi()) return this;
711 if (IsHeapNumber()) {
712 double value = HeapNumber::cast(this)->value();
713 int int_value = FastD2I(value);
714 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
715 return Smi::FromInt(int_value);
716 }
717 }
718 return Failure::Exception();
719}
720
721
722bool Object::HasSpecificClassOf(String* name) {
723 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
724}
725
726
727Object* Object::GetElement(uint32_t index) {
728 return GetElementWithReceiver(this, index);
729}
730
731
732Object* Object::GetProperty(String* key) {
733 PropertyAttributes attributes;
734 return GetPropertyWithReceiver(this, key, &attributes);
735}
736
737
738Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
739 return GetPropertyWithReceiver(this, key, attributes);
740}
741
742
743#define FIELD_ADDR(p, offset) \
744 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
745
746#define READ_FIELD(p, offset) \
747 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
748
749#define WRITE_FIELD(p, offset, value) \
750 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
751
752
753#define WRITE_BARRIER(object, offset) \
754 Heap::RecordWrite(object->address(), offset);
755
756// CONDITIONAL_WRITE_BARRIER must be issued after the actual
757// write due to the assert validating the written value.
758#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
759 if (mode == UPDATE_WRITE_BARRIER) { \
760 Heap::RecordWrite(object->address(), offset); \
761 } else { \
762 ASSERT(mode == SKIP_WRITE_BARRIER); \
763 ASSERT(Heap::InNewSpace(object) || \
Steve Block6ded16b2010-05-10 14:33:55 +0100764 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100765 Page::FromAddress(object->address())-> \
766 IsRegionDirty(object->address() + offset)); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000767 }
768
769#define READ_DOUBLE_FIELD(p, offset) \
770 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
771
772#define WRITE_DOUBLE_FIELD(p, offset, value) \
773 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
774
775#define READ_INT_FIELD(p, offset) \
776 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
777
778#define WRITE_INT_FIELD(p, offset, value) \
779 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
780
781#define READ_INTPTR_FIELD(p, offset) \
782 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
783
784#define WRITE_INTPTR_FIELD(p, offset, value) \
785 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
786
787#define READ_UINT32_FIELD(p, offset) \
788 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
789
790#define WRITE_UINT32_FIELD(p, offset, value) \
791 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
792
793#define READ_SHORT_FIELD(p, offset) \
794 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
795
796#define WRITE_SHORT_FIELD(p, offset, value) \
797 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
798
799#define READ_BYTE_FIELD(p, offset) \
800 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
801
802#define WRITE_BYTE_FIELD(p, offset, value) \
803 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
804
805
806Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
807 return &READ_FIELD(obj, byte_offset);
808}
809
810
811int Smi::value() {
812 return Internals::SmiValue(this);
813}
814
815
816Smi* Smi::FromInt(int value) {
817 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000818 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000819 intptr_t tagged_value =
Steve Block3ce2e202009-11-05 08:53:23 +0000820 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000821 return reinterpret_cast<Smi*>(tagged_value);
822}
823
824
825Smi* Smi::FromIntptr(intptr_t value) {
826 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000827 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
828 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000829}
830
831
832Failure::Type Failure::type() const {
833 return static_cast<Type>(value() & kFailureTypeTagMask);
834}
835
836
837bool Failure::IsInternalError() const {
838 return type() == INTERNAL_ERROR;
839}
840
841
842bool Failure::IsOutOfMemoryException() const {
843 return type() == OUT_OF_MEMORY_EXCEPTION;
844}
845
846
847int Failure::requested() const {
848 const int kShiftBits =
849 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
850 STATIC_ASSERT(kShiftBits >= 0);
851 ASSERT(type() == RETRY_AFTER_GC);
Steve Block3ce2e202009-11-05 08:53:23 +0000852 return static_cast<int>(value() >> kShiftBits);
Steve Blocka7e24c12009-10-30 11:49:00 +0000853}
854
855
856AllocationSpace Failure::allocation_space() const {
857 ASSERT_EQ(RETRY_AFTER_GC, type());
858 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
859 & kSpaceTagMask);
860}
861
862
863Failure* Failure::InternalError() {
864 return Construct(INTERNAL_ERROR);
865}
866
867
868Failure* Failure::Exception() {
869 return Construct(EXCEPTION);
870}
871
872
873Failure* Failure::OutOfMemoryException() {
874 return Construct(OUT_OF_MEMORY_EXCEPTION);
875}
876
877
Steve Block3ce2e202009-11-05 08:53:23 +0000878intptr_t Failure::value() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100879 return static_cast<intptr_t>(
880 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000881}
882
883
884Failure* Failure::RetryAfterGC(int requested_bytes) {
885 // Assert that the space encoding fits in the three bytes allotted for it.
886 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
Steve Block6ded16b2010-05-10 14:33:55 +0100887 uintptr_t requested =
888 static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
889 int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
Steve Block3ce2e202009-11-05 08:53:23 +0000890 if (((requested << tag_bits) >> tag_bits) != requested) {
891 // No room for entire requested size in the bits. Round down to
892 // maximally representable size.
893 requested = static_cast<intptr_t>(
894 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
895 }
Steve Blockd0582a62009-12-15 09:54:21 +0000896 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000897 return Construct(RETRY_AFTER_GC, value);
898}
899
900
Steve Block3ce2e202009-11-05 08:53:23 +0000901Failure* Failure::Construct(Type type, intptr_t value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100902 uintptr_t info =
903 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
Steve Block3ce2e202009-11-05 08:53:23 +0000905 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000906}
907
908
909bool Smi::IsValid(intptr_t value) {
910#ifdef DEBUG
911 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
912#endif
Steve Block3ce2e202009-11-05 08:53:23 +0000913
914#ifdef V8_TARGET_ARCH_X64
915 // To be representable as a long smi, the value must be a 32-bit integer.
916 bool result = (value == static_cast<int32_t>(value));
917#else
Steve Blocka7e24c12009-10-30 11:49:00 +0000918 // To be representable as an tagged small integer, the two
919 // most-significant bits of 'value' must be either 00 or 11 due to
920 // sign-extension. To check this we add 01 to the two
921 // most-significant bits, and check if the most-significant bit is 0
922 //
923 // CAUTION: The original code below:
924 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
925 // may lead to incorrect results according to the C language spec, and
926 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
927 // compiler may produce undefined results in case of signed integer
928 // overflow. The computation must be done w/ unsigned ints.
Steve Block3ce2e202009-11-05 08:53:23 +0000929 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
Steve Blocka7e24c12009-10-30 11:49:00 +0000930#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 ASSERT(result == in_range);
932 return result;
933}
934
935
936MapWord MapWord::FromMap(Map* map) {
937 return MapWord(reinterpret_cast<uintptr_t>(map));
938}
939
940
941Map* MapWord::ToMap() {
942 return reinterpret_cast<Map*>(value_);
943}
944
945
946bool MapWord::IsForwardingAddress() {
947 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
948}
949
950
951MapWord MapWord::FromForwardingAddress(HeapObject* object) {
952 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
953 return MapWord(reinterpret_cast<uintptr_t>(raw));
954}
955
956
957HeapObject* MapWord::ToForwardingAddress() {
958 ASSERT(IsForwardingAddress());
959 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
960}
961
962
963bool MapWord::IsMarked() {
964 return (value_ & kMarkingMask) == 0;
965}
966
967
968void MapWord::SetMark() {
969 value_ &= ~kMarkingMask;
970}
971
972
973void MapWord::ClearMark() {
974 value_ |= kMarkingMask;
975}
976
977
978bool MapWord::IsOverflowed() {
979 return (value_ & kOverflowMask) != 0;
980}
981
982
983void MapWord::SetOverflow() {
984 value_ |= kOverflowMask;
985}
986
987
988void MapWord::ClearOverflow() {
989 value_ &= ~kOverflowMask;
990}
991
992
993MapWord MapWord::EncodeAddress(Address map_address, int offset) {
994 // Offset is the distance in live bytes from the first live object in the
995 // same page. The offset between two objects in the same page should not
996 // exceed the object area size of a page.
997 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
998
Leon Clarkee46be812010-01-19 14:06:41 +0000999 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1001
1002 Page* map_page = Page::FromAddress(map_address);
1003 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1004
Leon Clarkee46be812010-01-19 14:06:41 +00001005 uintptr_t map_page_offset =
1006 map_page->Offset(map_address) >> kMapAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +00001007
1008 uintptr_t encoding =
1009 (compact_offset << kForwardingOffsetShift) |
1010 (map_page_offset << kMapPageOffsetShift) |
1011 (map_page->mc_page_index << kMapPageIndexShift);
1012 return MapWord(encoding);
1013}
1014
1015
1016Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1017 int map_page_index =
1018 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1019 ASSERT_MAP_PAGE_INDEX(map_page_index);
1020
1021 int map_page_offset = static_cast<int>(
Leon Clarkee46be812010-01-19 14:06:41 +00001022 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1023 kMapAlignmentBits);
Steve Blocka7e24c12009-10-30 11:49:00 +00001024
1025 return (map_space->PageAddress(map_page_index) + map_page_offset);
1026}
1027
1028
1029int MapWord::DecodeOffset() {
1030 // The offset field is represented in the kForwardingOffsetBits
1031 // most-significant bits.
Steve Blockd0582a62009-12-15 09:54:21 +00001032 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1033 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1034 return static_cast<int>(offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001035}
1036
1037
1038MapWord MapWord::FromEncodedAddress(Address address) {
1039 return MapWord(reinterpret_cast<uintptr_t>(address));
1040}
1041
1042
1043Address MapWord::ToEncodedAddress() {
1044 return reinterpret_cast<Address>(value_);
1045}
1046
1047
1048#ifdef DEBUG
1049void HeapObject::VerifyObjectField(int offset) {
1050 VerifyPointer(READ_FIELD(this, offset));
1051}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001052
1053void HeapObject::VerifySmiField(int offset) {
1054 ASSERT(READ_FIELD(this, offset)->IsSmi());
1055}
Steve Blocka7e24c12009-10-30 11:49:00 +00001056#endif
1057
1058
1059Map* HeapObject::map() {
1060 return map_word().ToMap();
1061}
1062
1063
1064void HeapObject::set_map(Map* value) {
1065 set_map_word(MapWord::FromMap(value));
1066}
1067
1068
1069MapWord HeapObject::map_word() {
1070 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1071}
1072
1073
1074void HeapObject::set_map_word(MapWord map_word) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001075 // WRITE_FIELD does not invoke write barrier, but there is no need
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 // here.
1077 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1078}
1079
1080
1081HeapObject* HeapObject::FromAddress(Address address) {
1082 ASSERT_TAG_ALIGNED(address);
1083 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1084}
1085
1086
1087Address HeapObject::address() {
1088 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1089}
1090
1091
1092int HeapObject::Size() {
1093 return SizeFromMap(map());
1094}
1095
1096
1097void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1098 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1099 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1100}
1101
1102
1103void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1104 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1105}
1106
1107
1108bool HeapObject::IsMarked() {
1109 return map_word().IsMarked();
1110}
1111
1112
1113void HeapObject::SetMark() {
1114 ASSERT(!IsMarked());
1115 MapWord first_word = map_word();
1116 first_word.SetMark();
1117 set_map_word(first_word);
1118}
1119
1120
1121void HeapObject::ClearMark() {
1122 ASSERT(IsMarked());
1123 MapWord first_word = map_word();
1124 first_word.ClearMark();
1125 set_map_word(first_word);
1126}
1127
1128
1129bool HeapObject::IsOverflowed() {
1130 return map_word().IsOverflowed();
1131}
1132
1133
1134void HeapObject::SetOverflow() {
1135 MapWord first_word = map_word();
1136 first_word.SetOverflow();
1137 set_map_word(first_word);
1138}
1139
1140
1141void HeapObject::ClearOverflow() {
1142 ASSERT(IsOverflowed());
1143 MapWord first_word = map_word();
1144 first_word.ClearOverflow();
1145 set_map_word(first_word);
1146}
1147
1148
1149double HeapNumber::value() {
1150 return READ_DOUBLE_FIELD(this, kValueOffset);
1151}
1152
1153
1154void HeapNumber::set_value(double value) {
1155 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1156}
1157
1158
Steve Block6ded16b2010-05-10 14:33:55 +01001159int HeapNumber::get_exponent() {
1160 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1161 kExponentShift) - kExponentBias;
1162}
1163
1164
1165int HeapNumber::get_sign() {
1166 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1167}
1168
1169
Steve Blocka7e24c12009-10-30 11:49:00 +00001170ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1171
1172
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001173HeapObject* JSObject::elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001174 Object* array = READ_FIELD(this, kElementsOffset);
1175 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001176 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1177 array->IsExternalArray());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001178 return reinterpret_cast<HeapObject*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001179}
1180
1181
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001182void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
Steve Block8defd9f2010-07-08 12:39:36 +01001183 ASSERT(map()->has_fast_elements() ==
Iain Merrick75681382010-08-19 15:07:18 +01001184 (value->map() == Heap::fixed_array_map() ||
1185 value->map() == Heap::fixed_cow_array_map()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001186 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001187 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1188 value->IsExternalArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00001189 WRITE_FIELD(this, kElementsOffset, value);
1190 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1191}
1192
1193
1194void JSObject::initialize_properties() {
1195 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1196 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1197}
1198
1199
1200void JSObject::initialize_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01001201 ASSERT(map()->has_fast_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00001202 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1203 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1204}
1205
1206
Steve Block8defd9f2010-07-08 12:39:36 +01001207Object* JSObject::ResetElements() {
1208 Object* obj = map()->GetFastElementsMap();
1209 if (obj->IsFailure()) return obj;
1210 set_map(Map::cast(obj));
1211 initialize_elements();
1212 return this;
1213}
1214
1215
Steve Blocka7e24c12009-10-30 11:49:00 +00001216ACCESSORS(Oddball, to_string, String, kToStringOffset)
1217ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1218
1219
1220Object* JSGlobalPropertyCell::value() {
1221 return READ_FIELD(this, kValueOffset);
1222}
1223
1224
1225void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1226 // The write barrier is not used for global property cells.
1227 ASSERT(!val->IsJSGlobalPropertyCell());
1228 WRITE_FIELD(this, kValueOffset, val);
1229}
1230
1231
1232int JSObject::GetHeaderSize() {
1233 InstanceType type = map()->instance_type();
1234 // Check for the most common kind of JavaScript object before
1235 // falling into the generic switch. This speeds up the internal
1236 // field operations considerably on average.
1237 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1238 switch (type) {
1239 case JS_GLOBAL_PROXY_TYPE:
1240 return JSGlobalProxy::kSize;
1241 case JS_GLOBAL_OBJECT_TYPE:
1242 return JSGlobalObject::kSize;
1243 case JS_BUILTINS_OBJECT_TYPE:
1244 return JSBuiltinsObject::kSize;
1245 case JS_FUNCTION_TYPE:
1246 return JSFunction::kSize;
1247 case JS_VALUE_TYPE:
1248 return JSValue::kSize;
1249 case JS_ARRAY_TYPE:
1250 return JSValue::kSize;
1251 case JS_REGEXP_TYPE:
1252 return JSValue::kSize;
1253 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1254 return JSObject::kHeaderSize;
1255 default:
1256 UNREACHABLE();
1257 return 0;
1258 }
1259}
1260
1261
1262int JSObject::GetInternalFieldCount() {
1263 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1264 // Make sure to adjust for the number of in-object properties. These
1265 // properties do contribute to the size, but are not internal fields.
1266 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1267 map()->inobject_properties();
1268}
1269
1270
1271Object* JSObject::GetInternalField(int index) {
1272 ASSERT(index < GetInternalFieldCount() && index >= 0);
1273 // Internal objects do follow immediately after the header, whereas in-object
1274 // properties are at the end of the object. Therefore there is no need
1275 // to adjust the index here.
1276 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1277}
1278
1279
1280void JSObject::SetInternalField(int index, Object* value) {
1281 ASSERT(index < GetInternalFieldCount() && index >= 0);
1282 // Internal objects do follow immediately after the header, whereas in-object
1283 // properties are at the end of the object. Therefore there is no need
1284 // to adjust the index here.
1285 int offset = GetHeaderSize() + (kPointerSize * index);
1286 WRITE_FIELD(this, offset, value);
1287 WRITE_BARRIER(this, offset);
1288}
1289
1290
1291// Access fast-case object properties at index. The use of these routines
1292// is needed to correctly distinguish between properties stored in-object and
1293// properties stored in the properties array.
1294Object* JSObject::FastPropertyAt(int index) {
1295 // Adjust for the number of properties stored in the object.
1296 index -= map()->inobject_properties();
1297 if (index < 0) {
1298 int offset = map()->instance_size() + (index * kPointerSize);
1299 return READ_FIELD(this, offset);
1300 } else {
1301 ASSERT(index < properties()->length());
1302 return properties()->get(index);
1303 }
1304}
1305
1306
1307Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1308 // Adjust for the number of properties stored in the object.
1309 index -= map()->inobject_properties();
1310 if (index < 0) {
1311 int offset = map()->instance_size() + (index * kPointerSize);
1312 WRITE_FIELD(this, offset, value);
1313 WRITE_BARRIER(this, offset);
1314 } else {
1315 ASSERT(index < properties()->length());
1316 properties()->set(index, value);
1317 }
1318 return value;
1319}
1320
1321
1322Object* JSObject::InObjectPropertyAt(int index) {
1323 // Adjust for the number of properties stored in the object.
1324 index -= map()->inobject_properties();
1325 ASSERT(index < 0);
1326 int offset = map()->instance_size() + (index * kPointerSize);
1327 return READ_FIELD(this, offset);
1328}
1329
1330
1331Object* JSObject::InObjectPropertyAtPut(int index,
1332 Object* value,
1333 WriteBarrierMode mode) {
1334 // Adjust for the number of properties stored in the object.
1335 index -= map()->inobject_properties();
1336 ASSERT(index < 0);
1337 int offset = map()->instance_size() + (index * kPointerSize);
1338 WRITE_FIELD(this, offset, value);
1339 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1340 return value;
1341}
1342
1343
1344
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001345void JSObject::InitializeBody(int object_size, Object* value) {
1346 ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1348 WRITE_FIELD(this, offset, value);
1349 }
1350}
1351
1352
Steve Block8defd9f2010-07-08 12:39:36 +01001353bool JSObject::HasFastProperties() {
1354 return !properties()->IsDictionary();
1355}
1356
1357
1358int JSObject::MaxFastProperties() {
1359 // Allow extra fast properties if the object has more than
1360 // kMaxFastProperties in-object properties. When this is the case,
1361 // it is very unlikely that the object is being used as a dictionary
1362 // and there is a good chance that allowing more map transitions
1363 // will be worth it.
1364 return Max(map()->inobject_properties(), kMaxFastProperties);
1365}
1366
1367
Steve Blocka7e24c12009-10-30 11:49:00 +00001368void Struct::InitializeBody(int object_size) {
1369 Object* value = Heap::undefined_value();
1370 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1371 WRITE_FIELD(this, offset, value);
1372 }
1373}
1374
1375
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001376bool Object::ToArrayIndex(uint32_t* index) {
1377 if (IsSmi()) {
1378 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001379 if (value < 0) return false;
1380 *index = value;
1381 return true;
1382 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001383 if (IsHeapNumber()) {
1384 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001385 uint32_t uint_value = static_cast<uint32_t>(value);
1386 if (value == static_cast<double>(uint_value)) {
1387 *index = uint_value;
1388 return true;
1389 }
1390 }
1391 return false;
1392}
1393
1394
1395bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1396 if (!this->IsJSValue()) return false;
1397
1398 JSValue* js_value = JSValue::cast(this);
1399 if (!js_value->value()->IsString()) return false;
1400
1401 String* str = String::cast(js_value->value());
1402 if (index >= (uint32_t)str->length()) return false;
1403
1404 return true;
1405}
1406
1407
1408Object* FixedArray::get(int index) {
1409 ASSERT(index >= 0 && index < this->length());
1410 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1411}
1412
1413
1414void FixedArray::set(int index, Smi* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001415 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1417 int offset = kHeaderSize + index * kPointerSize;
1418 WRITE_FIELD(this, offset, value);
1419}
1420
1421
1422void FixedArray::set(int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001423 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001424 ASSERT(index >= 0 && index < this->length());
1425 int offset = kHeaderSize + index * kPointerSize;
1426 WRITE_FIELD(this, offset, value);
1427 WRITE_BARRIER(this, offset);
1428}
1429
1430
Leon Clarke4515c472010-02-03 11:58:03 +00001431WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001432 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1433 return UPDATE_WRITE_BARRIER;
1434}
1435
1436
1437void FixedArray::set(int index,
1438 Object* value,
1439 WriteBarrierMode mode) {
Iain Merrick75681382010-08-19 15:07:18 +01001440 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001441 ASSERT(index >= 0 && index < this->length());
1442 int offset = kHeaderSize + index * kPointerSize;
1443 WRITE_FIELD(this, offset, value);
1444 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1445}
1446
1447
1448void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001449 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001450 ASSERT(index >= 0 && index < array->length());
Leon Clarke4515c472010-02-03 11:58:03 +00001451 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001452 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1453}
1454
1455
1456void FixedArray::set_undefined(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001457 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001458 ASSERT(index >= 0 && index < this->length());
1459 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1460 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1461 Heap::undefined_value());
1462}
1463
1464
1465void FixedArray::set_null(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001466 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001467 ASSERT(index >= 0 && index < this->length());
1468 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1469 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1470}
1471
1472
1473void FixedArray::set_the_hole(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001474 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 ASSERT(index >= 0 && index < this->length());
1476 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1477 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1478}
1479
1480
Iain Merrick75681382010-08-19 15:07:18 +01001481void FixedArray::set_unchecked(int index, Smi* value) {
1482 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1483 int offset = kHeaderSize + index * kPointerSize;
1484 WRITE_FIELD(this, offset, value);
1485}
1486
1487
1488void FixedArray::set_null_unchecked(int index) {
1489 ASSERT(index >= 0 && index < this->length());
1490 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1491 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1492}
1493
1494
Steve Block6ded16b2010-05-10 14:33:55 +01001495Object** FixedArray::data_start() {
1496 return HeapObject::RawField(this, kHeaderSize);
1497}
1498
1499
Steve Blocka7e24c12009-10-30 11:49:00 +00001500bool DescriptorArray::IsEmpty() {
1501 ASSERT(this == Heap::empty_descriptor_array() ||
1502 this->length() > 2);
1503 return this == Heap::empty_descriptor_array();
1504}
1505
1506
1507void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1508 Object* tmp = array->get(first);
1509 fast_set(array, first, array->get(second));
1510 fast_set(array, second, tmp);
1511}
1512
1513
1514int DescriptorArray::Search(String* name) {
1515 SLOW_ASSERT(IsSortedNoDuplicates());
1516
1517 // Check for empty descriptor array.
1518 int nof = number_of_descriptors();
1519 if (nof == 0) return kNotFound;
1520
1521 // Fast case: do linear search for small arrays.
1522 const int kMaxElementsForLinearSearch = 8;
1523 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1524 return LinearSearch(name, nof);
1525 }
1526
1527 // Slow case: perform binary search.
1528 return BinarySearch(name, 0, nof - 1);
1529}
1530
1531
Iain Merrick75681382010-08-19 15:07:18 +01001532int DescriptorArray::SearchWithCache(String* name) {
1533 int number = DescriptorLookupCache::Lookup(this, name);
1534 if (number == DescriptorLookupCache::kAbsent) {
1535 number = Search(name);
1536 DescriptorLookupCache::Update(this, name, number);
1537 }
1538 return number;
1539}
1540
1541
Steve Blocka7e24c12009-10-30 11:49:00 +00001542String* DescriptorArray::GetKey(int descriptor_number) {
1543 ASSERT(descriptor_number < number_of_descriptors());
1544 return String::cast(get(ToKeyIndex(descriptor_number)));
1545}
1546
1547
1548Object* DescriptorArray::GetValue(int descriptor_number) {
1549 ASSERT(descriptor_number < number_of_descriptors());
1550 return GetContentArray()->get(ToValueIndex(descriptor_number));
1551}
1552
1553
1554Smi* DescriptorArray::GetDetails(int descriptor_number) {
1555 ASSERT(descriptor_number < number_of_descriptors());
1556 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1557}
1558
1559
1560PropertyType DescriptorArray::GetType(int descriptor_number) {
1561 ASSERT(descriptor_number < number_of_descriptors());
1562 return PropertyDetails(GetDetails(descriptor_number)).type();
1563}
1564
1565
1566int DescriptorArray::GetFieldIndex(int descriptor_number) {
1567 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1568}
1569
1570
1571JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1572 return JSFunction::cast(GetValue(descriptor_number));
1573}
1574
1575
1576Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1577 ASSERT(GetType(descriptor_number) == CALLBACKS);
1578 return GetValue(descriptor_number);
1579}
1580
1581
1582AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1583 ASSERT(GetType(descriptor_number) == CALLBACKS);
1584 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1585 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1586}
1587
1588
1589bool DescriptorArray::IsProperty(int descriptor_number) {
1590 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1591}
1592
1593
1594bool DescriptorArray::IsTransition(int descriptor_number) {
1595 PropertyType t = GetType(descriptor_number);
1596 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1597}
1598
1599
1600bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1601 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1602}
1603
1604
1605bool DescriptorArray::IsDontEnum(int descriptor_number) {
1606 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1607}
1608
1609
1610void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1611 desc->Init(GetKey(descriptor_number),
1612 GetValue(descriptor_number),
1613 GetDetails(descriptor_number));
1614}
1615
1616
1617void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1618 // Range check.
1619 ASSERT(descriptor_number < number_of_descriptors());
1620
Leon Clarkee46be812010-01-19 14:06:41 +00001621 // Make sure none of the elements in desc are in new space.
Steve Blocka7e24c12009-10-30 11:49:00 +00001622 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1623 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1624
1625 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1626 FixedArray* content_array = GetContentArray();
1627 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1628 fast_set(content_array, ToDetailsIndex(descriptor_number),
1629 desc->GetDetails().AsSmi());
1630}
1631
1632
1633void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1634 Descriptor desc;
1635 src->Get(src_index, &desc);
1636 Set(index, &desc);
1637}
1638
1639
1640void DescriptorArray::Swap(int first, int second) {
1641 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1642 FixedArray* content_array = GetContentArray();
1643 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1644 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1645}
1646
1647
1648bool NumberDictionary::requires_slow_elements() {
1649 Object* max_index_object = get(kMaxNumberKeyIndex);
1650 if (!max_index_object->IsSmi()) return false;
1651 return 0 !=
1652 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1653}
1654
1655uint32_t NumberDictionary::max_number_key() {
1656 ASSERT(!requires_slow_elements());
1657 Object* max_index_object = get(kMaxNumberKeyIndex);
1658 if (!max_index_object->IsSmi()) return 0;
1659 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1660 return value >> kRequiresSlowElementsTagSize;
1661}
1662
1663void NumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00001664 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00001665}
1666
1667
1668// ------------------------------------
1669// Cast operations
1670
1671
1672CAST_ACCESSOR(FixedArray)
1673CAST_ACCESSOR(DescriptorArray)
1674CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001675CAST_ACCESSOR(JSFunctionResultCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001676CAST_ACCESSOR(NormalizedMapCache)
Steve Blocka7e24c12009-10-30 11:49:00 +00001677CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001678CAST_ACCESSOR(CodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00001679CAST_ACCESSOR(MapCache)
1680CAST_ACCESSOR(String)
1681CAST_ACCESSOR(SeqString)
1682CAST_ACCESSOR(SeqAsciiString)
1683CAST_ACCESSOR(SeqTwoByteString)
1684CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00001685CAST_ACCESSOR(ExternalString)
1686CAST_ACCESSOR(ExternalAsciiString)
1687CAST_ACCESSOR(ExternalTwoByteString)
1688CAST_ACCESSOR(JSObject)
1689CAST_ACCESSOR(Smi)
1690CAST_ACCESSOR(Failure)
1691CAST_ACCESSOR(HeapObject)
1692CAST_ACCESSOR(HeapNumber)
1693CAST_ACCESSOR(Oddball)
1694CAST_ACCESSOR(JSGlobalPropertyCell)
1695CAST_ACCESSOR(SharedFunctionInfo)
1696CAST_ACCESSOR(Map)
1697CAST_ACCESSOR(JSFunction)
1698CAST_ACCESSOR(GlobalObject)
1699CAST_ACCESSOR(JSGlobalProxy)
1700CAST_ACCESSOR(JSGlobalObject)
1701CAST_ACCESSOR(JSBuiltinsObject)
1702CAST_ACCESSOR(Code)
1703CAST_ACCESSOR(JSArray)
1704CAST_ACCESSOR(JSRegExp)
1705CAST_ACCESSOR(Proxy)
1706CAST_ACCESSOR(ByteArray)
1707CAST_ACCESSOR(PixelArray)
Steve Block3ce2e202009-11-05 08:53:23 +00001708CAST_ACCESSOR(ExternalArray)
1709CAST_ACCESSOR(ExternalByteArray)
1710CAST_ACCESSOR(ExternalUnsignedByteArray)
1711CAST_ACCESSOR(ExternalShortArray)
1712CAST_ACCESSOR(ExternalUnsignedShortArray)
1713CAST_ACCESSOR(ExternalIntArray)
1714CAST_ACCESSOR(ExternalUnsignedIntArray)
1715CAST_ACCESSOR(ExternalFloatArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00001716CAST_ACCESSOR(Struct)
1717
1718
1719#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1720 STRUCT_LIST(MAKE_STRUCT_CAST)
1721#undef MAKE_STRUCT_CAST
1722
1723
1724template <typename Shape, typename Key>
1725HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1726 ASSERT(obj->IsHashTable());
1727 return reinterpret_cast<HashTable*>(obj);
1728}
1729
1730
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001731SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1732SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1733
1734INT_ACCESSORS(PixelArray, length, kLengthOffset)
1735INT_ACCESSORS(ExternalArray, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00001736
1737
Steve Block6ded16b2010-05-10 14:33:55 +01001738SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00001739
1740
1741uint32_t String::hash_field() {
1742 return READ_UINT32_FIELD(this, kHashFieldOffset);
1743}
1744
1745
1746void String::set_hash_field(uint32_t value) {
1747 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001748#if V8_HOST_ARCH_64_BIT
1749 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1750#endif
Steve Blockd0582a62009-12-15 09:54:21 +00001751}
1752
1753
Steve Blocka7e24c12009-10-30 11:49:00 +00001754bool String::Equals(String* other) {
1755 if (other == this) return true;
1756 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1757 return false;
1758 }
1759 return SlowEquals(other);
1760}
1761
1762
Steve Block6ded16b2010-05-10 14:33:55 +01001763Object* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001764 if (!StringShape(this).IsCons()) return this;
1765 ConsString* cons = ConsString::cast(this);
1766 if (cons->second()->length() == 0) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01001767 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00001768}
1769
1770
Leon Clarkef7060e22010-06-03 12:02:55 +01001771String* String::TryFlattenGetString(PretenureFlag pretenure) {
1772 Object* flat = TryFlatten(pretenure);
1773 return flat->IsFailure() ? this : String::cast(flat);
1774}
1775
1776
Steve Blocka7e24c12009-10-30 11:49:00 +00001777uint16_t String::Get(int index) {
1778 ASSERT(index >= 0 && index < length());
1779 switch (StringShape(this).full_representation_tag()) {
1780 case kSeqStringTag | kAsciiStringTag:
1781 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1782 case kSeqStringTag | kTwoByteStringTag:
1783 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1784 case kConsStringTag | kAsciiStringTag:
1785 case kConsStringTag | kTwoByteStringTag:
1786 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001787 case kExternalStringTag | kAsciiStringTag:
1788 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1789 case kExternalStringTag | kTwoByteStringTag:
1790 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1791 default:
1792 break;
1793 }
1794
1795 UNREACHABLE();
1796 return 0;
1797}
1798
1799
1800void String::Set(int index, uint16_t value) {
1801 ASSERT(index >= 0 && index < length());
1802 ASSERT(StringShape(this).IsSequential());
1803
1804 return this->IsAsciiRepresentation()
1805 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1806 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1807}
1808
1809
1810bool String::IsFlat() {
1811 switch (StringShape(this).representation_tag()) {
1812 case kConsStringTag: {
1813 String* second = ConsString::cast(this)->second();
1814 // Only flattened strings have second part empty.
1815 return second->length() == 0;
1816 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001817 default:
1818 return true;
1819 }
1820}
1821
1822
1823uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1824 ASSERT(index >= 0 && index < length());
1825 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1826}
1827
1828
1829void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1830 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1831 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1832 static_cast<byte>(value));
1833}
1834
1835
1836Address SeqAsciiString::GetCharsAddress() {
1837 return FIELD_ADDR(this, kHeaderSize);
1838}
1839
1840
1841char* SeqAsciiString::GetChars() {
1842 return reinterpret_cast<char*>(GetCharsAddress());
1843}
1844
1845
1846Address SeqTwoByteString::GetCharsAddress() {
1847 return FIELD_ADDR(this, kHeaderSize);
1848}
1849
1850
1851uc16* SeqTwoByteString::GetChars() {
1852 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1853}
1854
1855
1856uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1857 ASSERT(index >= 0 && index < length());
1858 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1859}
1860
1861
1862void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1863 ASSERT(index >= 0 && index < length());
1864 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1865}
1866
1867
1868int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001869 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001870}
1871
1872
1873int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001874 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001875}
1876
1877
1878String* ConsString::first() {
1879 return String::cast(READ_FIELD(this, kFirstOffset));
1880}
1881
1882
1883Object* ConsString::unchecked_first() {
1884 return READ_FIELD(this, kFirstOffset);
1885}
1886
1887
1888void ConsString::set_first(String* value, WriteBarrierMode mode) {
1889 WRITE_FIELD(this, kFirstOffset, value);
1890 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1891}
1892
1893
1894String* ConsString::second() {
1895 return String::cast(READ_FIELD(this, kSecondOffset));
1896}
1897
1898
1899Object* ConsString::unchecked_second() {
1900 return READ_FIELD(this, kSecondOffset);
1901}
1902
1903
1904void ConsString::set_second(String* value, WriteBarrierMode mode) {
1905 WRITE_FIELD(this, kSecondOffset, value);
1906 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1907}
1908
1909
Steve Blocka7e24c12009-10-30 11:49:00 +00001910ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1911 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1912}
1913
1914
1915void ExternalAsciiString::set_resource(
1916 ExternalAsciiString::Resource* resource) {
1917 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1918}
1919
1920
Steve Blocka7e24c12009-10-30 11:49:00 +00001921ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1922 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1923}
1924
1925
1926void ExternalTwoByteString::set_resource(
1927 ExternalTwoByteString::Resource* resource) {
1928 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1929}
1930
1931
Steve Block6ded16b2010-05-10 14:33:55 +01001932void JSFunctionResultCache::MakeZeroSize() {
1933 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1934 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1935}
1936
1937
1938void JSFunctionResultCache::Clear() {
1939 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1940 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1941 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1942 MakeZeroSize();
1943}
1944
1945
Steve Blocka7e24c12009-10-30 11:49:00 +00001946byte ByteArray::get(int index) {
1947 ASSERT(index >= 0 && index < this->length());
1948 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1949}
1950
1951
1952void ByteArray::set(int index, byte value) {
1953 ASSERT(index >= 0 && index < this->length());
1954 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1955}
1956
1957
1958int ByteArray::get_int(int index) {
1959 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1960 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1961}
1962
1963
1964ByteArray* ByteArray::FromDataStartAddress(Address address) {
1965 ASSERT_TAG_ALIGNED(address);
1966 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1967}
1968
1969
1970Address ByteArray::GetDataStartAddress() {
1971 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1972}
1973
1974
1975uint8_t* PixelArray::external_pointer() {
1976 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1977 return reinterpret_cast<uint8_t*>(ptr);
1978}
1979
1980
1981void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1982 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1983 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1984}
1985
1986
1987uint8_t PixelArray::get(int index) {
1988 ASSERT((index >= 0) && (index < this->length()));
1989 uint8_t* ptr = external_pointer();
1990 return ptr[index];
1991}
1992
1993
1994void PixelArray::set(int index, uint8_t value) {
1995 ASSERT((index >= 0) && (index < this->length()));
1996 uint8_t* ptr = external_pointer();
1997 ptr[index] = value;
1998}
1999
2000
Steve Block3ce2e202009-11-05 08:53:23 +00002001void* ExternalArray::external_pointer() {
2002 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2003 return reinterpret_cast<void*>(ptr);
2004}
2005
2006
2007void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2008 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2009 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2010}
2011
2012
2013int8_t ExternalByteArray::get(int index) {
2014 ASSERT((index >= 0) && (index < this->length()));
2015 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2016 return ptr[index];
2017}
2018
2019
2020void ExternalByteArray::set(int index, int8_t value) {
2021 ASSERT((index >= 0) && (index < this->length()));
2022 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2023 ptr[index] = value;
2024}
2025
2026
2027uint8_t ExternalUnsignedByteArray::get(int index) {
2028 ASSERT((index >= 0) && (index < this->length()));
2029 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2030 return ptr[index];
2031}
2032
2033
2034void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2035 ASSERT((index >= 0) && (index < this->length()));
2036 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2037 ptr[index] = value;
2038}
2039
2040
2041int16_t ExternalShortArray::get(int index) {
2042 ASSERT((index >= 0) && (index < this->length()));
2043 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2044 return ptr[index];
2045}
2046
2047
2048void ExternalShortArray::set(int index, int16_t value) {
2049 ASSERT((index >= 0) && (index < this->length()));
2050 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2051 ptr[index] = value;
2052}
2053
2054
2055uint16_t ExternalUnsignedShortArray::get(int index) {
2056 ASSERT((index >= 0) && (index < this->length()));
2057 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2058 return ptr[index];
2059}
2060
2061
2062void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2063 ASSERT((index >= 0) && (index < this->length()));
2064 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2065 ptr[index] = value;
2066}
2067
2068
2069int32_t ExternalIntArray::get(int index) {
2070 ASSERT((index >= 0) && (index < this->length()));
2071 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2072 return ptr[index];
2073}
2074
2075
2076void ExternalIntArray::set(int index, int32_t value) {
2077 ASSERT((index >= 0) && (index < this->length()));
2078 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2079 ptr[index] = value;
2080}
2081
2082
2083uint32_t ExternalUnsignedIntArray::get(int index) {
2084 ASSERT((index >= 0) && (index < this->length()));
2085 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2086 return ptr[index];
2087}
2088
2089
2090void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2091 ASSERT((index >= 0) && (index < this->length()));
2092 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2093 ptr[index] = value;
2094}
2095
2096
2097float ExternalFloatArray::get(int index) {
2098 ASSERT((index >= 0) && (index < this->length()));
2099 float* ptr = static_cast<float*>(external_pointer());
2100 return ptr[index];
2101}
2102
2103
2104void ExternalFloatArray::set(int index, float value) {
2105 ASSERT((index >= 0) && (index < this->length()));
2106 float* ptr = static_cast<float*>(external_pointer());
2107 ptr[index] = value;
2108}
2109
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002110
Iain Merrick9ac36c92010-09-13 15:29:50 +01002111int Map::visitor_id() {
2112 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2113}
2114
2115
2116void Map::set_visitor_id(int id) {
2117 ASSERT(0 <= id && id < 256);
2118 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2119}
2120
Steve Block3ce2e202009-11-05 08:53:23 +00002121
Steve Blocka7e24c12009-10-30 11:49:00 +00002122int Map::instance_size() {
2123 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2124}
2125
2126
2127int Map::inobject_properties() {
2128 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2129}
2130
2131
2132int Map::pre_allocated_property_fields() {
2133 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2134}
2135
2136
2137int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01002138 int instance_size = map->instance_size();
2139 if (instance_size != kVariableSizeSentinel) return instance_size;
2140 // We can ignore the "symbol" bit becase it is only set for symbols
2141 // and implies a string type.
2142 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002143 // Only inline the most frequent cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00002144 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002145 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002146 }
Steve Block791712a2010-08-27 10:21:07 +01002147 if (instance_type == ASCII_STRING_TYPE) {
2148 return SeqAsciiString::SizeFor(
2149 reinterpret_cast<SeqAsciiString*>(this)->length());
2150 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002151 if (instance_type == BYTE_ARRAY_TYPE) {
2152 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2153 }
Steve Block791712a2010-08-27 10:21:07 +01002154 if (instance_type == STRING_TYPE) {
2155 return SeqTwoByteString::SizeFor(
2156 reinterpret_cast<SeqTwoByteString*>(this)->length());
2157 }
2158 ASSERT(instance_type == CODE_TYPE);
2159 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00002160}
2161
2162
2163void Map::set_instance_size(int value) {
2164 ASSERT_EQ(0, value & (kPointerSize - 1));
2165 value >>= kPointerSizeLog2;
2166 ASSERT(0 <= value && value < 256);
2167 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2168}
2169
2170
2171void Map::set_inobject_properties(int value) {
2172 ASSERT(0 <= value && value < 256);
2173 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2174}
2175
2176
2177void Map::set_pre_allocated_property_fields(int value) {
2178 ASSERT(0 <= value && value < 256);
2179 WRITE_BYTE_FIELD(this,
2180 kPreAllocatedPropertyFieldsOffset,
2181 static_cast<byte>(value));
2182}
2183
2184
2185InstanceType Map::instance_type() {
2186 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2187}
2188
2189
2190void Map::set_instance_type(InstanceType value) {
2191 ASSERT(0 <= value && value < 256);
2192 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2193}
2194
2195
2196int Map::unused_property_fields() {
2197 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2198}
2199
2200
2201void Map::set_unused_property_fields(int value) {
2202 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2203}
2204
2205
2206byte Map::bit_field() {
2207 return READ_BYTE_FIELD(this, kBitFieldOffset);
2208}
2209
2210
2211void Map::set_bit_field(byte value) {
2212 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2213}
2214
2215
2216byte Map::bit_field2() {
2217 return READ_BYTE_FIELD(this, kBitField2Offset);
2218}
2219
2220
2221void Map::set_bit_field2(byte value) {
2222 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2223}
2224
2225
2226void Map::set_non_instance_prototype(bool value) {
2227 if (value) {
2228 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2229 } else {
2230 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2231 }
2232}
2233
2234
2235bool Map::has_non_instance_prototype() {
2236 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2237}
2238
2239
Steve Block6ded16b2010-05-10 14:33:55 +01002240void Map::set_function_with_prototype(bool value) {
2241 if (value) {
2242 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2243 } else {
2244 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2245 }
2246}
2247
2248
2249bool Map::function_with_prototype() {
2250 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2251}
2252
2253
Steve Blocka7e24c12009-10-30 11:49:00 +00002254void Map::set_is_access_check_needed(bool access_check_needed) {
2255 if (access_check_needed) {
2256 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2257 } else {
2258 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2259 }
2260}
2261
2262
2263bool Map::is_access_check_needed() {
2264 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2265}
2266
2267
Steve Block8defd9f2010-07-08 12:39:36 +01002268void Map::set_is_extensible(bool value) {
2269 if (value) {
2270 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2271 } else {
2272 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2273 }
2274}
2275
2276bool Map::is_extensible() {
2277 return ((1 << kIsExtensible) & bit_field2()) != 0;
2278}
2279
2280
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002281void Map::set_attached_to_shared_function_info(bool value) {
2282 if (value) {
2283 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2284 } else {
2285 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2286 }
2287}
2288
2289bool Map::attached_to_shared_function_info() {
2290 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2291}
2292
2293
2294void Map::set_is_shared(bool value) {
2295 if (value) {
2296 set_bit_field2(bit_field2() | (1 << kIsShared));
2297 } else {
2298 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2299 }
2300}
2301
2302bool Map::is_shared() {
2303 return ((1 << kIsShared) & bit_field2()) != 0;
2304}
2305
2306
2307JSFunction* Map::unchecked_constructor() {
2308 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2309}
2310
Steve Block8defd9f2010-07-08 12:39:36 +01002311
Steve Blocka7e24c12009-10-30 11:49:00 +00002312Code::Flags Code::flags() {
2313 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2314}
2315
2316
2317void Code::set_flags(Code::Flags flags) {
2318 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2319 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002320 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2321 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002322 ExtractArgumentsCountFromFlags(flags) >= 0);
2323 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2324}
2325
2326
2327Code::Kind Code::kind() {
2328 return ExtractKindFromFlags(flags());
2329}
2330
2331
2332InLoopFlag Code::ic_in_loop() {
2333 return ExtractICInLoopFromFlags(flags());
2334}
2335
2336
2337InlineCacheState Code::ic_state() {
2338 InlineCacheState result = ExtractICStateFromFlags(flags());
2339 // Only allow uninitialized or debugger states for non-IC code
2340 // objects. This is used in the debugger to determine whether or not
2341 // a call to code object has been replaced with a debug break call.
2342 ASSERT(is_inline_cache_stub() ||
2343 result == UNINITIALIZED ||
2344 result == DEBUG_BREAK ||
2345 result == DEBUG_PREPARE_STEP_IN);
2346 return result;
2347}
2348
2349
2350PropertyType Code::type() {
2351 ASSERT(ic_state() == MONOMORPHIC);
2352 return ExtractTypeFromFlags(flags());
2353}
2354
2355
2356int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002357 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002358 return ExtractArgumentsCountFromFlags(flags());
2359}
2360
2361
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002362int Code::major_key() {
Steve Block6ded16b2010-05-10 14:33:55 +01002363 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002364 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00002365}
2366
2367
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002368void Code::set_major_key(int major) {
Steve Block6ded16b2010-05-10 14:33:55 +01002369 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002370 ASSERT(0 <= major && major < 256);
2371 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2372}
2373
2374
2375bool Code::is_inline_cache_stub() {
2376 Kind kind = this->kind();
2377 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2378}
2379
2380
2381Code::Flags Code::ComputeFlags(Kind kind,
2382 InLoopFlag in_loop,
2383 InlineCacheState ic_state,
2384 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002385 int argc,
2386 InlineCacheHolderFlag holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002387 // Compute the bit mask.
2388 int bits = kind << kFlagsKindShift;
2389 if (in_loop) bits |= kFlagsICInLoopMask;
2390 bits |= ic_state << kFlagsICStateShift;
2391 bits |= type << kFlagsTypeShift;
2392 bits |= argc << kFlagsArgumentsCountShift;
Steve Block8defd9f2010-07-08 12:39:36 +01002393 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002394 // Cast to flags and validate result before returning it.
2395 Flags result = static_cast<Flags>(bits);
2396 ASSERT(ExtractKindFromFlags(result) == kind);
2397 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2398 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2399 ASSERT(ExtractTypeFromFlags(result) == type);
2400 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2401 return result;
2402}
2403
2404
2405Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2406 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002407 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00002408 InLoopFlag in_loop,
2409 int argc) {
Steve Block8defd9f2010-07-08 12:39:36 +01002410 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00002411}
2412
2413
2414Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2415 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2416 return static_cast<Kind>(bits);
2417}
2418
2419
2420InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2421 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2422 return static_cast<InlineCacheState>(bits);
2423}
2424
2425
2426InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2427 int bits = (flags & kFlagsICInLoopMask);
2428 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2429}
2430
2431
2432PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2433 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2434 return static_cast<PropertyType>(bits);
2435}
2436
2437
2438int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2439 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2440}
2441
2442
Steve Block8defd9f2010-07-08 12:39:36 +01002443InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2444 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2445 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2446}
2447
2448
Steve Blocka7e24c12009-10-30 11:49:00 +00002449Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2450 int bits = flags & ~kFlagsTypeMask;
2451 return static_cast<Flags>(bits);
2452}
2453
2454
2455Code* Code::GetCodeFromTargetAddress(Address address) {
2456 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2457 // GetCodeFromTargetAddress might be called when marking objects during mark
2458 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2459 // Code::cast. Code::cast does not work when the object's map is
2460 // marked.
2461 Code* result = reinterpret_cast<Code*>(code);
2462 return result;
2463}
2464
2465
Steve Block791712a2010-08-27 10:21:07 +01002466Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2467 return HeapObject::
2468 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2469}
2470
2471
Steve Blocka7e24c12009-10-30 11:49:00 +00002472Object* Map::prototype() {
2473 return READ_FIELD(this, kPrototypeOffset);
2474}
2475
2476
2477void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2478 ASSERT(value->IsNull() || value->IsJSObject());
2479 WRITE_FIELD(this, kPrototypeOffset, value);
2480 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2481}
2482
2483
Steve Block8defd9f2010-07-08 12:39:36 +01002484Object* Map::GetFastElementsMap() {
2485 if (has_fast_elements()) return this;
2486 Object* obj = CopyDropTransitions();
2487 if (obj->IsFailure()) return obj;
2488 Map* new_map = Map::cast(obj);
2489 new_map->set_has_fast_elements(true);
Iain Merrick75681382010-08-19 15:07:18 +01002490 Counters::map_slow_to_fast_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002491 return new_map;
2492}
2493
2494
2495Object* Map::GetSlowElementsMap() {
2496 if (!has_fast_elements()) return this;
2497 Object* obj = CopyDropTransitions();
2498 if (obj->IsFailure()) return obj;
2499 Map* new_map = Map::cast(obj);
2500 new_map->set_has_fast_elements(false);
Iain Merrick75681382010-08-19 15:07:18 +01002501 Counters::map_fast_to_slow_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002502 return new_map;
2503}
2504
2505
Steve Blocka7e24c12009-10-30 11:49:00 +00002506ACCESSORS(Map, instance_descriptors, DescriptorArray,
2507 kInstanceDescriptorsOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002508ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002509ACCESSORS(Map, constructor, Object, kConstructorOffset)
2510
2511ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2512ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2513
2514ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2515ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2516ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2517
2518ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2519
2520ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2521ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2522ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2523ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2524ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002525ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002526
2527ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2528ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2529ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2530
2531ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2532ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2533ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2534ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2535ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2536ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2537
2538ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2539ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2540
2541ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2542ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2543
2544ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2545ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2546ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2547 kPropertyAccessorsOffset)
2548ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2549 kPrototypeTemplateOffset)
2550ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2551ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2552 kNamedPropertyHandlerOffset)
2553ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2554 kIndexedPropertyHandlerOffset)
2555ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2556 kInstanceTemplateOffset)
2557ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2558ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2559ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2560 kInstanceCallHandlerOffset)
2561ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2562 kAccessCheckInfoOffset)
2563ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2564
2565ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2566ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2567 kInternalFieldCountOffset)
2568
2569ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2570ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2571
2572ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2573
2574ACCESSORS(Script, source, Object, kSourceOffset)
2575ACCESSORS(Script, name, Object, kNameOffset)
2576ACCESSORS(Script, id, Object, kIdOffset)
2577ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2578ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2579ACCESSORS(Script, data, Object, kDataOffset)
2580ACCESSORS(Script, context_data, Object, kContextOffset)
2581ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2582ACCESSORS(Script, type, Smi, kTypeOffset)
2583ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2584ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002585ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002586ACCESSORS(Script, eval_from_instructions_offset, Smi,
2587 kEvalFrominstructionsOffsetOffset)
2588
2589#ifdef ENABLE_DEBUGGER_SUPPORT
2590ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2591ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2592ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2593ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2594
2595ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2596ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2597ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2598ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2599#endif
2600
Steve Blocka7e24c12009-10-30 11:49:00 +00002601ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002602ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002603ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002604ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2605 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002606ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002607ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2608ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2609ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2610ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2611 kThisPropertyAssignmentsOffset)
2612
2613BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2614 kHiddenPrototypeBit)
2615BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2616BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2617 kNeedsAccessCheckBit)
2618BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2619 kIsExpressionBit)
2620BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2621 kIsTopLevelBit)
2622BOOL_GETTER(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002623 has_only_simple_this_property_assignments,
2624 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00002625BOOL_ACCESSORS(SharedFunctionInfo,
2626 compiler_hints,
Leon Clarked91b9f72010-01-27 17:25:45 +00002627 try_full_codegen,
2628 kTryFullCodegen)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002629BOOL_ACCESSORS(SharedFunctionInfo,
2630 compiler_hints,
2631 allows_lazy_compilation,
2632 kAllowLazyCompilation)
Steve Blocka7e24c12009-10-30 11:49:00 +00002633
Iain Merrick75681382010-08-19 15:07:18 +01002634
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002635#if V8_HOST_ARCH_32_BIT
2636SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2637SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002638 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002639SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00002640 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002641SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2642SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00002643 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002644SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2645SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00002646 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002647SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002648 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002649SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002650 kThisPropertyAssignmentsCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002651#else
Steve Blocka7e24c12009-10-30 11:49:00 +00002652
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002653#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2654 int holder::name() { \
2655 int value = READ_INT_FIELD(this, offset); \
2656 ASSERT(kHeapObjectTag == 1); \
2657 ASSERT((value & kHeapObjectTag) == 0); \
2658 return value >> 1; \
2659 } \
2660 void holder::set_##name(int value) { \
2661 ASSERT(kHeapObjectTag == 1); \
2662 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2663 (value & 0xC0000000) == 0x000000000); \
2664 WRITE_INT_FIELD(this, \
2665 offset, \
2666 (value << 1) & ~kHeapObjectTag); \
2667 }
2668
2669#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2670 INT_ACCESSORS(holder, name, offset)
2671
2672
2673
2674PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2675PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2676 kFormalParameterCountOffset)
2677
2678PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2679 kExpectedNofPropertiesOffset)
2680PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2681
2682PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2683 kStartPositionAndTypeOffset)
2684PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2685
2686PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2687 kFunctionTokenPositionOffset)
2688PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2689 kCompilerHintsOffset)
2690
2691PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2692 kThisPropertyAssignmentsCountOffset)
2693#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002694
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002695
2696int SharedFunctionInfo::construction_count() {
2697 return READ_BYTE_FIELD(this, kConstructionCountOffset);
2698}
2699
2700
2701void SharedFunctionInfo::set_construction_count(int value) {
2702 ASSERT(0 <= value && value < 256);
2703 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
2704}
2705
2706
2707bool SharedFunctionInfo::live_objects_may_exist() {
2708 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
2709}
2710
2711
2712void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
2713 if (value) {
2714 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
2715 } else {
2716 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
2717 }
2718}
2719
2720
2721bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
2722 return initial_map() != Heap::undefined_value();
2723}
2724
2725
Steve Block6ded16b2010-05-10 14:33:55 +01002726ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2727ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2728
Steve Block3ce2e202009-11-05 08:53:23 +00002729bool Script::HasValidSource() {
2730 Object* src = this->source();
2731 if (!src->IsString()) return true;
2732 String* src_str = String::cast(src);
2733 if (!StringShape(src_str).IsExternal()) return true;
2734 if (src_str->IsAsciiRepresentation()) {
2735 return ExternalAsciiString::cast(src)->resource() != NULL;
2736 } else if (src_str->IsTwoByteRepresentation()) {
2737 return ExternalTwoByteString::cast(src)->resource() != NULL;
2738 }
2739 return true;
2740}
2741
2742
Steve Blocka7e24c12009-10-30 11:49:00 +00002743void SharedFunctionInfo::DontAdaptArguments() {
2744 ASSERT(code()->kind() == Code::BUILTIN);
2745 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2746}
2747
2748
2749int SharedFunctionInfo::start_position() {
2750 return start_position_and_type() >> kStartPositionShift;
2751}
2752
2753
2754void SharedFunctionInfo::set_start_position(int start_position) {
2755 set_start_position_and_type((start_position << kStartPositionShift)
2756 | (start_position_and_type() & ~kStartPositionMask));
2757}
2758
2759
2760Code* SharedFunctionInfo::code() {
2761 return Code::cast(READ_FIELD(this, kCodeOffset));
2762}
2763
2764
Iain Merrick75681382010-08-19 15:07:18 +01002765Code* SharedFunctionInfo::unchecked_code() {
2766 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2767}
2768
2769
Steve Blocka7e24c12009-10-30 11:49:00 +00002770void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2771 WRITE_FIELD(this, kCodeOffset, value);
2772 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2773}
2774
2775
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002776SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2777 return reinterpret_cast<SerializedScopeInfo*>(
2778 READ_FIELD(this, kScopeInfoOffset));
2779}
2780
2781
2782void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2783 WriteBarrierMode mode) {
2784 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2785 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2786}
2787
2788
Steve Blocka7e24c12009-10-30 11:49:00 +00002789bool SharedFunctionInfo::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01002790 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00002791}
2792
2793
Steve Block6ded16b2010-05-10 14:33:55 +01002794bool SharedFunctionInfo::IsApiFunction() {
2795 return function_data()->IsFunctionTemplateInfo();
2796}
2797
2798
2799FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2800 ASSERT(IsApiFunction());
2801 return FunctionTemplateInfo::cast(function_data());
2802}
2803
2804
2805bool SharedFunctionInfo::HasCustomCallGenerator() {
Kristian Monsen25f61362010-05-21 11:50:48 +01002806 return function_data()->IsSmi();
2807}
2808
2809
2810int SharedFunctionInfo::custom_call_generator_id() {
2811 ASSERT(HasCustomCallGenerator());
2812 return Smi::cast(function_data())->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002813}
2814
2815
Iain Merrick75681382010-08-19 15:07:18 +01002816int SharedFunctionInfo::code_age() {
2817 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
2818}
2819
2820
2821void SharedFunctionInfo::set_code_age(int code_age) {
2822 set_compiler_hints(compiler_hints() |
2823 ((code_age & kCodeAgeMask) << kCodeAgeShift));
2824}
2825
2826
Steve Blocka7e24c12009-10-30 11:49:00 +00002827bool JSFunction::IsBuiltin() {
2828 return context()->global()->IsJSBuiltinsObject();
2829}
2830
2831
Steve Blocka7e24c12009-10-30 11:49:00 +00002832Code* JSFunction::code() {
Steve Block791712a2010-08-27 10:21:07 +01002833 return Code::cast(unchecked_code());
Iain Merrick75681382010-08-19 15:07:18 +01002834}
2835
2836
2837Code* JSFunction::unchecked_code() {
Steve Block791712a2010-08-27 10:21:07 +01002838 return reinterpret_cast<Code*>(
2839 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002840}
2841
2842
2843void JSFunction::set_code(Code* value) {
Iain Merrick75681382010-08-19 15:07:18 +01002844 // Skip the write barrier because code is never in new space.
2845 ASSERT(!Heap::InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01002846 Address entry = value->entry();
2847 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Steve Blocka7e24c12009-10-30 11:49:00 +00002848}
2849
2850
2851Context* JSFunction::context() {
2852 return Context::cast(READ_FIELD(this, kContextOffset));
2853}
2854
2855
2856Object* JSFunction::unchecked_context() {
2857 return READ_FIELD(this, kContextOffset);
2858}
2859
2860
Iain Merrick75681382010-08-19 15:07:18 +01002861SharedFunctionInfo* JSFunction::unchecked_shared() {
2862 return reinterpret_cast<SharedFunctionInfo*>(
2863 READ_FIELD(this, kSharedFunctionInfoOffset));
2864}
2865
2866
Steve Blocka7e24c12009-10-30 11:49:00 +00002867void JSFunction::set_context(Object* value) {
2868 ASSERT(value == Heap::undefined_value() || value->IsContext());
2869 WRITE_FIELD(this, kContextOffset, value);
2870 WRITE_BARRIER(this, kContextOffset);
2871}
2872
2873ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2874 kPrototypeOrInitialMapOffset)
2875
2876
2877Map* JSFunction::initial_map() {
2878 return Map::cast(prototype_or_initial_map());
2879}
2880
2881
2882void JSFunction::set_initial_map(Map* value) {
2883 set_prototype_or_initial_map(value);
2884}
2885
2886
2887bool JSFunction::has_initial_map() {
2888 return prototype_or_initial_map()->IsMap();
2889}
2890
2891
2892bool JSFunction::has_instance_prototype() {
2893 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2894}
2895
2896
2897bool JSFunction::has_prototype() {
2898 return map()->has_non_instance_prototype() || has_instance_prototype();
2899}
2900
2901
2902Object* JSFunction::instance_prototype() {
2903 ASSERT(has_instance_prototype());
2904 if (has_initial_map()) return initial_map()->prototype();
2905 // When there is no initial map and the prototype is a JSObject, the
2906 // initial map field is used for the prototype field.
2907 return prototype_or_initial_map();
2908}
2909
2910
2911Object* JSFunction::prototype() {
2912 ASSERT(has_prototype());
2913 // If the function's prototype property has been set to a non-JSObject
2914 // value, that value is stored in the constructor field of the map.
2915 if (map()->has_non_instance_prototype()) return map()->constructor();
2916 return instance_prototype();
2917}
2918
Steve Block6ded16b2010-05-10 14:33:55 +01002919bool JSFunction::should_have_prototype() {
2920 return map()->function_with_prototype();
2921}
2922
Steve Blocka7e24c12009-10-30 11:49:00 +00002923
2924bool JSFunction::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01002925 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00002926}
2927
2928
2929int JSFunction::NumberOfLiterals() {
2930 return literals()->length();
2931}
2932
2933
2934Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2935 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002936 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00002937}
2938
2939
2940void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2941 Object* value) {
2942 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002943 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2944 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2945}
2946
2947
2948Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2949 ASSERT(0 <= id && id < kJSBuiltinsCount);
2950 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2951}
2952
2953
2954void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2955 Code* value) {
2956 ASSERT(0 <= id && id < kJSBuiltinsCount);
2957 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2958 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002959}
2960
2961
2962Address Proxy::proxy() {
2963 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2964}
2965
2966
2967void Proxy::set_proxy(Address value) {
2968 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2969}
2970
2971
Steve Blocka7e24c12009-10-30 11:49:00 +00002972ACCESSORS(JSValue, value, Object, kValueOffset)
2973
2974
2975JSValue* JSValue::cast(Object* obj) {
2976 ASSERT(obj->IsJSValue());
2977 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2978 return reinterpret_cast<JSValue*>(obj);
2979}
2980
2981
2982INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01002983ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002984
2985
2986byte* Code::instruction_start() {
2987 return FIELD_ADDR(this, kHeaderSize);
2988}
2989
2990
Leon Clarkeac952652010-07-15 11:15:24 +01002991byte* Code::instruction_end() {
2992 return instruction_start() + instruction_size();
2993}
2994
2995
Steve Blocka7e24c12009-10-30 11:49:00 +00002996int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01002997 return RoundUp(instruction_size(), kObjectAlignment);
2998}
2999
3000
3001ByteArray* Code::unchecked_relocation_info() {
3002 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00003003}
3004
3005
3006byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01003007 return unchecked_relocation_info()->GetDataStartAddress();
3008}
3009
3010
3011int Code::relocation_size() {
3012 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00003013}
3014
3015
3016byte* Code::entry() {
3017 return instruction_start();
3018}
3019
3020
3021bool Code::contains(byte* pc) {
3022 return (instruction_start() <= pc) &&
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003023 (pc <= instruction_start() + instruction_size());
Steve Blocka7e24c12009-10-30 11:49:00 +00003024}
3025
3026
Steve Blocka7e24c12009-10-30 11:49:00 +00003027ACCESSORS(JSArray, length, Object, kLengthOffset)
3028
3029
3030ACCESSORS(JSRegExp, data, Object, kDataOffset)
3031
3032
3033JSRegExp::Type JSRegExp::TypeTag() {
3034 Object* data = this->data();
3035 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3036 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3037 return static_cast<JSRegExp::Type>(smi->value());
3038}
3039
3040
3041int JSRegExp::CaptureCount() {
3042 switch (TypeTag()) {
3043 case ATOM:
3044 return 0;
3045 case IRREGEXP:
3046 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3047 default:
3048 UNREACHABLE();
3049 return -1;
3050 }
3051}
3052
3053
3054JSRegExp::Flags JSRegExp::GetFlags() {
3055 ASSERT(this->data()->IsFixedArray());
3056 Object* data = this->data();
3057 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3058 return Flags(smi->value());
3059}
3060
3061
3062String* JSRegExp::Pattern() {
3063 ASSERT(this->data()->IsFixedArray());
3064 Object* data = this->data();
3065 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3066 return pattern;
3067}
3068
3069
3070Object* JSRegExp::DataAt(int index) {
3071 ASSERT(TypeTag() != NOT_COMPILED);
3072 return FixedArray::cast(data())->get(index);
3073}
3074
3075
3076void JSRegExp::SetDataAt(int index, Object* value) {
3077 ASSERT(TypeTag() != NOT_COMPILED);
3078 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3079 FixedArray::cast(data())->set(index, value);
3080}
3081
3082
3083JSObject::ElementsKind JSObject::GetElementsKind() {
Iain Merrick75681382010-08-19 15:07:18 +01003084 if (map()->has_fast_elements()) {
3085 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3086 elements()->map() == Heap::fixed_cow_array_map());
3087 return FAST_ELEMENTS;
3088 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003089 HeapObject* array = elements();
Steve Blocka7e24c12009-10-30 11:49:00 +00003090 if (array->IsFixedArray()) {
Iain Merrick75681382010-08-19 15:07:18 +01003091 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3092 // FixedArray, but FAST_ELEMENTS is already handled above.
Steve Blocka7e24c12009-10-30 11:49:00 +00003093 ASSERT(array->IsDictionary());
3094 return DICTIONARY_ELEMENTS;
3095 }
Steve Block3ce2e202009-11-05 08:53:23 +00003096 if (array->IsExternalArray()) {
3097 switch (array->map()->instance_type()) {
3098 case EXTERNAL_BYTE_ARRAY_TYPE:
3099 return EXTERNAL_BYTE_ELEMENTS;
3100 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3101 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3102 case EXTERNAL_SHORT_ARRAY_TYPE:
3103 return EXTERNAL_SHORT_ELEMENTS;
3104 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3105 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3106 case EXTERNAL_INT_ARRAY_TYPE:
3107 return EXTERNAL_INT_ELEMENTS;
3108 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3109 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3110 default:
3111 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3112 return EXTERNAL_FLOAT_ELEMENTS;
3113 }
3114 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003115 ASSERT(array->IsPixelArray());
3116 return PIXEL_ELEMENTS;
3117}
3118
3119
3120bool JSObject::HasFastElements() {
3121 return GetElementsKind() == FAST_ELEMENTS;
3122}
3123
3124
3125bool JSObject::HasDictionaryElements() {
3126 return GetElementsKind() == DICTIONARY_ELEMENTS;
3127}
3128
3129
3130bool JSObject::HasPixelElements() {
3131 return GetElementsKind() == PIXEL_ELEMENTS;
3132}
3133
3134
Steve Block3ce2e202009-11-05 08:53:23 +00003135bool JSObject::HasExternalArrayElements() {
3136 return (HasExternalByteElements() ||
3137 HasExternalUnsignedByteElements() ||
3138 HasExternalShortElements() ||
3139 HasExternalUnsignedShortElements() ||
3140 HasExternalIntElements() ||
3141 HasExternalUnsignedIntElements() ||
3142 HasExternalFloatElements());
3143}
3144
3145
3146bool JSObject::HasExternalByteElements() {
3147 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3148}
3149
3150
3151bool JSObject::HasExternalUnsignedByteElements() {
3152 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3153}
3154
3155
3156bool JSObject::HasExternalShortElements() {
3157 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3158}
3159
3160
3161bool JSObject::HasExternalUnsignedShortElements() {
3162 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3163}
3164
3165
3166bool JSObject::HasExternalIntElements() {
3167 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3168}
3169
3170
3171bool JSObject::HasExternalUnsignedIntElements() {
3172 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3173}
3174
3175
3176bool JSObject::HasExternalFloatElements() {
3177 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3178}
3179
3180
Steve Blocka7e24c12009-10-30 11:49:00 +00003181bool JSObject::HasNamedInterceptor() {
3182 return map()->has_named_interceptor();
3183}
3184
3185
3186bool JSObject::HasIndexedInterceptor() {
3187 return map()->has_indexed_interceptor();
3188}
3189
3190
Steve Block6ded16b2010-05-10 14:33:55 +01003191bool JSObject::AllowsSetElementsLength() {
3192 bool result = elements()->IsFixedArray();
3193 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3194 return result;
3195}
3196
3197
Iain Merrick75681382010-08-19 15:07:18 +01003198Object* JSObject::EnsureWritableFastElements() {
3199 ASSERT(HasFastElements());
3200 FixedArray* elems = FixedArray::cast(elements());
3201 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003202 Object* writable_elems = Heap::CopyFixedArrayWithMap(elems,
3203 Heap::fixed_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003204 if (writable_elems->IsFailure()) return writable_elems;
Iain Merrick75681382010-08-19 15:07:18 +01003205 set_elements(FixedArray::cast(writable_elems));
3206 Counters::cow_arrays_converted.Increment();
3207 return writable_elems;
3208}
3209
3210
Steve Blocka7e24c12009-10-30 11:49:00 +00003211StringDictionary* JSObject::property_dictionary() {
3212 ASSERT(!HasFastProperties());
3213 return StringDictionary::cast(properties());
3214}
3215
3216
3217NumberDictionary* JSObject::element_dictionary() {
3218 ASSERT(HasDictionaryElements());
3219 return NumberDictionary::cast(elements());
3220}
3221
3222
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003223bool String::IsHashFieldComputed(uint32_t field) {
3224 return (field & kHashNotComputedMask) == 0;
3225}
3226
3227
Steve Blocka7e24c12009-10-30 11:49:00 +00003228bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003229 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00003230}
3231
3232
3233uint32_t String::Hash() {
3234 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00003235 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003236 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003237 // Slow case: compute hash code and set it.
3238 return ComputeAndSetHash();
3239}
3240
3241
3242StringHasher::StringHasher(int length)
3243 : length_(length),
3244 raw_running_hash_(0),
3245 array_index_(0),
3246 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3247 is_first_char_(true),
3248 is_valid_(true) { }
3249
3250
3251bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00003252 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00003253}
3254
3255
3256void StringHasher::AddCharacter(uc32 c) {
3257 // Use the Jenkins one-at-a-time hash function to update the hash
3258 // for the given character.
3259 raw_running_hash_ += c;
3260 raw_running_hash_ += (raw_running_hash_ << 10);
3261 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3262 // Incremental array index computation.
3263 if (is_array_index_) {
3264 if (c < '0' || c > '9') {
3265 is_array_index_ = false;
3266 } else {
3267 int d = c - '0';
3268 if (is_first_char_) {
3269 is_first_char_ = false;
3270 if (c == '0' && length_ > 1) {
3271 is_array_index_ = false;
3272 return;
3273 }
3274 }
3275 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3276 is_array_index_ = false;
3277 } else {
3278 array_index_ = array_index_ * 10 + d;
3279 }
3280 }
3281 }
3282}
3283
3284
3285void StringHasher::AddCharacterNoIndex(uc32 c) {
3286 ASSERT(!is_array_index());
3287 raw_running_hash_ += c;
3288 raw_running_hash_ += (raw_running_hash_ << 10);
3289 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3290}
3291
3292
3293uint32_t StringHasher::GetHash() {
3294 // Get the calculated raw hash value and do some more bit ops to distribute
3295 // the hash further. Ensure that we never return zero as the hash value.
3296 uint32_t result = raw_running_hash_;
3297 result += (result << 3);
3298 result ^= (result >> 11);
3299 result += (result << 15);
3300 if (result == 0) {
3301 result = 27;
3302 }
3303 return result;
3304}
3305
3306
3307bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00003308 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003309 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3310 return false;
3311 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003312 return SlowAsArrayIndex(index);
3313}
3314
3315
3316Object* JSObject::GetPrototype() {
3317 return JSObject::cast(this)->map()->prototype();
3318}
3319
3320
3321PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3322 return GetPropertyAttributeWithReceiver(this, key);
3323}
3324
Steve Blockd0582a62009-12-15 09:54:21 +00003325// TODO(504): this may be useful in other places too where JSGlobalProxy
3326// is used.
3327Object* JSObject::BypassGlobalProxy() {
3328 if (IsJSGlobalProxy()) {
3329 Object* proto = GetPrototype();
3330 if (proto->IsNull()) return Heap::undefined_value();
3331 ASSERT(proto->IsJSGlobalObject());
3332 return proto;
3333 }
3334 return this;
3335}
3336
3337
3338bool JSObject::HasHiddenPropertiesObject() {
3339 ASSERT(!IsJSGlobalProxy());
3340 return GetPropertyAttributePostInterceptor(this,
3341 Heap::hidden_symbol(),
3342 false) != ABSENT;
3343}
3344
3345
3346Object* JSObject::GetHiddenPropertiesObject() {
3347 ASSERT(!IsJSGlobalProxy());
3348 PropertyAttributes attributes;
3349 return GetLocalPropertyPostInterceptor(this,
3350 Heap::hidden_symbol(),
3351 &attributes);
3352}
3353
3354
3355Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3356 ASSERT(!IsJSGlobalProxy());
3357 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3358 hidden_obj,
3359 DONT_ENUM);
3360}
3361
Steve Blocka7e24c12009-10-30 11:49:00 +00003362
3363bool JSObject::HasElement(uint32_t index) {
3364 return HasElementWithReceiver(this, index);
3365}
3366
3367
3368bool AccessorInfo::all_can_read() {
3369 return BooleanBit::get(flag(), kAllCanReadBit);
3370}
3371
3372
3373void AccessorInfo::set_all_can_read(bool value) {
3374 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3375}
3376
3377
3378bool AccessorInfo::all_can_write() {
3379 return BooleanBit::get(flag(), kAllCanWriteBit);
3380}
3381
3382
3383void AccessorInfo::set_all_can_write(bool value) {
3384 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3385}
3386
3387
3388bool AccessorInfo::prohibits_overwriting() {
3389 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3390}
3391
3392
3393void AccessorInfo::set_prohibits_overwriting(bool value) {
3394 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3395}
3396
3397
3398PropertyAttributes AccessorInfo::property_attributes() {
3399 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3400}
3401
3402
3403void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3404 ASSERT(AttributesField::is_valid(attributes));
3405 int rest_value = flag()->value() & ~AttributesField::mask();
3406 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3407}
3408
3409template<typename Shape, typename Key>
3410void Dictionary<Shape, Key>::SetEntry(int entry,
3411 Object* key,
3412 Object* value,
3413 PropertyDetails details) {
3414 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3415 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00003416 AssertNoAllocation no_gc;
3417 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00003418 FixedArray::set(index, key, mode);
3419 FixedArray::set(index+1, value, mode);
3420 FixedArray::fast_set(this, index+2, details.AsSmi());
3421}
3422
3423
3424void Map::ClearCodeCache() {
3425 // No write barrier is needed since empty_fixed_array is not in new space.
3426 // Please note this function is used during marking:
3427 // - MarkCompactCollector::MarkUnmarkedObject
3428 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3429 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3430}
3431
3432
3433void JSArray::EnsureSize(int required_size) {
3434 ASSERT(HasFastElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003435 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00003436 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3437 if (elts->length() < required_size) {
3438 // Doubling in size would be overkill, but leave some slack to avoid
3439 // constantly growing.
3440 Expand(required_size + (required_size >> 3));
3441 // It's a performance benefit to keep a frequently used array in new-space.
3442 } else if (!Heap::new_space()->Contains(elts) &&
3443 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3444 // Expand will allocate a new backing store in new space even if the size
3445 // we asked for isn't larger than what we had before.
3446 Expand(required_size);
3447 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003448}
3449
3450
Leon Clarke4515c472010-02-03 11:58:03 +00003451void JSArray::set_length(Smi* length) {
3452 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3453}
3454
3455
Steve Blocka7e24c12009-10-30 11:49:00 +00003456void JSArray::SetContent(FixedArray* storage) {
Leon Clarke4515c472010-02-03 11:58:03 +00003457 set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00003458 set_elements(storage);
3459}
3460
3461
3462Object* FixedArray::Copy() {
3463 if (length() == 0) return this;
3464 return Heap::CopyFixedArray(this);
3465}
3466
3467
Iain Merrick75681382010-08-19 15:07:18 +01003468int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3469 return map->instance_size();
3470}
3471
3472
3473void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3474 v->VisitExternalReference(
3475 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3476}
3477
3478
3479template<typename StaticVisitor>
3480void Proxy::ProxyIterateBody() {
3481 StaticVisitor::VisitExternalReference(
3482 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3483}
3484
3485
3486void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3487 typedef v8::String::ExternalAsciiStringResource Resource;
3488 v->VisitExternalAsciiString(
3489 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3490}
3491
3492
3493template<typename StaticVisitor>
3494void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3495 typedef v8::String::ExternalAsciiStringResource Resource;
3496 StaticVisitor::VisitExternalAsciiString(
3497 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3498}
3499
3500
3501void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3502 typedef v8::String::ExternalStringResource Resource;
3503 v->VisitExternalTwoByteString(
3504 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3505}
3506
3507
3508template<typename StaticVisitor>
3509void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3510 typedef v8::String::ExternalStringResource Resource;
3511 StaticVisitor::VisitExternalTwoByteString(
3512 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3513}
3514
3515#define SLOT_ADDR(obj, offset) \
3516 reinterpret_cast<Object**>((obj)->address() + offset)
3517
3518template<int start_offset, int end_offset, int size>
3519void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3520 HeapObject* obj,
3521 ObjectVisitor* v) {
3522 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3523}
3524
3525
3526template<int start_offset>
3527void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3528 int object_size,
3529 ObjectVisitor* v) {
3530 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3531}
3532
3533#undef SLOT_ADDR
3534
3535
Steve Blocka7e24c12009-10-30 11:49:00 +00003536#undef CAST_ACCESSOR
3537#undef INT_ACCESSORS
3538#undef SMI_ACCESSORS
3539#undef ACCESSORS
3540#undef FIELD_ADDR
3541#undef READ_FIELD
3542#undef WRITE_FIELD
3543#undef WRITE_BARRIER
3544#undef CONDITIONAL_WRITE_BARRIER
3545#undef READ_MEMADDR_FIELD
3546#undef WRITE_MEMADDR_FIELD
3547#undef READ_DOUBLE_FIELD
3548#undef WRITE_DOUBLE_FIELD
3549#undef READ_INT_FIELD
3550#undef WRITE_INT_FIELD
3551#undef READ_SHORT_FIELD
3552#undef WRITE_SHORT_FIELD
3553#undef READ_BYTE_FIELD
3554#undef WRITE_BYTE_FIELD
3555
3556
3557} } // namespace v8::internal
3558
3559#endif // V8_OBJECTS_INL_H_