blob: 793591247834f4dc82ec0802944837b184c66788 [file] [log] [blame]
Ben Murdochb0fe1622011-05-05 13:52:32 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27//
28// Review notes:
29//
30// - The use of macros in these inline functions may seem superfluous
31// but it is absolutely needed to make sure gcc generates optimal
32// code. gcc is not happy when attempting to inline too deep.
33//
34
35#ifndef V8_OBJECTS_INL_H_
36#define V8_OBJECTS_INL_H_
37
Kristian Monsen80d68ea2010-09-08 11:05:35 +010038#include "objects.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "contexts.h"
40#include "conversions-inl.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010041#include "heap.h"
42#include "memory.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043#include "property.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010044#include "spaces.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000045
46namespace v8 {
47namespace internal {
48
49PropertyDetails::PropertyDetails(Smi* smi) {
50 value_ = smi->value();
51}
52
53
54Smi* PropertyDetails::AsSmi() {
55 return Smi::FromInt(value_);
56}
57
58
59PropertyDetails PropertyDetails::AsDeleted() {
60 PropertyDetails d(DONT_ENUM, NORMAL);
61 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
62 return PropertyDetails(smi);
63}
64
65
66#define CAST_ACCESSOR(type) \
67 type* type::cast(Object* object) { \
68 ASSERT(object->Is##type()); \
69 return reinterpret_cast<type*>(object); \
70 }
71
72
73#define INT_ACCESSORS(holder, name, offset) \
74 int holder::name() { return READ_INT_FIELD(this, offset); } \
75 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
76
77
78#define ACCESSORS(holder, name, type, offset) \
79 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
80 void holder::set_##name(type* value, WriteBarrierMode mode) { \
81 WRITE_FIELD(this, offset, value); \
82 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
83 }
84
85
Steve Blocka7e24c12009-10-30 11:49:00 +000086#define SMI_ACCESSORS(holder, name, offset) \
87 int holder::name() { \
88 Object* value = READ_FIELD(this, offset); \
89 return Smi::cast(value)->value(); \
90 } \
91 void holder::set_##name(int value) { \
92 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
93 }
94
95
96#define BOOL_GETTER(holder, field, name, offset) \
97 bool holder::name() { \
98 return BooleanBit::get(field(), offset); \
99 } \
100
101
102#define BOOL_ACCESSORS(holder, field, name, offset) \
103 bool holder::name() { \
104 return BooleanBit::get(field(), offset); \
105 } \
106 void holder::set_##name(bool value) { \
107 set_##field(BooleanBit::set(field(), offset, value)); \
108 }
109
110
111bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
112 // There is a constraint on the object; check.
113 if (!this->IsJSObject()) return false;
114 // Fetch the constructor function of the object.
115 Object* cons_obj = JSObject::cast(this)->map()->constructor();
116 if (!cons_obj->IsJSFunction()) return false;
117 JSFunction* fun = JSFunction::cast(cons_obj);
118 // Iterate through the chain of inheriting function templates to
119 // see if the required one occurs.
120 for (Object* type = fun->shared()->function_data();
121 type->IsFunctionTemplateInfo();
122 type = FunctionTemplateInfo::cast(type)->parent_template()) {
123 if (type == expected) return true;
124 }
125 // Didn't find the required type in the inheritance chain.
126 return false;
127}
128
129
130bool Object::IsSmi() {
131 return HAS_SMI_TAG(this);
132}
133
134
135bool Object::IsHeapObject() {
136 return Internals::HasHeapObjectTag(this);
137}
138
139
140bool Object::IsHeapNumber() {
141 return Object::IsHeapObject()
142 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
143}
144
145
146bool Object::IsString() {
147 return Object::IsHeapObject()
148 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
149}
150
151
152bool Object::IsSymbol() {
153 if (!this->IsHeapObject()) return false;
154 uint32_t type = HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000155 // Because the symbol tag is non-zero and no non-string types have the
156 // symbol bit set we can test for symbols with a very simple test
157 // operation.
158 ASSERT(kSymbolTag != 0);
159 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
160 return (type & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000161}
162
163
164bool Object::IsConsString() {
165 if (!this->IsHeapObject()) return false;
166 uint32_t type = HeapObject::cast(this)->map()->instance_type();
167 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
168 (kStringTag | kConsStringTag);
169}
170
171
Steve Blocka7e24c12009-10-30 11:49:00 +0000172bool Object::IsSeqString() {
173 if (!IsString()) return false;
174 return StringShape(String::cast(this)).IsSequential();
175}
176
177
178bool Object::IsSeqAsciiString() {
179 if (!IsString()) return false;
180 return StringShape(String::cast(this)).IsSequential() &&
181 String::cast(this)->IsAsciiRepresentation();
182}
183
184
185bool Object::IsSeqTwoByteString() {
186 if (!IsString()) return false;
187 return StringShape(String::cast(this)).IsSequential() &&
188 String::cast(this)->IsTwoByteRepresentation();
189}
190
191
192bool Object::IsExternalString() {
193 if (!IsString()) return false;
194 return StringShape(String::cast(this)).IsExternal();
195}
196
197
198bool Object::IsExternalAsciiString() {
199 if (!IsString()) return false;
200 return StringShape(String::cast(this)).IsExternal() &&
201 String::cast(this)->IsAsciiRepresentation();
202}
203
204
205bool Object::IsExternalTwoByteString() {
206 if (!IsString()) return false;
207 return StringShape(String::cast(this)).IsExternal() &&
208 String::cast(this)->IsTwoByteRepresentation();
209}
210
211
Steve Blocka7e24c12009-10-30 11:49:00 +0000212StringShape::StringShape(String* str)
213 : type_(str->map()->instance_type()) {
214 set_valid();
215 ASSERT((type_ & kIsNotStringMask) == kStringTag);
216}
217
218
219StringShape::StringShape(Map* map)
220 : type_(map->instance_type()) {
221 set_valid();
222 ASSERT((type_ & kIsNotStringMask) == kStringTag);
223}
224
225
226StringShape::StringShape(InstanceType t)
227 : type_(static_cast<uint32_t>(t)) {
228 set_valid();
229 ASSERT((type_ & kIsNotStringMask) == kStringTag);
230}
231
232
233bool StringShape::IsSymbol() {
234 ASSERT(valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000235 ASSERT(kSymbolTag != 0);
236 return (type_ & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000237}
238
239
240bool String::IsAsciiRepresentation() {
241 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 return (type & kStringEncodingMask) == kAsciiStringTag;
243}
244
245
246bool String::IsTwoByteRepresentation() {
247 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000248 return (type & kStringEncodingMask) == kTwoByteStringTag;
249}
250
251
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100252bool String::HasOnlyAsciiChars() {
253 uint32_t type = map()->instance_type();
254 return (type & kStringEncodingMask) == kAsciiStringTag ||
255 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
Steve Block6ded16b2010-05-10 14:33:55 +0100256}
257
258
Steve Blocka7e24c12009-10-30 11:49:00 +0000259bool StringShape::IsCons() {
260 return (type_ & kStringRepresentationMask) == kConsStringTag;
261}
262
263
Steve Blocka7e24c12009-10-30 11:49:00 +0000264bool StringShape::IsExternal() {
265 return (type_ & kStringRepresentationMask) == kExternalStringTag;
266}
267
268
269bool StringShape::IsSequential() {
270 return (type_ & kStringRepresentationMask) == kSeqStringTag;
271}
272
273
274StringRepresentationTag StringShape::representation_tag() {
275 uint32_t tag = (type_ & kStringRepresentationMask);
276 return static_cast<StringRepresentationTag>(tag);
277}
278
279
280uint32_t StringShape::full_representation_tag() {
281 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
282}
283
284
285STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
286 Internals::kFullStringRepresentationMask);
287
288
Steve Blocka7e24c12009-10-30 11:49:00 +0000289bool StringShape::IsSequentialAscii() {
290 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
291}
292
293
294bool StringShape::IsSequentialTwoByte() {
295 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
296}
297
298
299bool StringShape::IsExternalAscii() {
300 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
301}
302
303
304bool StringShape::IsExternalTwoByte() {
305 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
306}
307
308
309STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
310 Internals::kExternalTwoByteRepresentationTag);
311
312
313uc32 FlatStringReader::Get(int index) {
314 ASSERT(0 <= index && index <= length_);
315 if (is_ascii_) {
316 return static_cast<const byte*>(start_)[index];
317 } else {
318 return static_cast<const uc16*>(start_)[index];
319 }
320}
321
322
323bool Object::IsNumber() {
324 return IsSmi() || IsHeapNumber();
325}
326
327
328bool Object::IsByteArray() {
329 return Object::IsHeapObject()
330 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
331}
332
333
334bool Object::IsPixelArray() {
335 return Object::IsHeapObject() &&
336 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
337}
338
339
Steve Block3ce2e202009-11-05 08:53:23 +0000340bool Object::IsExternalArray() {
341 if (!Object::IsHeapObject())
342 return false;
343 InstanceType instance_type =
344 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000345 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
346 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000347}
348
349
350bool Object::IsExternalByteArray() {
351 return Object::IsHeapObject() &&
352 HeapObject::cast(this)->map()->instance_type() ==
353 EXTERNAL_BYTE_ARRAY_TYPE;
354}
355
356
357bool Object::IsExternalUnsignedByteArray() {
358 return Object::IsHeapObject() &&
359 HeapObject::cast(this)->map()->instance_type() ==
360 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
361}
362
363
364bool Object::IsExternalShortArray() {
365 return Object::IsHeapObject() &&
366 HeapObject::cast(this)->map()->instance_type() ==
367 EXTERNAL_SHORT_ARRAY_TYPE;
368}
369
370
371bool Object::IsExternalUnsignedShortArray() {
372 return Object::IsHeapObject() &&
373 HeapObject::cast(this)->map()->instance_type() ==
374 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
375}
376
377
378bool Object::IsExternalIntArray() {
379 return Object::IsHeapObject() &&
380 HeapObject::cast(this)->map()->instance_type() ==
381 EXTERNAL_INT_ARRAY_TYPE;
382}
383
384
385bool Object::IsExternalUnsignedIntArray() {
386 return Object::IsHeapObject() &&
387 HeapObject::cast(this)->map()->instance_type() ==
388 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
389}
390
391
392bool Object::IsExternalFloatArray() {
393 return Object::IsHeapObject() &&
394 HeapObject::cast(this)->map()->instance_type() ==
395 EXTERNAL_FLOAT_ARRAY_TYPE;
396}
397
398
John Reck59135872010-11-02 12:39:01 -0700399bool MaybeObject::IsFailure() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 return HAS_FAILURE_TAG(this);
401}
402
403
John Reck59135872010-11-02 12:39:01 -0700404bool MaybeObject::IsRetryAfterGC() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 return HAS_FAILURE_TAG(this)
406 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
407}
408
409
John Reck59135872010-11-02 12:39:01 -0700410bool MaybeObject::IsOutOfMemory() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 return HAS_FAILURE_TAG(this)
412 && Failure::cast(this)->IsOutOfMemoryException();
413}
414
415
John Reck59135872010-11-02 12:39:01 -0700416bool MaybeObject::IsException() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 return this == Failure::Exception();
418}
419
420
John Reck59135872010-11-02 12:39:01 -0700421bool MaybeObject::IsTheHole() {
422 return this == Heap::the_hole_value();
423}
424
425
426Failure* Failure::cast(MaybeObject* obj) {
427 ASSERT(HAS_FAILURE_TAG(obj));
428 return reinterpret_cast<Failure*>(obj);
429}
430
431
Steve Blocka7e24c12009-10-30 11:49:00 +0000432bool Object::IsJSObject() {
433 return IsHeapObject()
434 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
435}
436
437
438bool Object::IsJSContextExtensionObject() {
439 return IsHeapObject()
440 && (HeapObject::cast(this)->map()->instance_type() ==
441 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
442}
443
444
445bool Object::IsMap() {
446 return Object::IsHeapObject()
447 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
448}
449
450
451bool Object::IsFixedArray() {
452 return Object::IsHeapObject()
453 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
454}
455
456
457bool Object::IsDescriptorArray() {
458 return IsFixedArray();
459}
460
461
Ben Murdochb0fe1622011-05-05 13:52:32 +0100462bool Object::IsDeoptimizationInputData() {
463 // Must be a fixed array.
464 if (!IsFixedArray()) return false;
465
466 // There's no sure way to detect the difference between a fixed array and
467 // a deoptimization data array. Since this is used for asserts we can
468 // check that the length is zero or else the fixed size plus a multiple of
469 // the entry size.
470 int length = FixedArray::cast(this)->length();
471 if (length == 0) return true;
472
473 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
474 return length >= 0 &&
475 length % DeoptimizationInputData::kDeoptEntrySize == 0;
476}
477
478
479bool Object::IsDeoptimizationOutputData() {
480 if (!IsFixedArray()) return false;
481 // There's actually no way to see the difference between a fixed array and
482 // a deoptimization data array. Since this is used for asserts we can check
483 // that the length is plausible though.
484 if (FixedArray::cast(this)->length() % 2 != 0) return false;
485 return true;
486}
487
488
Steve Blocka7e24c12009-10-30 11:49:00 +0000489bool Object::IsContext() {
490 return Object::IsHeapObject()
491 && (HeapObject::cast(this)->map() == Heap::context_map() ||
492 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
493 HeapObject::cast(this)->map() == Heap::global_context_map());
494}
495
496
497bool Object::IsCatchContext() {
498 return Object::IsHeapObject()
499 && HeapObject::cast(this)->map() == Heap::catch_context_map();
500}
501
502
503bool Object::IsGlobalContext() {
504 return Object::IsHeapObject()
505 && HeapObject::cast(this)->map() == Heap::global_context_map();
506}
507
508
509bool Object::IsJSFunction() {
510 return Object::IsHeapObject()
511 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
512}
513
514
515template <> inline bool Is<JSFunction>(Object* obj) {
516 return obj->IsJSFunction();
517}
518
519
520bool Object::IsCode() {
521 return Object::IsHeapObject()
522 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
523}
524
525
526bool Object::IsOddball() {
527 return Object::IsHeapObject()
528 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
529}
530
531
532bool Object::IsJSGlobalPropertyCell() {
533 return Object::IsHeapObject()
534 && HeapObject::cast(this)->map()->instance_type()
535 == JS_GLOBAL_PROPERTY_CELL_TYPE;
536}
537
538
539bool Object::IsSharedFunctionInfo() {
540 return Object::IsHeapObject() &&
541 (HeapObject::cast(this)->map()->instance_type() ==
542 SHARED_FUNCTION_INFO_TYPE);
543}
544
545
546bool Object::IsJSValue() {
547 return Object::IsHeapObject()
548 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
549}
550
551
552bool Object::IsStringWrapper() {
553 return IsJSValue() && JSValue::cast(this)->value()->IsString();
554}
555
556
557bool Object::IsProxy() {
558 return Object::IsHeapObject()
559 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
560}
561
562
563bool Object::IsBoolean() {
564 return IsTrue() || IsFalse();
565}
566
567
568bool Object::IsJSArray() {
569 return Object::IsHeapObject()
570 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
571}
572
573
574bool Object::IsJSRegExp() {
575 return Object::IsHeapObject()
576 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
577}
578
579
580template <> inline bool Is<JSArray>(Object* obj) {
581 return obj->IsJSArray();
582}
583
584
585bool Object::IsHashTable() {
586 return Object::IsHeapObject()
587 && HeapObject::cast(this)->map() == Heap::hash_table_map();
588}
589
590
591bool Object::IsDictionary() {
592 return IsHashTable() && this != Heap::symbol_table();
593}
594
595
596bool Object::IsSymbolTable() {
597 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
598}
599
600
Steve Block6ded16b2010-05-10 14:33:55 +0100601bool Object::IsJSFunctionResultCache() {
602 if (!IsFixedArray()) return false;
603 FixedArray* self = FixedArray::cast(this);
604 int length = self->length();
605 if (length < JSFunctionResultCache::kEntriesIndex) return false;
606 if ((length - JSFunctionResultCache::kEntriesIndex)
607 % JSFunctionResultCache::kEntrySize != 0) {
608 return false;
609 }
610#ifdef DEBUG
611 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
612#endif
613 return true;
614}
615
616
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100617bool Object::IsNormalizedMapCache() {
618 if (!IsFixedArray()) return false;
619 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
620 return false;
621 }
622#ifdef DEBUG
623 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
624#endif
625 return true;
626}
627
628
Steve Blocka7e24c12009-10-30 11:49:00 +0000629bool Object::IsCompilationCacheTable() {
630 return IsHashTable();
631}
632
633
Steve Block6ded16b2010-05-10 14:33:55 +0100634bool Object::IsCodeCacheHashTable() {
635 return IsHashTable();
636}
637
638
Steve Blocka7e24c12009-10-30 11:49:00 +0000639bool Object::IsMapCache() {
640 return IsHashTable();
641}
642
643
644bool Object::IsPrimitive() {
645 return IsOddball() || IsNumber() || IsString();
646}
647
648
649bool Object::IsJSGlobalProxy() {
650 bool result = IsHeapObject() &&
651 (HeapObject::cast(this)->map()->instance_type() ==
652 JS_GLOBAL_PROXY_TYPE);
653 ASSERT(!result || IsAccessCheckNeeded());
654 return result;
655}
656
657
658bool Object::IsGlobalObject() {
659 if (!IsHeapObject()) return false;
660
661 InstanceType type = HeapObject::cast(this)->map()->instance_type();
662 return type == JS_GLOBAL_OBJECT_TYPE ||
663 type == JS_BUILTINS_OBJECT_TYPE;
664}
665
666
667bool Object::IsJSGlobalObject() {
668 return IsHeapObject() &&
669 (HeapObject::cast(this)->map()->instance_type() ==
670 JS_GLOBAL_OBJECT_TYPE);
671}
672
673
674bool Object::IsJSBuiltinsObject() {
675 return IsHeapObject() &&
676 (HeapObject::cast(this)->map()->instance_type() ==
677 JS_BUILTINS_OBJECT_TYPE);
678}
679
680
681bool Object::IsUndetectableObject() {
682 return IsHeapObject()
683 && HeapObject::cast(this)->map()->is_undetectable();
684}
685
686
687bool Object::IsAccessCheckNeeded() {
688 return IsHeapObject()
689 && HeapObject::cast(this)->map()->is_access_check_needed();
690}
691
692
693bool Object::IsStruct() {
694 if (!IsHeapObject()) return false;
695 switch (HeapObject::cast(this)->map()->instance_type()) {
696#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
697 STRUCT_LIST(MAKE_STRUCT_CASE)
698#undef MAKE_STRUCT_CASE
699 default: return false;
700 }
701}
702
703
704#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
705 bool Object::Is##Name() { \
706 return Object::IsHeapObject() \
707 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
708 }
709 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
710#undef MAKE_STRUCT_PREDICATE
711
712
713bool Object::IsUndefined() {
714 return this == Heap::undefined_value();
715}
716
717
Steve Blocka7e24c12009-10-30 11:49:00 +0000718bool Object::IsNull() {
719 return this == Heap::null_value();
720}
721
722
723bool Object::IsTrue() {
724 return this == Heap::true_value();
725}
726
727
728bool Object::IsFalse() {
729 return this == Heap::false_value();
730}
731
732
733double Object::Number() {
734 ASSERT(IsNumber());
735 return IsSmi()
736 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
737 : reinterpret_cast<HeapNumber*>(this)->value();
738}
739
740
741
John Reck59135872010-11-02 12:39:01 -0700742MaybeObject* Object::ToSmi() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 if (IsSmi()) return this;
744 if (IsHeapNumber()) {
745 double value = HeapNumber::cast(this)->value();
746 int int_value = FastD2I(value);
747 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
748 return Smi::FromInt(int_value);
749 }
750 }
751 return Failure::Exception();
752}
753
754
755bool Object::HasSpecificClassOf(String* name) {
756 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
757}
758
759
John Reck59135872010-11-02 12:39:01 -0700760MaybeObject* Object::GetElement(uint32_t index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000761 return GetElementWithReceiver(this, index);
762}
763
764
John Reck59135872010-11-02 12:39:01 -0700765Object* Object::GetElementNoExceptionThrown(uint32_t index) {
766 MaybeObject* maybe = GetElementWithReceiver(this, index);
767 ASSERT(!maybe->IsFailure());
768 Object* result = NULL; // Initialization to please compiler.
769 maybe->ToObject(&result);
770 return result;
771}
772
773
774MaybeObject* Object::GetProperty(String* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000775 PropertyAttributes attributes;
776 return GetPropertyWithReceiver(this, key, &attributes);
777}
778
779
John Reck59135872010-11-02 12:39:01 -0700780MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000781 return GetPropertyWithReceiver(this, key, attributes);
782}
783
784
785#define FIELD_ADDR(p, offset) \
786 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
787
788#define READ_FIELD(p, offset) \
789 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
790
791#define WRITE_FIELD(p, offset, value) \
792 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
793
794
795#define WRITE_BARRIER(object, offset) \
796 Heap::RecordWrite(object->address(), offset);
797
798// CONDITIONAL_WRITE_BARRIER must be issued after the actual
799// write due to the assert validating the written value.
800#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
801 if (mode == UPDATE_WRITE_BARRIER) { \
802 Heap::RecordWrite(object->address(), offset); \
803 } else { \
804 ASSERT(mode == SKIP_WRITE_BARRIER); \
805 ASSERT(Heap::InNewSpace(object) || \
Steve Block6ded16b2010-05-10 14:33:55 +0100806 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100807 Page::FromAddress(object->address())-> \
808 IsRegionDirty(object->address() + offset)); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 }
810
811#define READ_DOUBLE_FIELD(p, offset) \
812 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
813
814#define WRITE_DOUBLE_FIELD(p, offset, value) \
815 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
816
817#define READ_INT_FIELD(p, offset) \
818 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
819
820#define WRITE_INT_FIELD(p, offset, value) \
821 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
822
823#define READ_INTPTR_FIELD(p, offset) \
824 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
825
826#define WRITE_INTPTR_FIELD(p, offset, value) \
827 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
828
829#define READ_UINT32_FIELD(p, offset) \
830 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
831
832#define WRITE_UINT32_FIELD(p, offset, value) \
833 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
834
835#define READ_SHORT_FIELD(p, offset) \
836 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
837
838#define WRITE_SHORT_FIELD(p, offset, value) \
839 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
840
841#define READ_BYTE_FIELD(p, offset) \
842 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
843
844#define WRITE_BYTE_FIELD(p, offset, value) \
845 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
846
847
848Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
849 return &READ_FIELD(obj, byte_offset);
850}
851
852
853int Smi::value() {
854 return Internals::SmiValue(this);
855}
856
857
858Smi* Smi::FromInt(int value) {
859 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000860 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 intptr_t tagged_value =
Steve Block3ce2e202009-11-05 08:53:23 +0000862 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 return reinterpret_cast<Smi*>(tagged_value);
864}
865
866
867Smi* Smi::FromIntptr(intptr_t value) {
868 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000869 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
870 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871}
872
873
874Failure::Type Failure::type() const {
875 return static_cast<Type>(value() & kFailureTypeTagMask);
876}
877
878
879bool Failure::IsInternalError() const {
880 return type() == INTERNAL_ERROR;
881}
882
883
884bool Failure::IsOutOfMemoryException() const {
885 return type() == OUT_OF_MEMORY_EXCEPTION;
886}
887
888
Steve Blocka7e24c12009-10-30 11:49:00 +0000889AllocationSpace Failure::allocation_space() const {
890 ASSERT_EQ(RETRY_AFTER_GC, type());
891 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
892 & kSpaceTagMask);
893}
894
895
896Failure* Failure::InternalError() {
897 return Construct(INTERNAL_ERROR);
898}
899
900
901Failure* Failure::Exception() {
902 return Construct(EXCEPTION);
903}
904
905
906Failure* Failure::OutOfMemoryException() {
907 return Construct(OUT_OF_MEMORY_EXCEPTION);
908}
909
910
Steve Block3ce2e202009-11-05 08:53:23 +0000911intptr_t Failure::value() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100912 return static_cast<intptr_t>(
913 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000914}
915
916
Ben Murdochf87a2032010-10-22 12:50:53 +0100917Failure* Failure::RetryAfterGC() {
918 return RetryAfterGC(NEW_SPACE);
919}
920
921
922Failure* Failure::RetryAfterGC(AllocationSpace space) {
923 ASSERT((space & ~kSpaceTagMask) == 0);
924 return Construct(RETRY_AFTER_GC, space);
Steve Blocka7e24c12009-10-30 11:49:00 +0000925}
926
927
Steve Block3ce2e202009-11-05 08:53:23 +0000928Failure* Failure::Construct(Type type, intptr_t value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100929 uintptr_t info =
930 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
Steve Block3ce2e202009-11-05 08:53:23 +0000932 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000933}
934
935
936bool Smi::IsValid(intptr_t value) {
937#ifdef DEBUG
938 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
939#endif
Steve Block3ce2e202009-11-05 08:53:23 +0000940
941#ifdef V8_TARGET_ARCH_X64
942 // To be representable as a long smi, the value must be a 32-bit integer.
943 bool result = (value == static_cast<int32_t>(value));
944#else
Steve Blocka7e24c12009-10-30 11:49:00 +0000945 // To be representable as an tagged small integer, the two
946 // most-significant bits of 'value' must be either 00 or 11 due to
947 // sign-extension. To check this we add 01 to the two
948 // most-significant bits, and check if the most-significant bit is 0
949 //
950 // CAUTION: The original code below:
951 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
952 // may lead to incorrect results according to the C language spec, and
953 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
954 // compiler may produce undefined results in case of signed integer
955 // overflow. The computation must be done w/ unsigned ints.
Steve Block3ce2e202009-11-05 08:53:23 +0000956 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
Steve Blocka7e24c12009-10-30 11:49:00 +0000957#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000958 ASSERT(result == in_range);
959 return result;
960}
961
962
963MapWord MapWord::FromMap(Map* map) {
964 return MapWord(reinterpret_cast<uintptr_t>(map));
965}
966
967
968Map* MapWord::ToMap() {
969 return reinterpret_cast<Map*>(value_);
970}
971
972
973bool MapWord::IsForwardingAddress() {
974 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
975}
976
977
978MapWord MapWord::FromForwardingAddress(HeapObject* object) {
979 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
980 return MapWord(reinterpret_cast<uintptr_t>(raw));
981}
982
983
984HeapObject* MapWord::ToForwardingAddress() {
985 ASSERT(IsForwardingAddress());
986 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
987}
988
989
990bool MapWord::IsMarked() {
991 return (value_ & kMarkingMask) == 0;
992}
993
994
995void MapWord::SetMark() {
996 value_ &= ~kMarkingMask;
997}
998
999
1000void MapWord::ClearMark() {
1001 value_ |= kMarkingMask;
1002}
1003
1004
1005bool MapWord::IsOverflowed() {
1006 return (value_ & kOverflowMask) != 0;
1007}
1008
1009
1010void MapWord::SetOverflow() {
1011 value_ |= kOverflowMask;
1012}
1013
1014
1015void MapWord::ClearOverflow() {
1016 value_ &= ~kOverflowMask;
1017}
1018
1019
1020MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1021 // Offset is the distance in live bytes from the first live object in the
1022 // same page. The offset between two objects in the same page should not
1023 // exceed the object area size of a page.
1024 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1025
Leon Clarkee46be812010-01-19 14:06:41 +00001026 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +00001027 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1028
1029 Page* map_page = Page::FromAddress(map_address);
1030 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1031
Leon Clarkee46be812010-01-19 14:06:41 +00001032 uintptr_t map_page_offset =
1033 map_page->Offset(map_address) >> kMapAlignmentBits;
Steve Blocka7e24c12009-10-30 11:49:00 +00001034
1035 uintptr_t encoding =
1036 (compact_offset << kForwardingOffsetShift) |
1037 (map_page_offset << kMapPageOffsetShift) |
1038 (map_page->mc_page_index << kMapPageIndexShift);
1039 return MapWord(encoding);
1040}
1041
1042
1043Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1044 int map_page_index =
1045 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1046 ASSERT_MAP_PAGE_INDEX(map_page_index);
1047
1048 int map_page_offset = static_cast<int>(
Leon Clarkee46be812010-01-19 14:06:41 +00001049 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1050 kMapAlignmentBits);
Steve Blocka7e24c12009-10-30 11:49:00 +00001051
1052 return (map_space->PageAddress(map_page_index) + map_page_offset);
1053}
1054
1055
1056int MapWord::DecodeOffset() {
1057 // The offset field is represented in the kForwardingOffsetBits
1058 // most-significant bits.
Steve Blockd0582a62009-12-15 09:54:21 +00001059 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1060 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1061 return static_cast<int>(offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001062}
1063
1064
1065MapWord MapWord::FromEncodedAddress(Address address) {
1066 return MapWord(reinterpret_cast<uintptr_t>(address));
1067}
1068
1069
1070Address MapWord::ToEncodedAddress() {
1071 return reinterpret_cast<Address>(value_);
1072}
1073
1074
1075#ifdef DEBUG
1076void HeapObject::VerifyObjectField(int offset) {
1077 VerifyPointer(READ_FIELD(this, offset));
1078}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001079
1080void HeapObject::VerifySmiField(int offset) {
1081 ASSERT(READ_FIELD(this, offset)->IsSmi());
1082}
Steve Blocka7e24c12009-10-30 11:49:00 +00001083#endif
1084
1085
1086Map* HeapObject::map() {
1087 return map_word().ToMap();
1088}
1089
1090
1091void HeapObject::set_map(Map* value) {
1092 set_map_word(MapWord::FromMap(value));
1093}
1094
1095
1096MapWord HeapObject::map_word() {
1097 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1098}
1099
1100
1101void HeapObject::set_map_word(MapWord map_word) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001102 // WRITE_FIELD does not invoke write barrier, but there is no need
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 // here.
1104 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1105}
1106
1107
1108HeapObject* HeapObject::FromAddress(Address address) {
1109 ASSERT_TAG_ALIGNED(address);
1110 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1111}
1112
1113
1114Address HeapObject::address() {
1115 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1116}
1117
1118
1119int HeapObject::Size() {
1120 return SizeFromMap(map());
1121}
1122
1123
1124void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1125 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1126 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1127}
1128
1129
1130void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1131 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1132}
1133
1134
1135bool HeapObject::IsMarked() {
1136 return map_word().IsMarked();
1137}
1138
1139
1140void HeapObject::SetMark() {
1141 ASSERT(!IsMarked());
1142 MapWord first_word = map_word();
1143 first_word.SetMark();
1144 set_map_word(first_word);
1145}
1146
1147
1148void HeapObject::ClearMark() {
1149 ASSERT(IsMarked());
1150 MapWord first_word = map_word();
1151 first_word.ClearMark();
1152 set_map_word(first_word);
1153}
1154
1155
1156bool HeapObject::IsOverflowed() {
1157 return map_word().IsOverflowed();
1158}
1159
1160
1161void HeapObject::SetOverflow() {
1162 MapWord first_word = map_word();
1163 first_word.SetOverflow();
1164 set_map_word(first_word);
1165}
1166
1167
1168void HeapObject::ClearOverflow() {
1169 ASSERT(IsOverflowed());
1170 MapWord first_word = map_word();
1171 first_word.ClearOverflow();
1172 set_map_word(first_word);
1173}
1174
1175
1176double HeapNumber::value() {
1177 return READ_DOUBLE_FIELD(this, kValueOffset);
1178}
1179
1180
1181void HeapNumber::set_value(double value) {
1182 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1183}
1184
1185
Steve Block6ded16b2010-05-10 14:33:55 +01001186int HeapNumber::get_exponent() {
1187 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1188 kExponentShift) - kExponentBias;
1189}
1190
1191
1192int HeapNumber::get_sign() {
1193 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1194}
1195
1196
Steve Blocka7e24c12009-10-30 11:49:00 +00001197ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1198
1199
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001200HeapObject* JSObject::elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001201 Object* array = READ_FIELD(this, kElementsOffset);
1202 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001203 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1204 array->IsExternalArray());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001205 return reinterpret_cast<HeapObject*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001206}
1207
1208
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001209void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
Steve Block8defd9f2010-07-08 12:39:36 +01001210 ASSERT(map()->has_fast_elements() ==
Iain Merrick75681382010-08-19 15:07:18 +01001211 (value->map() == Heap::fixed_array_map() ||
1212 value->map() == Heap::fixed_cow_array_map()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001213 // In the assert below Dictionary is covered under FixedArray.
Steve Block3ce2e202009-11-05 08:53:23 +00001214 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1215 value->IsExternalArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00001216 WRITE_FIELD(this, kElementsOffset, value);
1217 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1218}
1219
1220
1221void JSObject::initialize_properties() {
1222 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1223 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1224}
1225
1226
1227void JSObject::initialize_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01001228 ASSERT(map()->has_fast_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1230 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1231}
1232
1233
John Reck59135872010-11-02 12:39:01 -07001234MaybeObject* JSObject::ResetElements() {
1235 Object* obj;
1236 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1237 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1238 }
Steve Block8defd9f2010-07-08 12:39:36 +01001239 set_map(Map::cast(obj));
1240 initialize_elements();
1241 return this;
1242}
1243
1244
Steve Blocka7e24c12009-10-30 11:49:00 +00001245ACCESSORS(Oddball, to_string, String, kToStringOffset)
1246ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1247
1248
1249Object* JSGlobalPropertyCell::value() {
1250 return READ_FIELD(this, kValueOffset);
1251}
1252
1253
1254void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1255 // The write barrier is not used for global property cells.
1256 ASSERT(!val->IsJSGlobalPropertyCell());
1257 WRITE_FIELD(this, kValueOffset, val);
1258}
1259
1260
1261int JSObject::GetHeaderSize() {
1262 InstanceType type = map()->instance_type();
1263 // Check for the most common kind of JavaScript object before
1264 // falling into the generic switch. This speeds up the internal
1265 // field operations considerably on average.
1266 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1267 switch (type) {
1268 case JS_GLOBAL_PROXY_TYPE:
1269 return JSGlobalProxy::kSize;
1270 case JS_GLOBAL_OBJECT_TYPE:
1271 return JSGlobalObject::kSize;
1272 case JS_BUILTINS_OBJECT_TYPE:
1273 return JSBuiltinsObject::kSize;
1274 case JS_FUNCTION_TYPE:
1275 return JSFunction::kSize;
1276 case JS_VALUE_TYPE:
1277 return JSValue::kSize;
1278 case JS_ARRAY_TYPE:
1279 return JSValue::kSize;
1280 case JS_REGEXP_TYPE:
1281 return JSValue::kSize;
1282 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1283 return JSObject::kHeaderSize;
1284 default:
1285 UNREACHABLE();
1286 return 0;
1287 }
1288}
1289
1290
1291int JSObject::GetInternalFieldCount() {
1292 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1293 // Make sure to adjust for the number of in-object properties. These
1294 // properties do contribute to the size, but are not internal fields.
1295 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1296 map()->inobject_properties();
1297}
1298
1299
1300Object* JSObject::GetInternalField(int index) {
1301 ASSERT(index < GetInternalFieldCount() && index >= 0);
1302 // Internal objects do follow immediately after the header, whereas in-object
1303 // properties are at the end of the object. Therefore there is no need
1304 // to adjust the index here.
1305 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1306}
1307
1308
1309void JSObject::SetInternalField(int index, Object* value) {
1310 ASSERT(index < GetInternalFieldCount() && index >= 0);
1311 // Internal objects do follow immediately after the header, whereas in-object
1312 // properties are at the end of the object. Therefore there is no need
1313 // to adjust the index here.
1314 int offset = GetHeaderSize() + (kPointerSize * index);
1315 WRITE_FIELD(this, offset, value);
1316 WRITE_BARRIER(this, offset);
1317}
1318
1319
1320// Access fast-case object properties at index. The use of these routines
1321// is needed to correctly distinguish between properties stored in-object and
1322// properties stored in the properties array.
1323Object* JSObject::FastPropertyAt(int index) {
1324 // Adjust for the number of properties stored in the object.
1325 index -= map()->inobject_properties();
1326 if (index < 0) {
1327 int offset = map()->instance_size() + (index * kPointerSize);
1328 return READ_FIELD(this, offset);
1329 } else {
1330 ASSERT(index < properties()->length());
1331 return properties()->get(index);
1332 }
1333}
1334
1335
1336Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1337 // Adjust for the number of properties stored in the object.
1338 index -= map()->inobject_properties();
1339 if (index < 0) {
1340 int offset = map()->instance_size() + (index * kPointerSize);
1341 WRITE_FIELD(this, offset, value);
1342 WRITE_BARRIER(this, offset);
1343 } else {
1344 ASSERT(index < properties()->length());
1345 properties()->set(index, value);
1346 }
1347 return value;
1348}
1349
1350
1351Object* JSObject::InObjectPropertyAt(int index) {
1352 // Adjust for the number of properties stored in the object.
1353 index -= map()->inobject_properties();
1354 ASSERT(index < 0);
1355 int offset = map()->instance_size() + (index * kPointerSize);
1356 return READ_FIELD(this, offset);
1357}
1358
1359
1360Object* JSObject::InObjectPropertyAtPut(int index,
1361 Object* value,
1362 WriteBarrierMode mode) {
1363 // Adjust for the number of properties stored in the object.
1364 index -= map()->inobject_properties();
1365 ASSERT(index < 0);
1366 int offset = map()->instance_size() + (index * kPointerSize);
1367 WRITE_FIELD(this, offset, value);
1368 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1369 return value;
1370}
1371
1372
1373
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001374void JSObject::InitializeBody(int object_size, Object* value) {
1375 ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001376 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1377 WRITE_FIELD(this, offset, value);
1378 }
1379}
1380
1381
Steve Block8defd9f2010-07-08 12:39:36 +01001382bool JSObject::HasFastProperties() {
1383 return !properties()->IsDictionary();
1384}
1385
1386
1387int JSObject::MaxFastProperties() {
1388 // Allow extra fast properties if the object has more than
1389 // kMaxFastProperties in-object properties. When this is the case,
1390 // it is very unlikely that the object is being used as a dictionary
1391 // and there is a good chance that allowing more map transitions
1392 // will be worth it.
1393 return Max(map()->inobject_properties(), kMaxFastProperties);
1394}
1395
1396
Steve Blocka7e24c12009-10-30 11:49:00 +00001397void Struct::InitializeBody(int object_size) {
1398 Object* value = Heap::undefined_value();
1399 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1400 WRITE_FIELD(this, offset, value);
1401 }
1402}
1403
1404
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001405bool Object::ToArrayIndex(uint32_t* index) {
1406 if (IsSmi()) {
1407 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001408 if (value < 0) return false;
1409 *index = value;
1410 return true;
1411 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001412 if (IsHeapNumber()) {
1413 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 uint32_t uint_value = static_cast<uint32_t>(value);
1415 if (value == static_cast<double>(uint_value)) {
1416 *index = uint_value;
1417 return true;
1418 }
1419 }
1420 return false;
1421}
1422
1423
1424bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1425 if (!this->IsJSValue()) return false;
1426
1427 JSValue* js_value = JSValue::cast(this);
1428 if (!js_value->value()->IsString()) return false;
1429
1430 String* str = String::cast(js_value->value());
1431 if (index >= (uint32_t)str->length()) return false;
1432
1433 return true;
1434}
1435
1436
1437Object* FixedArray::get(int index) {
1438 ASSERT(index >= 0 && index < this->length());
1439 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1440}
1441
1442
1443void FixedArray::set(int index, Smi* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001444 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1446 int offset = kHeaderSize + index * kPointerSize;
1447 WRITE_FIELD(this, offset, value);
1448}
1449
1450
1451void FixedArray::set(int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001452 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 ASSERT(index >= 0 && index < this->length());
1454 int offset = kHeaderSize + index * kPointerSize;
1455 WRITE_FIELD(this, offset, value);
1456 WRITE_BARRIER(this, offset);
1457}
1458
1459
Leon Clarke4515c472010-02-03 11:58:03 +00001460WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1462 return UPDATE_WRITE_BARRIER;
1463}
1464
1465
1466void FixedArray::set(int index,
1467 Object* value,
1468 WriteBarrierMode mode) {
Iain Merrick75681382010-08-19 15:07:18 +01001469 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001470 ASSERT(index >= 0 && index < this->length());
1471 int offset = kHeaderSize + index * kPointerSize;
1472 WRITE_FIELD(this, offset, value);
1473 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1474}
1475
1476
1477void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
Iain Merrick75681382010-08-19 15:07:18 +01001478 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001479 ASSERT(index >= 0 && index < array->length());
Leon Clarke4515c472010-02-03 11:58:03 +00001480 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1482}
1483
1484
1485void FixedArray::set_undefined(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001486 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001487 ASSERT(index >= 0 && index < this->length());
1488 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1489 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1490 Heap::undefined_value());
1491}
1492
1493
1494void FixedArray::set_null(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001495 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001496 ASSERT(index >= 0 && index < this->length());
1497 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1498 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1499}
1500
1501
1502void FixedArray::set_the_hole(int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001503 ASSERT(map() != Heap::fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001504 ASSERT(index >= 0 && index < this->length());
1505 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1506 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1507}
1508
1509
Iain Merrick75681382010-08-19 15:07:18 +01001510void FixedArray::set_unchecked(int index, Smi* value) {
1511 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1512 int offset = kHeaderSize + index * kPointerSize;
1513 WRITE_FIELD(this, offset, value);
1514}
1515
1516
Ben Murdochf87a2032010-10-22 12:50:53 +01001517void FixedArray::set_unchecked(int index,
1518 Object* value,
1519 WriteBarrierMode mode) {
1520 int offset = kHeaderSize + index * kPointerSize;
1521 WRITE_FIELD(this, offset, value);
1522 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1523}
1524
1525
Iain Merrick75681382010-08-19 15:07:18 +01001526void FixedArray::set_null_unchecked(int index) {
1527 ASSERT(index >= 0 && index < this->length());
1528 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1529 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1530}
1531
1532
Steve Block6ded16b2010-05-10 14:33:55 +01001533Object** FixedArray::data_start() {
1534 return HeapObject::RawField(this, kHeaderSize);
1535}
1536
1537
Steve Blocka7e24c12009-10-30 11:49:00 +00001538bool DescriptorArray::IsEmpty() {
1539 ASSERT(this == Heap::empty_descriptor_array() ||
1540 this->length() > 2);
1541 return this == Heap::empty_descriptor_array();
1542}
1543
1544
1545void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1546 Object* tmp = array->get(first);
1547 fast_set(array, first, array->get(second));
1548 fast_set(array, second, tmp);
1549}
1550
1551
1552int DescriptorArray::Search(String* name) {
1553 SLOW_ASSERT(IsSortedNoDuplicates());
1554
1555 // Check for empty descriptor array.
1556 int nof = number_of_descriptors();
1557 if (nof == 0) return kNotFound;
1558
1559 // Fast case: do linear search for small arrays.
1560 const int kMaxElementsForLinearSearch = 8;
1561 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1562 return LinearSearch(name, nof);
1563 }
1564
1565 // Slow case: perform binary search.
1566 return BinarySearch(name, 0, nof - 1);
1567}
1568
1569
Iain Merrick75681382010-08-19 15:07:18 +01001570int DescriptorArray::SearchWithCache(String* name) {
1571 int number = DescriptorLookupCache::Lookup(this, name);
1572 if (number == DescriptorLookupCache::kAbsent) {
1573 number = Search(name);
1574 DescriptorLookupCache::Update(this, name, number);
1575 }
1576 return number;
1577}
1578
1579
Steve Blocka7e24c12009-10-30 11:49:00 +00001580String* DescriptorArray::GetKey(int descriptor_number) {
1581 ASSERT(descriptor_number < number_of_descriptors());
1582 return String::cast(get(ToKeyIndex(descriptor_number)));
1583}
1584
1585
1586Object* DescriptorArray::GetValue(int descriptor_number) {
1587 ASSERT(descriptor_number < number_of_descriptors());
1588 return GetContentArray()->get(ToValueIndex(descriptor_number));
1589}
1590
1591
1592Smi* DescriptorArray::GetDetails(int descriptor_number) {
1593 ASSERT(descriptor_number < number_of_descriptors());
1594 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1595}
1596
1597
1598PropertyType DescriptorArray::GetType(int descriptor_number) {
1599 ASSERT(descriptor_number < number_of_descriptors());
1600 return PropertyDetails(GetDetails(descriptor_number)).type();
1601}
1602
1603
1604int DescriptorArray::GetFieldIndex(int descriptor_number) {
1605 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1606}
1607
1608
1609JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1610 return JSFunction::cast(GetValue(descriptor_number));
1611}
1612
1613
1614Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1615 ASSERT(GetType(descriptor_number) == CALLBACKS);
1616 return GetValue(descriptor_number);
1617}
1618
1619
1620AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1621 ASSERT(GetType(descriptor_number) == CALLBACKS);
1622 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1623 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1624}
1625
1626
1627bool DescriptorArray::IsProperty(int descriptor_number) {
1628 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1629}
1630
1631
1632bool DescriptorArray::IsTransition(int descriptor_number) {
1633 PropertyType t = GetType(descriptor_number);
1634 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1635}
1636
1637
1638bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1639 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1640}
1641
1642
1643bool DescriptorArray::IsDontEnum(int descriptor_number) {
1644 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1645}
1646
1647
1648void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1649 desc->Init(GetKey(descriptor_number),
1650 GetValue(descriptor_number),
1651 GetDetails(descriptor_number));
1652}
1653
1654
1655void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1656 // Range check.
1657 ASSERT(descriptor_number < number_of_descriptors());
1658
Leon Clarkee46be812010-01-19 14:06:41 +00001659 // Make sure none of the elements in desc are in new space.
Steve Blocka7e24c12009-10-30 11:49:00 +00001660 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1661 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1662
1663 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1664 FixedArray* content_array = GetContentArray();
1665 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1666 fast_set(content_array, ToDetailsIndex(descriptor_number),
1667 desc->GetDetails().AsSmi());
1668}
1669
1670
1671void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1672 Descriptor desc;
1673 src->Get(src_index, &desc);
1674 Set(index, &desc);
1675}
1676
1677
1678void DescriptorArray::Swap(int first, int second) {
1679 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1680 FixedArray* content_array = GetContentArray();
1681 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1682 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1683}
1684
1685
1686bool NumberDictionary::requires_slow_elements() {
1687 Object* max_index_object = get(kMaxNumberKeyIndex);
1688 if (!max_index_object->IsSmi()) return false;
1689 return 0 !=
1690 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1691}
1692
1693uint32_t NumberDictionary::max_number_key() {
1694 ASSERT(!requires_slow_elements());
1695 Object* max_index_object = get(kMaxNumberKeyIndex);
1696 if (!max_index_object->IsSmi()) return 0;
1697 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1698 return value >> kRequiresSlowElementsTagSize;
1699}
1700
1701void NumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00001702 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00001703}
1704
1705
1706// ------------------------------------
1707// Cast operations
1708
1709
1710CAST_ACCESSOR(FixedArray)
1711CAST_ACCESSOR(DescriptorArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001712CAST_ACCESSOR(DeoptimizationInputData)
1713CAST_ACCESSOR(DeoptimizationOutputData)
Steve Blocka7e24c12009-10-30 11:49:00 +00001714CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001715CAST_ACCESSOR(JSFunctionResultCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001716CAST_ACCESSOR(NormalizedMapCache)
Steve Blocka7e24c12009-10-30 11:49:00 +00001717CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01001718CAST_ACCESSOR(CodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00001719CAST_ACCESSOR(MapCache)
1720CAST_ACCESSOR(String)
1721CAST_ACCESSOR(SeqString)
1722CAST_ACCESSOR(SeqAsciiString)
1723CAST_ACCESSOR(SeqTwoByteString)
1724CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00001725CAST_ACCESSOR(ExternalString)
1726CAST_ACCESSOR(ExternalAsciiString)
1727CAST_ACCESSOR(ExternalTwoByteString)
1728CAST_ACCESSOR(JSObject)
1729CAST_ACCESSOR(Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00001730CAST_ACCESSOR(HeapObject)
1731CAST_ACCESSOR(HeapNumber)
1732CAST_ACCESSOR(Oddball)
1733CAST_ACCESSOR(JSGlobalPropertyCell)
1734CAST_ACCESSOR(SharedFunctionInfo)
1735CAST_ACCESSOR(Map)
1736CAST_ACCESSOR(JSFunction)
1737CAST_ACCESSOR(GlobalObject)
1738CAST_ACCESSOR(JSGlobalProxy)
1739CAST_ACCESSOR(JSGlobalObject)
1740CAST_ACCESSOR(JSBuiltinsObject)
1741CAST_ACCESSOR(Code)
1742CAST_ACCESSOR(JSArray)
1743CAST_ACCESSOR(JSRegExp)
1744CAST_ACCESSOR(Proxy)
1745CAST_ACCESSOR(ByteArray)
1746CAST_ACCESSOR(PixelArray)
Steve Block3ce2e202009-11-05 08:53:23 +00001747CAST_ACCESSOR(ExternalArray)
1748CAST_ACCESSOR(ExternalByteArray)
1749CAST_ACCESSOR(ExternalUnsignedByteArray)
1750CAST_ACCESSOR(ExternalShortArray)
1751CAST_ACCESSOR(ExternalUnsignedShortArray)
1752CAST_ACCESSOR(ExternalIntArray)
1753CAST_ACCESSOR(ExternalUnsignedIntArray)
1754CAST_ACCESSOR(ExternalFloatArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00001755CAST_ACCESSOR(Struct)
1756
1757
1758#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1759 STRUCT_LIST(MAKE_STRUCT_CAST)
1760#undef MAKE_STRUCT_CAST
1761
1762
1763template <typename Shape, typename Key>
1764HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1765 ASSERT(obj->IsHashTable());
1766 return reinterpret_cast<HashTable*>(obj);
1767}
1768
1769
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001770SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1771SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1772
1773INT_ACCESSORS(PixelArray, length, kLengthOffset)
1774INT_ACCESSORS(ExternalArray, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00001775
1776
Steve Block6ded16b2010-05-10 14:33:55 +01001777SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00001778
1779
1780uint32_t String::hash_field() {
1781 return READ_UINT32_FIELD(this, kHashFieldOffset);
1782}
1783
1784
1785void String::set_hash_field(uint32_t value) {
1786 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001787#if V8_HOST_ARCH_64_BIT
1788 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1789#endif
Steve Blockd0582a62009-12-15 09:54:21 +00001790}
1791
1792
Steve Blocka7e24c12009-10-30 11:49:00 +00001793bool String::Equals(String* other) {
1794 if (other == this) return true;
1795 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1796 return false;
1797 }
1798 return SlowEquals(other);
1799}
1800
1801
John Reck59135872010-11-02 12:39:01 -07001802MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001803 if (!StringShape(this).IsCons()) return this;
1804 ConsString* cons = ConsString::cast(this);
1805 if (cons->second()->length() == 0) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01001806 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807}
1808
1809
Leon Clarkef7060e22010-06-03 12:02:55 +01001810String* String::TryFlattenGetString(PretenureFlag pretenure) {
John Reck59135872010-11-02 12:39:01 -07001811 MaybeObject* flat = TryFlatten(pretenure);
1812 Object* successfully_flattened;
1813 if (flat->ToObject(&successfully_flattened)) {
1814 return String::cast(successfully_flattened);
1815 }
1816 return this;
Leon Clarkef7060e22010-06-03 12:02:55 +01001817}
1818
1819
Steve Blocka7e24c12009-10-30 11:49:00 +00001820uint16_t String::Get(int index) {
1821 ASSERT(index >= 0 && index < length());
1822 switch (StringShape(this).full_representation_tag()) {
1823 case kSeqStringTag | kAsciiStringTag:
1824 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1825 case kSeqStringTag | kTwoByteStringTag:
1826 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1827 case kConsStringTag | kAsciiStringTag:
1828 case kConsStringTag | kTwoByteStringTag:
1829 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001830 case kExternalStringTag | kAsciiStringTag:
1831 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1832 case kExternalStringTag | kTwoByteStringTag:
1833 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1834 default:
1835 break;
1836 }
1837
1838 UNREACHABLE();
1839 return 0;
1840}
1841
1842
1843void String::Set(int index, uint16_t value) {
1844 ASSERT(index >= 0 && index < length());
1845 ASSERT(StringShape(this).IsSequential());
1846
1847 return this->IsAsciiRepresentation()
1848 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1849 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1850}
1851
1852
1853bool String::IsFlat() {
1854 switch (StringShape(this).representation_tag()) {
1855 case kConsStringTag: {
1856 String* second = ConsString::cast(this)->second();
1857 // Only flattened strings have second part empty.
1858 return second->length() == 0;
1859 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001860 default:
1861 return true;
1862 }
1863}
1864
1865
1866uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1867 ASSERT(index >= 0 && index < length());
1868 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1869}
1870
1871
1872void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1873 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1874 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1875 static_cast<byte>(value));
1876}
1877
1878
1879Address SeqAsciiString::GetCharsAddress() {
1880 return FIELD_ADDR(this, kHeaderSize);
1881}
1882
1883
1884char* SeqAsciiString::GetChars() {
1885 return reinterpret_cast<char*>(GetCharsAddress());
1886}
1887
1888
1889Address SeqTwoByteString::GetCharsAddress() {
1890 return FIELD_ADDR(this, kHeaderSize);
1891}
1892
1893
1894uc16* SeqTwoByteString::GetChars() {
1895 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1896}
1897
1898
1899uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1900 ASSERT(index >= 0 && index < length());
1901 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1902}
1903
1904
1905void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1906 ASSERT(index >= 0 && index < length());
1907 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1908}
1909
1910
1911int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001912 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001913}
1914
1915
1916int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01001917 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001918}
1919
1920
1921String* ConsString::first() {
1922 return String::cast(READ_FIELD(this, kFirstOffset));
1923}
1924
1925
1926Object* ConsString::unchecked_first() {
1927 return READ_FIELD(this, kFirstOffset);
1928}
1929
1930
1931void ConsString::set_first(String* value, WriteBarrierMode mode) {
1932 WRITE_FIELD(this, kFirstOffset, value);
1933 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1934}
1935
1936
1937String* ConsString::second() {
1938 return String::cast(READ_FIELD(this, kSecondOffset));
1939}
1940
1941
1942Object* ConsString::unchecked_second() {
1943 return READ_FIELD(this, kSecondOffset);
1944}
1945
1946
1947void ConsString::set_second(String* value, WriteBarrierMode mode) {
1948 WRITE_FIELD(this, kSecondOffset, value);
1949 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1950}
1951
1952
Steve Blocka7e24c12009-10-30 11:49:00 +00001953ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1954 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1955}
1956
1957
1958void ExternalAsciiString::set_resource(
1959 ExternalAsciiString::Resource* resource) {
1960 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1961}
1962
1963
Steve Blocka7e24c12009-10-30 11:49:00 +00001964ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1965 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1966}
1967
1968
1969void ExternalTwoByteString::set_resource(
1970 ExternalTwoByteString::Resource* resource) {
1971 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1972}
1973
1974
Steve Block6ded16b2010-05-10 14:33:55 +01001975void JSFunctionResultCache::MakeZeroSize() {
1976 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1977 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1978}
1979
1980
1981void JSFunctionResultCache::Clear() {
1982 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1983 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001984 MemsetPointer(entries_start,
1985 Heap::the_hole_value(),
1986 cache_size - kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01001987 MakeZeroSize();
1988}
1989
1990
Steve Blocka7e24c12009-10-30 11:49:00 +00001991byte ByteArray::get(int index) {
1992 ASSERT(index >= 0 && index < this->length());
1993 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1994}
1995
1996
1997void ByteArray::set(int index, byte value) {
1998 ASSERT(index >= 0 && index < this->length());
1999 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2000}
2001
2002
2003int ByteArray::get_int(int index) {
2004 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2005 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2006}
2007
2008
2009ByteArray* ByteArray::FromDataStartAddress(Address address) {
2010 ASSERT_TAG_ALIGNED(address);
2011 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2012}
2013
2014
2015Address ByteArray::GetDataStartAddress() {
2016 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2017}
2018
2019
2020uint8_t* PixelArray::external_pointer() {
2021 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2022 return reinterpret_cast<uint8_t*>(ptr);
2023}
2024
2025
2026void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
2027 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2028 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2029}
2030
2031
2032uint8_t PixelArray::get(int index) {
2033 ASSERT((index >= 0) && (index < this->length()));
2034 uint8_t* ptr = external_pointer();
2035 return ptr[index];
2036}
2037
2038
2039void PixelArray::set(int index, uint8_t value) {
2040 ASSERT((index >= 0) && (index < this->length()));
2041 uint8_t* ptr = external_pointer();
2042 ptr[index] = value;
2043}
2044
2045
Steve Block3ce2e202009-11-05 08:53:23 +00002046void* ExternalArray::external_pointer() {
2047 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2048 return reinterpret_cast<void*>(ptr);
2049}
2050
2051
2052void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2053 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2054 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2055}
2056
2057
2058int8_t ExternalByteArray::get(int index) {
2059 ASSERT((index >= 0) && (index < this->length()));
2060 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2061 return ptr[index];
2062}
2063
2064
2065void ExternalByteArray::set(int index, int8_t value) {
2066 ASSERT((index >= 0) && (index < this->length()));
2067 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2068 ptr[index] = value;
2069}
2070
2071
2072uint8_t ExternalUnsignedByteArray::get(int index) {
2073 ASSERT((index >= 0) && (index < this->length()));
2074 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2075 return ptr[index];
2076}
2077
2078
2079void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2080 ASSERT((index >= 0) && (index < this->length()));
2081 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2082 ptr[index] = value;
2083}
2084
2085
2086int16_t ExternalShortArray::get(int index) {
2087 ASSERT((index >= 0) && (index < this->length()));
2088 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2089 return ptr[index];
2090}
2091
2092
2093void ExternalShortArray::set(int index, int16_t value) {
2094 ASSERT((index >= 0) && (index < this->length()));
2095 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2096 ptr[index] = value;
2097}
2098
2099
2100uint16_t ExternalUnsignedShortArray::get(int index) {
2101 ASSERT((index >= 0) && (index < this->length()));
2102 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2103 return ptr[index];
2104}
2105
2106
2107void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2108 ASSERT((index >= 0) && (index < this->length()));
2109 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2110 ptr[index] = value;
2111}
2112
2113
2114int32_t ExternalIntArray::get(int index) {
2115 ASSERT((index >= 0) && (index < this->length()));
2116 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2117 return ptr[index];
2118}
2119
2120
2121void ExternalIntArray::set(int index, int32_t value) {
2122 ASSERT((index >= 0) && (index < this->length()));
2123 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2124 ptr[index] = value;
2125}
2126
2127
2128uint32_t ExternalUnsignedIntArray::get(int index) {
2129 ASSERT((index >= 0) && (index < this->length()));
2130 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2131 return ptr[index];
2132}
2133
2134
2135void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2136 ASSERT((index >= 0) && (index < this->length()));
2137 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2138 ptr[index] = value;
2139}
2140
2141
2142float ExternalFloatArray::get(int index) {
2143 ASSERT((index >= 0) && (index < this->length()));
2144 float* ptr = static_cast<float*>(external_pointer());
2145 return ptr[index];
2146}
2147
2148
2149void ExternalFloatArray::set(int index, float value) {
2150 ASSERT((index >= 0) && (index < this->length()));
2151 float* ptr = static_cast<float*>(external_pointer());
2152 ptr[index] = value;
2153}
2154
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002155
Iain Merrick9ac36c92010-09-13 15:29:50 +01002156int Map::visitor_id() {
2157 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2158}
2159
2160
2161void Map::set_visitor_id(int id) {
2162 ASSERT(0 <= id && id < 256);
2163 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2164}
2165
Steve Block3ce2e202009-11-05 08:53:23 +00002166
Steve Blocka7e24c12009-10-30 11:49:00 +00002167int Map::instance_size() {
2168 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2169}
2170
2171
2172int Map::inobject_properties() {
2173 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2174}
2175
2176
2177int Map::pre_allocated_property_fields() {
2178 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2179}
2180
2181
2182int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01002183 int instance_size = map->instance_size();
2184 if (instance_size != kVariableSizeSentinel) return instance_size;
2185 // We can ignore the "symbol" bit becase it is only set for symbols
2186 // and implies a string type.
2187 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 // Only inline the most frequent cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00002189 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002190 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002191 }
Steve Block791712a2010-08-27 10:21:07 +01002192 if (instance_type == ASCII_STRING_TYPE) {
2193 return SeqAsciiString::SizeFor(
2194 reinterpret_cast<SeqAsciiString*>(this)->length());
2195 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002196 if (instance_type == BYTE_ARRAY_TYPE) {
2197 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2198 }
Steve Block791712a2010-08-27 10:21:07 +01002199 if (instance_type == STRING_TYPE) {
2200 return SeqTwoByteString::SizeFor(
2201 reinterpret_cast<SeqTwoByteString*>(this)->length());
2202 }
2203 ASSERT(instance_type == CODE_TYPE);
2204 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00002205}
2206
2207
2208void Map::set_instance_size(int value) {
2209 ASSERT_EQ(0, value & (kPointerSize - 1));
2210 value >>= kPointerSizeLog2;
2211 ASSERT(0 <= value && value < 256);
2212 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2213}
2214
2215
2216void Map::set_inobject_properties(int value) {
2217 ASSERT(0 <= value && value < 256);
2218 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2219}
2220
2221
2222void Map::set_pre_allocated_property_fields(int value) {
2223 ASSERT(0 <= value && value < 256);
2224 WRITE_BYTE_FIELD(this,
2225 kPreAllocatedPropertyFieldsOffset,
2226 static_cast<byte>(value));
2227}
2228
2229
2230InstanceType Map::instance_type() {
2231 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2232}
2233
2234
2235void Map::set_instance_type(InstanceType value) {
2236 ASSERT(0 <= value && value < 256);
2237 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2238}
2239
2240
2241int Map::unused_property_fields() {
2242 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2243}
2244
2245
2246void Map::set_unused_property_fields(int value) {
2247 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2248}
2249
2250
2251byte Map::bit_field() {
2252 return READ_BYTE_FIELD(this, kBitFieldOffset);
2253}
2254
2255
2256void Map::set_bit_field(byte value) {
2257 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2258}
2259
2260
2261byte Map::bit_field2() {
2262 return READ_BYTE_FIELD(this, kBitField2Offset);
2263}
2264
2265
2266void Map::set_bit_field2(byte value) {
2267 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2268}
2269
2270
2271void Map::set_non_instance_prototype(bool value) {
2272 if (value) {
2273 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2274 } else {
2275 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2276 }
2277}
2278
2279
2280bool Map::has_non_instance_prototype() {
2281 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2282}
2283
2284
Steve Block6ded16b2010-05-10 14:33:55 +01002285void Map::set_function_with_prototype(bool value) {
2286 if (value) {
2287 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2288 } else {
2289 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2290 }
2291}
2292
2293
2294bool Map::function_with_prototype() {
2295 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2296}
2297
2298
Steve Blocka7e24c12009-10-30 11:49:00 +00002299void Map::set_is_access_check_needed(bool access_check_needed) {
2300 if (access_check_needed) {
2301 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2302 } else {
2303 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2304 }
2305}
2306
2307
2308bool Map::is_access_check_needed() {
2309 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2310}
2311
2312
Steve Block8defd9f2010-07-08 12:39:36 +01002313void Map::set_is_extensible(bool value) {
2314 if (value) {
2315 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2316 } else {
2317 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2318 }
2319}
2320
2321bool Map::is_extensible() {
2322 return ((1 << kIsExtensible) & bit_field2()) != 0;
2323}
2324
2325
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002326void Map::set_attached_to_shared_function_info(bool value) {
2327 if (value) {
2328 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2329 } else {
2330 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2331 }
2332}
2333
2334bool Map::attached_to_shared_function_info() {
2335 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2336}
2337
2338
2339void Map::set_is_shared(bool value) {
2340 if (value) {
2341 set_bit_field2(bit_field2() | (1 << kIsShared));
2342 } else {
2343 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2344 }
2345}
2346
2347bool Map::is_shared() {
2348 return ((1 << kIsShared) & bit_field2()) != 0;
2349}
2350
2351
2352JSFunction* Map::unchecked_constructor() {
2353 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2354}
2355
Steve Block8defd9f2010-07-08 12:39:36 +01002356
Steve Blocka7e24c12009-10-30 11:49:00 +00002357Code::Flags Code::flags() {
2358 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2359}
2360
2361
2362void Code::set_flags(Code::Flags flags) {
2363 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2364 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002365 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2366 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002367 ExtractArgumentsCountFromFlags(flags) >= 0);
2368 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2369}
2370
2371
2372Code::Kind Code::kind() {
2373 return ExtractKindFromFlags(flags());
2374}
2375
2376
2377InLoopFlag Code::ic_in_loop() {
2378 return ExtractICInLoopFromFlags(flags());
2379}
2380
2381
2382InlineCacheState Code::ic_state() {
2383 InlineCacheState result = ExtractICStateFromFlags(flags());
2384 // Only allow uninitialized or debugger states for non-IC code
2385 // objects. This is used in the debugger to determine whether or not
2386 // a call to code object has been replaced with a debug break call.
2387 ASSERT(is_inline_cache_stub() ||
2388 result == UNINITIALIZED ||
2389 result == DEBUG_BREAK ||
2390 result == DEBUG_PREPARE_STEP_IN);
2391 return result;
2392}
2393
2394
2395PropertyType Code::type() {
2396 ASSERT(ic_state() == MONOMORPHIC);
2397 return ExtractTypeFromFlags(flags());
2398}
2399
2400
2401int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002402 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002403 return ExtractArgumentsCountFromFlags(flags());
2404}
2405
2406
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002407int Code::major_key() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002408 ASSERT(kind() == STUB ||
2409 kind() == BINARY_OP_IC ||
2410 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2411 kind() == COMPARE_IC);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002412 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00002413}
2414
2415
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002416void Code::set_major_key(int major) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002417 ASSERT(kind() == STUB ||
2418 kind() == BINARY_OP_IC ||
2419 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2420 kind() == COMPARE_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002421 ASSERT(0 <= major && major < 256);
2422 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2423}
2424
2425
Ben Murdochb0fe1622011-05-05 13:52:32 +01002426bool Code::optimizable() {
2427 ASSERT(kind() == FUNCTION);
2428 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2429}
2430
2431
2432void Code::set_optimizable(bool value) {
2433 ASSERT(kind() == FUNCTION);
2434 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2435}
2436
2437
2438bool Code::has_deoptimization_support() {
2439 ASSERT(kind() == FUNCTION);
2440 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2441}
2442
2443
2444void Code::set_has_deoptimization_support(bool value) {
2445 ASSERT(kind() == FUNCTION);
2446 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2447}
2448
2449
2450int Code::allow_osr_at_loop_nesting_level() {
2451 ASSERT(kind() == FUNCTION);
2452 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2453}
2454
2455
2456void Code::set_allow_osr_at_loop_nesting_level(int level) {
2457 ASSERT(kind() == FUNCTION);
2458 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2459 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2460}
2461
2462
2463unsigned Code::stack_slots() {
2464 ASSERT(kind() == OPTIMIZED_FUNCTION);
2465 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2466}
2467
2468
2469void Code::set_stack_slots(unsigned slots) {
2470 ASSERT(kind() == OPTIMIZED_FUNCTION);
2471 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2472}
2473
2474
2475unsigned Code::safepoint_table_start() {
2476 ASSERT(kind() == OPTIMIZED_FUNCTION);
2477 return READ_UINT32_FIELD(this, kSafepointTableStartOffset);
2478}
2479
2480
2481void Code::set_safepoint_table_start(unsigned offset) {
2482 ASSERT(kind() == OPTIMIZED_FUNCTION);
2483 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2484 WRITE_UINT32_FIELD(this, kSafepointTableStartOffset, offset);
2485}
2486
2487
2488unsigned Code::stack_check_table_start() {
2489 ASSERT(kind() == FUNCTION);
2490 return READ_UINT32_FIELD(this, kStackCheckTableStartOffset);
2491}
2492
2493
2494void Code::set_stack_check_table_start(unsigned offset) {
2495 ASSERT(kind() == FUNCTION);
2496 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2497 WRITE_UINT32_FIELD(this, kStackCheckTableStartOffset, offset);
2498}
2499
2500
2501CheckType Code::check_type() {
2502 ASSERT(is_call_stub() || is_keyed_call_stub());
2503 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2504 return static_cast<CheckType>(type);
2505}
2506
2507
2508void Code::set_check_type(CheckType value) {
2509 ASSERT(is_call_stub() || is_keyed_call_stub());
2510 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2511}
2512
2513
2514byte Code::binary_op_type() {
2515 ASSERT(is_binary_op_stub());
2516 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2517}
2518
2519
2520void Code::set_binary_op_type(byte value) {
2521 ASSERT(is_binary_op_stub());
2522 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2523}
2524
2525
2526byte Code::type_recording_binary_op_type() {
2527 ASSERT(is_type_recording_binary_op_stub());
2528 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2529}
2530
2531
2532void Code::set_type_recording_binary_op_type(byte value) {
2533 ASSERT(is_type_recording_binary_op_stub());
2534 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2535}
2536
2537
2538byte Code::type_recording_binary_op_result_type() {
2539 ASSERT(is_type_recording_binary_op_stub());
2540 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2541}
2542
2543
2544void Code::set_type_recording_binary_op_result_type(byte value) {
2545 ASSERT(is_type_recording_binary_op_stub());
2546 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2547}
2548
2549
2550byte Code::compare_state() {
2551 ASSERT(is_compare_ic_stub());
2552 return READ_BYTE_FIELD(this, kCompareStateOffset);
2553}
2554
2555
2556void Code::set_compare_state(byte value) {
2557 ASSERT(is_compare_ic_stub());
2558 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2559}
2560
2561
Steve Blocka7e24c12009-10-30 11:49:00 +00002562bool Code::is_inline_cache_stub() {
2563 Kind kind = this->kind();
2564 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2565}
2566
2567
2568Code::Flags Code::ComputeFlags(Kind kind,
2569 InLoopFlag in_loop,
2570 InlineCacheState ic_state,
2571 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002572 int argc,
2573 InlineCacheHolderFlag holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002574 // Compute the bit mask.
2575 int bits = kind << kFlagsKindShift;
2576 if (in_loop) bits |= kFlagsICInLoopMask;
2577 bits |= ic_state << kFlagsICStateShift;
2578 bits |= type << kFlagsTypeShift;
2579 bits |= argc << kFlagsArgumentsCountShift;
Steve Block8defd9f2010-07-08 12:39:36 +01002580 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002581 // Cast to flags and validate result before returning it.
2582 Flags result = static_cast<Flags>(bits);
2583 ASSERT(ExtractKindFromFlags(result) == kind);
2584 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2585 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2586 ASSERT(ExtractTypeFromFlags(result) == type);
2587 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2588 return result;
2589}
2590
2591
2592Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2593 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002594 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00002595 InLoopFlag in_loop,
2596 int argc) {
Steve Block8defd9f2010-07-08 12:39:36 +01002597 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00002598}
2599
2600
2601Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2602 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2603 return static_cast<Kind>(bits);
2604}
2605
2606
2607InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2608 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2609 return static_cast<InlineCacheState>(bits);
2610}
2611
2612
2613InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2614 int bits = (flags & kFlagsICInLoopMask);
2615 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2616}
2617
2618
2619PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2620 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2621 return static_cast<PropertyType>(bits);
2622}
2623
2624
2625int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2626 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2627}
2628
2629
Steve Block8defd9f2010-07-08 12:39:36 +01002630InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2631 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2632 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2633}
2634
2635
Steve Blocka7e24c12009-10-30 11:49:00 +00002636Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2637 int bits = flags & ~kFlagsTypeMask;
2638 return static_cast<Flags>(bits);
2639}
2640
2641
2642Code* Code::GetCodeFromTargetAddress(Address address) {
2643 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2644 // GetCodeFromTargetAddress might be called when marking objects during mark
2645 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2646 // Code::cast. Code::cast does not work when the object's map is
2647 // marked.
2648 Code* result = reinterpret_cast<Code*>(code);
2649 return result;
2650}
2651
2652
Steve Block791712a2010-08-27 10:21:07 +01002653Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2654 return HeapObject::
2655 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2656}
2657
2658
Steve Blocka7e24c12009-10-30 11:49:00 +00002659Object* Map::prototype() {
2660 return READ_FIELD(this, kPrototypeOffset);
2661}
2662
2663
2664void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2665 ASSERT(value->IsNull() || value->IsJSObject());
2666 WRITE_FIELD(this, kPrototypeOffset, value);
2667 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2668}
2669
2670
John Reck59135872010-11-02 12:39:01 -07002671MaybeObject* Map::GetFastElementsMap() {
Steve Block8defd9f2010-07-08 12:39:36 +01002672 if (has_fast_elements()) return this;
John Reck59135872010-11-02 12:39:01 -07002673 Object* obj;
2674 { MaybeObject* maybe_obj = CopyDropTransitions();
2675 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2676 }
Steve Block8defd9f2010-07-08 12:39:36 +01002677 Map* new_map = Map::cast(obj);
2678 new_map->set_has_fast_elements(true);
Iain Merrick75681382010-08-19 15:07:18 +01002679 Counters::map_slow_to_fast_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002680 return new_map;
2681}
2682
2683
John Reck59135872010-11-02 12:39:01 -07002684MaybeObject* Map::GetSlowElementsMap() {
Steve Block8defd9f2010-07-08 12:39:36 +01002685 if (!has_fast_elements()) return this;
John Reck59135872010-11-02 12:39:01 -07002686 Object* obj;
2687 { MaybeObject* maybe_obj = CopyDropTransitions();
2688 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2689 }
Steve Block8defd9f2010-07-08 12:39:36 +01002690 Map* new_map = Map::cast(obj);
2691 new_map->set_has_fast_elements(false);
Iain Merrick75681382010-08-19 15:07:18 +01002692 Counters::map_fast_to_slow_elements.Increment();
Steve Block8defd9f2010-07-08 12:39:36 +01002693 return new_map;
2694}
2695
2696
Steve Blocka7e24c12009-10-30 11:49:00 +00002697ACCESSORS(Map, instance_descriptors, DescriptorArray,
2698 kInstanceDescriptorsOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002699ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002700ACCESSORS(Map, constructor, Object, kConstructorOffset)
2701
2702ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2703ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002704ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002705
2706ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2707ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2708ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2709
2710ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2711
2712ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2713ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2714ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2715ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2716ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2717
2718ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2719ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2720ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2721
2722ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2723ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2724ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2725ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2726ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2727ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2728
2729ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2730ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2731
2732ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2733ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2734
2735ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2736ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2737ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2738 kPropertyAccessorsOffset)
2739ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2740 kPrototypeTemplateOffset)
2741ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2742ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2743 kNamedPropertyHandlerOffset)
2744ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2745 kIndexedPropertyHandlerOffset)
2746ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2747 kInstanceTemplateOffset)
2748ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2749ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2750ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2751 kInstanceCallHandlerOffset)
2752ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2753 kAccessCheckInfoOffset)
2754ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2755
2756ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2757ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2758 kInternalFieldCountOffset)
2759
2760ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2761ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2762
2763ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2764
2765ACCESSORS(Script, source, Object, kSourceOffset)
2766ACCESSORS(Script, name, Object, kNameOffset)
2767ACCESSORS(Script, id, Object, kIdOffset)
2768ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2769ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2770ACCESSORS(Script, data, Object, kDataOffset)
2771ACCESSORS(Script, context_data, Object, kContextOffset)
2772ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2773ACCESSORS(Script, type, Smi, kTypeOffset)
2774ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2775ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002776ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002777ACCESSORS(Script, eval_from_instructions_offset, Smi,
2778 kEvalFrominstructionsOffsetOffset)
2779
2780#ifdef ENABLE_DEBUGGER_SUPPORT
2781ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2782ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2783ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2784ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2785
2786ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2787ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2788ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2789ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2790#endif
2791
Steve Blocka7e24c12009-10-30 11:49:00 +00002792ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002793ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002794ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002795ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2796 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01002797ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002798ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2799ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2800ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2801ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2802 kThisPropertyAssignmentsOffset)
2803
2804BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2805 kHiddenPrototypeBit)
2806BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2807BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2808 kNeedsAccessCheckBit)
2809BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2810 kIsExpressionBit)
2811BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2812 kIsTopLevelBit)
2813BOOL_GETTER(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002814 has_only_simple_this_property_assignments,
2815 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00002816BOOL_ACCESSORS(SharedFunctionInfo,
2817 compiler_hints,
Leon Clarked91b9f72010-01-27 17:25:45 +00002818 try_full_codegen,
2819 kTryFullCodegen)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002820BOOL_ACCESSORS(SharedFunctionInfo,
2821 compiler_hints,
2822 allows_lazy_compilation,
2823 kAllowLazyCompilation)
Steve Blocka7e24c12009-10-30 11:49:00 +00002824
Iain Merrick75681382010-08-19 15:07:18 +01002825
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002826#if V8_HOST_ARCH_32_BIT
2827SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2828SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002829 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002830SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00002831 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002832SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2833SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00002834 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002835SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2836SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00002837 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002838SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00002839 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002840SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00002841 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002842SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002843#else
Steve Blocka7e24c12009-10-30 11:49:00 +00002844
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002845#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002846 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002847 int holder::name() { \
2848 int value = READ_INT_FIELD(this, offset); \
2849 ASSERT(kHeapObjectTag == 1); \
2850 ASSERT((value & kHeapObjectTag) == 0); \
2851 return value >> 1; \
2852 } \
2853 void holder::set_##name(int value) { \
2854 ASSERT(kHeapObjectTag == 1); \
2855 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2856 (value & 0xC0000000) == 0x000000000); \
2857 WRITE_INT_FIELD(this, \
2858 offset, \
2859 (value << 1) & ~kHeapObjectTag); \
2860 }
2861
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002862#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2863 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002864 INT_ACCESSORS(holder, name, offset)
2865
2866
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002867PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002868PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2869 formal_parameter_count,
2870 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002871
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002872PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2873 expected_nof_properties,
2874 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002875PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2876
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002877PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
2878PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2879 start_position_and_type,
2880 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002881
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002882PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2883 function_token_position,
2884 kFunctionTokenPositionOffset)
2885PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2886 compiler_hints,
2887 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002888
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002889PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2890 this_property_assignments_count,
2891 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002892PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002893#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002894
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002895
2896int SharedFunctionInfo::construction_count() {
2897 return READ_BYTE_FIELD(this, kConstructionCountOffset);
2898}
2899
2900
2901void SharedFunctionInfo::set_construction_count(int value) {
2902 ASSERT(0 <= value && value < 256);
2903 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
2904}
2905
2906
2907bool SharedFunctionInfo::live_objects_may_exist() {
2908 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
2909}
2910
2911
2912void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
2913 if (value) {
2914 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
2915 } else {
2916 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
2917 }
2918}
2919
2920
2921bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
2922 return initial_map() != Heap::undefined_value();
2923}
2924
2925
Ben Murdochb0fe1622011-05-05 13:52:32 +01002926bool SharedFunctionInfo::optimization_disabled() {
2927 return BooleanBit::get(compiler_hints(), kOptimizationDisabled);
2928}
2929
2930
2931void SharedFunctionInfo::set_optimization_disabled(bool disable) {
2932 set_compiler_hints(BooleanBit::set(compiler_hints(),
2933 kOptimizationDisabled,
2934 disable));
2935 // If disabling optimizations we reflect that in the code object so
2936 // it will not be counted as optimizable code.
2937 if ((code()->kind() == Code::FUNCTION) && disable) {
2938 code()->set_optimizable(false);
2939 }
2940}
2941
2942
Steve Block6ded16b2010-05-10 14:33:55 +01002943ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2944ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2945
Steve Block3ce2e202009-11-05 08:53:23 +00002946bool Script::HasValidSource() {
2947 Object* src = this->source();
2948 if (!src->IsString()) return true;
2949 String* src_str = String::cast(src);
2950 if (!StringShape(src_str).IsExternal()) return true;
2951 if (src_str->IsAsciiRepresentation()) {
2952 return ExternalAsciiString::cast(src)->resource() != NULL;
2953 } else if (src_str->IsTwoByteRepresentation()) {
2954 return ExternalTwoByteString::cast(src)->resource() != NULL;
2955 }
2956 return true;
2957}
2958
2959
Steve Blocka7e24c12009-10-30 11:49:00 +00002960void SharedFunctionInfo::DontAdaptArguments() {
2961 ASSERT(code()->kind() == Code::BUILTIN);
2962 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2963}
2964
2965
2966int SharedFunctionInfo::start_position() {
2967 return start_position_and_type() >> kStartPositionShift;
2968}
2969
2970
2971void SharedFunctionInfo::set_start_position(int start_position) {
2972 set_start_position_and_type((start_position << kStartPositionShift)
2973 | (start_position_and_type() & ~kStartPositionMask));
2974}
2975
2976
2977Code* SharedFunctionInfo::code() {
2978 return Code::cast(READ_FIELD(this, kCodeOffset));
2979}
2980
2981
Iain Merrick75681382010-08-19 15:07:18 +01002982Code* SharedFunctionInfo::unchecked_code() {
2983 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2984}
2985
2986
Steve Blocka7e24c12009-10-30 11:49:00 +00002987void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002988 // If optimization has been disabled for the shared function info,
2989 // reflect that in the code object so it will not be counted as
2990 // optimizable code.
2991 ASSERT(value->kind() != Code::FUNCTION ||
2992 !value->optimizable() ||
2993 this->code() == Builtins::builtin(Builtins::Illegal) ||
2994 this->allows_lazy_compilation());
Steve Blocka7e24c12009-10-30 11:49:00 +00002995 WRITE_FIELD(this, kCodeOffset, value);
2996 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2997}
2998
2999
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003000SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3001 return reinterpret_cast<SerializedScopeInfo*>(
3002 READ_FIELD(this, kScopeInfoOffset));
3003}
3004
3005
3006void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3007 WriteBarrierMode mode) {
3008 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3009 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
3010}
3011
3012
Ben Murdochb0fe1622011-05-05 13:52:32 +01003013Smi* SharedFunctionInfo::deopt_counter() {
3014 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3015}
3016
3017
3018void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3019 WRITE_FIELD(this, kDeoptCounterOffset, value);
3020}
3021
3022
Steve Blocka7e24c12009-10-30 11:49:00 +00003023bool SharedFunctionInfo::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01003024 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003025}
3026
3027
Steve Block6ded16b2010-05-10 14:33:55 +01003028bool SharedFunctionInfo::IsApiFunction() {
3029 return function_data()->IsFunctionTemplateInfo();
3030}
3031
3032
3033FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3034 ASSERT(IsApiFunction());
3035 return FunctionTemplateInfo::cast(function_data());
3036}
3037
3038
Ben Murdochb0fe1622011-05-05 13:52:32 +01003039bool SharedFunctionInfo::HasBuiltinFunctionId() {
Kristian Monsen25f61362010-05-21 11:50:48 +01003040 return function_data()->IsSmi();
3041}
3042
3043
Ben Murdochb0fe1622011-05-05 13:52:32 +01003044bool SharedFunctionInfo::IsBuiltinMathFunction() {
3045 return HasBuiltinFunctionId() &&
3046 builtin_function_id() >= kFirstMathFunctionId;
3047}
3048
3049
3050BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3051 ASSERT(HasBuiltinFunctionId());
3052 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003053}
3054
3055
Iain Merrick75681382010-08-19 15:07:18 +01003056int SharedFunctionInfo::code_age() {
3057 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3058}
3059
3060
3061void SharedFunctionInfo::set_code_age(int code_age) {
3062 set_compiler_hints(compiler_hints() |
3063 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3064}
3065
3066
Ben Murdochb0fe1622011-05-05 13:52:32 +01003067bool SharedFunctionInfo::has_deoptimization_support() {
3068 Code* code = this->code();
3069 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3070}
3071
3072
Steve Blocka7e24c12009-10-30 11:49:00 +00003073bool JSFunction::IsBuiltin() {
3074 return context()->global()->IsJSBuiltinsObject();
3075}
3076
3077
Ben Murdochb0fe1622011-05-05 13:52:32 +01003078bool JSFunction::NeedsArgumentsAdaption() {
3079 return shared()->formal_parameter_count() !=
3080 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3081}
3082
3083
3084bool JSFunction::IsOptimized() {
3085 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3086}
3087
3088
3089bool JSFunction::IsMarkedForLazyRecompilation() {
3090 return code() == Builtins::builtin(Builtins::LazyRecompile);
3091}
3092
3093
Steve Blocka7e24c12009-10-30 11:49:00 +00003094Code* JSFunction::code() {
Steve Block791712a2010-08-27 10:21:07 +01003095 return Code::cast(unchecked_code());
Iain Merrick75681382010-08-19 15:07:18 +01003096}
3097
3098
3099Code* JSFunction::unchecked_code() {
Steve Block791712a2010-08-27 10:21:07 +01003100 return reinterpret_cast<Code*>(
3101 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003102}
3103
3104
3105void JSFunction::set_code(Code* value) {
Iain Merrick75681382010-08-19 15:07:18 +01003106 // Skip the write barrier because code is never in new space.
3107 ASSERT(!Heap::InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01003108 Address entry = value->entry();
3109 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Steve Blocka7e24c12009-10-30 11:49:00 +00003110}
3111
3112
Ben Murdochb0fe1622011-05-05 13:52:32 +01003113void JSFunction::ReplaceCode(Code* code) {
3114 bool was_optimized = IsOptimized();
3115 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3116
3117 set_code(code);
3118
3119 // Add/remove the function from the list of optimized functions for this
3120 // context based on the state change.
3121 if (!was_optimized && is_optimized) {
3122 context()->global_context()->AddOptimizedFunction(this);
3123 }
3124 if (was_optimized && !is_optimized) {
3125 context()->global_context()->RemoveOptimizedFunction(this);
3126 }
3127}
3128
3129
Steve Blocka7e24c12009-10-30 11:49:00 +00003130Context* JSFunction::context() {
3131 return Context::cast(READ_FIELD(this, kContextOffset));
3132}
3133
3134
3135Object* JSFunction::unchecked_context() {
3136 return READ_FIELD(this, kContextOffset);
3137}
3138
3139
Iain Merrick75681382010-08-19 15:07:18 +01003140SharedFunctionInfo* JSFunction::unchecked_shared() {
3141 return reinterpret_cast<SharedFunctionInfo*>(
3142 READ_FIELD(this, kSharedFunctionInfoOffset));
3143}
3144
3145
Steve Blocka7e24c12009-10-30 11:49:00 +00003146void JSFunction::set_context(Object* value) {
3147 ASSERT(value == Heap::undefined_value() || value->IsContext());
3148 WRITE_FIELD(this, kContextOffset, value);
3149 WRITE_BARRIER(this, kContextOffset);
3150}
3151
3152ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3153 kPrototypeOrInitialMapOffset)
3154
3155
3156Map* JSFunction::initial_map() {
3157 return Map::cast(prototype_or_initial_map());
3158}
3159
3160
3161void JSFunction::set_initial_map(Map* value) {
3162 set_prototype_or_initial_map(value);
3163}
3164
3165
3166bool JSFunction::has_initial_map() {
3167 return prototype_or_initial_map()->IsMap();
3168}
3169
3170
3171bool JSFunction::has_instance_prototype() {
3172 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3173}
3174
3175
3176bool JSFunction::has_prototype() {
3177 return map()->has_non_instance_prototype() || has_instance_prototype();
3178}
3179
3180
3181Object* JSFunction::instance_prototype() {
3182 ASSERT(has_instance_prototype());
3183 if (has_initial_map()) return initial_map()->prototype();
3184 // When there is no initial map and the prototype is a JSObject, the
3185 // initial map field is used for the prototype field.
3186 return prototype_or_initial_map();
3187}
3188
3189
3190Object* JSFunction::prototype() {
3191 ASSERT(has_prototype());
3192 // If the function's prototype property has been set to a non-JSObject
3193 // value, that value is stored in the constructor field of the map.
3194 if (map()->has_non_instance_prototype()) return map()->constructor();
3195 return instance_prototype();
3196}
3197
Steve Block6ded16b2010-05-10 14:33:55 +01003198bool JSFunction::should_have_prototype() {
3199 return map()->function_with_prototype();
3200}
3201
Steve Blocka7e24c12009-10-30 11:49:00 +00003202
3203bool JSFunction::is_compiled() {
Iain Merrick75681382010-08-19 15:07:18 +01003204 return code() != Builtins::builtin(Builtins::LazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003205}
3206
3207
3208int JSFunction::NumberOfLiterals() {
3209 return literals()->length();
3210}
3211
3212
3213Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
3214 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01003215 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00003216}
3217
3218
3219void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3220 Object* value) {
3221 ASSERT(0 <= id && id < kJSBuiltinsCount);
Steve Block6ded16b2010-05-10 14:33:55 +01003222 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3223 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3224}
3225
3226
3227Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
3228 ASSERT(0 <= id && id < kJSBuiltinsCount);
3229 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3230}
3231
3232
3233void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3234 Code* value) {
3235 ASSERT(0 <= id && id < kJSBuiltinsCount);
3236 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3237 ASSERT(!Heap::InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00003238}
3239
3240
3241Address Proxy::proxy() {
3242 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
3243}
3244
3245
3246void Proxy::set_proxy(Address value) {
3247 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
3248}
3249
3250
Steve Blocka7e24c12009-10-30 11:49:00 +00003251ACCESSORS(JSValue, value, Object, kValueOffset)
3252
3253
3254JSValue* JSValue::cast(Object* obj) {
3255 ASSERT(obj->IsJSValue());
3256 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3257 return reinterpret_cast<JSValue*>(obj);
3258}
3259
3260
3261INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01003262ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003263ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003264
3265
3266byte* Code::instruction_start() {
3267 return FIELD_ADDR(this, kHeaderSize);
3268}
3269
3270
Leon Clarkeac952652010-07-15 11:15:24 +01003271byte* Code::instruction_end() {
3272 return instruction_start() + instruction_size();
3273}
3274
3275
Steve Blocka7e24c12009-10-30 11:49:00 +00003276int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01003277 return RoundUp(instruction_size(), kObjectAlignment);
3278}
3279
3280
Ben Murdochb0fe1622011-05-05 13:52:32 +01003281FixedArray* Code::unchecked_deoptimization_data() {
3282 return reinterpret_cast<FixedArray*>(
3283 READ_FIELD(this, kDeoptimizationDataOffset));
3284}
3285
3286
Leon Clarkeac952652010-07-15 11:15:24 +01003287ByteArray* Code::unchecked_relocation_info() {
3288 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00003289}
3290
3291
3292byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01003293 return unchecked_relocation_info()->GetDataStartAddress();
3294}
3295
3296
3297int Code::relocation_size() {
3298 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00003299}
3300
3301
3302byte* Code::entry() {
3303 return instruction_start();
3304}
3305
3306
3307bool Code::contains(byte* pc) {
3308 return (instruction_start() <= pc) &&
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003309 (pc <= instruction_start() + instruction_size());
Steve Blocka7e24c12009-10-30 11:49:00 +00003310}
3311
3312
Steve Blocka7e24c12009-10-30 11:49:00 +00003313ACCESSORS(JSArray, length, Object, kLengthOffset)
3314
3315
3316ACCESSORS(JSRegExp, data, Object, kDataOffset)
3317
3318
3319JSRegExp::Type JSRegExp::TypeTag() {
3320 Object* data = this->data();
3321 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3322 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3323 return static_cast<JSRegExp::Type>(smi->value());
3324}
3325
3326
3327int JSRegExp::CaptureCount() {
3328 switch (TypeTag()) {
3329 case ATOM:
3330 return 0;
3331 case IRREGEXP:
3332 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3333 default:
3334 UNREACHABLE();
3335 return -1;
3336 }
3337}
3338
3339
3340JSRegExp::Flags JSRegExp::GetFlags() {
3341 ASSERT(this->data()->IsFixedArray());
3342 Object* data = this->data();
3343 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3344 return Flags(smi->value());
3345}
3346
3347
3348String* JSRegExp::Pattern() {
3349 ASSERT(this->data()->IsFixedArray());
3350 Object* data = this->data();
3351 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3352 return pattern;
3353}
3354
3355
3356Object* JSRegExp::DataAt(int index) {
3357 ASSERT(TypeTag() != NOT_COMPILED);
3358 return FixedArray::cast(data())->get(index);
3359}
3360
3361
3362void JSRegExp::SetDataAt(int index, Object* value) {
3363 ASSERT(TypeTag() != NOT_COMPILED);
3364 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3365 FixedArray::cast(data())->set(index, value);
3366}
3367
3368
3369JSObject::ElementsKind JSObject::GetElementsKind() {
Iain Merrick75681382010-08-19 15:07:18 +01003370 if (map()->has_fast_elements()) {
3371 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3372 elements()->map() == Heap::fixed_cow_array_map());
3373 return FAST_ELEMENTS;
3374 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003375 HeapObject* array = elements();
Steve Blocka7e24c12009-10-30 11:49:00 +00003376 if (array->IsFixedArray()) {
Iain Merrick75681382010-08-19 15:07:18 +01003377 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3378 // FixedArray, but FAST_ELEMENTS is already handled above.
Steve Blocka7e24c12009-10-30 11:49:00 +00003379 ASSERT(array->IsDictionary());
3380 return DICTIONARY_ELEMENTS;
3381 }
Steve Block3ce2e202009-11-05 08:53:23 +00003382 if (array->IsExternalArray()) {
3383 switch (array->map()->instance_type()) {
3384 case EXTERNAL_BYTE_ARRAY_TYPE:
3385 return EXTERNAL_BYTE_ELEMENTS;
3386 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3387 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3388 case EXTERNAL_SHORT_ARRAY_TYPE:
3389 return EXTERNAL_SHORT_ELEMENTS;
3390 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3391 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3392 case EXTERNAL_INT_ARRAY_TYPE:
3393 return EXTERNAL_INT_ELEMENTS;
3394 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3395 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3396 default:
3397 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3398 return EXTERNAL_FLOAT_ELEMENTS;
3399 }
3400 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003401 ASSERT(array->IsPixelArray());
3402 return PIXEL_ELEMENTS;
3403}
3404
3405
3406bool JSObject::HasFastElements() {
3407 return GetElementsKind() == FAST_ELEMENTS;
3408}
3409
3410
3411bool JSObject::HasDictionaryElements() {
3412 return GetElementsKind() == DICTIONARY_ELEMENTS;
3413}
3414
3415
3416bool JSObject::HasPixelElements() {
3417 return GetElementsKind() == PIXEL_ELEMENTS;
3418}
3419
3420
Steve Block3ce2e202009-11-05 08:53:23 +00003421bool JSObject::HasExternalArrayElements() {
3422 return (HasExternalByteElements() ||
3423 HasExternalUnsignedByteElements() ||
3424 HasExternalShortElements() ||
3425 HasExternalUnsignedShortElements() ||
3426 HasExternalIntElements() ||
3427 HasExternalUnsignedIntElements() ||
3428 HasExternalFloatElements());
3429}
3430
3431
3432bool JSObject::HasExternalByteElements() {
3433 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3434}
3435
3436
3437bool JSObject::HasExternalUnsignedByteElements() {
3438 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3439}
3440
3441
3442bool JSObject::HasExternalShortElements() {
3443 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3444}
3445
3446
3447bool JSObject::HasExternalUnsignedShortElements() {
3448 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3449}
3450
3451
3452bool JSObject::HasExternalIntElements() {
3453 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3454}
3455
3456
3457bool JSObject::HasExternalUnsignedIntElements() {
3458 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3459}
3460
3461
3462bool JSObject::HasExternalFloatElements() {
3463 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3464}
3465
3466
Steve Blocka7e24c12009-10-30 11:49:00 +00003467bool JSObject::HasNamedInterceptor() {
3468 return map()->has_named_interceptor();
3469}
3470
3471
3472bool JSObject::HasIndexedInterceptor() {
3473 return map()->has_indexed_interceptor();
3474}
3475
3476
Steve Block6ded16b2010-05-10 14:33:55 +01003477bool JSObject::AllowsSetElementsLength() {
3478 bool result = elements()->IsFixedArray();
3479 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3480 return result;
3481}
3482
3483
John Reck59135872010-11-02 12:39:01 -07003484MaybeObject* JSObject::EnsureWritableFastElements() {
Iain Merrick75681382010-08-19 15:07:18 +01003485 ASSERT(HasFastElements());
3486 FixedArray* elems = FixedArray::cast(elements());
3487 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
John Reck59135872010-11-02 12:39:01 -07003488 Object* writable_elems;
3489 { MaybeObject* maybe_writable_elems =
3490 Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
3491 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3492 return maybe_writable_elems;
3493 }
3494 }
Iain Merrick75681382010-08-19 15:07:18 +01003495 set_elements(FixedArray::cast(writable_elems));
3496 Counters::cow_arrays_converted.Increment();
3497 return writable_elems;
3498}
3499
3500
Steve Blocka7e24c12009-10-30 11:49:00 +00003501StringDictionary* JSObject::property_dictionary() {
3502 ASSERT(!HasFastProperties());
3503 return StringDictionary::cast(properties());
3504}
3505
3506
3507NumberDictionary* JSObject::element_dictionary() {
3508 ASSERT(HasDictionaryElements());
3509 return NumberDictionary::cast(elements());
3510}
3511
3512
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003513bool String::IsHashFieldComputed(uint32_t field) {
3514 return (field & kHashNotComputedMask) == 0;
3515}
3516
3517
Steve Blocka7e24c12009-10-30 11:49:00 +00003518bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003519 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00003520}
3521
3522
3523uint32_t String::Hash() {
3524 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00003525 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003526 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003527 // Slow case: compute hash code and set it.
3528 return ComputeAndSetHash();
3529}
3530
3531
3532StringHasher::StringHasher(int length)
3533 : length_(length),
3534 raw_running_hash_(0),
3535 array_index_(0),
3536 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3537 is_first_char_(true),
3538 is_valid_(true) { }
3539
3540
3541bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00003542 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00003543}
3544
3545
3546void StringHasher::AddCharacter(uc32 c) {
3547 // Use the Jenkins one-at-a-time hash function to update the hash
3548 // for the given character.
3549 raw_running_hash_ += c;
3550 raw_running_hash_ += (raw_running_hash_ << 10);
3551 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3552 // Incremental array index computation.
3553 if (is_array_index_) {
3554 if (c < '0' || c > '9') {
3555 is_array_index_ = false;
3556 } else {
3557 int d = c - '0';
3558 if (is_first_char_) {
3559 is_first_char_ = false;
3560 if (c == '0' && length_ > 1) {
3561 is_array_index_ = false;
3562 return;
3563 }
3564 }
3565 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3566 is_array_index_ = false;
3567 } else {
3568 array_index_ = array_index_ * 10 + d;
3569 }
3570 }
3571 }
3572}
3573
3574
3575void StringHasher::AddCharacterNoIndex(uc32 c) {
3576 ASSERT(!is_array_index());
3577 raw_running_hash_ += c;
3578 raw_running_hash_ += (raw_running_hash_ << 10);
3579 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3580}
3581
3582
3583uint32_t StringHasher::GetHash() {
3584 // Get the calculated raw hash value and do some more bit ops to distribute
3585 // the hash further. Ensure that we never return zero as the hash value.
3586 uint32_t result = raw_running_hash_;
3587 result += (result << 3);
3588 result ^= (result >> 11);
3589 result += (result << 15);
3590 if (result == 0) {
3591 result = 27;
3592 }
3593 return result;
3594}
3595
3596
3597bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00003598 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003599 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3600 return false;
3601 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003602 return SlowAsArrayIndex(index);
3603}
3604
3605
3606Object* JSObject::GetPrototype() {
3607 return JSObject::cast(this)->map()->prototype();
3608}
3609
3610
3611PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3612 return GetPropertyAttributeWithReceiver(this, key);
3613}
3614
Steve Blockd0582a62009-12-15 09:54:21 +00003615// TODO(504): this may be useful in other places too where JSGlobalProxy
3616// is used.
3617Object* JSObject::BypassGlobalProxy() {
3618 if (IsJSGlobalProxy()) {
3619 Object* proto = GetPrototype();
3620 if (proto->IsNull()) return Heap::undefined_value();
3621 ASSERT(proto->IsJSGlobalObject());
3622 return proto;
3623 }
3624 return this;
3625}
3626
3627
3628bool JSObject::HasHiddenPropertiesObject() {
3629 ASSERT(!IsJSGlobalProxy());
3630 return GetPropertyAttributePostInterceptor(this,
3631 Heap::hidden_symbol(),
3632 false) != ABSENT;
3633}
3634
3635
3636Object* JSObject::GetHiddenPropertiesObject() {
3637 ASSERT(!IsJSGlobalProxy());
3638 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07003639 // You can't install a getter on a property indexed by the hidden symbol,
3640 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3641 // object.
3642 Object* result =
3643 GetLocalPropertyPostInterceptor(this,
3644 Heap::hidden_symbol(),
3645 &attributes)->ToObjectUnchecked();
3646 return result;
Steve Blockd0582a62009-12-15 09:54:21 +00003647}
3648
3649
John Reck59135872010-11-02 12:39:01 -07003650MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
Steve Blockd0582a62009-12-15 09:54:21 +00003651 ASSERT(!IsJSGlobalProxy());
3652 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3653 hidden_obj,
3654 DONT_ENUM);
3655}
3656
Steve Blocka7e24c12009-10-30 11:49:00 +00003657
3658bool JSObject::HasElement(uint32_t index) {
3659 return HasElementWithReceiver(this, index);
3660}
3661
3662
3663bool AccessorInfo::all_can_read() {
3664 return BooleanBit::get(flag(), kAllCanReadBit);
3665}
3666
3667
3668void AccessorInfo::set_all_can_read(bool value) {
3669 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3670}
3671
3672
3673bool AccessorInfo::all_can_write() {
3674 return BooleanBit::get(flag(), kAllCanWriteBit);
3675}
3676
3677
3678void AccessorInfo::set_all_can_write(bool value) {
3679 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3680}
3681
3682
3683bool AccessorInfo::prohibits_overwriting() {
3684 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3685}
3686
3687
3688void AccessorInfo::set_prohibits_overwriting(bool value) {
3689 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3690}
3691
3692
3693PropertyAttributes AccessorInfo::property_attributes() {
3694 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3695}
3696
3697
3698void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3699 ASSERT(AttributesField::is_valid(attributes));
3700 int rest_value = flag()->value() & ~AttributesField::mask();
3701 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3702}
3703
3704template<typename Shape, typename Key>
3705void Dictionary<Shape, Key>::SetEntry(int entry,
3706 Object* key,
3707 Object* value,
3708 PropertyDetails details) {
3709 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3710 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00003711 AssertNoAllocation no_gc;
3712 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00003713 FixedArray::set(index, key, mode);
3714 FixedArray::set(index+1, value, mode);
3715 FixedArray::fast_set(this, index+2, details.AsSmi());
3716}
3717
3718
3719void Map::ClearCodeCache() {
3720 // No write barrier is needed since empty_fixed_array is not in new space.
3721 // Please note this function is used during marking:
3722 // - MarkCompactCollector::MarkUnmarkedObject
3723 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3724 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3725}
3726
3727
3728void JSArray::EnsureSize(int required_size) {
3729 ASSERT(HasFastElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003730 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00003731 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3732 if (elts->length() < required_size) {
3733 // Doubling in size would be overkill, but leave some slack to avoid
3734 // constantly growing.
3735 Expand(required_size + (required_size >> 3));
3736 // It's a performance benefit to keep a frequently used array in new-space.
3737 } else if (!Heap::new_space()->Contains(elts) &&
3738 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3739 // Expand will allocate a new backing store in new space even if the size
3740 // we asked for isn't larger than what we had before.
3741 Expand(required_size);
3742 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003743}
3744
3745
Leon Clarke4515c472010-02-03 11:58:03 +00003746void JSArray::set_length(Smi* length) {
3747 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3748}
3749
3750
Steve Blocka7e24c12009-10-30 11:49:00 +00003751void JSArray::SetContent(FixedArray* storage) {
Leon Clarke4515c472010-02-03 11:58:03 +00003752 set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00003753 set_elements(storage);
3754}
3755
3756
John Reck59135872010-11-02 12:39:01 -07003757MaybeObject* FixedArray::Copy() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003758 if (length() == 0) return this;
3759 return Heap::CopyFixedArray(this);
3760}
3761
3762
Iain Merrick75681382010-08-19 15:07:18 +01003763int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3764 return map->instance_size();
3765}
3766
3767
3768void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3769 v->VisitExternalReference(
3770 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3771}
3772
3773
3774template<typename StaticVisitor>
3775void Proxy::ProxyIterateBody() {
3776 StaticVisitor::VisitExternalReference(
3777 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3778}
3779
3780
3781void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3782 typedef v8::String::ExternalAsciiStringResource Resource;
3783 v->VisitExternalAsciiString(
3784 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3785}
3786
3787
3788template<typename StaticVisitor>
3789void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3790 typedef v8::String::ExternalAsciiStringResource Resource;
3791 StaticVisitor::VisitExternalAsciiString(
3792 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3793}
3794
3795
3796void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3797 typedef v8::String::ExternalStringResource Resource;
3798 v->VisitExternalTwoByteString(
3799 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3800}
3801
3802
3803template<typename StaticVisitor>
3804void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3805 typedef v8::String::ExternalStringResource Resource;
3806 StaticVisitor::VisitExternalTwoByteString(
3807 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3808}
3809
3810#define SLOT_ADDR(obj, offset) \
3811 reinterpret_cast<Object**>((obj)->address() + offset)
3812
3813template<int start_offset, int end_offset, int size>
3814void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3815 HeapObject* obj,
3816 ObjectVisitor* v) {
3817 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3818}
3819
3820
3821template<int start_offset>
3822void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3823 int object_size,
3824 ObjectVisitor* v) {
3825 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3826}
3827
3828#undef SLOT_ADDR
3829
3830
Steve Blocka7e24c12009-10-30 11:49:00 +00003831#undef CAST_ACCESSOR
3832#undef INT_ACCESSORS
3833#undef SMI_ACCESSORS
3834#undef ACCESSORS
3835#undef FIELD_ADDR
3836#undef READ_FIELD
3837#undef WRITE_FIELD
3838#undef WRITE_BARRIER
3839#undef CONDITIONAL_WRITE_BARRIER
3840#undef READ_MEMADDR_FIELD
3841#undef WRITE_MEMADDR_FIELD
3842#undef READ_DOUBLE_FIELD
3843#undef WRITE_DOUBLE_FIELD
3844#undef READ_INT_FIELD
3845#undef WRITE_INT_FIELD
3846#undef READ_SHORT_FIELD
3847#undef WRITE_SHORT_FIELD
3848#undef READ_BYTE_FIELD
3849#undef WRITE_BYTE_FIELD
3850
3851
3852} } // namespace v8::internal
3853
3854#endif // V8_OBJECTS_INL_H_