blob: d6571bff090a5eb9cf568d054b3b490599d3104d [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 Blocka7e24c12009-10-30 11:49:00 +00001169 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001170 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1171 value->IsExternalArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00001172 WRITE_FIELD(this, kElementsOffset, value);
1173 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1174}
1175
1176
1177void JSObject::initialize_properties() {
1178 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1179 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1180}
1181
1182
1183void JSObject::initialize_elements() {
1184 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1185 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1186}
1187
1188
1189ACCESSORS(Oddball, to_string, String, kToStringOffset)
1190ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1191
1192
1193Object* JSGlobalPropertyCell::value() {
1194 return READ_FIELD(this, kValueOffset);
1195}
1196
1197
1198void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1199 // The write barrier is not used for global property cells.
1200 ASSERT(!val->IsJSGlobalPropertyCell());
1201 WRITE_FIELD(this, kValueOffset, val);
1202}
1203
1204
1205int JSObject::GetHeaderSize() {
1206 InstanceType type = map()->instance_type();
1207 // Check for the most common kind of JavaScript object before
1208 // falling into the generic switch. This speeds up the internal
1209 // field operations considerably on average.
1210 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1211 switch (type) {
1212 case JS_GLOBAL_PROXY_TYPE:
1213 return JSGlobalProxy::kSize;
1214 case JS_GLOBAL_OBJECT_TYPE:
1215 return JSGlobalObject::kSize;
1216 case JS_BUILTINS_OBJECT_TYPE:
1217 return JSBuiltinsObject::kSize;
1218 case JS_FUNCTION_TYPE:
1219 return JSFunction::kSize;
1220 case JS_VALUE_TYPE:
1221 return JSValue::kSize;
1222 case JS_ARRAY_TYPE:
1223 return JSValue::kSize;
1224 case JS_REGEXP_TYPE:
1225 return JSValue::kSize;
1226 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1227 return JSObject::kHeaderSize;
1228 default:
1229 UNREACHABLE();
1230 return 0;
1231 }
1232}
1233
1234
1235int JSObject::GetInternalFieldCount() {
1236 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1237 // Make sure to adjust for the number of in-object properties. These
1238 // properties do contribute to the size, but are not internal fields.
1239 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1240 map()->inobject_properties();
1241}
1242
1243
1244Object* JSObject::GetInternalField(int index) {
1245 ASSERT(index < GetInternalFieldCount() && index >= 0);
1246 // Internal objects do follow immediately after the header, whereas in-object
1247 // properties are at the end of the object. Therefore there is no need
1248 // to adjust the index here.
1249 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1250}
1251
1252
1253void JSObject::SetInternalField(int index, Object* value) {
1254 ASSERT(index < GetInternalFieldCount() && index >= 0);
1255 // Internal objects do follow immediately after the header, whereas in-object
1256 // properties are at the end of the object. Therefore there is no need
1257 // to adjust the index here.
1258 int offset = GetHeaderSize() + (kPointerSize * index);
1259 WRITE_FIELD(this, offset, value);
1260 WRITE_BARRIER(this, offset);
1261}
1262
1263
1264// Access fast-case object properties at index. The use of these routines
1265// is needed to correctly distinguish between properties stored in-object and
1266// properties stored in the properties array.
1267Object* JSObject::FastPropertyAt(int index) {
1268 // Adjust for the number of properties stored in the object.
1269 index -= map()->inobject_properties();
1270 if (index < 0) {
1271 int offset = map()->instance_size() + (index * kPointerSize);
1272 return READ_FIELD(this, offset);
1273 } else {
1274 ASSERT(index < properties()->length());
1275 return properties()->get(index);
1276 }
1277}
1278
1279
1280Object* JSObject::FastPropertyAtPut(int index, Object* value) {
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 WRITE_FIELD(this, offset, value);
1286 WRITE_BARRIER(this, offset);
1287 } else {
1288 ASSERT(index < properties()->length());
1289 properties()->set(index, value);
1290 }
1291 return value;
1292}
1293
1294
1295Object* JSObject::InObjectPropertyAt(int index) {
1296 // Adjust for the number of properties stored in the object.
1297 index -= map()->inobject_properties();
1298 ASSERT(index < 0);
1299 int offset = map()->instance_size() + (index * kPointerSize);
1300 return READ_FIELD(this, offset);
1301}
1302
1303
1304Object* JSObject::InObjectPropertyAtPut(int index,
1305 Object* value,
1306 WriteBarrierMode mode) {
1307 // Adjust for the number of properties stored in the object.
1308 index -= map()->inobject_properties();
1309 ASSERT(index < 0);
1310 int offset = map()->instance_size() + (index * kPointerSize);
1311 WRITE_FIELD(this, offset, value);
1312 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1313 return value;
1314}
1315
1316
1317
1318void JSObject::InitializeBody(int object_size) {
1319 Object* value = Heap::undefined_value();
1320 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1321 WRITE_FIELD(this, offset, value);
1322 }
1323}
1324
1325
1326void Struct::InitializeBody(int object_size) {
1327 Object* value = Heap::undefined_value();
1328 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1329 WRITE_FIELD(this, offset, value);
1330 }
1331}
1332
1333
1334bool JSObject::HasFastProperties() {
1335 return !properties()->IsDictionary();
1336}
1337
1338
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001339bool Object::ToArrayIndex(uint32_t* index) {
1340 if (IsSmi()) {
1341 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 if (value < 0) return false;
1343 *index = value;
1344 return true;
1345 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001346 if (IsHeapNumber()) {
1347 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001348 uint32_t uint_value = static_cast<uint32_t>(value);
1349 if (value == static_cast<double>(uint_value)) {
1350 *index = uint_value;
1351 return true;
1352 }
1353 }
1354 return false;
1355}
1356
1357
1358bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1359 if (!this->IsJSValue()) return false;
1360
1361 JSValue* js_value = JSValue::cast(this);
1362 if (!js_value->value()->IsString()) return false;
1363
1364 String* str = String::cast(js_value->value());
1365 if (index >= (uint32_t)str->length()) return false;
1366
1367 return true;
1368}
1369
1370
1371Object* FixedArray::get(int index) {
1372 ASSERT(index >= 0 && index < this->length());
1373 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1374}
1375
1376
1377void FixedArray::set(int index, Smi* value) {
1378 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1379 int offset = kHeaderSize + index * kPointerSize;
1380 WRITE_FIELD(this, offset, value);
1381}
1382
1383
1384void FixedArray::set(int index, Object* value) {
1385 ASSERT(index >= 0 && index < this->length());
1386 int offset = kHeaderSize + index * kPointerSize;
1387 WRITE_FIELD(this, offset, value);
1388 WRITE_BARRIER(this, offset);
1389}
1390
1391
Leon Clarke4515c472010-02-03 11:58:03 +00001392WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001393 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1394 return UPDATE_WRITE_BARRIER;
1395}
1396
1397
1398void FixedArray::set(int index,
1399 Object* value,
1400 WriteBarrierMode mode) {
1401 ASSERT(index >= 0 && index < this->length());
1402 int offset = kHeaderSize + index * kPointerSize;
1403 WRITE_FIELD(this, offset, value);
1404 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1405}
1406
1407
1408void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1409 ASSERT(index >= 0 && index < array->length());
Leon Clarke4515c472010-02-03 11:58:03 +00001410 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001411 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1412}
1413
1414
1415void FixedArray::set_undefined(int index) {
1416 ASSERT(index >= 0 && index < this->length());
1417 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1418 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1419 Heap::undefined_value());
1420}
1421
1422
1423void FixedArray::set_null(int index) {
1424 ASSERT(index >= 0 && index < this->length());
1425 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1426 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1427}
1428
1429
1430void FixedArray::set_the_hole(int index) {
1431 ASSERT(index >= 0 && index < this->length());
1432 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1433 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1434}
1435
1436
Steve Block6ded16b2010-05-10 14:33:55 +01001437Object** FixedArray::data_start() {
1438 return HeapObject::RawField(this, kHeaderSize);
1439}
1440
1441
Steve Blocka7e24c12009-10-30 11:49:00 +00001442bool DescriptorArray::IsEmpty() {
1443 ASSERT(this == Heap::empty_descriptor_array() ||
1444 this->length() > 2);
1445 return this == Heap::empty_descriptor_array();
1446}
1447
1448
1449void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1450 Object* tmp = array->get(first);
1451 fast_set(array, first, array->get(second));
1452 fast_set(array, second, tmp);
1453}
1454
1455
1456int DescriptorArray::Search(String* name) {
1457 SLOW_ASSERT(IsSortedNoDuplicates());
1458
1459 // Check for empty descriptor array.
1460 int nof = number_of_descriptors();
1461 if (nof == 0) return kNotFound;
1462
1463 // Fast case: do linear search for small arrays.
1464 const int kMaxElementsForLinearSearch = 8;
1465 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1466 return LinearSearch(name, nof);
1467 }
1468
1469 // Slow case: perform binary search.
1470 return BinarySearch(name, 0, nof - 1);
1471}
1472
1473
1474String* DescriptorArray::GetKey(int descriptor_number) {
1475 ASSERT(descriptor_number < number_of_descriptors());
1476 return String::cast(get(ToKeyIndex(descriptor_number)));
1477}
1478
1479
1480Object* DescriptorArray::GetValue(int descriptor_number) {
1481 ASSERT(descriptor_number < number_of_descriptors());
1482 return GetContentArray()->get(ToValueIndex(descriptor_number));
1483}
1484
1485
1486Smi* DescriptorArray::GetDetails(int descriptor_number) {
1487 ASSERT(descriptor_number < number_of_descriptors());
1488 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1489}
1490
1491
1492PropertyType DescriptorArray::GetType(int descriptor_number) {
1493 ASSERT(descriptor_number < number_of_descriptors());
1494 return PropertyDetails(GetDetails(descriptor_number)).type();
1495}
1496
1497
1498int DescriptorArray::GetFieldIndex(int descriptor_number) {
1499 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1500}
1501
1502
1503JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1504 return JSFunction::cast(GetValue(descriptor_number));
1505}
1506
1507
1508Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1509 ASSERT(GetType(descriptor_number) == CALLBACKS);
1510 return GetValue(descriptor_number);
1511}
1512
1513
1514AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1515 ASSERT(GetType(descriptor_number) == CALLBACKS);
1516 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1517 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1518}
1519
1520
1521bool DescriptorArray::IsProperty(int descriptor_number) {
1522 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1523}
1524
1525
1526bool DescriptorArray::IsTransition(int descriptor_number) {
1527 PropertyType t = GetType(descriptor_number);
1528 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1529}
1530
1531
1532bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1533 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1534}
1535
1536
1537bool DescriptorArray::IsDontEnum(int descriptor_number) {
1538 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1539}
1540
1541
1542void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1543 desc->Init(GetKey(descriptor_number),
1544 GetValue(descriptor_number),
1545 GetDetails(descriptor_number));
1546}
1547
1548
1549void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1550 // Range check.
1551 ASSERT(descriptor_number < number_of_descriptors());
1552
Leon Clarkee46be812010-01-19 14:06:41 +00001553 // Make sure none of the elements in desc are in new space.
Steve Blocka7e24c12009-10-30 11:49:00 +00001554 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1555 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1556
1557 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1558 FixedArray* content_array = GetContentArray();
1559 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1560 fast_set(content_array, ToDetailsIndex(descriptor_number),
1561 desc->GetDetails().AsSmi());
1562}
1563
1564
1565void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1566 Descriptor desc;
1567 src->Get(src_index, &desc);
1568 Set(index, &desc);
1569}
1570
1571
1572void DescriptorArray::Swap(int first, int second) {
1573 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1574 FixedArray* content_array = GetContentArray();
1575 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1576 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1577}
1578
1579
1580bool NumberDictionary::requires_slow_elements() {
1581 Object* max_index_object = get(kMaxNumberKeyIndex);
1582 if (!max_index_object->IsSmi()) return false;
1583 return 0 !=
1584 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1585}
1586
1587uint32_t NumberDictionary::max_number_key() {
1588 ASSERT(!requires_slow_elements());
1589 Object* max_index_object = get(kMaxNumberKeyIndex);
1590 if (!max_index_object->IsSmi()) return 0;
1591 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1592 return value >> kRequiresSlowElementsTagSize;
1593}
1594
1595void NumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00001596 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00001597}
1598
1599
1600// ------------------------------------
1601// Cast operations
1602
1603
1604CAST_ACCESSOR(FixedArray)
1605CAST_ACCESSOR(DescriptorArray)
1606CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001607CAST_ACCESSOR(JSFunctionResultCache)
Steve Blocka7e24c12009-10-30 11:49:00 +00001608CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001609CAST_ACCESSOR(CodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00001610CAST_ACCESSOR(MapCache)
1611CAST_ACCESSOR(String)
1612CAST_ACCESSOR(SeqString)
1613CAST_ACCESSOR(SeqAsciiString)
1614CAST_ACCESSOR(SeqTwoByteString)
1615CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00001616CAST_ACCESSOR(ExternalString)
1617CAST_ACCESSOR(ExternalAsciiString)
1618CAST_ACCESSOR(ExternalTwoByteString)
1619CAST_ACCESSOR(JSObject)
1620CAST_ACCESSOR(Smi)
1621CAST_ACCESSOR(Failure)
1622CAST_ACCESSOR(HeapObject)
1623CAST_ACCESSOR(HeapNumber)
1624CAST_ACCESSOR(Oddball)
1625CAST_ACCESSOR(JSGlobalPropertyCell)
1626CAST_ACCESSOR(SharedFunctionInfo)
1627CAST_ACCESSOR(Map)
1628CAST_ACCESSOR(JSFunction)
1629CAST_ACCESSOR(GlobalObject)
1630CAST_ACCESSOR(JSGlobalProxy)
1631CAST_ACCESSOR(JSGlobalObject)
1632CAST_ACCESSOR(JSBuiltinsObject)
1633CAST_ACCESSOR(Code)
1634CAST_ACCESSOR(JSArray)
1635CAST_ACCESSOR(JSRegExp)
1636CAST_ACCESSOR(Proxy)
1637CAST_ACCESSOR(ByteArray)
1638CAST_ACCESSOR(PixelArray)
Steve Block3ce2e202009-11-05 08:53:23 +00001639CAST_ACCESSOR(ExternalArray)
1640CAST_ACCESSOR(ExternalByteArray)
1641CAST_ACCESSOR(ExternalUnsignedByteArray)
1642CAST_ACCESSOR(ExternalShortArray)
1643CAST_ACCESSOR(ExternalUnsignedShortArray)
1644CAST_ACCESSOR(ExternalIntArray)
1645CAST_ACCESSOR(ExternalUnsignedIntArray)
1646CAST_ACCESSOR(ExternalFloatArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00001647CAST_ACCESSOR(Struct)
1648
1649
1650#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1651 STRUCT_LIST(MAKE_STRUCT_CAST)
1652#undef MAKE_STRUCT_CAST
1653
1654
1655template <typename Shape, typename Key>
1656HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1657 ASSERT(obj->IsHashTable());
1658 return reinterpret_cast<HashTable*>(obj);
1659}
1660
1661
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001662SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1663SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1664
1665INT_ACCESSORS(PixelArray, length, kLengthOffset)
1666INT_ACCESSORS(ExternalArray, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00001667
1668
Steve Block6ded16b2010-05-10 14:33:55 +01001669SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00001670
1671
1672uint32_t String::hash_field() {
1673 return READ_UINT32_FIELD(this, kHashFieldOffset);
1674}
1675
1676
1677void String::set_hash_field(uint32_t value) {
1678 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001679#if V8_HOST_ARCH_64_BIT
1680 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1681#endif
Steve Blockd0582a62009-12-15 09:54:21 +00001682}
1683
1684
Steve Blocka7e24c12009-10-30 11:49:00 +00001685bool String::Equals(String* other) {
1686 if (other == this) return true;
1687 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1688 return false;
1689 }
1690 return SlowEquals(other);
1691}
1692
1693
Steve Block6ded16b2010-05-10 14:33:55 +01001694Object* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001695 if (!StringShape(this).IsCons()) return this;
1696 ConsString* cons = ConsString::cast(this);
1697 if (cons->second()->length() == 0) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01001698 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00001699}
1700
1701
Leon Clarkef7060e22010-06-03 12:02:55 +01001702String* String::TryFlattenGetString(PretenureFlag pretenure) {
1703 Object* flat = TryFlatten(pretenure);
1704 return flat->IsFailure() ? this : String::cast(flat);
1705}
1706
1707
Steve Blocka7e24c12009-10-30 11:49:00 +00001708uint16_t String::Get(int index) {
1709 ASSERT(index >= 0 && index < length());
1710 switch (StringShape(this).full_representation_tag()) {
1711 case kSeqStringTag | kAsciiStringTag:
1712 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1713 case kSeqStringTag | kTwoByteStringTag:
1714 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1715 case kConsStringTag | kAsciiStringTag:
1716 case kConsStringTag | kTwoByteStringTag:
1717 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001718 case kExternalStringTag | kAsciiStringTag:
1719 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1720 case kExternalStringTag | kTwoByteStringTag:
1721 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1722 default:
1723 break;
1724 }
1725
1726 UNREACHABLE();
1727 return 0;
1728}
1729
1730
1731void String::Set(int index, uint16_t value) {
1732 ASSERT(index >= 0 && index < length());
1733 ASSERT(StringShape(this).IsSequential());
1734
1735 return this->IsAsciiRepresentation()
1736 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1737 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1738}
1739
1740
1741bool String::IsFlat() {
1742 switch (StringShape(this).representation_tag()) {
1743 case kConsStringTag: {
1744 String* second = ConsString::cast(this)->second();
1745 // Only flattened strings have second part empty.
1746 return second->length() == 0;
1747 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001748 default:
1749 return true;
1750 }
1751}
1752
1753
1754uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1755 ASSERT(index >= 0 && index < length());
1756 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1757}
1758
1759
1760void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1761 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1762 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1763 static_cast<byte>(value));
1764}
1765
1766
1767Address SeqAsciiString::GetCharsAddress() {
1768 return FIELD_ADDR(this, kHeaderSize);
1769}
1770
1771
1772char* SeqAsciiString::GetChars() {
1773 return reinterpret_cast<char*>(GetCharsAddress());
1774}
1775
1776
1777Address SeqTwoByteString::GetCharsAddress() {
1778 return FIELD_ADDR(this, kHeaderSize);
1779}
1780
1781
1782uc16* SeqTwoByteString::GetChars() {
1783 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1784}
1785
1786
1787uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1788 ASSERT(index >= 0 && index < length());
1789 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1790}
1791
1792
1793void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1794 ASSERT(index >= 0 && index < length());
1795 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1796}
1797
1798
1799int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001800 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001801}
1802
1803
1804int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001805 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001806}
1807
1808
1809String* ConsString::first() {
1810 return String::cast(READ_FIELD(this, kFirstOffset));
1811}
1812
1813
1814Object* ConsString::unchecked_first() {
1815 return READ_FIELD(this, kFirstOffset);
1816}
1817
1818
1819void ConsString::set_first(String* value, WriteBarrierMode mode) {
1820 WRITE_FIELD(this, kFirstOffset, value);
1821 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1822}
1823
1824
1825String* ConsString::second() {
1826 return String::cast(READ_FIELD(this, kSecondOffset));
1827}
1828
1829
1830Object* ConsString::unchecked_second() {
1831 return READ_FIELD(this, kSecondOffset);
1832}
1833
1834
1835void ConsString::set_second(String* value, WriteBarrierMode mode) {
1836 WRITE_FIELD(this, kSecondOffset, value);
1837 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1838}
1839
1840
Steve Blocka7e24c12009-10-30 11:49:00 +00001841ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1842 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1843}
1844
1845
1846void ExternalAsciiString::set_resource(
1847 ExternalAsciiString::Resource* resource) {
1848 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1849}
1850
1851
Steve Blocka7e24c12009-10-30 11:49:00 +00001852ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1853 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1854}
1855
1856
1857void ExternalTwoByteString::set_resource(
1858 ExternalTwoByteString::Resource* resource) {
1859 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1860}
1861
1862
Steve Block6ded16b2010-05-10 14:33:55 +01001863void JSFunctionResultCache::MakeZeroSize() {
1864 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1865 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1866}
1867
1868
1869void JSFunctionResultCache::Clear() {
1870 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1871 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1872 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1873 MakeZeroSize();
1874}
1875
1876
Steve Blocka7e24c12009-10-30 11:49:00 +00001877byte ByteArray::get(int index) {
1878 ASSERT(index >= 0 && index < this->length());
1879 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1880}
1881
1882
1883void ByteArray::set(int index, byte value) {
1884 ASSERT(index >= 0 && index < this->length());
1885 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1886}
1887
1888
1889int ByteArray::get_int(int index) {
1890 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1891 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1892}
1893
1894
1895ByteArray* ByteArray::FromDataStartAddress(Address address) {
1896 ASSERT_TAG_ALIGNED(address);
1897 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1898}
1899
1900
1901Address ByteArray::GetDataStartAddress() {
1902 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1903}
1904
1905
1906uint8_t* PixelArray::external_pointer() {
1907 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1908 return reinterpret_cast<uint8_t*>(ptr);
1909}
1910
1911
1912void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1913 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1914 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1915}
1916
1917
1918uint8_t PixelArray::get(int index) {
1919 ASSERT((index >= 0) && (index < this->length()));
1920 uint8_t* ptr = external_pointer();
1921 return ptr[index];
1922}
1923
1924
1925void PixelArray::set(int index, uint8_t value) {
1926 ASSERT((index >= 0) && (index < this->length()));
1927 uint8_t* ptr = external_pointer();
1928 ptr[index] = value;
1929}
1930
1931
Steve Block3ce2e202009-11-05 08:53:23 +00001932void* ExternalArray::external_pointer() {
1933 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1934 return reinterpret_cast<void*>(ptr);
1935}
1936
1937
1938void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1939 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1940 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1941}
1942
1943
1944int8_t ExternalByteArray::get(int index) {
1945 ASSERT((index >= 0) && (index < this->length()));
1946 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1947 return ptr[index];
1948}
1949
1950
1951void ExternalByteArray::set(int index, int8_t value) {
1952 ASSERT((index >= 0) && (index < this->length()));
1953 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1954 ptr[index] = value;
1955}
1956
1957
1958uint8_t ExternalUnsignedByteArray::get(int index) {
1959 ASSERT((index >= 0) && (index < this->length()));
1960 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1961 return ptr[index];
1962}
1963
1964
1965void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1966 ASSERT((index >= 0) && (index < this->length()));
1967 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1968 ptr[index] = value;
1969}
1970
1971
1972int16_t ExternalShortArray::get(int index) {
1973 ASSERT((index >= 0) && (index < this->length()));
1974 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1975 return ptr[index];
1976}
1977
1978
1979void ExternalShortArray::set(int index, int16_t value) {
1980 ASSERT((index >= 0) && (index < this->length()));
1981 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1982 ptr[index] = value;
1983}
1984
1985
1986uint16_t ExternalUnsignedShortArray::get(int index) {
1987 ASSERT((index >= 0) && (index < this->length()));
1988 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1989 return ptr[index];
1990}
1991
1992
1993void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1994 ASSERT((index >= 0) && (index < this->length()));
1995 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1996 ptr[index] = value;
1997}
1998
1999
2000int32_t ExternalIntArray::get(int index) {
2001 ASSERT((index >= 0) && (index < this->length()));
2002 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2003 return ptr[index];
2004}
2005
2006
2007void ExternalIntArray::set(int index, int32_t value) {
2008 ASSERT((index >= 0) && (index < this->length()));
2009 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2010 ptr[index] = value;
2011}
2012
2013
2014uint32_t ExternalUnsignedIntArray::get(int index) {
2015 ASSERT((index >= 0) && (index < this->length()));
2016 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2017 return ptr[index];
2018}
2019
2020
2021void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2022 ASSERT((index >= 0) && (index < this->length()));
2023 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2024 ptr[index] = value;
2025}
2026
2027
2028float ExternalFloatArray::get(int index) {
2029 ASSERT((index >= 0) && (index < this->length()));
2030 float* ptr = static_cast<float*>(external_pointer());
2031 return ptr[index];
2032}
2033
2034
2035void ExternalFloatArray::set(int index, float value) {
2036 ASSERT((index >= 0) && (index < this->length()));
2037 float* ptr = static_cast<float*>(external_pointer());
2038 ptr[index] = value;
2039}
2040
2041
Steve Blocka7e24c12009-10-30 11:49:00 +00002042int Map::instance_size() {
2043 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2044}
2045
2046
2047int Map::inobject_properties() {
2048 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2049}
2050
2051
2052int Map::pre_allocated_property_fields() {
2053 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2054}
2055
2056
2057int HeapObject::SizeFromMap(Map* map) {
2058 InstanceType instance_type = map->instance_type();
2059 // Only inline the most frequent cases.
2060 if (instance_type == JS_OBJECT_TYPE ||
2061 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
2062 (kStringTag | kConsStringTag) ||
2063 instance_type == JS_ARRAY_TYPE) return map->instance_size();
2064 if (instance_type == FIXED_ARRAY_TYPE) {
2065 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
2066 }
2067 if (instance_type == BYTE_ARRAY_TYPE) {
2068 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2069 }
2070 // Otherwise do the general size computation.
2071 return SlowSizeFromMap(map);
2072}
2073
2074
2075void Map::set_instance_size(int value) {
2076 ASSERT_EQ(0, value & (kPointerSize - 1));
2077 value >>= kPointerSizeLog2;
2078 ASSERT(0 <= value && value < 256);
2079 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2080}
2081
2082
2083void Map::set_inobject_properties(int value) {
2084 ASSERT(0 <= value && value < 256);
2085 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2086}
2087
2088
2089void Map::set_pre_allocated_property_fields(int value) {
2090 ASSERT(0 <= value && value < 256);
2091 WRITE_BYTE_FIELD(this,
2092 kPreAllocatedPropertyFieldsOffset,
2093 static_cast<byte>(value));
2094}
2095
2096
2097InstanceType Map::instance_type() {
2098 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2099}
2100
2101
2102void Map::set_instance_type(InstanceType value) {
2103 ASSERT(0 <= value && value < 256);
2104 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2105}
2106
2107
2108int Map::unused_property_fields() {
2109 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2110}
2111
2112
2113void Map::set_unused_property_fields(int value) {
2114 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2115}
2116
2117
2118byte Map::bit_field() {
2119 return READ_BYTE_FIELD(this, kBitFieldOffset);
2120}
2121
2122
2123void Map::set_bit_field(byte value) {
2124 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2125}
2126
2127
2128byte Map::bit_field2() {
2129 return READ_BYTE_FIELD(this, kBitField2Offset);
2130}
2131
2132
2133void Map::set_bit_field2(byte value) {
2134 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2135}
2136
2137
2138void Map::set_non_instance_prototype(bool value) {
2139 if (value) {
2140 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2141 } else {
2142 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2143 }
2144}
2145
2146
2147bool Map::has_non_instance_prototype() {
2148 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2149}
2150
2151
Steve Block6ded16b2010-05-10 14:33:55 +01002152void Map::set_function_with_prototype(bool value) {
2153 if (value) {
2154 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2155 } else {
2156 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2157 }
2158}
2159
2160
2161bool Map::function_with_prototype() {
2162 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2163}
2164
2165
Steve Blocka7e24c12009-10-30 11:49:00 +00002166void Map::set_is_access_check_needed(bool access_check_needed) {
2167 if (access_check_needed) {
2168 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2169 } else {
2170 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2171 }
2172}
2173
2174
2175bool Map::is_access_check_needed() {
2176 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2177}
2178
2179
2180Code::Flags Code::flags() {
2181 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2182}
2183
2184
2185void Code::set_flags(Code::Flags flags) {
2186 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2187 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002188 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2189 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002190 ExtractArgumentsCountFromFlags(flags) >= 0);
2191 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2192}
2193
2194
2195Code::Kind Code::kind() {
2196 return ExtractKindFromFlags(flags());
2197}
2198
2199
2200InLoopFlag Code::ic_in_loop() {
2201 return ExtractICInLoopFromFlags(flags());
2202}
2203
2204
2205InlineCacheState Code::ic_state() {
2206 InlineCacheState result = ExtractICStateFromFlags(flags());
2207 // Only allow uninitialized or debugger states for non-IC code
2208 // objects. This is used in the debugger to determine whether or not
2209 // a call to code object has been replaced with a debug break call.
2210 ASSERT(is_inline_cache_stub() ||
2211 result == UNINITIALIZED ||
2212 result == DEBUG_BREAK ||
2213 result == DEBUG_PREPARE_STEP_IN);
2214 return result;
2215}
2216
2217
2218PropertyType Code::type() {
2219 ASSERT(ic_state() == MONOMORPHIC);
2220 return ExtractTypeFromFlags(flags());
2221}
2222
2223
2224int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002225 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002226 return ExtractArgumentsCountFromFlags(flags());
2227}
2228
2229
2230CodeStub::Major Code::major_key() {
Steve Block6ded16b2010-05-10 14:33:55 +01002231 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002232 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2233 kStubMajorKeyOffset));
2234}
2235
2236
2237void Code::set_major_key(CodeStub::Major major) {
Steve Block6ded16b2010-05-10 14:33:55 +01002238 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002239 ASSERT(0 <= major && major < 256);
2240 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2241}
2242
2243
2244bool Code::is_inline_cache_stub() {
2245 Kind kind = this->kind();
2246 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2247}
2248
2249
2250Code::Flags Code::ComputeFlags(Kind kind,
2251 InLoopFlag in_loop,
2252 InlineCacheState ic_state,
2253 PropertyType type,
2254 int argc) {
2255 // Compute the bit mask.
2256 int bits = kind << kFlagsKindShift;
2257 if (in_loop) bits |= kFlagsICInLoopMask;
2258 bits |= ic_state << kFlagsICStateShift;
2259 bits |= type << kFlagsTypeShift;
2260 bits |= argc << kFlagsArgumentsCountShift;
2261 // Cast to flags and validate result before returning it.
2262 Flags result = static_cast<Flags>(bits);
2263 ASSERT(ExtractKindFromFlags(result) == kind);
2264 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2265 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2266 ASSERT(ExtractTypeFromFlags(result) == type);
2267 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2268 return result;
2269}
2270
2271
2272Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2273 PropertyType type,
2274 InLoopFlag in_loop,
2275 int argc) {
2276 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
2277}
2278
2279
2280Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2281 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2282 return static_cast<Kind>(bits);
2283}
2284
2285
2286InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2287 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2288 return static_cast<InlineCacheState>(bits);
2289}
2290
2291
2292InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2293 int bits = (flags & kFlagsICInLoopMask);
2294 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2295}
2296
2297
2298PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2299 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2300 return static_cast<PropertyType>(bits);
2301}
2302
2303
2304int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2305 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2306}
2307
2308
2309Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2310 int bits = flags & ~kFlagsTypeMask;
2311 return static_cast<Flags>(bits);
2312}
2313
2314
2315Code* Code::GetCodeFromTargetAddress(Address address) {
2316 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2317 // GetCodeFromTargetAddress might be called when marking objects during mark
2318 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2319 // Code::cast. Code::cast does not work when the object's map is
2320 // marked.
2321 Code* result = reinterpret_cast<Code*>(code);
2322 return result;
2323}
2324
2325
2326Object* Map::prototype() {
2327 return READ_FIELD(this, kPrototypeOffset);
2328}
2329
2330
2331void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2332 ASSERT(value->IsNull() || value->IsJSObject());
2333 WRITE_FIELD(this, kPrototypeOffset, value);
2334 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2335}
2336
2337
2338ACCESSORS(Map, instance_descriptors, DescriptorArray,
2339 kInstanceDescriptorsOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002340ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002341ACCESSORS(Map, constructor, Object, kConstructorOffset)
2342
2343ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2344ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2345
2346ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2347ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2348ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2349
2350ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2351
2352ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2353ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2354ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2355ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2356ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002357ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002358
2359ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2360ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2361ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2362
2363ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2364ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2365ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2366ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2367ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2368ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2369
2370ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2371ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2372
2373ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2374ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2375
2376ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2377ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2378ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2379 kPropertyAccessorsOffset)
2380ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2381 kPrototypeTemplateOffset)
2382ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2383ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2384 kNamedPropertyHandlerOffset)
2385ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2386 kIndexedPropertyHandlerOffset)
2387ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2388 kInstanceTemplateOffset)
2389ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2390ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2391ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2392 kInstanceCallHandlerOffset)
2393ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2394 kAccessCheckInfoOffset)
2395ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2396
2397ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2398ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2399 kInternalFieldCountOffset)
2400
2401ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2402ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2403
2404ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2405
2406ACCESSORS(Script, source, Object, kSourceOffset)
2407ACCESSORS(Script, name, Object, kNameOffset)
2408ACCESSORS(Script, id, Object, kIdOffset)
2409ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2410ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2411ACCESSORS(Script, data, Object, kDataOffset)
2412ACCESSORS(Script, context_data, Object, kContextOffset)
2413ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2414ACCESSORS(Script, type, Smi, kTypeOffset)
2415ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2416ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002417ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002418ACCESSORS(Script, eval_from_instructions_offset, Smi,
2419 kEvalFrominstructionsOffsetOffset)
2420
2421#ifdef ENABLE_DEBUGGER_SUPPORT
2422ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2423ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2424ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2425ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2426
2427ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2428ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2429ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2430ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2431#endif
2432
Steve Blocka7e24c12009-10-30 11:49:00 +00002433ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002434ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002435ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2436 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002437ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002438ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2439ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2440ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2441ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2442 kThisPropertyAssignmentsOffset)
2443
2444BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2445 kHiddenPrototypeBit)
2446BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2447BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2448 kNeedsAccessCheckBit)
2449BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2450 kIsExpressionBit)
2451BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2452 kIsTopLevelBit)
2453BOOL_GETTER(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002454 has_only_simple_this_property_assignments,
2455 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00002456BOOL_ACCESSORS(SharedFunctionInfo,
2457 compiler_hints,
Leon Clarked91b9f72010-01-27 17:25:45 +00002458 try_full_codegen,
2459 kTryFullCodegen)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002460BOOL_ACCESSORS(SharedFunctionInfo,
2461 compiler_hints,
2462 allows_lazy_compilation,
2463 kAllowLazyCompilation)
Steve Blocka7e24c12009-10-30 11:49:00 +00002464
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002465#if V8_HOST_ARCH_32_BIT
2466SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2467SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002468 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002469SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00002470 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002471SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2472SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00002473 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002474SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2475SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00002476 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002477SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002478 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002479SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002480 kThisPropertyAssignmentsCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002481#else
Steve Blocka7e24c12009-10-30 11:49:00 +00002482
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002483#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2484 int holder::name() { \
2485 int value = READ_INT_FIELD(this, offset); \
2486 ASSERT(kHeapObjectTag == 1); \
2487 ASSERT((value & kHeapObjectTag) == 0); \
2488 return value >> 1; \
2489 } \
2490 void holder::set_##name(int value) { \
2491 ASSERT(kHeapObjectTag == 1); \
2492 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2493 (value & 0xC0000000) == 0x000000000); \
2494 WRITE_INT_FIELD(this, \
2495 offset, \
2496 (value << 1) & ~kHeapObjectTag); \
2497 }
2498
2499#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2500 INT_ACCESSORS(holder, name, offset)
2501
2502
2503
2504PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2505PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2506 kFormalParameterCountOffset)
2507
2508PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2509 kExpectedNofPropertiesOffset)
2510PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2511
2512PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2513 kStartPositionAndTypeOffset)
2514PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2515
2516PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2517 kFunctionTokenPositionOffset)
2518PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2519 kCompilerHintsOffset)
2520
2521PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2522 kThisPropertyAssignmentsCountOffset)
2523#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002524
Steve Block6ded16b2010-05-10 14:33:55 +01002525ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2526ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2527
Steve Block3ce2e202009-11-05 08:53:23 +00002528bool Script::HasValidSource() {
2529 Object* src = this->source();
2530 if (!src->IsString()) return true;
2531 String* src_str = String::cast(src);
2532 if (!StringShape(src_str).IsExternal()) return true;
2533 if (src_str->IsAsciiRepresentation()) {
2534 return ExternalAsciiString::cast(src)->resource() != NULL;
2535 } else if (src_str->IsTwoByteRepresentation()) {
2536 return ExternalTwoByteString::cast(src)->resource() != NULL;
2537 }
2538 return true;
2539}
2540
2541
Steve Blocka7e24c12009-10-30 11:49:00 +00002542void SharedFunctionInfo::DontAdaptArguments() {
2543 ASSERT(code()->kind() == Code::BUILTIN);
2544 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2545}
2546
2547
2548int SharedFunctionInfo::start_position() {
2549 return start_position_and_type() >> kStartPositionShift;
2550}
2551
2552
2553void SharedFunctionInfo::set_start_position(int start_position) {
2554 set_start_position_and_type((start_position << kStartPositionShift)
2555 | (start_position_and_type() & ~kStartPositionMask));
2556}
2557
2558
2559Code* SharedFunctionInfo::code() {
2560 return Code::cast(READ_FIELD(this, kCodeOffset));
2561}
2562
2563
2564void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2565 WRITE_FIELD(this, kCodeOffset, value);
2566 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2567}
2568
2569
2570bool SharedFunctionInfo::is_compiled() {
2571 // TODO(1242782): Create a code kind for uncompiled code.
2572 return code()->kind() != Code::STUB;
2573}
2574
2575
Steve Block6ded16b2010-05-10 14:33:55 +01002576bool SharedFunctionInfo::IsApiFunction() {
2577 return function_data()->IsFunctionTemplateInfo();
2578}
2579
2580
2581FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2582 ASSERT(IsApiFunction());
2583 return FunctionTemplateInfo::cast(function_data());
2584}
2585
2586
2587bool SharedFunctionInfo::HasCustomCallGenerator() {
Kristian Monsen25f61362010-05-21 11:50:48 +01002588 return function_data()->IsSmi();
2589}
2590
2591
2592int SharedFunctionInfo::custom_call_generator_id() {
2593 ASSERT(HasCustomCallGenerator());
2594 return Smi::cast(function_data())->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002595}
2596
2597
2598bool JSFunction::IsBuiltin() {
2599 return context()->global()->IsJSBuiltinsObject();
2600}
2601
2602
Steve Blocka7e24c12009-10-30 11:49:00 +00002603Code* JSFunction::code() {
2604 return shared()->code();
2605}
2606
2607
2608void JSFunction::set_code(Code* value) {
2609 shared()->set_code(value);
2610}
2611
2612
2613Context* JSFunction::context() {
2614 return Context::cast(READ_FIELD(this, kContextOffset));
2615}
2616
2617
2618Object* JSFunction::unchecked_context() {
2619 return READ_FIELD(this, kContextOffset);
2620}
2621
2622
2623void JSFunction::set_context(Object* value) {
2624 ASSERT(value == Heap::undefined_value() || value->IsContext());
2625 WRITE_FIELD(this, kContextOffset, value);
2626 WRITE_BARRIER(this, kContextOffset);
2627}
2628
2629ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2630 kPrototypeOrInitialMapOffset)
2631
2632
2633Map* JSFunction::initial_map() {
2634 return Map::cast(prototype_or_initial_map());
2635}
2636
2637
2638void JSFunction::set_initial_map(Map* value) {
2639 set_prototype_or_initial_map(value);
2640}
2641
2642
2643bool JSFunction::has_initial_map() {
2644 return prototype_or_initial_map()->IsMap();
2645}
2646
2647
2648bool JSFunction::has_instance_prototype() {
2649 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2650}
2651
2652
2653bool JSFunction::has_prototype() {
2654 return map()->has_non_instance_prototype() || has_instance_prototype();
2655}
2656
2657
2658Object* JSFunction::instance_prototype() {
2659 ASSERT(has_instance_prototype());
2660 if (has_initial_map()) return initial_map()->prototype();
2661 // When there is no initial map and the prototype is a JSObject, the
2662 // initial map field is used for the prototype field.
2663 return prototype_or_initial_map();
2664}
2665
2666
2667Object* JSFunction::prototype() {
2668 ASSERT(has_prototype());
2669 // If the function's prototype property has been set to a non-JSObject
2670 // value, that value is stored in the constructor field of the map.
2671 if (map()->has_non_instance_prototype()) return map()->constructor();
2672 return instance_prototype();
2673}
2674
Steve Block6ded16b2010-05-10 14:33:55 +01002675bool JSFunction::should_have_prototype() {
2676 return map()->function_with_prototype();
2677}
2678
Steve Blocka7e24c12009-10-30 11:49:00 +00002679
2680bool JSFunction::is_compiled() {
2681 return shared()->is_compiled();
2682}
2683
2684
2685int JSFunction::NumberOfLiterals() {
2686 return literals()->length();
2687}
2688
2689
2690Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2691 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002692 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00002693}
2694
2695
2696void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2697 Object* value) {
2698 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01002699 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2700 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2701}
2702
2703
2704Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2705 ASSERT(0 <= id && id < kJSBuiltinsCount);
2706 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2707}
2708
2709
2710void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2711 Code* value) {
2712 ASSERT(0 <= id && id < kJSBuiltinsCount);
2713 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2714 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002715}
2716
2717
2718Address Proxy::proxy() {
2719 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2720}
2721
2722
2723void Proxy::set_proxy(Address value) {
2724 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2725}
2726
2727
2728void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2729 visitor->VisitExternalReference(
2730 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2731}
2732
2733
2734ACCESSORS(JSValue, value, Object, kValueOffset)
2735
2736
2737JSValue* JSValue::cast(Object* obj) {
2738 ASSERT(obj->IsJSValue());
2739 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2740 return reinterpret_cast<JSValue*>(obj);
2741}
2742
2743
2744INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2745INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2746INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2747
2748
2749byte* Code::instruction_start() {
2750 return FIELD_ADDR(this, kHeaderSize);
2751}
2752
2753
2754int Code::body_size() {
2755 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2756}
2757
2758
2759byte* Code::relocation_start() {
2760 return FIELD_ADDR(this, kHeaderSize + instruction_size());
2761}
2762
2763
2764byte* Code::entry() {
2765 return instruction_start();
2766}
2767
2768
2769bool Code::contains(byte* pc) {
2770 return (instruction_start() <= pc) &&
2771 (pc < instruction_start() + instruction_size());
2772}
2773
2774
2775byte* Code::sinfo_start() {
2776 return FIELD_ADDR(this, kHeaderSize + body_size());
2777}
2778
2779
2780ACCESSORS(JSArray, length, Object, kLengthOffset)
2781
2782
2783ACCESSORS(JSRegExp, data, Object, kDataOffset)
2784
2785
2786JSRegExp::Type JSRegExp::TypeTag() {
2787 Object* data = this->data();
2788 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2789 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2790 return static_cast<JSRegExp::Type>(smi->value());
2791}
2792
2793
2794int JSRegExp::CaptureCount() {
2795 switch (TypeTag()) {
2796 case ATOM:
2797 return 0;
2798 case IRREGEXP:
2799 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2800 default:
2801 UNREACHABLE();
2802 return -1;
2803 }
2804}
2805
2806
2807JSRegExp::Flags JSRegExp::GetFlags() {
2808 ASSERT(this->data()->IsFixedArray());
2809 Object* data = this->data();
2810 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2811 return Flags(smi->value());
2812}
2813
2814
2815String* JSRegExp::Pattern() {
2816 ASSERT(this->data()->IsFixedArray());
2817 Object* data = this->data();
2818 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2819 return pattern;
2820}
2821
2822
2823Object* JSRegExp::DataAt(int index) {
2824 ASSERT(TypeTag() != NOT_COMPILED);
2825 return FixedArray::cast(data())->get(index);
2826}
2827
2828
2829void JSRegExp::SetDataAt(int index, Object* value) {
2830 ASSERT(TypeTag() != NOT_COMPILED);
2831 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2832 FixedArray::cast(data())->set(index, value);
2833}
2834
2835
2836JSObject::ElementsKind JSObject::GetElementsKind() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002837 HeapObject* array = elements();
Steve Blocka7e24c12009-10-30 11:49:00 +00002838 if (array->IsFixedArray()) {
2839 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2840 if (array->map() == Heap::fixed_array_map()) {
2841 return FAST_ELEMENTS;
2842 }
2843 ASSERT(array->IsDictionary());
2844 return DICTIONARY_ELEMENTS;
2845 }
Steve Block3ce2e202009-11-05 08:53:23 +00002846 if (array->IsExternalArray()) {
2847 switch (array->map()->instance_type()) {
2848 case EXTERNAL_BYTE_ARRAY_TYPE:
2849 return EXTERNAL_BYTE_ELEMENTS;
2850 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2851 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2852 case EXTERNAL_SHORT_ARRAY_TYPE:
2853 return EXTERNAL_SHORT_ELEMENTS;
2854 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2855 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2856 case EXTERNAL_INT_ARRAY_TYPE:
2857 return EXTERNAL_INT_ELEMENTS;
2858 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2859 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2860 default:
2861 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2862 return EXTERNAL_FLOAT_ELEMENTS;
2863 }
2864 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002865 ASSERT(array->IsPixelArray());
2866 return PIXEL_ELEMENTS;
2867}
2868
2869
2870bool JSObject::HasFastElements() {
2871 return GetElementsKind() == FAST_ELEMENTS;
2872}
2873
2874
2875bool JSObject::HasDictionaryElements() {
2876 return GetElementsKind() == DICTIONARY_ELEMENTS;
2877}
2878
2879
2880bool JSObject::HasPixelElements() {
2881 return GetElementsKind() == PIXEL_ELEMENTS;
2882}
2883
2884
Steve Block3ce2e202009-11-05 08:53:23 +00002885bool JSObject::HasExternalArrayElements() {
2886 return (HasExternalByteElements() ||
2887 HasExternalUnsignedByteElements() ||
2888 HasExternalShortElements() ||
2889 HasExternalUnsignedShortElements() ||
2890 HasExternalIntElements() ||
2891 HasExternalUnsignedIntElements() ||
2892 HasExternalFloatElements());
2893}
2894
2895
2896bool JSObject::HasExternalByteElements() {
2897 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2898}
2899
2900
2901bool JSObject::HasExternalUnsignedByteElements() {
2902 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2903}
2904
2905
2906bool JSObject::HasExternalShortElements() {
2907 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2908}
2909
2910
2911bool JSObject::HasExternalUnsignedShortElements() {
2912 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2913}
2914
2915
2916bool JSObject::HasExternalIntElements() {
2917 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2918}
2919
2920
2921bool JSObject::HasExternalUnsignedIntElements() {
2922 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2923}
2924
2925
2926bool JSObject::HasExternalFloatElements() {
2927 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2928}
2929
2930
Steve Blocka7e24c12009-10-30 11:49:00 +00002931bool JSObject::HasNamedInterceptor() {
2932 return map()->has_named_interceptor();
2933}
2934
2935
2936bool JSObject::HasIndexedInterceptor() {
2937 return map()->has_indexed_interceptor();
2938}
2939
2940
Steve Block6ded16b2010-05-10 14:33:55 +01002941bool JSObject::AllowsSetElementsLength() {
2942 bool result = elements()->IsFixedArray();
2943 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
2944 return result;
2945}
2946
2947
Steve Blocka7e24c12009-10-30 11:49:00 +00002948StringDictionary* JSObject::property_dictionary() {
2949 ASSERT(!HasFastProperties());
2950 return StringDictionary::cast(properties());
2951}
2952
2953
2954NumberDictionary* JSObject::element_dictionary() {
2955 ASSERT(HasDictionaryElements());
2956 return NumberDictionary::cast(elements());
2957}
2958
2959
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002960bool String::IsHashFieldComputed(uint32_t field) {
2961 return (field & kHashNotComputedMask) == 0;
2962}
2963
2964
Steve Blocka7e24c12009-10-30 11:49:00 +00002965bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002966 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00002967}
2968
2969
2970uint32_t String::Hash() {
2971 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00002972 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002973 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00002974 // Slow case: compute hash code and set it.
2975 return ComputeAndSetHash();
2976}
2977
2978
2979StringHasher::StringHasher(int length)
2980 : length_(length),
2981 raw_running_hash_(0),
2982 array_index_(0),
2983 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2984 is_first_char_(true),
2985 is_valid_(true) { }
2986
2987
2988bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00002989 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00002990}
2991
2992
2993void StringHasher::AddCharacter(uc32 c) {
2994 // Use the Jenkins one-at-a-time hash function to update the hash
2995 // for the given character.
2996 raw_running_hash_ += c;
2997 raw_running_hash_ += (raw_running_hash_ << 10);
2998 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2999 // Incremental array index computation.
3000 if (is_array_index_) {
3001 if (c < '0' || c > '9') {
3002 is_array_index_ = false;
3003 } else {
3004 int d = c - '0';
3005 if (is_first_char_) {
3006 is_first_char_ = false;
3007 if (c == '0' && length_ > 1) {
3008 is_array_index_ = false;
3009 return;
3010 }
3011 }
3012 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3013 is_array_index_ = false;
3014 } else {
3015 array_index_ = array_index_ * 10 + d;
3016 }
3017 }
3018 }
3019}
3020
3021
3022void StringHasher::AddCharacterNoIndex(uc32 c) {
3023 ASSERT(!is_array_index());
3024 raw_running_hash_ += c;
3025 raw_running_hash_ += (raw_running_hash_ << 10);
3026 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3027}
3028
3029
3030uint32_t StringHasher::GetHash() {
3031 // Get the calculated raw hash value and do some more bit ops to distribute
3032 // the hash further. Ensure that we never return zero as the hash value.
3033 uint32_t result = raw_running_hash_;
3034 result += (result << 3);
3035 result ^= (result >> 11);
3036 result += (result << 15);
3037 if (result == 0) {
3038 result = 27;
3039 }
3040 return result;
3041}
3042
3043
3044bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00003045 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003046 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3047 return false;
3048 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003049 return SlowAsArrayIndex(index);
3050}
3051
3052
3053Object* JSObject::GetPrototype() {
3054 return JSObject::cast(this)->map()->prototype();
3055}
3056
3057
3058PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3059 return GetPropertyAttributeWithReceiver(this, key);
3060}
3061
Steve Blockd0582a62009-12-15 09:54:21 +00003062// TODO(504): this may be useful in other places too where JSGlobalProxy
3063// is used.
3064Object* JSObject::BypassGlobalProxy() {
3065 if (IsJSGlobalProxy()) {
3066 Object* proto = GetPrototype();
3067 if (proto->IsNull()) return Heap::undefined_value();
3068 ASSERT(proto->IsJSGlobalObject());
3069 return proto;
3070 }
3071 return this;
3072}
3073
3074
3075bool JSObject::HasHiddenPropertiesObject() {
3076 ASSERT(!IsJSGlobalProxy());
3077 return GetPropertyAttributePostInterceptor(this,
3078 Heap::hidden_symbol(),
3079 false) != ABSENT;
3080}
3081
3082
3083Object* JSObject::GetHiddenPropertiesObject() {
3084 ASSERT(!IsJSGlobalProxy());
3085 PropertyAttributes attributes;
3086 return GetLocalPropertyPostInterceptor(this,
3087 Heap::hidden_symbol(),
3088 &attributes);
3089}
3090
3091
3092Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3093 ASSERT(!IsJSGlobalProxy());
3094 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3095 hidden_obj,
3096 DONT_ENUM);
3097}
3098
Steve Blocka7e24c12009-10-30 11:49:00 +00003099
3100bool JSObject::HasElement(uint32_t index) {
3101 return HasElementWithReceiver(this, index);
3102}
3103
3104
3105bool AccessorInfo::all_can_read() {
3106 return BooleanBit::get(flag(), kAllCanReadBit);
3107}
3108
3109
3110void AccessorInfo::set_all_can_read(bool value) {
3111 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3112}
3113
3114
3115bool AccessorInfo::all_can_write() {
3116 return BooleanBit::get(flag(), kAllCanWriteBit);
3117}
3118
3119
3120void AccessorInfo::set_all_can_write(bool value) {
3121 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3122}
3123
3124
3125bool AccessorInfo::prohibits_overwriting() {
3126 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3127}
3128
3129
3130void AccessorInfo::set_prohibits_overwriting(bool value) {
3131 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3132}
3133
3134
3135PropertyAttributes AccessorInfo::property_attributes() {
3136 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3137}
3138
3139
3140void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3141 ASSERT(AttributesField::is_valid(attributes));
3142 int rest_value = flag()->value() & ~AttributesField::mask();
3143 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3144}
3145
3146template<typename Shape, typename Key>
3147void Dictionary<Shape, Key>::SetEntry(int entry,
3148 Object* key,
3149 Object* value,
3150 PropertyDetails details) {
3151 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3152 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00003153 AssertNoAllocation no_gc;
3154 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00003155 FixedArray::set(index, key, mode);
3156 FixedArray::set(index+1, value, mode);
3157 FixedArray::fast_set(this, index+2, details.AsSmi());
3158}
3159
3160
3161void Map::ClearCodeCache() {
3162 // No write barrier is needed since empty_fixed_array is not in new space.
3163 // Please note this function is used during marking:
3164 // - MarkCompactCollector::MarkUnmarkedObject
3165 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3166 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3167}
3168
3169
3170void JSArray::EnsureSize(int required_size) {
3171 ASSERT(HasFastElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003172 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00003173 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3174 if (elts->length() < required_size) {
3175 // Doubling in size would be overkill, but leave some slack to avoid
3176 // constantly growing.
3177 Expand(required_size + (required_size >> 3));
3178 // It's a performance benefit to keep a frequently used array in new-space.
3179 } else if (!Heap::new_space()->Contains(elts) &&
3180 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3181 // Expand will allocate a new backing store in new space even if the size
3182 // we asked for isn't larger than what we had before.
3183 Expand(required_size);
3184 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003185}
3186
3187
Leon Clarke4515c472010-02-03 11:58:03 +00003188void JSArray::set_length(Smi* length) {
3189 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3190}
3191
3192
Steve Blocka7e24c12009-10-30 11:49:00 +00003193void JSArray::SetContent(FixedArray* storage) {
Leon Clarke4515c472010-02-03 11:58:03 +00003194 set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00003195 set_elements(storage);
3196}
3197
3198
3199Object* FixedArray::Copy() {
3200 if (length() == 0) return this;
3201 return Heap::CopyFixedArray(this);
3202}
3203
3204
3205#undef CAST_ACCESSOR
3206#undef INT_ACCESSORS
3207#undef SMI_ACCESSORS
3208#undef ACCESSORS
3209#undef FIELD_ADDR
3210#undef READ_FIELD
3211#undef WRITE_FIELD
3212#undef WRITE_BARRIER
3213#undef CONDITIONAL_WRITE_BARRIER
3214#undef READ_MEMADDR_FIELD
3215#undef WRITE_MEMADDR_FIELD
3216#undef READ_DOUBLE_FIELD
3217#undef WRITE_DOUBLE_FIELD
3218#undef READ_INT_FIELD
3219#undef WRITE_INT_FIELD
3220#undef READ_SHORT_FIELD
3221#undef WRITE_SHORT_FIELD
3222#undef READ_BYTE_FIELD
3223#undef WRITE_BYTE_FIELD
3224
3225
3226} } // namespace v8::internal
3227
3228#endif // V8_OBJECTS_INL_H_