blob: c70ab022c6c4b3adccf285ea2365ae602e731b98 [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
38#include "objects.h"
39#include "contexts.h"
40#include "conversions-inl.h"
41#include "property.h"
42
43namespace v8 {
44namespace internal {
45
46PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48}
49
50
51Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53}
54
55
56PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60}
61
62
63#define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70#define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75#define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
77 void holder::set_##name(type* value, WriteBarrierMode mode) { \
78 WRITE_FIELD(this, offset, value); \
79 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
80 }
81
82
83
84#define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
94#define BOOL_GETTER(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98
99
100#define BOOL_ACCESSORS(holder, field, name, offset) \
101 bool holder::name() { \
102 return BooleanBit::get(field(), offset); \
103 } \
104 void holder::set_##name(bool value) { \
105 set_##field(BooleanBit::set(field(), offset, value)); \
106 }
107
108
109bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110 // There is a constraint on the object; check.
111 if (!this->IsJSObject()) return false;
112 // Fetch the constructor function of the object.
113 Object* cons_obj = JSObject::cast(this)->map()->constructor();
114 if (!cons_obj->IsJSFunction()) return false;
115 JSFunction* fun = JSFunction::cast(cons_obj);
116 // Iterate through the chain of inheriting function templates to
117 // see if the required one occurs.
118 for (Object* type = fun->shared()->function_data();
119 type->IsFunctionTemplateInfo();
120 type = FunctionTemplateInfo::cast(type)->parent_template()) {
121 if (type == expected) return true;
122 }
123 // Didn't find the required type in the inheritance chain.
124 return false;
125}
126
127
128bool Object::IsSmi() {
129 return HAS_SMI_TAG(this);
130}
131
132
133bool Object::IsHeapObject() {
134 return Internals::HasHeapObjectTag(this);
135}
136
137
138bool Object::IsHeapNumber() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141}
142
143
144bool Object::IsString() {
145 return Object::IsHeapObject()
146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147}
148
149
150bool Object::IsSymbol() {
151 if (!this->IsHeapObject()) return false;
152 uint32_t type = HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000153 // Because the symbol tag is non-zero and no non-string types have the
154 // symbol bit set we can test for symbols with a very simple test
155 // operation.
156 ASSERT(kSymbolTag != 0);
157 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
158 return (type & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000159}
160
161
162bool Object::IsConsString() {
163 if (!this->IsHeapObject()) return false;
164 uint32_t type = HeapObject::cast(this)->map()->instance_type();
165 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
166 (kStringTag | kConsStringTag);
167}
168
169
Steve Blocka7e24c12009-10-30 11:49:00 +0000170bool Object::IsSeqString() {
171 if (!IsString()) return false;
172 return StringShape(String::cast(this)).IsSequential();
173}
174
175
176bool Object::IsSeqAsciiString() {
177 if (!IsString()) return false;
178 return StringShape(String::cast(this)).IsSequential() &&
179 String::cast(this)->IsAsciiRepresentation();
180}
181
182
183bool Object::IsSeqTwoByteString() {
184 if (!IsString()) return false;
185 return StringShape(String::cast(this)).IsSequential() &&
186 String::cast(this)->IsTwoByteRepresentation();
187}
188
189
190bool Object::IsExternalString() {
191 if (!IsString()) return false;
192 return StringShape(String::cast(this)).IsExternal();
193}
194
195
196bool Object::IsExternalAsciiString() {
197 if (!IsString()) return false;
198 return StringShape(String::cast(this)).IsExternal() &&
199 String::cast(this)->IsAsciiRepresentation();
200}
201
202
203bool Object::IsExternalTwoByteString() {
204 if (!IsString()) return false;
205 return StringShape(String::cast(this)).IsExternal() &&
206 String::cast(this)->IsTwoByteRepresentation();
207}
208
209
Steve Blocka7e24c12009-10-30 11:49:00 +0000210StringShape::StringShape(String* str)
211 : type_(str->map()->instance_type()) {
212 set_valid();
213 ASSERT((type_ & kIsNotStringMask) == kStringTag);
214}
215
216
217StringShape::StringShape(Map* map)
218 : type_(map->instance_type()) {
219 set_valid();
220 ASSERT((type_ & kIsNotStringMask) == kStringTag);
221}
222
223
224StringShape::StringShape(InstanceType t)
225 : type_(static_cast<uint32_t>(t)) {
226 set_valid();
227 ASSERT((type_ & kIsNotStringMask) == kStringTag);
228}
229
230
231bool StringShape::IsSymbol() {
232 ASSERT(valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000233 ASSERT(kSymbolTag != 0);
234 return (type_ & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000235}
236
237
238bool String::IsAsciiRepresentation() {
239 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000240 return (type & kStringEncodingMask) == kAsciiStringTag;
241}
242
243
244bool String::IsTwoByteRepresentation() {
245 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000246 return (type & kStringEncodingMask) == kTwoByteStringTag;
247}
248
249
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100250bool String::HasOnlyAsciiChars() {
251 uint32_t type = map()->instance_type();
252 return (type & kStringEncodingMask) == kAsciiStringTag ||
253 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
Steve Block6ded16b2010-05-10 14:33:55 +0100254}
255
256
Steve Blocka7e24c12009-10-30 11:49:00 +0000257bool StringShape::IsCons() {
258 return (type_ & kStringRepresentationMask) == kConsStringTag;
259}
260
261
Steve Blocka7e24c12009-10-30 11:49:00 +0000262bool StringShape::IsExternal() {
263 return (type_ & kStringRepresentationMask) == kExternalStringTag;
264}
265
266
267bool StringShape::IsSequential() {
268 return (type_ & kStringRepresentationMask) == kSeqStringTag;
269}
270
271
272StringRepresentationTag StringShape::representation_tag() {
273 uint32_t tag = (type_ & kStringRepresentationMask);
274 return static_cast<StringRepresentationTag>(tag);
275}
276
277
278uint32_t StringShape::full_representation_tag() {
279 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
280}
281
282
283STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
284 Internals::kFullStringRepresentationMask);
285
286
Steve Blocka7e24c12009-10-30 11:49:00 +0000287bool StringShape::IsSequentialAscii() {
288 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
289}
290
291
292bool StringShape::IsSequentialTwoByte() {
293 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
294}
295
296
297bool StringShape::IsExternalAscii() {
298 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
299}
300
301
302bool StringShape::IsExternalTwoByte() {
303 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
304}
305
306
307STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
308 Internals::kExternalTwoByteRepresentationTag);
309
310
311uc32 FlatStringReader::Get(int index) {
312 ASSERT(0 <= index && index <= length_);
313 if (is_ascii_) {
314 return static_cast<const byte*>(start_)[index];
315 } else {
316 return static_cast<const uc16*>(start_)[index];
317 }
318}
319
320
321bool Object::IsNumber() {
322 return IsSmi() || IsHeapNumber();
323}
324
325
326bool Object::IsByteArray() {
327 return Object::IsHeapObject()
328 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
329}
330
331
332bool Object::IsPixelArray() {
333 return Object::IsHeapObject() &&
334 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
335}
336
337
Steve Block3ce2e202009-11-05 08:53:23 +0000338bool Object::IsExternalArray() {
339 if (!Object::IsHeapObject())
340 return false;
341 InstanceType instance_type =
342 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000343 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
344 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000345}
346
347
348bool Object::IsExternalByteArray() {
349 return Object::IsHeapObject() &&
350 HeapObject::cast(this)->map()->instance_type() ==
351 EXTERNAL_BYTE_ARRAY_TYPE;
352}
353
354
355bool Object::IsExternalUnsignedByteArray() {
356 return Object::IsHeapObject() &&
357 HeapObject::cast(this)->map()->instance_type() ==
358 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
359}
360
361
362bool Object::IsExternalShortArray() {
363 return Object::IsHeapObject() &&
364 HeapObject::cast(this)->map()->instance_type() ==
365 EXTERNAL_SHORT_ARRAY_TYPE;
366}
367
368
369bool Object::IsExternalUnsignedShortArray() {
370 return Object::IsHeapObject() &&
371 HeapObject::cast(this)->map()->instance_type() ==
372 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
373}
374
375
376bool Object::IsExternalIntArray() {
377 return Object::IsHeapObject() &&
378 HeapObject::cast(this)->map()->instance_type() ==
379 EXTERNAL_INT_ARRAY_TYPE;
380}
381
382
383bool Object::IsExternalUnsignedIntArray() {
384 return Object::IsHeapObject() &&
385 HeapObject::cast(this)->map()->instance_type() ==
386 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
387}
388
389
390bool Object::IsExternalFloatArray() {
391 return Object::IsHeapObject() &&
392 HeapObject::cast(this)->map()->instance_type() ==
393 EXTERNAL_FLOAT_ARRAY_TYPE;
394}
395
396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397bool Object::IsFailure() {
398 return HAS_FAILURE_TAG(this);
399}
400
401
402bool Object::IsRetryAfterGC() {
403 return HAS_FAILURE_TAG(this)
404 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
405}
406
407
408bool Object::IsOutOfMemoryFailure() {
409 return HAS_FAILURE_TAG(this)
410 && Failure::cast(this)->IsOutOfMemoryException();
411}
412
413
414bool Object::IsException() {
415 return this == Failure::Exception();
416}
417
418
419bool Object::IsJSObject() {
420 return IsHeapObject()
421 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
422}
423
424
425bool Object::IsJSContextExtensionObject() {
426 return IsHeapObject()
427 && (HeapObject::cast(this)->map()->instance_type() ==
428 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
429}
430
431
432bool Object::IsMap() {
433 return Object::IsHeapObject()
434 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
435}
436
437
438bool Object::IsFixedArray() {
439 return Object::IsHeapObject()
440 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
441}
442
443
444bool Object::IsDescriptorArray() {
445 return IsFixedArray();
446}
447
448
449bool Object::IsContext() {
450 return Object::IsHeapObject()
451 && (HeapObject::cast(this)->map() == Heap::context_map() ||
452 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
453 HeapObject::cast(this)->map() == Heap::global_context_map());
454}
455
456
457bool Object::IsCatchContext() {
458 return Object::IsHeapObject()
459 && HeapObject::cast(this)->map() == Heap::catch_context_map();
460}
461
462
463bool Object::IsGlobalContext() {
464 return Object::IsHeapObject()
465 && HeapObject::cast(this)->map() == Heap::global_context_map();
466}
467
468
469bool Object::IsJSFunction() {
470 return Object::IsHeapObject()
471 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
472}
473
474
475template <> inline bool Is<JSFunction>(Object* obj) {
476 return obj->IsJSFunction();
477}
478
479
480bool Object::IsCode() {
481 return Object::IsHeapObject()
482 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
483}
484
485
486bool Object::IsOddball() {
487 return Object::IsHeapObject()
488 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
489}
490
491
492bool Object::IsJSGlobalPropertyCell() {
493 return Object::IsHeapObject()
494 && HeapObject::cast(this)->map()->instance_type()
495 == JS_GLOBAL_PROPERTY_CELL_TYPE;
496}
497
498
499bool Object::IsSharedFunctionInfo() {
500 return Object::IsHeapObject() &&
501 (HeapObject::cast(this)->map()->instance_type() ==
502 SHARED_FUNCTION_INFO_TYPE);
503}
504
505
506bool Object::IsJSValue() {
507 return Object::IsHeapObject()
508 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
509}
510
511
512bool Object::IsStringWrapper() {
513 return IsJSValue() && JSValue::cast(this)->value()->IsString();
514}
515
516
517bool Object::IsProxy() {
518 return Object::IsHeapObject()
519 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
520}
521
522
523bool Object::IsBoolean() {
524 return IsTrue() || IsFalse();
525}
526
527
528bool Object::IsJSArray() {
529 return Object::IsHeapObject()
530 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
531}
532
533
534bool Object::IsJSRegExp() {
535 return Object::IsHeapObject()
536 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
537}
538
539
540template <> inline bool Is<JSArray>(Object* obj) {
541 return obj->IsJSArray();
542}
543
544
545bool Object::IsHashTable() {
546 return Object::IsHeapObject()
547 && HeapObject::cast(this)->map() == Heap::hash_table_map();
548}
549
550
551bool Object::IsDictionary() {
552 return IsHashTable() && this != Heap::symbol_table();
553}
554
555
556bool Object::IsSymbolTable() {
557 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
558}
559
560
Steve Block6ded16b2010-05-10 14:33:55 +0100561bool Object::IsJSFunctionResultCache() {
562 if (!IsFixedArray()) return false;
563 FixedArray* self = FixedArray::cast(this);
564 int length = self->length();
565 if (length < JSFunctionResultCache::kEntriesIndex) return false;
566 if ((length - JSFunctionResultCache::kEntriesIndex)
567 % JSFunctionResultCache::kEntrySize != 0) {
568 return false;
569 }
570#ifdef DEBUG
571 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
572#endif
573 return true;
574}
575
576
Steve Blocka7e24c12009-10-30 11:49:00 +0000577bool Object::IsCompilationCacheTable() {
578 return IsHashTable();
579}
580
581
Steve Block6ded16b2010-05-10 14:33:55 +0100582bool Object::IsCodeCacheHashTable() {
583 return IsHashTable();
584}
585
586
Steve Blocka7e24c12009-10-30 11:49:00 +0000587bool Object::IsMapCache() {
588 return IsHashTable();
589}
590
591
592bool Object::IsPrimitive() {
593 return IsOddball() || IsNumber() || IsString();
594}
595
596
597bool Object::IsJSGlobalProxy() {
598 bool result = IsHeapObject() &&
599 (HeapObject::cast(this)->map()->instance_type() ==
600 JS_GLOBAL_PROXY_TYPE);
601 ASSERT(!result || IsAccessCheckNeeded());
602 return result;
603}
604
605
606bool Object::IsGlobalObject() {
607 if (!IsHeapObject()) return false;
608
609 InstanceType type = HeapObject::cast(this)->map()->instance_type();
610 return type == JS_GLOBAL_OBJECT_TYPE ||
611 type == JS_BUILTINS_OBJECT_TYPE;
612}
613
614
615bool Object::IsJSGlobalObject() {
616 return IsHeapObject() &&
617 (HeapObject::cast(this)->map()->instance_type() ==
618 JS_GLOBAL_OBJECT_TYPE);
619}
620
621
622bool Object::IsJSBuiltinsObject() {
623 return IsHeapObject() &&
624 (HeapObject::cast(this)->map()->instance_type() ==
625 JS_BUILTINS_OBJECT_TYPE);
626}
627
628
629bool Object::IsUndetectableObject() {
630 return IsHeapObject()
631 && HeapObject::cast(this)->map()->is_undetectable();
632}
633
634
635bool Object::IsAccessCheckNeeded() {
636 return IsHeapObject()
637 && HeapObject::cast(this)->map()->is_access_check_needed();
638}
639
640
641bool Object::IsStruct() {
642 if (!IsHeapObject()) return false;
643 switch (HeapObject::cast(this)->map()->instance_type()) {
644#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
645 STRUCT_LIST(MAKE_STRUCT_CASE)
646#undef MAKE_STRUCT_CASE
647 default: return false;
648 }
649}
650
651
652#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
653 bool Object::Is##Name() { \
654 return Object::IsHeapObject() \
655 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
656 }
657 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
658#undef MAKE_STRUCT_PREDICATE
659
660
661bool Object::IsUndefined() {
662 return this == Heap::undefined_value();
663}
664
665
666bool Object::IsTheHole() {
667 return this == Heap::the_hole_value();
668}
669
670
671bool Object::IsNull() {
672 return this == Heap::null_value();
673}
674
675
676bool Object::IsTrue() {
677 return this == Heap::true_value();
678}
679
680
681bool Object::IsFalse() {
682 return this == Heap::false_value();
683}
684
685
686double Object::Number() {
687 ASSERT(IsNumber());
688 return IsSmi()
689 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
690 : reinterpret_cast<HeapNumber*>(this)->value();
691}
692
693
694
695Object* Object::ToSmi() {
696 if (IsSmi()) return this;
697 if (IsHeapNumber()) {
698 double value = HeapNumber::cast(this)->value();
699 int int_value = FastD2I(value);
700 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
701 return Smi::FromInt(int_value);
702 }
703 }
704 return Failure::Exception();
705}
706
707
708bool Object::HasSpecificClassOf(String* name) {
709 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
710}
711
712
713Object* Object::GetElement(uint32_t index) {
714 return GetElementWithReceiver(this, index);
715}
716
717
718Object* Object::GetProperty(String* key) {
719 PropertyAttributes attributes;
720 return GetPropertyWithReceiver(this, key, &attributes);
721}
722
723
724Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
725 return GetPropertyWithReceiver(this, key, attributes);
726}
727
728
729#define FIELD_ADDR(p, offset) \
730 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
731
732#define READ_FIELD(p, offset) \
733 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
734
735#define WRITE_FIELD(p, offset, value) \
736 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
737
738
739#define WRITE_BARRIER(object, offset) \
740 Heap::RecordWrite(object->address(), offset);
741
742// CONDITIONAL_WRITE_BARRIER must be issued after the actual
743// write due to the assert validating the written value.
744#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
745 if (mode == UPDATE_WRITE_BARRIER) { \
746 Heap::RecordWrite(object->address(), offset); \
747 } else { \
748 ASSERT(mode == SKIP_WRITE_BARRIER); \
749 ASSERT(Heap::InNewSpace(object) || \
Steve Block6ded16b2010-05-10 14:33:55 +0100750 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100751 Page::FromAddress(object->address())-> \
752 IsRegionDirty(object->address() + offset)); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000753 }
754
755#define READ_DOUBLE_FIELD(p, offset) \
756 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
757
758#define WRITE_DOUBLE_FIELD(p, offset, value) \
759 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
760
761#define READ_INT_FIELD(p, offset) \
762 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
763
764#define WRITE_INT_FIELD(p, offset, value) \
765 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
766
767#define READ_INTPTR_FIELD(p, offset) \
768 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
769
770#define WRITE_INTPTR_FIELD(p, offset, value) \
771 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
772
773#define READ_UINT32_FIELD(p, offset) \
774 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
775
776#define WRITE_UINT32_FIELD(p, offset, value) \
777 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
778
779#define READ_SHORT_FIELD(p, offset) \
780 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
781
782#define WRITE_SHORT_FIELD(p, offset, value) \
783 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
784
785#define READ_BYTE_FIELD(p, offset) \
786 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
787
788#define WRITE_BYTE_FIELD(p, offset, value) \
789 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
790
791
792Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
793 return &READ_FIELD(obj, byte_offset);
794}
795
796
797int Smi::value() {
798 return Internals::SmiValue(this);
799}
800
801
802Smi* Smi::FromInt(int value) {
803 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000804 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000805 intptr_t tagged_value =
Steve Block3ce2e202009-11-05 08:53:23 +0000806 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 return reinterpret_cast<Smi*>(tagged_value);
808}
809
810
811Smi* Smi::FromIntptr(intptr_t value) {
812 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000813 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
814 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000815}
816
817
818Failure::Type Failure::type() const {
819 return static_cast<Type>(value() & kFailureTypeTagMask);
820}
821
822
823bool Failure::IsInternalError() const {
824 return type() == INTERNAL_ERROR;
825}
826
827
828bool Failure::IsOutOfMemoryException() const {
829 return type() == OUT_OF_MEMORY_EXCEPTION;
830}
831
832
833int Failure::requested() const {
834 const int kShiftBits =
835 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
836 STATIC_ASSERT(kShiftBits >= 0);
837 ASSERT(type() == RETRY_AFTER_GC);
Steve Block3ce2e202009-11-05 08:53:23 +0000838 return static_cast<int>(value() >> kShiftBits);
Steve Blocka7e24c12009-10-30 11:49:00 +0000839}
840
841
842AllocationSpace Failure::allocation_space() const {
843 ASSERT_EQ(RETRY_AFTER_GC, type());
844 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
845 & kSpaceTagMask);
846}
847
848
849Failure* Failure::InternalError() {
850 return Construct(INTERNAL_ERROR);
851}
852
853
854Failure* Failure::Exception() {
855 return Construct(EXCEPTION);
856}
857
858
859Failure* Failure::OutOfMemoryException() {
860 return Construct(OUT_OF_MEMORY_EXCEPTION);
861}
862
863
Steve Block3ce2e202009-11-05 08:53:23 +0000864intptr_t Failure::value() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100865 return static_cast<intptr_t>(
866 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000867}
868
869
870Failure* Failure::RetryAfterGC(int requested_bytes) {
871 // Assert that the space encoding fits in the three bytes allotted for it.
872 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
Steve Block6ded16b2010-05-10 14:33:55 +0100873 uintptr_t requested =
874 static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
875 int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
Steve Block3ce2e202009-11-05 08:53:23 +0000876 if (((requested << tag_bits) >> tag_bits) != requested) {
877 // No room for entire requested size in the bits. Round down to
878 // maximally representable size.
879 requested = static_cast<intptr_t>(
880 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
881 }
Steve Blockd0582a62009-12-15 09:54:21 +0000882 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000883 return Construct(RETRY_AFTER_GC, value);
884}
885
886
Steve Block3ce2e202009-11-05 08:53:23 +0000887Failure* Failure::Construct(Type type, intptr_t value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100888 uintptr_t info =
889 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
Steve Blocka7e24c12009-10-30 11:49:00 +0000890 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
Steve Block3ce2e202009-11-05 08:53:23 +0000891 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000892}
893
894
895bool Smi::IsValid(intptr_t value) {
896#ifdef DEBUG
897 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
898#endif
Steve Block3ce2e202009-11-05 08:53:23 +0000899
900#ifdef V8_TARGET_ARCH_X64
901 // To be representable as a long smi, the value must be a 32-bit integer.
902 bool result = (value == static_cast<int32_t>(value));
903#else
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 // To be representable as an tagged small integer, the two
905 // most-significant bits of 'value' must be either 00 or 11 due to
906 // sign-extension. To check this we add 01 to the two
907 // most-significant bits, and check if the most-significant bit is 0
908 //
909 // CAUTION: The original code below:
910 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
911 // may lead to incorrect results according to the C language spec, and
912 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
913 // compiler may produce undefined results in case of signed integer
914 // overflow. The computation must be done w/ unsigned ints.
Steve Block3ce2e202009-11-05 08:53:23 +0000915 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
Steve Blocka7e24c12009-10-30 11:49:00 +0000916#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000917 ASSERT(result == in_range);
918 return result;
919}
920
921
922MapWord MapWord::FromMap(Map* map) {
923 return MapWord(reinterpret_cast<uintptr_t>(map));
924}
925
926
927Map* MapWord::ToMap() {
928 return reinterpret_cast<Map*>(value_);
929}
930
931
932bool MapWord::IsForwardingAddress() {
933 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
934}
935
936
937MapWord MapWord::FromForwardingAddress(HeapObject* object) {
938 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
939 return MapWord(reinterpret_cast<uintptr_t>(raw));
940}
941
942
943HeapObject* MapWord::ToForwardingAddress() {
944 ASSERT(IsForwardingAddress());
945 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
946}
947
948
949bool MapWord::IsMarked() {
950 return (value_ & kMarkingMask) == 0;
951}
952
953
954void MapWord::SetMark() {
955 value_ &= ~kMarkingMask;
956}
957
958
959void MapWord::ClearMark() {
960 value_ |= kMarkingMask;
961}
962
963
964bool MapWord::IsOverflowed() {
965 return (value_ & kOverflowMask) != 0;
966}
967
968
969void MapWord::SetOverflow() {
970 value_ |= kOverflowMask;
971}
972
973
974void MapWord::ClearOverflow() {
975 value_ &= ~kOverflowMask;
976}
977
978
979MapWord MapWord::EncodeAddress(Address map_address, int offset) {
980 // Offset is the distance in live bytes from the first live object in the
981 // same page. The offset between two objects in the same page should not
982 // exceed the object area size of a page.
983 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
984
Leon Clarkee46be812010-01-19 14:06:41 +0000985 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +0000986 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
987
988 Page* map_page = Page::FromAddress(map_address);
989 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
990
Leon Clarkee46be812010-01-19 14:06:41 +0000991 uintptr_t map_page_offset =
992 map_page->Offset(map_address) >> kMapAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +0000993
994 uintptr_t encoding =
995 (compact_offset << kForwardingOffsetShift) |
996 (map_page_offset << kMapPageOffsetShift) |
997 (map_page->mc_page_index << kMapPageIndexShift);
998 return MapWord(encoding);
999}
1000
1001
1002Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1003 int map_page_index =
1004 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1005 ASSERT_MAP_PAGE_INDEX(map_page_index);
1006
1007 int map_page_offset = static_cast<int>(
Leon Clarkee46be812010-01-19 14:06:41 +00001008 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1009 kMapAlignmentBits);
Steve Blocka7e24c12009-10-30 11:49:00 +00001010
1011 return (map_space->PageAddress(map_page_index) + map_page_offset);
1012}
1013
1014
1015int MapWord::DecodeOffset() {
1016 // The offset field is represented in the kForwardingOffsetBits
1017 // most-significant bits.
Steve Blockd0582a62009-12-15 09:54:21 +00001018 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1019 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1020 return static_cast<int>(offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001021}
1022
1023
1024MapWord MapWord::FromEncodedAddress(Address address) {
1025 return MapWord(reinterpret_cast<uintptr_t>(address));
1026}
1027
1028
1029Address MapWord::ToEncodedAddress() {
1030 return reinterpret_cast<Address>(value_);
1031}
1032
1033
1034#ifdef DEBUG
1035void HeapObject::VerifyObjectField(int offset) {
1036 VerifyPointer(READ_FIELD(this, offset));
1037}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001038
1039void HeapObject::VerifySmiField(int offset) {
1040 ASSERT(READ_FIELD(this, offset)->IsSmi());
1041}
Steve Blocka7e24c12009-10-30 11:49:00 +00001042#endif
1043
1044
1045Map* HeapObject::map() {
1046 return map_word().ToMap();
1047}
1048
1049
1050void HeapObject::set_map(Map* value) {
1051 set_map_word(MapWord::FromMap(value));
1052}
1053
1054
1055MapWord HeapObject::map_word() {
1056 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1057}
1058
1059
1060void HeapObject::set_map_word(MapWord map_word) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001061 // WRITE_FIELD does not invoke write barrier, but there is no need
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 // here.
1063 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1064}
1065
1066
1067HeapObject* HeapObject::FromAddress(Address address) {
1068 ASSERT_TAG_ALIGNED(address);
1069 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1070}
1071
1072
1073Address HeapObject::address() {
1074 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1075}
1076
1077
1078int HeapObject::Size() {
1079 return SizeFromMap(map());
1080}
1081
1082
1083void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1084 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1085 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1086}
1087
1088
1089void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1090 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1091}
1092
1093
1094bool HeapObject::IsMarked() {
1095 return map_word().IsMarked();
1096}
1097
1098
1099void HeapObject::SetMark() {
1100 ASSERT(!IsMarked());
1101 MapWord first_word = map_word();
1102 first_word.SetMark();
1103 set_map_word(first_word);
1104}
1105
1106
1107void HeapObject::ClearMark() {
1108 ASSERT(IsMarked());
1109 MapWord first_word = map_word();
1110 first_word.ClearMark();
1111 set_map_word(first_word);
1112}
1113
1114
1115bool HeapObject::IsOverflowed() {
1116 return map_word().IsOverflowed();
1117}
1118
1119
1120void HeapObject::SetOverflow() {
1121 MapWord first_word = map_word();
1122 first_word.SetOverflow();
1123 set_map_word(first_word);
1124}
1125
1126
1127void HeapObject::ClearOverflow() {
1128 ASSERT(IsOverflowed());
1129 MapWord first_word = map_word();
1130 first_word.ClearOverflow();
1131 set_map_word(first_word);
1132}
1133
1134
1135double HeapNumber::value() {
1136 return READ_DOUBLE_FIELD(this, kValueOffset);
1137}
1138
1139
1140void HeapNumber::set_value(double value) {
1141 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1142}
1143
1144
Steve Block6ded16b2010-05-10 14:33:55 +01001145int HeapNumber::get_exponent() {
1146 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1147 kExponentShift) - kExponentBias;
1148}
1149
1150
1151int HeapNumber::get_sign() {
1152 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1153}
1154
1155
Steve Blocka7e24c12009-10-30 11:49:00 +00001156ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1157
1158
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001159HeapObject* JSObject::elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001160 Object* array = READ_FIELD(this, kElementsOffset);
1161 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001162 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1163 array->IsExternalArray());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001164 return reinterpret_cast<HeapObject*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001165}
1166
1167
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001168void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
Steve Block8defd9f2010-07-08 12:39:36 +01001169 ASSERT(map()->has_fast_elements() ==
Iain Merrick75681382010-08-19 15:07:18 +01001170 (value->map() == Heap::fixed_array_map() ||
1171 value->map() == Heap::fixed_cow_array_map()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001172 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001173 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1174 value->IsExternalArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 WRITE_FIELD(this, kElementsOffset, value);
1176 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1177}
1178
1179
1180void JSObject::initialize_properties() {
1181 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1182 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1183}
1184
1185
1186void JSObject::initialize_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01001187 ASSERT(map()->has_fast_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00001188 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1189 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1190}
1191
1192
Steve Block8defd9f2010-07-08 12:39:36 +01001193Object* JSObject::ResetElements() {
1194 Object* obj = map()->GetFastElementsMap();
1195 if (obj->IsFailure()) return obj;
1196 set_map(Map::cast(obj));
1197 initialize_elements();
1198 return this;
1199}
1200
1201
Steve Blocka7e24c12009-10-30 11:49:00 +00001202ACCESSORS(Oddball, to_string, String, kToStringOffset)
1203ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1204
1205
1206Object* JSGlobalPropertyCell::value() {
1207 return READ_FIELD(this, kValueOffset);
1208}
1209
1210
1211void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1212 // The write barrier is not used for global property cells.
1213 ASSERT(!val->IsJSGlobalPropertyCell());
1214 WRITE_FIELD(this, kValueOffset, val);
1215}
1216
1217
1218int JSObject::GetHeaderSize() {
1219 InstanceType type = map()->instance_type();
1220 // Check for the most common kind of JavaScript object before
1221 // falling into the generic switch. This speeds up the internal
1222 // field operations considerably on average.
1223 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1224 switch (type) {
1225 case JS_GLOBAL_PROXY_TYPE:
1226 return JSGlobalProxy::kSize;
1227 case JS_GLOBAL_OBJECT_TYPE:
1228 return JSGlobalObject::kSize;
1229 case JS_BUILTINS_OBJECT_TYPE:
1230 return JSBuiltinsObject::kSize;
1231 case JS_FUNCTION_TYPE:
1232 return JSFunction::kSize;
1233 case JS_VALUE_TYPE:
1234 return JSValue::kSize;
1235 case JS_ARRAY_TYPE:
1236 return JSValue::kSize;
1237 case JS_REGEXP_TYPE:
1238 return JSValue::kSize;
1239 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1240 return JSObject::kHeaderSize;
1241 default:
1242 UNREACHABLE();
1243 return 0;
1244 }
1245}
1246
1247
1248int JSObject::GetInternalFieldCount() {
1249 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1250 // Make sure to adjust for the number of in-object properties. These
1251 // properties do contribute to the size, but are not internal fields.
1252 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1253 map()->inobject_properties();
1254}
1255
1256
1257Object* JSObject::GetInternalField(int index) {
1258 ASSERT(index < GetInternalFieldCount() && index >= 0);
1259 // Internal objects do follow immediately after the header, whereas in-object
1260 // properties are at the end of the object. Therefore there is no need
1261 // to adjust the index here.
1262 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1263}
1264
1265
1266void JSObject::SetInternalField(int index, Object* value) {
1267 ASSERT(index < GetInternalFieldCount() && index >= 0);
1268 // Internal objects do follow immediately after the header, whereas in-object
1269 // properties are at the end of the object. Therefore there is no need
1270 // to adjust the index here.
1271 int offset = GetHeaderSize() + (kPointerSize * index);
1272 WRITE_FIELD(this, offset, value);
1273 WRITE_BARRIER(this, offset);
1274}
1275
1276
1277// Access fast-case object properties at index. The use of these routines
1278// is needed to correctly distinguish between properties stored in-object and
1279// properties stored in the properties array.
1280Object* JSObject::FastPropertyAt(int index) {
1281 // Adjust for the number of properties stored in the object.
1282 index -= map()->inobject_properties();
1283 if (index < 0) {
1284 int offset = map()->instance_size() + (index * kPointerSize);
1285 return READ_FIELD(this, offset);
1286 } else {
1287 ASSERT(index < properties()->length());
1288 return properties()->get(index);
1289 }
1290}
1291
1292
1293Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1294 // Adjust for the number of properties stored in the object.
1295 index -= map()->inobject_properties();
1296 if (index < 0) {
1297 int offset = map()->instance_size() + (index * kPointerSize);
1298 WRITE_FIELD(this, offset, value);
1299 WRITE_BARRIER(this, offset);
1300 } else {
1301 ASSERT(index < properties()->length());
1302 properties()->set(index, value);
1303 }
1304 return value;
1305}
1306
1307
1308Object* JSObject::InObjectPropertyAt(int index) {
1309 // Adjust for the number of properties stored in the object.
1310 index -= map()->inobject_properties();
1311 ASSERT(index < 0);
1312 int offset = map()->instance_size() + (index * kPointerSize);
1313 return READ_FIELD(this, offset);
1314}
1315
1316
1317Object* JSObject::InObjectPropertyAtPut(int index,
1318 Object* value,
1319 WriteBarrierMode mode) {
1320 // Adjust for the number of properties stored in the object.
1321 index -= map()->inobject_properties();
1322 ASSERT(index < 0);
1323 int offset = map()->instance_size() + (index * kPointerSize);
1324 WRITE_FIELD(this, offset, value);
1325 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1326 return value;
1327}
1328
1329
1330
1331void JSObject::InitializeBody(int object_size) {
1332 Object* value = Heap::undefined_value();
1333 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1334 WRITE_FIELD(this, offset, value);
1335 }
1336}
1337
1338
Steve Block8defd9f2010-07-08 12:39:36 +01001339bool JSObject::HasFastProperties() {
1340 return !properties()->IsDictionary();
1341}
1342
1343
1344int JSObject::MaxFastProperties() {
1345 // Allow extra fast properties if the object has more than
1346 // kMaxFastProperties in-object properties. When this is the case,
1347 // it is very unlikely that the object is being used as a dictionary
1348 // and there is a good chance that allowing more map transitions
1349 // will be worth it.
1350 return Max(map()->inobject_properties(), kMaxFastProperties);
1351}
1352
1353
Steve Blocka7e24c12009-10-30 11:49:00 +00001354void Struct::InitializeBody(int object_size) {
1355 Object* value = Heap::undefined_value();
1356 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1357 WRITE_FIELD(this, offset, value);
1358 }
1359}
1360
1361
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001362bool Object::ToArrayIndex(uint32_t* index) {
1363 if (IsSmi()) {
1364 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001365 if (value < 0) return false;
1366 *index = value;
1367 return true;
1368 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001369 if (IsHeapNumber()) {
1370 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 uint32_t uint_value = static_cast<uint32_t>(value);
1372 if (value == static_cast<double>(uint_value)) {
1373 *index = uint_value;
1374 return true;
1375 }
1376 }
1377 return false;
1378}
1379
1380
1381bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1382 if (!this->IsJSValue()) return false;
1383
1384 JSValue* js_value = JSValue::cast(this);
1385 if (!js_value->value()->IsString()) return false;
1386
1387 String* str = String::cast(js_value->value());
1388 if (index >= (uint32_t)str->length()) return false;
1389
1390 return true;
1391}
1392
1393
1394Object* FixedArray::get(int index) {
1395 ASSERT(index >= 0 && index < this->length());
1396 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1397}
1398
1399
1400void FixedArray::set(int index, Smi* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001401 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1403 int offset = kHeaderSize + index * kPointerSize;
1404 WRITE_FIELD(this, offset, value);
1405}
1406
1407
1408void FixedArray::set(int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001409 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 ASSERT(index >= 0 && index < this->length());
1411 int offset = kHeaderSize + index * kPointerSize;
1412 WRITE_FIELD(this, offset, value);
1413 WRITE_BARRIER(this, offset);
1414}
1415
1416
Leon Clarke4515c472010-02-03 11:58:03 +00001417WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1419 return UPDATE_WRITE_BARRIER;
1420}
1421
1422
1423void FixedArray::set(int index,
1424 Object* value,
1425 WriteBarrierMode mode) {
Iain Merrick75681382010-08-19 15:07:18 +01001426 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001427 ASSERT(index >= 0 && index < this->length());
1428 int offset = kHeaderSize + index * kPointerSize;
1429 WRITE_FIELD(this, offset, value);
1430 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1431}
1432
1433
1434void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001435 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001436 ASSERT(index >= 0 && index < array->length());
Leon Clarke4515c472010-02-03 11:58:03 +00001437 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001438 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1439}
1440
1441
1442void FixedArray::set_undefined(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001443 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001444 ASSERT(index >= 0 && index < this->length());
1445 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1446 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1447 Heap::undefined_value());
1448}
1449
1450
1451void FixedArray::set_null(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001452 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 ASSERT(index >= 0 && index < this->length());
1454 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1455 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1456}
1457
1458
1459void FixedArray::set_the_hole(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001460 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 ASSERT(index >= 0 && index < this->length());
1462 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1463 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1464}
1465
1466
Iain Merrick75681382010-08-19 15:07:18 +01001467void FixedArray::set_unchecked(int index, Smi* value) {
1468 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1469 int offset = kHeaderSize + index * kPointerSize;
1470 WRITE_FIELD(this, offset, value);
1471}
1472
1473
1474void FixedArray::set_null_unchecked(int index) {
1475 ASSERT(index >= 0 && index < this->length());
1476 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1477 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1478}
1479
1480
Steve Block6ded16b2010-05-10 14:33:55 +01001481Object** FixedArray::data_start() {
1482 return HeapObject::RawField(this, kHeaderSize);
1483}
1484
1485
Steve Blocka7e24c12009-10-30 11:49:00 +00001486bool DescriptorArray::IsEmpty() {
1487 ASSERT(this == Heap::empty_descriptor_array() ||
1488 this->length() > 2);
1489 return this == Heap::empty_descriptor_array();
1490}
1491
1492
1493void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1494 Object* tmp = array->get(first);
1495 fast_set(array, first, array->get(second));
1496 fast_set(array, second, tmp);
1497}
1498
1499
1500int DescriptorArray::Search(String* name) {
1501 SLOW_ASSERT(IsSortedNoDuplicates());
1502
1503 // Check for empty descriptor array.
1504 int nof = number_of_descriptors();
1505 if (nof == 0) return kNotFound;
1506
1507 // Fast case: do linear search for small arrays.
1508 const int kMaxElementsForLinearSearch = 8;
1509 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1510 return LinearSearch(name, nof);
1511 }
1512
1513 // Slow case: perform binary search.
1514 return BinarySearch(name, 0, nof - 1);
1515}
1516
1517
Iain Merrick75681382010-08-19 15:07:18 +01001518int DescriptorArray::SearchWithCache(String* name) {
1519 int number = DescriptorLookupCache::Lookup(this, name);
1520 if (number == DescriptorLookupCache::kAbsent) {
1521 number = Search(name);
1522 DescriptorLookupCache::Update(this, name, number);
1523 }
1524 return number;
1525}
1526
1527
Steve Blocka7e24c12009-10-30 11:49:00 +00001528String* DescriptorArray::GetKey(int descriptor_number) {
1529 ASSERT(descriptor_number < number_of_descriptors());
1530 return String::cast(get(ToKeyIndex(descriptor_number)));
1531}
1532
1533
1534Object* DescriptorArray::GetValue(int descriptor_number) {
1535 ASSERT(descriptor_number < number_of_descriptors());
1536 return GetContentArray()->get(ToValueIndex(descriptor_number));
1537}
1538
1539
1540Smi* DescriptorArray::GetDetails(int descriptor_number) {
1541 ASSERT(descriptor_number < number_of_descriptors());
1542 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1543}
1544
1545
1546PropertyType DescriptorArray::GetType(int descriptor_number) {
1547 ASSERT(descriptor_number < number_of_descriptors());
1548 return PropertyDetails(GetDetails(descriptor_number)).type();
1549}
1550
1551
1552int DescriptorArray::GetFieldIndex(int descriptor_number) {
1553 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1554}
1555
1556
1557JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1558 return JSFunction::cast(GetValue(descriptor_number));
1559}
1560
1561
1562Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1563 ASSERT(GetType(descriptor_number) == CALLBACKS);
1564 return GetValue(descriptor_number);
1565}
1566
1567
1568AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1569 ASSERT(GetType(descriptor_number) == CALLBACKS);
1570 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1571 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1572}
1573
1574
1575bool DescriptorArray::IsProperty(int descriptor_number) {
1576 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1577}
1578
1579
1580bool DescriptorArray::IsTransition(int descriptor_number) {
1581 PropertyType t = GetType(descriptor_number);
1582 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1583}
1584
1585
1586bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1587 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1588}
1589
1590
1591bool DescriptorArray::IsDontEnum(int descriptor_number) {
1592 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1593}
1594
1595
1596void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1597 desc->Init(GetKey(descriptor_number),
1598 GetValue(descriptor_number),
1599 GetDetails(descriptor_number));
1600}
1601
1602
1603void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1604 // Range check.
1605 ASSERT(descriptor_number < number_of_descriptors());
1606
Leon Clarkee46be812010-01-19 14:06:41 +00001607 // Make sure none of the elements in desc are in new space.
Steve Blocka7e24c12009-10-30 11:49:00 +00001608 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1609 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1610
1611 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1612 FixedArray* content_array = GetContentArray();
1613 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1614 fast_set(content_array, ToDetailsIndex(descriptor_number),
1615 desc->GetDetails().AsSmi());
1616}
1617
1618
1619void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1620 Descriptor desc;
1621 src->Get(src_index, &desc);
1622 Set(index, &desc);
1623}
1624
1625
1626void DescriptorArray::Swap(int first, int second) {
1627 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1628 FixedArray* content_array = GetContentArray();
1629 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1630 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1631}
1632
1633
1634bool NumberDictionary::requires_slow_elements() {
1635 Object* max_index_object = get(kMaxNumberKeyIndex);
1636 if (!max_index_object->IsSmi()) return false;
1637 return 0 !=
1638 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1639}
1640
1641uint32_t NumberDictionary::max_number_key() {
1642 ASSERT(!requires_slow_elements());
1643 Object* max_index_object = get(kMaxNumberKeyIndex);
1644 if (!max_index_object->IsSmi()) return 0;
1645 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1646 return value >> kRequiresSlowElementsTagSize;
1647}
1648
1649void NumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00001650 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00001651}
1652
1653
1654// ------------------------------------
1655// Cast operations
1656
1657
1658CAST_ACCESSOR(FixedArray)
1659CAST_ACCESSOR(DescriptorArray)
1660CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001661CAST_ACCESSOR(JSFunctionResultCache)
Steve Blocka7e24c12009-10-30 11:49:00 +00001662CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001663CAST_ACCESSOR(CodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00001664CAST_ACCESSOR(MapCache)
1665CAST_ACCESSOR(String)
1666CAST_ACCESSOR(SeqString)
1667CAST_ACCESSOR(SeqAsciiString)
1668CAST_ACCESSOR(SeqTwoByteString)
1669CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00001670CAST_ACCESSOR(ExternalString)
1671CAST_ACCESSOR(ExternalAsciiString)
1672CAST_ACCESSOR(ExternalTwoByteString)
1673CAST_ACCESSOR(JSObject)
1674CAST_ACCESSOR(Smi)
1675CAST_ACCESSOR(Failure)
1676CAST_ACCESSOR(HeapObject)
1677CAST_ACCESSOR(HeapNumber)
1678CAST_ACCESSOR(Oddball)
1679CAST_ACCESSOR(JSGlobalPropertyCell)
1680CAST_ACCESSOR(SharedFunctionInfo)
1681CAST_ACCESSOR(Map)
1682CAST_ACCESSOR(JSFunction)
1683CAST_ACCESSOR(GlobalObject)
1684CAST_ACCESSOR(JSGlobalProxy)
1685CAST_ACCESSOR(JSGlobalObject)
1686CAST_ACCESSOR(JSBuiltinsObject)
1687CAST_ACCESSOR(Code)
1688CAST_ACCESSOR(JSArray)
1689CAST_ACCESSOR(JSRegExp)
1690CAST_ACCESSOR(Proxy)
1691CAST_ACCESSOR(ByteArray)
1692CAST_ACCESSOR(PixelArray)
Steve Block3ce2e202009-11-05 08:53:23 +00001693CAST_ACCESSOR(ExternalArray)
1694CAST_ACCESSOR(ExternalByteArray)
1695CAST_ACCESSOR(ExternalUnsignedByteArray)
1696CAST_ACCESSOR(ExternalShortArray)
1697CAST_ACCESSOR(ExternalUnsignedShortArray)
1698CAST_ACCESSOR(ExternalIntArray)
1699CAST_ACCESSOR(ExternalUnsignedIntArray)
1700CAST_ACCESSOR(ExternalFloatArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00001701CAST_ACCESSOR(Struct)
1702
1703
1704#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1705 STRUCT_LIST(MAKE_STRUCT_CAST)
1706#undef MAKE_STRUCT_CAST
1707
1708
1709template <typename Shape, typename Key>
1710HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1711 ASSERT(obj->IsHashTable());
1712 return reinterpret_cast<HashTable*>(obj);
1713}
1714
1715
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001716SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1717SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1718
1719INT_ACCESSORS(PixelArray, length, kLengthOffset)
1720INT_ACCESSORS(ExternalArray, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00001721
1722
Steve Block6ded16b2010-05-10 14:33:55 +01001723SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00001724
1725
1726uint32_t String::hash_field() {
1727 return READ_UINT32_FIELD(this, kHashFieldOffset);
1728}
1729
1730
1731void String::set_hash_field(uint32_t value) {
1732 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001733#if V8_HOST_ARCH_64_BIT
1734 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1735#endif
Steve Blockd0582a62009-12-15 09:54:21 +00001736}
1737
1738
Steve Blocka7e24c12009-10-30 11:49:00 +00001739bool String::Equals(String* other) {
1740 if (other == this) return true;
1741 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1742 return false;
1743 }
1744 return SlowEquals(other);
1745}
1746
1747
Steve Block6ded16b2010-05-10 14:33:55 +01001748Object* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001749 if (!StringShape(this).IsCons()) return this;
1750 ConsString* cons = ConsString::cast(this);
1751 if (cons->second()->length() == 0) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01001752 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00001753}
1754
1755
Leon Clarkef7060e22010-06-03 12:02:55 +01001756String* String::TryFlattenGetString(PretenureFlag pretenure) {
1757 Object* flat = TryFlatten(pretenure);
1758 return flat->IsFailure() ? this : String::cast(flat);
1759}
1760
1761
Steve Blocka7e24c12009-10-30 11:49:00 +00001762uint16_t String::Get(int index) {
1763 ASSERT(index >= 0 && index < length());
1764 switch (StringShape(this).full_representation_tag()) {
1765 case kSeqStringTag | kAsciiStringTag:
1766 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1767 case kSeqStringTag | kTwoByteStringTag:
1768 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1769 case kConsStringTag | kAsciiStringTag:
1770 case kConsStringTag | kTwoByteStringTag:
1771 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001772 case kExternalStringTag | kAsciiStringTag:
1773 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1774 case kExternalStringTag | kTwoByteStringTag:
1775 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1776 default:
1777 break;
1778 }
1779
1780 UNREACHABLE();
1781 return 0;
1782}
1783
1784
1785void String::Set(int index, uint16_t value) {
1786 ASSERT(index >= 0 && index < length());
1787 ASSERT(StringShape(this).IsSequential());
1788
1789 return this->IsAsciiRepresentation()
1790 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1791 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1792}
1793
1794
1795bool String::IsFlat() {
1796 switch (StringShape(this).representation_tag()) {
1797 case kConsStringTag: {
1798 String* second = ConsString::cast(this)->second();
1799 // Only flattened strings have second part empty.
1800 return second->length() == 0;
1801 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001802 default:
1803 return true;
1804 }
1805}
1806
1807
1808uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1809 ASSERT(index >= 0 && index < length());
1810 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1811}
1812
1813
1814void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1815 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1816 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1817 static_cast<byte>(value));
1818}
1819
1820
1821Address SeqAsciiString::GetCharsAddress() {
1822 return FIELD_ADDR(this, kHeaderSize);
1823}
1824
1825
1826char* SeqAsciiString::GetChars() {
1827 return reinterpret_cast<char*>(GetCharsAddress());
1828}
1829
1830
1831Address SeqTwoByteString::GetCharsAddress() {
1832 return FIELD_ADDR(this, kHeaderSize);
1833}
1834
1835
1836uc16* SeqTwoByteString::GetChars() {
1837 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1838}
1839
1840
1841uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1842 ASSERT(index >= 0 && index < length());
1843 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1844}
1845
1846
1847void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1848 ASSERT(index >= 0 && index < length());
1849 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1850}
1851
1852
1853int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001854 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001855}
1856
1857
1858int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001859 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001860}
1861
1862
1863String* ConsString::first() {
1864 return String::cast(READ_FIELD(this, kFirstOffset));
1865}
1866
1867
1868Object* ConsString::unchecked_first() {
1869 return READ_FIELD(this, kFirstOffset);
1870}
1871
1872
1873void ConsString::set_first(String* value, WriteBarrierMode mode) {
1874 WRITE_FIELD(this, kFirstOffset, value);
1875 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1876}
1877
1878
1879String* ConsString::second() {
1880 return String::cast(READ_FIELD(this, kSecondOffset));
1881}
1882
1883
1884Object* ConsString::unchecked_second() {
1885 return READ_FIELD(this, kSecondOffset);
1886}
1887
1888
1889void ConsString::set_second(String* value, WriteBarrierMode mode) {
1890 WRITE_FIELD(this, kSecondOffset, value);
1891 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1892}
1893
1894
Steve Blocka7e24c12009-10-30 11:49:00 +00001895ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1896 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1897}
1898
1899
1900void ExternalAsciiString::set_resource(
1901 ExternalAsciiString::Resource* resource) {
1902 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1903}
1904
1905
Steve Blocka7e24c12009-10-30 11:49:00 +00001906ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1907 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1908}
1909
1910
1911void ExternalTwoByteString::set_resource(
1912 ExternalTwoByteString::Resource* resource) {
1913 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1914}
1915
1916
Steve Block6ded16b2010-05-10 14:33:55 +01001917void JSFunctionResultCache::MakeZeroSize() {
1918 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1919 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1920}
1921
1922
1923void JSFunctionResultCache::Clear() {
1924 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1925 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1926 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1927 MakeZeroSize();
1928}
1929
1930
Steve Blocka7e24c12009-10-30 11:49:00 +00001931byte ByteArray::get(int index) {
1932 ASSERT(index >= 0 && index < this->length());
1933 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1934}
1935
1936
1937void ByteArray::set(int index, byte value) {
1938 ASSERT(index >= 0 && index < this->length());
1939 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1940}
1941
1942
1943int ByteArray::get_int(int index) {
1944 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1945 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1946}
1947
1948
1949ByteArray* ByteArray::FromDataStartAddress(Address address) {
1950 ASSERT_TAG_ALIGNED(address);
1951 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1952}
1953
1954
1955Address ByteArray::GetDataStartAddress() {
1956 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1957}
1958
1959
1960uint8_t* PixelArray::external_pointer() {
1961 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1962 return reinterpret_cast<uint8_t*>(ptr);
1963}
1964
1965
1966void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1967 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1968 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1969}
1970
1971
1972uint8_t PixelArray::get(int index) {
1973 ASSERT((index >= 0) && (index < this->length()));
1974 uint8_t* ptr = external_pointer();
1975 return ptr[index];
1976}
1977
1978
1979void PixelArray::set(int index, uint8_t value) {
1980 ASSERT((index >= 0) && (index < this->length()));
1981 uint8_t* ptr = external_pointer();
1982 ptr[index] = value;
1983}
1984
1985
Steve Block3ce2e202009-11-05 08:53:23 +00001986void* ExternalArray::external_pointer() {
1987 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1988 return reinterpret_cast<void*>(ptr);
1989}
1990
1991
1992void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1993 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1994 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1995}
1996
1997
1998int8_t ExternalByteArray::get(int index) {
1999 ASSERT((index >= 0) && (index < this->length()));
2000 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2001 return ptr[index];
2002}
2003
2004
2005void ExternalByteArray::set(int index, int8_t value) {
2006 ASSERT((index >= 0) && (index < this->length()));
2007 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2008 ptr[index] = value;
2009}
2010
2011
2012uint8_t ExternalUnsignedByteArray::get(int index) {
2013 ASSERT((index >= 0) && (index < this->length()));
2014 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2015 return ptr[index];
2016}
2017
2018
2019void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2020 ASSERT((index >= 0) && (index < this->length()));
2021 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2022 ptr[index] = value;
2023}
2024
2025
2026int16_t ExternalShortArray::get(int index) {
2027 ASSERT((index >= 0) && (index < this->length()));
2028 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2029 return ptr[index];
2030}
2031
2032
2033void ExternalShortArray::set(int index, int16_t value) {
2034 ASSERT((index >= 0) && (index < this->length()));
2035 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2036 ptr[index] = value;
2037}
2038
2039
2040uint16_t ExternalUnsignedShortArray::get(int index) {
2041 ASSERT((index >= 0) && (index < this->length()));
2042 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2043 return ptr[index];
2044}
2045
2046
2047void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2048 ASSERT((index >= 0) && (index < this->length()));
2049 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2050 ptr[index] = value;
2051}
2052
2053
2054int32_t ExternalIntArray::get(int index) {
2055 ASSERT((index >= 0) && (index < this->length()));
2056 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2057 return ptr[index];
2058}
2059
2060
2061void ExternalIntArray::set(int index, int32_t value) {
2062 ASSERT((index >= 0) && (index < this->length()));
2063 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2064 ptr[index] = value;
2065}
2066
2067
2068uint32_t ExternalUnsignedIntArray::get(int index) {
2069 ASSERT((index >= 0) && (index < this->length()));
2070 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2071 return ptr[index];
2072}
2073
2074
2075void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2076 ASSERT((index >= 0) && (index < this->length()));
2077 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2078 ptr[index] = value;
2079}
2080
2081
2082float ExternalFloatArray::get(int index) {
2083 ASSERT((index >= 0) && (index < this->length()));
2084 float* ptr = static_cast<float*>(external_pointer());
2085 return ptr[index];
2086}
2087
2088
2089void ExternalFloatArray::set(int index, float value) {
2090 ASSERT((index >= 0) && (index < this->length()));
2091 float* ptr = static_cast<float*>(external_pointer());
2092 ptr[index] = value;
2093}
2094
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002095
Iain Merrick75681382010-08-19 15:07:18 +01002096INT_ACCESSORS(Map, visitor_id, kScavengerCallbackOffset)
Steve Block3ce2e202009-11-05 08:53:23 +00002097
Steve Blocka7e24c12009-10-30 11:49:00 +00002098int Map::instance_size() {
2099 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2100}
2101
2102
2103int Map::inobject_properties() {
2104 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2105}
2106
2107
2108int Map::pre_allocated_property_fields() {
2109 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2110}
2111
2112
2113int HeapObject::SizeFromMap(Map* map) {
2114 InstanceType instance_type = map->instance_type();
2115 // Only inline the most frequent cases.
2116 if (instance_type == JS_OBJECT_TYPE ||
2117 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
2118 (kStringTag | kConsStringTag) ||
2119 instance_type == JS_ARRAY_TYPE) return map->instance_size();
2120 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002121 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002122 }
2123 if (instance_type == BYTE_ARRAY_TYPE) {
2124 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2125 }
2126 // Otherwise do the general size computation.
2127 return SlowSizeFromMap(map);
2128}
2129
2130
2131void Map::set_instance_size(int value) {
2132 ASSERT_EQ(0, value & (kPointerSize - 1));
2133 value >>= kPointerSizeLog2;
2134 ASSERT(0 <= value && value < 256);
2135 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2136}
2137
2138
2139void Map::set_inobject_properties(int value) {
2140 ASSERT(0 <= value && value < 256);
2141 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2142}
2143
2144
2145void Map::set_pre_allocated_property_fields(int value) {
2146 ASSERT(0 <= value && value < 256);
2147 WRITE_BYTE_FIELD(this,
2148 kPreAllocatedPropertyFieldsOffset,
2149 static_cast<byte>(value));
2150}
2151
2152
2153InstanceType Map::instance_type() {
2154 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2155}
2156
2157
2158void Map::set_instance_type(InstanceType value) {
2159 ASSERT(0 <= value && value < 256);
2160 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2161}
2162
2163
2164int Map::unused_property_fields() {
2165 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2166}
2167
2168
2169void Map::set_unused_property_fields(int value) {
2170 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2171}
2172
2173
2174byte Map::bit_field() {
2175 return READ_BYTE_FIELD(this, kBitFieldOffset);
2176}
2177
2178
2179void Map::set_bit_field(byte value) {
2180 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2181}
2182
2183
2184byte Map::bit_field2() {
2185 return READ_BYTE_FIELD(this, kBitField2Offset);
2186}
2187
2188
2189void Map::set_bit_field2(byte value) {
2190 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2191}
2192
2193
2194void Map::set_non_instance_prototype(bool value) {
2195 if (value) {
2196 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2197 } else {
2198 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2199 }
2200}
2201
2202
2203bool Map::has_non_instance_prototype() {
2204 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2205}
2206
2207
Steve Block6ded16b2010-05-10 14:33:55 +01002208void Map::set_function_with_prototype(bool value) {
2209 if (value) {
2210 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2211 } else {
2212 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2213 }
2214}
2215
2216
2217bool Map::function_with_prototype() {
2218 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2219}
2220
2221
Steve Blocka7e24c12009-10-30 11:49:00 +00002222void Map::set_is_access_check_needed(bool access_check_needed) {
2223 if (access_check_needed) {
2224 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2225 } else {
2226 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2227 }
2228}
2229
2230
2231bool Map::is_access_check_needed() {
2232 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2233}
2234
2235
Steve Block8defd9f2010-07-08 12:39:36 +01002236void Map::set_is_extensible(bool value) {
2237 if (value) {
2238 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2239 } else {
2240 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2241 }
2242}
2243
2244bool Map::is_extensible() {
2245 return ((1 << kIsExtensible) & bit_field2()) != 0;
2246}
2247
2248
2249
Steve Blocka7e24c12009-10-30 11:49:00 +00002250Code::Flags Code::flags() {
2251 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2252}
2253
2254
2255void Code::set_flags(Code::Flags flags) {
2256 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2257 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002258 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2259 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002260 ExtractArgumentsCountFromFlags(flags) >= 0);
2261 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2262}
2263
2264
2265Code::Kind Code::kind() {
2266 return ExtractKindFromFlags(flags());
2267}
2268
2269
2270InLoopFlag Code::ic_in_loop() {
2271 return ExtractICInLoopFromFlags(flags());
2272}
2273
2274
2275InlineCacheState Code::ic_state() {
2276 InlineCacheState result = ExtractICStateFromFlags(flags());
2277 // Only allow uninitialized or debugger states for non-IC code
2278 // objects. This is used in the debugger to determine whether or not
2279 // a call to code object has been replaced with a debug break call.
2280 ASSERT(is_inline_cache_stub() ||
2281 result == UNINITIALIZED ||
2282 result == DEBUG_BREAK ||
2283 result == DEBUG_PREPARE_STEP_IN);
2284 return result;
2285}
2286
2287
2288PropertyType Code::type() {
2289 ASSERT(ic_state() == MONOMORPHIC);
2290 return ExtractTypeFromFlags(flags());
2291}
2292
2293
2294int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002295 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002296 return ExtractArgumentsCountFromFlags(flags());
2297}
2298
2299
2300CodeStub::Major Code::major_key() {
Steve Block6ded16b2010-05-10 14:33:55 +01002301 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002302 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2303 kStubMajorKeyOffset));
2304}
2305
2306
2307void Code::set_major_key(CodeStub::Major major) {
Steve Block6ded16b2010-05-10 14:33:55 +01002308 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002309 ASSERT(0 <= major && major < 256);
2310 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2311}
2312
2313
2314bool Code::is_inline_cache_stub() {
2315 Kind kind = this->kind();
2316 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2317}
2318
2319
2320Code::Flags Code::ComputeFlags(Kind kind,
2321 InLoopFlag in_loop,
2322 InlineCacheState ic_state,
2323 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002324 int argc,
2325 InlineCacheHolderFlag holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002326 // Compute the bit mask.
2327 int bits = kind << kFlagsKindShift;
2328 if (in_loop) bits |= kFlagsICInLoopMask;
2329 bits |= ic_state << kFlagsICStateShift;
2330 bits |= type << kFlagsTypeShift;
2331 bits |= argc << kFlagsArgumentsCountShift;
Steve Block8defd9f2010-07-08 12:39:36 +01002332 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002333 // Cast to flags and validate result before returning it.
2334 Flags result = static_cast<Flags>(bits);
2335 ASSERT(ExtractKindFromFlags(result) == kind);
2336 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2337 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2338 ASSERT(ExtractTypeFromFlags(result) == type);
2339 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2340 return result;
2341}
2342
2343
2344Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2345 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002346 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00002347 InLoopFlag in_loop,
2348 int argc) {
Steve Block8defd9f2010-07-08 12:39:36 +01002349 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00002350}
2351
2352
2353Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2354 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2355 return static_cast<Kind>(bits);
2356}
2357
2358
2359InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2360 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2361 return static_cast<InlineCacheState>(bits);
2362}
2363
2364
2365InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2366 int bits = (flags & kFlagsICInLoopMask);
2367 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2368}
2369
2370
2371PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2372 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2373 return static_cast<PropertyType>(bits);
2374}
2375
2376
2377int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2378 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2379}
2380
2381
Steve Block8defd9f2010-07-08 12:39:36 +01002382InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2383 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2384 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2385}
2386
2387
Steve Blocka7e24c12009-10-30 11:49:00 +00002388Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2389 int bits = flags & ~kFlagsTypeMask;
2390 return static_cast<Flags>(bits);
2391}
2392
2393
2394Code* Code::GetCodeFromTargetAddress(Address address) {
2395 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2396 // GetCodeFromTargetAddress might be called when marking objects during mark
2397 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2398 // Code::cast. Code::cast does not work when the object's map is
2399 // marked.
2400 Code* result = reinterpret_cast<Code*>(code);
2401 return result;
2402}
2403
2404
2405Object* Map::prototype() {
2406 return READ_FIELD(this, kPrototypeOffset);
2407}
2408
2409
2410void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2411 ASSERT(value->IsNull() || value->IsJSObject());
2412 WRITE_FIELD(this, kPrototypeOffset, value);
2413 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2414}
2415
2416
Steve Block8defd9f2010-07-08 12:39:36 +01002417Object* Map::GetFastElementsMap() {
2418 if (has_fast_elements()) return this;
2419 Object* obj = CopyDropTransitions();
2420 if (obj->IsFailure()) return obj;
2421 Map* new_map = Map::cast(obj);
2422 new_map->set_has_fast_elements(true);
Iain Merrick75681382010-08-19 15:07:18 +01002423 Counters::map_slow_to_fast_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002424 return new_map;
2425}
2426
2427
2428Object* Map::GetSlowElementsMap() {
2429 if (!has_fast_elements()) return this;
2430 Object* obj = CopyDropTransitions();
2431 if (obj->IsFailure()) return obj;
2432 Map* new_map = Map::cast(obj);
2433 new_map->set_has_fast_elements(false);
Iain Merrick75681382010-08-19 15:07:18 +01002434 Counters::map_fast_to_slow_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002435 return new_map;
2436}
2437
2438
Steve Blocka7e24c12009-10-30 11:49:00 +00002439ACCESSORS(Map, instance_descriptors, DescriptorArray,
2440 kInstanceDescriptorsOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002441ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002442ACCESSORS(Map, constructor, Object, kConstructorOffset)
2443
2444ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2445ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2446
2447ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2448ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2449ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2450
2451ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2452
2453ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2454ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2455ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2456ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2457ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002458ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002459
2460ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2461ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2462ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2463
2464ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2465ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2466ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2467ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2468ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2469ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2470
2471ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2472ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2473
2474ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2475ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2476
2477ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2478ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2479ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2480 kPropertyAccessorsOffset)
2481ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2482 kPrototypeTemplateOffset)
2483ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2484ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2485 kNamedPropertyHandlerOffset)
2486ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2487 kIndexedPropertyHandlerOffset)
2488ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2489 kInstanceTemplateOffset)
2490ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2491ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2492ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2493 kInstanceCallHandlerOffset)
2494ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2495 kAccessCheckInfoOffset)
2496ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2497
2498ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2499ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2500 kInternalFieldCountOffset)
2501
2502ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2503ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2504
2505ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2506
2507ACCESSORS(Script, source, Object, kSourceOffset)
2508ACCESSORS(Script, name, Object, kNameOffset)
2509ACCESSORS(Script, id, Object, kIdOffset)
2510ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2511ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2512ACCESSORS(Script, data, Object, kDataOffset)
2513ACCESSORS(Script, context_data, Object, kContextOffset)
2514ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2515ACCESSORS(Script, type, Smi, kTypeOffset)
2516ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2517ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002518ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002519ACCESSORS(Script, eval_from_instructions_offset, Smi,
2520 kEvalFrominstructionsOffsetOffset)
2521
2522#ifdef ENABLE_DEBUGGER_SUPPORT
2523ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2524ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2525ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2526ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2527
2528ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2529ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2530ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2531ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2532#endif
2533
Steve Blocka7e24c12009-10-30 11:49:00 +00002534ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002535ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002536ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2537 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002538ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002539ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2540ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2541ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2542ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2543 kThisPropertyAssignmentsOffset)
2544
2545BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2546 kHiddenPrototypeBit)
2547BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2548BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2549 kNeedsAccessCheckBit)
2550BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2551 kIsExpressionBit)
2552BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2553 kIsTopLevelBit)
2554BOOL_GETTER(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002555 has_only_simple_this_property_assignments,
2556 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00002557BOOL_ACCESSORS(SharedFunctionInfo,
2558 compiler_hints,
Leon Clarked91b9f72010-01-27 17:25:45 +00002559 try_full_codegen,
2560 kTryFullCodegen)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002561BOOL_ACCESSORS(SharedFunctionInfo,
2562 compiler_hints,
2563 allows_lazy_compilation,
2564 kAllowLazyCompilation)
Steve Blocka7e24c12009-10-30 11:49:00 +00002565
Iain Merrick75681382010-08-19 15:07:18 +01002566
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002567#if V8_HOST_ARCH_32_BIT
2568SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2569SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002570 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002571SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00002572 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002573SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2574SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00002575 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002576SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2577SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00002578 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002579SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002580 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002581SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002582 kThisPropertyAssignmentsCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002583#else
Steve Blocka7e24c12009-10-30 11:49:00 +00002584
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002585#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2586 int holder::name() { \
2587 int value = READ_INT_FIELD(this, offset); \
2588 ASSERT(kHeapObjectTag == 1); \
2589 ASSERT((value & kHeapObjectTag) == 0); \
2590 return value >> 1; \
2591 } \
2592 void holder::set_##name(int value) { \
2593 ASSERT(kHeapObjectTag == 1); \
2594 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2595 (value & 0xC0000000) == 0x000000000); \
2596 WRITE_INT_FIELD(this, \
2597 offset, \
2598 (value << 1) & ~kHeapObjectTag); \
2599 }
2600
2601#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2602 INT_ACCESSORS(holder, name, offset)
2603
2604
2605
2606PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2607PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2608 kFormalParameterCountOffset)
2609
2610PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2611 kExpectedNofPropertiesOffset)
2612PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2613
2614PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2615 kStartPositionAndTypeOffset)
2616PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2617
2618PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2619 kFunctionTokenPositionOffset)
2620PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2621 kCompilerHintsOffset)
2622
2623PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2624 kThisPropertyAssignmentsCountOffset)
2625#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002626
Steve Block6ded16b2010-05-10 14:33:55 +01002627ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2628ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2629
Steve Block3ce2e202009-11-05 08:53:23 +00002630bool Script::HasValidSource() {
2631 Object* src = this->source();
2632 if (!src->IsString()) return true;
2633 String* src_str = String::cast(src);
2634 if (!StringShape(src_str).IsExternal()) return true;
2635 if (src_str->IsAsciiRepresentation()) {
2636 return ExternalAsciiString::cast(src)->resource() != NULL;
2637 } else if (src_str->IsTwoByteRepresentation()) {
2638 return ExternalTwoByteString::cast(src)->resource() != NULL;
2639 }
2640 return true;
2641}
2642
2643
Steve Blocka7e24c12009-10-30 11:49:00 +00002644void SharedFunctionInfo::DontAdaptArguments() {
2645 ASSERT(code()->kind() == Code::BUILTIN);
2646 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2647}
2648
2649
2650int SharedFunctionInfo::start_position() {
2651 return start_position_and_type() >> kStartPositionShift;
2652}
2653
2654
2655void SharedFunctionInfo::set_start_position(int start_position) {
2656 set_start_position_and_type((start_position << kStartPositionShift)
2657 | (start_position_and_type() & ~kStartPositionMask));
2658}
2659
2660
2661Code* SharedFunctionInfo::code() {
2662 return Code::cast(READ_FIELD(this, kCodeOffset));
2663}
2664
2665
Iain Merrick75681382010-08-19 15:07:18 +01002666Code* SharedFunctionInfo::unchecked_code() {
2667 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2668}
2669
2670
Steve Blocka7e24c12009-10-30 11:49:00 +00002671void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2672 WRITE_FIELD(this, kCodeOffset, value);
2673 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2674}
2675
2676
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002677SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2678 return reinterpret_cast<SerializedScopeInfo*>(
2679 READ_FIELD(this, kScopeInfoOffset));
2680}
2681
2682
2683void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2684 WriteBarrierMode mode) {
2685 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2686 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2687}
2688
2689
Steve Blocka7e24c12009-10-30 11:49:00 +00002690bool SharedFunctionInfo::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01002691 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00002692}
2693
2694
Steve Block6ded16b2010-05-10 14:33:55 +01002695bool SharedFunctionInfo::IsApiFunction() {
2696 return function_data()->IsFunctionTemplateInfo();
2697}
2698
2699
2700FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2701 ASSERT(IsApiFunction());
2702 return FunctionTemplateInfo::cast(function_data());
2703}
2704
2705
2706bool SharedFunctionInfo::HasCustomCallGenerator() {
Kristian Monsen25f61362010-05-21 11:50:48 +01002707 return function_data()->IsSmi();
2708}
2709
2710
2711int SharedFunctionInfo::custom_call_generator_id() {
2712 ASSERT(HasCustomCallGenerator());
2713 return Smi::cast(function_data())->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002714}
2715
2716
Iain Merrick75681382010-08-19 15:07:18 +01002717int SharedFunctionInfo::code_age() {
2718 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
2719}
2720
2721
2722void SharedFunctionInfo::set_code_age(int code_age) {
2723 set_compiler_hints(compiler_hints() |
2724 ((code_age & kCodeAgeMask) << kCodeAgeShift));
2725}
2726
2727
Steve Blocka7e24c12009-10-30 11:49:00 +00002728bool JSFunction::IsBuiltin() {
2729 return context()->global()->IsJSBuiltinsObject();
2730}
2731
2732
Steve Blocka7e24c12009-10-30 11:49:00 +00002733Code* JSFunction::code() {
Iain Merrick75681382010-08-19 15:07:18 +01002734 return Code::cast(READ_FIELD(this, kCodeOffset));
2735}
2736
2737
2738Code* JSFunction::unchecked_code() {
2739 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002740}
2741
2742
2743void JSFunction::set_code(Code* value) {
Iain Merrick75681382010-08-19 15:07:18 +01002744 // Skip the write barrier because code is never in new space.
2745 ASSERT(!Heap::InNewSpace(value));
2746 WRITE_FIELD(this, kCodeOffset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002747}
2748
2749
2750Context* JSFunction::context() {
2751 return Context::cast(READ_FIELD(this, kContextOffset));
2752}
2753
2754
2755Object* JSFunction::unchecked_context() {
2756 return READ_FIELD(this, kContextOffset);
2757}
2758
2759
Iain Merrick75681382010-08-19 15:07:18 +01002760SharedFunctionInfo* JSFunction::unchecked_shared() {
2761 return reinterpret_cast<SharedFunctionInfo*>(
2762 READ_FIELD(this, kSharedFunctionInfoOffset));
2763}
2764
2765
Steve Blocka7e24c12009-10-30 11:49:00 +00002766void JSFunction::set_context(Object* value) {
2767 ASSERT(value == Heap::undefined_value() || value->IsContext());
2768 WRITE_FIELD(this, kContextOffset, value);
2769 WRITE_BARRIER(this, kContextOffset);
2770}
2771
2772ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2773 kPrototypeOrInitialMapOffset)
2774
2775
2776Map* JSFunction::initial_map() {
2777 return Map::cast(prototype_or_initial_map());
2778}
2779
2780
2781void JSFunction::set_initial_map(Map* value) {
2782 set_prototype_or_initial_map(value);
2783}
2784
2785
2786bool JSFunction::has_initial_map() {
2787 return prototype_or_initial_map()->IsMap();
2788}
2789
2790
2791bool JSFunction::has_instance_prototype() {
2792 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2793}
2794
2795
2796bool JSFunction::has_prototype() {
2797 return map()->has_non_instance_prototype() || has_instance_prototype();
2798}
2799
2800
2801Object* JSFunction::instance_prototype() {
2802 ASSERT(has_instance_prototype());
2803 if (has_initial_map()) return initial_map()->prototype();
2804 // When there is no initial map and the prototype is a JSObject, the
2805 // initial map field is used for the prototype field.
2806 return prototype_or_initial_map();
2807}
2808
2809
2810Object* JSFunction::prototype() {
2811 ASSERT(has_prototype());
2812 // If the function's prototype property has been set to a non-JSObject
2813 // value, that value is stored in the constructor field of the map.
2814 if (map()->has_non_instance_prototype()) return map()->constructor();
2815 return instance_prototype();
2816}
2817
Steve Block6ded16b2010-05-10 14:33:55 +01002818bool JSFunction::should_have_prototype() {
2819 return map()->function_with_prototype();
2820}
2821
Steve Blocka7e24c12009-10-30 11:49:00 +00002822
2823bool JSFunction::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01002824 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00002825}
2826
2827
2828int JSFunction::NumberOfLiterals() {
2829 return literals()->length();
2830}
2831
2832
2833Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2834 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002835 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00002836}
2837
2838
2839void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2840 Object* value) {
2841 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002842 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2843 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2844}
2845
2846
2847Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2848 ASSERT(0 <= id && id < kJSBuiltinsCount);
2849 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2850}
2851
2852
2853void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2854 Code* value) {
2855 ASSERT(0 <= id && id < kJSBuiltinsCount);
2856 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2857 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002858}
2859
2860
2861Address Proxy::proxy() {
2862 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2863}
2864
2865
2866void Proxy::set_proxy(Address value) {
2867 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2868}
2869
2870
Steve Blocka7e24c12009-10-30 11:49:00 +00002871ACCESSORS(JSValue, value, Object, kValueOffset)
2872
2873
2874JSValue* JSValue::cast(Object* obj) {
2875 ASSERT(obj->IsJSValue());
2876 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2877 return reinterpret_cast<JSValue*>(obj);
2878}
2879
2880
2881INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01002882ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002883
2884
2885byte* Code::instruction_start() {
2886 return FIELD_ADDR(this, kHeaderSize);
2887}
2888
2889
Leon Clarkeac952652010-07-15 11:15:24 +01002890byte* Code::instruction_end() {
2891 return instruction_start() + instruction_size();
2892}
2893
2894
Steve Blocka7e24c12009-10-30 11:49:00 +00002895int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01002896 return RoundUp(instruction_size(), kObjectAlignment);
2897}
2898
2899
2900ByteArray* Code::unchecked_relocation_info() {
2901 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002902}
2903
2904
2905byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01002906 return unchecked_relocation_info()->GetDataStartAddress();
2907}
2908
2909
2910int Code::relocation_size() {
2911 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00002912}
2913
2914
2915byte* Code::entry() {
2916 return instruction_start();
2917}
2918
2919
2920bool Code::contains(byte* pc) {
2921 return (instruction_start() <= pc) &&
2922 (pc < instruction_start() + instruction_size());
2923}
2924
2925
Steve Blocka7e24c12009-10-30 11:49:00 +00002926ACCESSORS(JSArray, length, Object, kLengthOffset)
2927
2928
2929ACCESSORS(JSRegExp, data, Object, kDataOffset)
2930
2931
2932JSRegExp::Type JSRegExp::TypeTag() {
2933 Object* data = this->data();
2934 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2935 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2936 return static_cast<JSRegExp::Type>(smi->value());
2937}
2938
2939
2940int JSRegExp::CaptureCount() {
2941 switch (TypeTag()) {
2942 case ATOM:
2943 return 0;
2944 case IRREGEXP:
2945 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2946 default:
2947 UNREACHABLE();
2948 return -1;
2949 }
2950}
2951
2952
2953JSRegExp::Flags JSRegExp::GetFlags() {
2954 ASSERT(this->data()->IsFixedArray());
2955 Object* data = this->data();
2956 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2957 return Flags(smi->value());
2958}
2959
2960
2961String* JSRegExp::Pattern() {
2962 ASSERT(this->data()->IsFixedArray());
2963 Object* data = this->data();
2964 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2965 return pattern;
2966}
2967
2968
2969Object* JSRegExp::DataAt(int index) {
2970 ASSERT(TypeTag() != NOT_COMPILED);
2971 return FixedArray::cast(data())->get(index);
2972}
2973
2974
2975void JSRegExp::SetDataAt(int index, Object* value) {
2976 ASSERT(TypeTag() != NOT_COMPILED);
2977 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2978 FixedArray::cast(data())->set(index, value);
2979}
2980
2981
2982JSObject::ElementsKind JSObject::GetElementsKind() {
Iain Merrick75681382010-08-19 15:07:18 +01002983 if (map()->has_fast_elements()) {
2984 ASSERT(elements()->map() == Heap::fixed_array_map() ||
2985 elements()->map() == Heap::fixed_cow_array_map());
2986 return FAST_ELEMENTS;
2987 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002988 HeapObject* array = elements();
Steve Blocka7e24c12009-10-30 11:49:00 +00002989 if (array->IsFixedArray()) {
Iain Merrick75681382010-08-19 15:07:18 +01002990 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
2991 // FixedArray, but FAST_ELEMENTS is already handled above.
Steve Blocka7e24c12009-10-30 11:49:00 +00002992 ASSERT(array->IsDictionary());
2993 return DICTIONARY_ELEMENTS;
2994 }
Steve Block3ce2e202009-11-05 08:53:23 +00002995 if (array->IsExternalArray()) {
2996 switch (array->map()->instance_type()) {
2997 case EXTERNAL_BYTE_ARRAY_TYPE:
2998 return EXTERNAL_BYTE_ELEMENTS;
2999 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3000 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3001 case EXTERNAL_SHORT_ARRAY_TYPE:
3002 return EXTERNAL_SHORT_ELEMENTS;
3003 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3004 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3005 case EXTERNAL_INT_ARRAY_TYPE:
3006 return EXTERNAL_INT_ELEMENTS;
3007 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3008 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3009 default:
3010 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3011 return EXTERNAL_FLOAT_ELEMENTS;
3012 }
3013 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003014 ASSERT(array->IsPixelArray());
3015 return PIXEL_ELEMENTS;
3016}
3017
3018
3019bool JSObject::HasFastElements() {
3020 return GetElementsKind() == FAST_ELEMENTS;
3021}
3022
3023
3024bool JSObject::HasDictionaryElements() {
3025 return GetElementsKind() == DICTIONARY_ELEMENTS;
3026}
3027
3028
3029bool JSObject::HasPixelElements() {
3030 return GetElementsKind() == PIXEL_ELEMENTS;
3031}
3032
3033
Steve Block3ce2e202009-11-05 08:53:23 +00003034bool JSObject::HasExternalArrayElements() {
3035 return (HasExternalByteElements() ||
3036 HasExternalUnsignedByteElements() ||
3037 HasExternalShortElements() ||
3038 HasExternalUnsignedShortElements() ||
3039 HasExternalIntElements() ||
3040 HasExternalUnsignedIntElements() ||
3041 HasExternalFloatElements());
3042}
3043
3044
3045bool JSObject::HasExternalByteElements() {
3046 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3047}
3048
3049
3050bool JSObject::HasExternalUnsignedByteElements() {
3051 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3052}
3053
3054
3055bool JSObject::HasExternalShortElements() {
3056 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3057}
3058
3059
3060bool JSObject::HasExternalUnsignedShortElements() {
3061 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3062}
3063
3064
3065bool JSObject::HasExternalIntElements() {
3066 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3067}
3068
3069
3070bool JSObject::HasExternalUnsignedIntElements() {
3071 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3072}
3073
3074
3075bool JSObject::HasExternalFloatElements() {
3076 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3077}
3078
3079
Steve Blocka7e24c12009-10-30 11:49:00 +00003080bool JSObject::HasNamedInterceptor() {
3081 return map()->has_named_interceptor();
3082}
3083
3084
3085bool JSObject::HasIndexedInterceptor() {
3086 return map()->has_indexed_interceptor();
3087}
3088
3089
Steve Block6ded16b2010-05-10 14:33:55 +01003090bool JSObject::AllowsSetElementsLength() {
3091 bool result = elements()->IsFixedArray();
3092 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3093 return result;
3094}
3095
3096
Iain Merrick75681382010-08-19 15:07:18 +01003097Object* JSObject::EnsureWritableFastElements() {
3098 ASSERT(HasFastElements());
3099 FixedArray* elems = FixedArray::cast(elements());
3100 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
3101 Object* writable_elems = Heap::CopyFixedArray(elems);
3102 if (writable_elems->IsFailure()) return writable_elems;
3103 FixedArray::cast(writable_elems)->set_map(Heap::fixed_array_map());
3104 set_elements(FixedArray::cast(writable_elems));
3105 Counters::cow_arrays_converted.Increment();
3106 return writable_elems;
3107}
3108
3109
Steve Blocka7e24c12009-10-30 11:49:00 +00003110StringDictionary* JSObject::property_dictionary() {
3111 ASSERT(!HasFastProperties());
3112 return StringDictionary::cast(properties());
3113}
3114
3115
3116NumberDictionary* JSObject::element_dictionary() {
3117 ASSERT(HasDictionaryElements());
3118 return NumberDictionary::cast(elements());
3119}
3120
3121
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003122bool String::IsHashFieldComputed(uint32_t field) {
3123 return (field & kHashNotComputedMask) == 0;
3124}
3125
3126
Steve Blocka7e24c12009-10-30 11:49:00 +00003127bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003128 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00003129}
3130
3131
3132uint32_t String::Hash() {
3133 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00003134 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003135 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003136 // Slow case: compute hash code and set it.
3137 return ComputeAndSetHash();
3138}
3139
3140
3141StringHasher::StringHasher(int length)
3142 : length_(length),
3143 raw_running_hash_(0),
3144 array_index_(0),
3145 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3146 is_first_char_(true),
3147 is_valid_(true) { }
3148
3149
3150bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00003151 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00003152}
3153
3154
3155void StringHasher::AddCharacter(uc32 c) {
3156 // Use the Jenkins one-at-a-time hash function to update the hash
3157 // for the given character.
3158 raw_running_hash_ += c;
3159 raw_running_hash_ += (raw_running_hash_ << 10);
3160 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3161 // Incremental array index computation.
3162 if (is_array_index_) {
3163 if (c < '0' || c > '9') {
3164 is_array_index_ = false;
3165 } else {
3166 int d = c - '0';
3167 if (is_first_char_) {
3168 is_first_char_ = false;
3169 if (c == '0' && length_ > 1) {
3170 is_array_index_ = false;
3171 return;
3172 }
3173 }
3174 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3175 is_array_index_ = false;
3176 } else {
3177 array_index_ = array_index_ * 10 + d;
3178 }
3179 }
3180 }
3181}
3182
3183
3184void StringHasher::AddCharacterNoIndex(uc32 c) {
3185 ASSERT(!is_array_index());
3186 raw_running_hash_ += c;
3187 raw_running_hash_ += (raw_running_hash_ << 10);
3188 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3189}
3190
3191
3192uint32_t StringHasher::GetHash() {
3193 // Get the calculated raw hash value and do some more bit ops to distribute
3194 // the hash further. Ensure that we never return zero as the hash value.
3195 uint32_t result = raw_running_hash_;
3196 result += (result << 3);
3197 result ^= (result >> 11);
3198 result += (result << 15);
3199 if (result == 0) {
3200 result = 27;
3201 }
3202 return result;
3203}
3204
3205
3206bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00003207 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003208 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3209 return false;
3210 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003211 return SlowAsArrayIndex(index);
3212}
3213
3214
3215Object* JSObject::GetPrototype() {
3216 return JSObject::cast(this)->map()->prototype();
3217}
3218
3219
3220PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3221 return GetPropertyAttributeWithReceiver(this, key);
3222}
3223
Steve Blockd0582a62009-12-15 09:54:21 +00003224// TODO(504): this may be useful in other places too where JSGlobalProxy
3225// is used.
3226Object* JSObject::BypassGlobalProxy() {
3227 if (IsJSGlobalProxy()) {
3228 Object* proto = GetPrototype();
3229 if (proto->IsNull()) return Heap::undefined_value();
3230 ASSERT(proto->IsJSGlobalObject());
3231 return proto;
3232 }
3233 return this;
3234}
3235
3236
3237bool JSObject::HasHiddenPropertiesObject() {
3238 ASSERT(!IsJSGlobalProxy());
3239 return GetPropertyAttributePostInterceptor(this,
3240 Heap::hidden_symbol(),
3241 false) != ABSENT;
3242}
3243
3244
3245Object* JSObject::GetHiddenPropertiesObject() {
3246 ASSERT(!IsJSGlobalProxy());
3247 PropertyAttributes attributes;
3248 return GetLocalPropertyPostInterceptor(this,
3249 Heap::hidden_symbol(),
3250 &attributes);
3251}
3252
3253
3254Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3255 ASSERT(!IsJSGlobalProxy());
3256 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3257 hidden_obj,
3258 DONT_ENUM);
3259}
3260
Steve Blocka7e24c12009-10-30 11:49:00 +00003261
3262bool JSObject::HasElement(uint32_t index) {
3263 return HasElementWithReceiver(this, index);
3264}
3265
3266
3267bool AccessorInfo::all_can_read() {
3268 return BooleanBit::get(flag(), kAllCanReadBit);
3269}
3270
3271
3272void AccessorInfo::set_all_can_read(bool value) {
3273 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3274}
3275
3276
3277bool AccessorInfo::all_can_write() {
3278 return BooleanBit::get(flag(), kAllCanWriteBit);
3279}
3280
3281
3282void AccessorInfo::set_all_can_write(bool value) {
3283 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3284}
3285
3286
3287bool AccessorInfo::prohibits_overwriting() {
3288 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3289}
3290
3291
3292void AccessorInfo::set_prohibits_overwriting(bool value) {
3293 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3294}
3295
3296
3297PropertyAttributes AccessorInfo::property_attributes() {
3298 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3299}
3300
3301
3302void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3303 ASSERT(AttributesField::is_valid(attributes));
3304 int rest_value = flag()->value() & ~AttributesField::mask();
3305 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3306}
3307
3308template<typename Shape, typename Key>
3309void Dictionary<Shape, Key>::SetEntry(int entry,
3310 Object* key,
3311 Object* value,
3312 PropertyDetails details) {
3313 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3314 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00003315 AssertNoAllocation no_gc;
3316 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00003317 FixedArray::set(index, key, mode);
3318 FixedArray::set(index+1, value, mode);
3319 FixedArray::fast_set(this, index+2, details.AsSmi());
3320}
3321
3322
3323void Map::ClearCodeCache() {
3324 // No write barrier is needed since empty_fixed_array is not in new space.
3325 // Please note this function is used during marking:
3326 // - MarkCompactCollector::MarkUnmarkedObject
3327 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3328 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3329}
3330
3331
3332void JSArray::EnsureSize(int required_size) {
3333 ASSERT(HasFastElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003334 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00003335 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3336 if (elts->length() < required_size) {
3337 // Doubling in size would be overkill, but leave some slack to avoid
3338 // constantly growing.
3339 Expand(required_size + (required_size >> 3));
3340 // It's a performance benefit to keep a frequently used array in new-space.
3341 } else if (!Heap::new_space()->Contains(elts) &&
3342 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3343 // Expand will allocate a new backing store in new space even if the size
3344 // we asked for isn't larger than what we had before.
3345 Expand(required_size);
3346 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003347}
3348
3349
Leon Clarke4515c472010-02-03 11:58:03 +00003350void JSArray::set_length(Smi* length) {
3351 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3352}
3353
3354
Steve Blocka7e24c12009-10-30 11:49:00 +00003355void JSArray::SetContent(FixedArray* storage) {
Leon Clarke4515c472010-02-03 11:58:03 +00003356 set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00003357 set_elements(storage);
3358}
3359
3360
3361Object* FixedArray::Copy() {
3362 if (length() == 0) return this;
3363 return Heap::CopyFixedArray(this);
3364}
3365
3366
Iain Merrick75681382010-08-19 15:07:18 +01003367int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3368 return map->instance_size();
3369}
3370
3371
3372void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3373 v->VisitExternalReference(
3374 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3375}
3376
3377
3378template<typename StaticVisitor>
3379void Proxy::ProxyIterateBody() {
3380 StaticVisitor::VisitExternalReference(
3381 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3382}
3383
3384
3385void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3386 typedef v8::String::ExternalAsciiStringResource Resource;
3387 v->VisitExternalAsciiString(
3388 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3389}
3390
3391
3392template<typename StaticVisitor>
3393void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3394 typedef v8::String::ExternalAsciiStringResource Resource;
3395 StaticVisitor::VisitExternalAsciiString(
3396 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3397}
3398
3399
3400void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3401 typedef v8::String::ExternalStringResource Resource;
3402 v->VisitExternalTwoByteString(
3403 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3404}
3405
3406
3407template<typename StaticVisitor>
3408void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3409 typedef v8::String::ExternalStringResource Resource;
3410 StaticVisitor::VisitExternalTwoByteString(
3411 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3412}
3413
3414#define SLOT_ADDR(obj, offset) \
3415 reinterpret_cast<Object**>((obj)->address() + offset)
3416
3417template<int start_offset, int end_offset, int size>
3418void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3419 HeapObject* obj,
3420 ObjectVisitor* v) {
3421 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3422}
3423
3424
3425template<int start_offset>
3426void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3427 int object_size,
3428 ObjectVisitor* v) {
3429 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3430}
3431
3432#undef SLOT_ADDR
3433
3434
Steve Blocka7e24c12009-10-30 11:49:00 +00003435#undef CAST_ACCESSOR
3436#undef INT_ACCESSORS
3437#undef SMI_ACCESSORS
3438#undef ACCESSORS
3439#undef FIELD_ADDR
3440#undef READ_FIELD
3441#undef WRITE_FIELD
3442#undef WRITE_BARRIER
3443#undef CONDITIONAL_WRITE_BARRIER
3444#undef READ_MEMADDR_FIELD
3445#undef WRITE_MEMADDR_FIELD
3446#undef READ_DOUBLE_FIELD
3447#undef WRITE_DOUBLE_FIELD
3448#undef READ_INT_FIELD
3449#undef WRITE_INT_FIELD
3450#undef READ_SHORT_FIELD
3451#undef WRITE_SHORT_FIELD
3452#undef READ_BYTE_FIELD
3453#undef WRITE_BYTE_FIELD
3454
3455
3456} } // namespace v8::internal
3457
3458#endif // V8_OBJECTS_INL_H_