• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Review notes:
29 //
30 // - The use of macros in these inline functions may seem superfluous
31 // but it is absolutely needed to make sure gcc generates optimal
32 // code. gcc is not happy when attempting to inline too deep.
33 //
34 
35 #ifndef V8_OBJECTS_INL_H_
36 #define V8_OBJECTS_INL_H_
37 
38 #include "objects.h"
39 #include "contexts.h"
40 #include "conversions-inl.h"
41 #include "property.h"
42 
43 namespace v8 {
44 namespace internal {
45 
PropertyDetails(Smi * smi)46 PropertyDetails::PropertyDetails(Smi* smi) {
47   value_ = smi->value();
48 }
49 
50 
AsSmi()51 Smi* PropertyDetails::AsSmi() {
52   return Smi::FromInt(value_);
53 }
54 
55 
AsDeleted()56 PropertyDetails PropertyDetails::AsDeleted() {
57   PropertyDetails d(DONT_ENUM, NORMAL);
58   Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59   return PropertyDetails(smi);
60 }
61 
62 
63 #define CAST_ACCESSOR(type)                     \
64   type* type::cast(Object* object) {            \
65     ASSERT(object->Is##type());                 \
66     return reinterpret_cast<type*>(object);     \
67   }
68 
69 
70 #define INT_ACCESSORS(holder, name, offset)                             \
71   int holder::name() { return READ_INT_FIELD(this, offset); }           \
72   void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73 
74 
75 #define ACCESSORS(holder, name, type, offset)                           \
76   type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
77   void holder::set_##name(type* value, WriteBarrierMode mode) {         \
78     WRITE_FIELD(this, offset, value);                                   \
79     CONDITIONAL_WRITE_BARRIER(this, offset, mode);                      \
80   }
81 
82 
83 
84 #define SMI_ACCESSORS(holder, name, offset)             \
85   int holder::name() {                                  \
86     Object* value = READ_FIELD(this, offset);           \
87     return Smi::cast(value)->value();                   \
88   }                                                     \
89   void holder::set_##name(int value) {                  \
90     WRITE_FIELD(this, offset, Smi::FromInt(value));     \
91   }
92 
93 
94 #define BOOL_GETTER(holder, field, name, offset)           \
95   bool holder::name() {                                    \
96     return BooleanBit::get(field(), offset);               \
97   }                                                        \
98 
99 
100 #define BOOL_ACCESSORS(holder, field, name, offset)        \
101   bool holder::name() {                                    \
102     return BooleanBit::get(field(), offset);               \
103   }                                                        \
104   void holder::set_##name(bool value) {                    \
105     set_##field(BooleanBit::set(field(), offset, value));  \
106   }
107 
108 
IsInstanceOf(FunctionTemplateInfo * expected)109 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110   // There is a constraint on the object; check.
111   if (!this->IsJSObject()) return false;
112   // Fetch the constructor function of the object.
113   Object* cons_obj = JSObject::cast(this)->map()->constructor();
114   if (!cons_obj->IsJSFunction()) return false;
115   JSFunction* fun = JSFunction::cast(cons_obj);
116   // Iterate through the chain of inheriting function templates to
117   // see if the required one occurs.
118   for (Object* type = fun->shared()->function_data();
119        type->IsFunctionTemplateInfo();
120        type = FunctionTemplateInfo::cast(type)->parent_template()) {
121     if (type == expected) return true;
122   }
123   // Didn't find the required type in the inheritance chain.
124   return false;
125 }
126 
127 
IsSmi()128 bool Object::IsSmi() {
129   return HAS_SMI_TAG(this);
130 }
131 
132 
IsHeapObject()133 bool Object::IsHeapObject() {
134   return Internals::HasHeapObjectTag(this);
135 }
136 
137 
IsHeapNumber()138 bool Object::IsHeapNumber() {
139   return Object::IsHeapObject()
140     && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141 }
142 
143 
IsString()144 bool Object::IsString() {
145   return Object::IsHeapObject()
146     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147 }
148 
149 
IsSymbol()150 bool Object::IsSymbol() {
151   if (!this->IsHeapObject()) return false;
152   uint32_t type = HeapObject::cast(this)->map()->instance_type();
153   // Because the symbol tag is non-zero and no non-string types have the
154   // symbol bit set we can test for symbols with a very simple test
155   // operation.
156   ASSERT(kSymbolTag != 0);
157   ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
158   return (type & kIsSymbolMask) != 0;
159 }
160 
161 
IsConsString()162 bool Object::IsConsString() {
163   if (!this->IsHeapObject()) return false;
164   uint32_t type = HeapObject::cast(this)->map()->instance_type();
165   return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
166          (kStringTag | kConsStringTag);
167 }
168 
169 
IsSeqString()170 bool Object::IsSeqString() {
171   if (!IsString()) return false;
172   return StringShape(String::cast(this)).IsSequential();
173 }
174 
175 
IsSeqAsciiString()176 bool Object::IsSeqAsciiString() {
177   if (!IsString()) return false;
178   return StringShape(String::cast(this)).IsSequential() &&
179          String::cast(this)->IsAsciiRepresentation();
180 }
181 
182 
IsSeqTwoByteString()183 bool Object::IsSeqTwoByteString() {
184   if (!IsString()) return false;
185   return StringShape(String::cast(this)).IsSequential() &&
186          String::cast(this)->IsTwoByteRepresentation();
187 }
188 
189 
IsExternalString()190 bool Object::IsExternalString() {
191   if (!IsString()) return false;
192   return StringShape(String::cast(this)).IsExternal();
193 }
194 
195 
IsExternalAsciiString()196 bool Object::IsExternalAsciiString() {
197   if (!IsString()) return false;
198   return StringShape(String::cast(this)).IsExternal() &&
199          String::cast(this)->IsAsciiRepresentation();
200 }
201 
202 
IsExternalTwoByteString()203 bool Object::IsExternalTwoByteString() {
204   if (!IsString()) return false;
205   return StringShape(String::cast(this)).IsExternal() &&
206          String::cast(this)->IsTwoByteRepresentation();
207 }
208 
209 
StringShape(String * str)210 StringShape::StringShape(String* str)
211   : type_(str->map()->instance_type()) {
212   set_valid();
213   ASSERT((type_ & kIsNotStringMask) == kStringTag);
214 }
215 
216 
StringShape(Map * map)217 StringShape::StringShape(Map* map)
218   : type_(map->instance_type()) {
219   set_valid();
220   ASSERT((type_ & kIsNotStringMask) == kStringTag);
221 }
222 
223 
StringShape(InstanceType t)224 StringShape::StringShape(InstanceType t)
225   : type_(static_cast<uint32_t>(t)) {
226   set_valid();
227   ASSERT((type_ & kIsNotStringMask) == kStringTag);
228 }
229 
230 
IsSymbol()231 bool StringShape::IsSymbol() {
232   ASSERT(valid());
233   ASSERT(kSymbolTag != 0);
234   return (type_ & kIsSymbolMask) != 0;
235 }
236 
237 
IsAsciiRepresentation()238 bool String::IsAsciiRepresentation() {
239   uint32_t type = map()->instance_type();
240   if ((type & kStringRepresentationMask) == kConsStringTag &&
241       ConsString::cast(this)->second()->length() == 0) {
242     return ConsString::cast(this)->first()->IsAsciiRepresentation();
243   }
244   return (type & kStringEncodingMask) == kAsciiStringTag;
245 }
246 
247 
IsTwoByteRepresentation()248 bool String::IsTwoByteRepresentation() {
249   uint32_t type = map()->instance_type();
250   if ((type & kStringRepresentationMask) == kConsStringTag &&
251              ConsString::cast(this)->second()->length() == 0) {
252     return ConsString::cast(this)->first()->IsTwoByteRepresentation();
253   }
254   return (type & kStringEncodingMask) == kTwoByteStringTag;
255 }
256 
257 
IsCons()258 bool StringShape::IsCons() {
259   return (type_ & kStringRepresentationMask) == kConsStringTag;
260 }
261 
262 
IsExternal()263 bool StringShape::IsExternal() {
264   return (type_ & kStringRepresentationMask) == kExternalStringTag;
265 }
266 
267 
IsSequential()268 bool StringShape::IsSequential() {
269   return (type_ & kStringRepresentationMask) == kSeqStringTag;
270 }
271 
272 
representation_tag()273 StringRepresentationTag StringShape::representation_tag() {
274   uint32_t tag = (type_ & kStringRepresentationMask);
275   return static_cast<StringRepresentationTag>(tag);
276 }
277 
278 
full_representation_tag()279 uint32_t StringShape::full_representation_tag() {
280   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
281 }
282 
283 
284 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
285              Internals::kFullStringRepresentationMask);
286 
287 
IsSequentialAscii()288 bool StringShape::IsSequentialAscii() {
289   return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
290 }
291 
292 
IsSequentialTwoByte()293 bool StringShape::IsSequentialTwoByte() {
294   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
295 }
296 
297 
IsExternalAscii()298 bool StringShape::IsExternalAscii() {
299   return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
300 }
301 
302 
IsExternalTwoByte()303 bool StringShape::IsExternalTwoByte() {
304   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
305 }
306 
307 
308 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
309              Internals::kExternalTwoByteRepresentationTag);
310 
311 
Get(int index)312 uc32 FlatStringReader::Get(int index) {
313   ASSERT(0 <= index && index <= length_);
314   if (is_ascii_) {
315     return static_cast<const byte*>(start_)[index];
316   } else {
317     return static_cast<const uc16*>(start_)[index];
318   }
319 }
320 
321 
IsNumber()322 bool Object::IsNumber() {
323   return IsSmi() || IsHeapNumber();
324 }
325 
326 
IsByteArray()327 bool Object::IsByteArray() {
328   return Object::IsHeapObject()
329     && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
330 }
331 
332 
IsPixelArray()333 bool Object::IsPixelArray() {
334   return Object::IsHeapObject() &&
335       HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
336 }
337 
338 
IsExternalArray()339 bool Object::IsExternalArray() {
340   if (!Object::IsHeapObject())
341     return false;
342   InstanceType instance_type =
343       HeapObject::cast(this)->map()->instance_type();
344   return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
345           instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
346 }
347 
348 
IsExternalByteArray()349 bool Object::IsExternalByteArray() {
350   return Object::IsHeapObject() &&
351       HeapObject::cast(this)->map()->instance_type() ==
352       EXTERNAL_BYTE_ARRAY_TYPE;
353 }
354 
355 
IsExternalUnsignedByteArray()356 bool Object::IsExternalUnsignedByteArray() {
357   return Object::IsHeapObject() &&
358       HeapObject::cast(this)->map()->instance_type() ==
359       EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
360 }
361 
362 
IsExternalShortArray()363 bool Object::IsExternalShortArray() {
364   return Object::IsHeapObject() &&
365       HeapObject::cast(this)->map()->instance_type() ==
366       EXTERNAL_SHORT_ARRAY_TYPE;
367 }
368 
369 
IsExternalUnsignedShortArray()370 bool Object::IsExternalUnsignedShortArray() {
371   return Object::IsHeapObject() &&
372       HeapObject::cast(this)->map()->instance_type() ==
373       EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
374 }
375 
376 
IsExternalIntArray()377 bool Object::IsExternalIntArray() {
378   return Object::IsHeapObject() &&
379       HeapObject::cast(this)->map()->instance_type() ==
380       EXTERNAL_INT_ARRAY_TYPE;
381 }
382 
383 
IsExternalUnsignedIntArray()384 bool Object::IsExternalUnsignedIntArray() {
385   return Object::IsHeapObject() &&
386       HeapObject::cast(this)->map()->instance_type() ==
387       EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
388 }
389 
390 
IsExternalFloatArray()391 bool Object::IsExternalFloatArray() {
392   return Object::IsHeapObject() &&
393       HeapObject::cast(this)->map()->instance_type() ==
394       EXTERNAL_FLOAT_ARRAY_TYPE;
395 }
396 
397 
IsFailure()398 bool Object::IsFailure() {
399   return HAS_FAILURE_TAG(this);
400 }
401 
402 
IsRetryAfterGC()403 bool Object::IsRetryAfterGC() {
404   return HAS_FAILURE_TAG(this)
405     && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
406 }
407 
408 
IsOutOfMemoryFailure()409 bool Object::IsOutOfMemoryFailure() {
410   return HAS_FAILURE_TAG(this)
411     && Failure::cast(this)->IsOutOfMemoryException();
412 }
413 
414 
IsException()415 bool Object::IsException() {
416   return this == Failure::Exception();
417 }
418 
419 
IsJSObject()420 bool Object::IsJSObject() {
421   return IsHeapObject()
422     && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
423 }
424 
425 
IsJSContextExtensionObject()426 bool Object::IsJSContextExtensionObject() {
427   return IsHeapObject()
428     && (HeapObject::cast(this)->map()->instance_type() ==
429         JS_CONTEXT_EXTENSION_OBJECT_TYPE);
430 }
431 
432 
IsMap()433 bool Object::IsMap() {
434   return Object::IsHeapObject()
435     && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
436 }
437 
438 
IsFixedArray()439 bool Object::IsFixedArray() {
440   return Object::IsHeapObject()
441     && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
442 }
443 
444 
IsDescriptorArray()445 bool Object::IsDescriptorArray() {
446   return IsFixedArray();
447 }
448 
449 
IsContext()450 bool Object::IsContext() {
451   return Object::IsHeapObject()
452     && (HeapObject::cast(this)->map() == Heap::context_map() ||
453         HeapObject::cast(this)->map() == Heap::catch_context_map() ||
454         HeapObject::cast(this)->map() == Heap::global_context_map());
455 }
456 
457 
IsCatchContext()458 bool Object::IsCatchContext() {
459   return Object::IsHeapObject()
460     && HeapObject::cast(this)->map() == Heap::catch_context_map();
461 }
462 
463 
IsGlobalContext()464 bool Object::IsGlobalContext() {
465   return Object::IsHeapObject()
466     && HeapObject::cast(this)->map() == Heap::global_context_map();
467 }
468 
469 
IsJSFunction()470 bool Object::IsJSFunction() {
471   return Object::IsHeapObject()
472     && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
473 }
474 
475 
476 template <> inline bool Is<JSFunction>(Object* obj) {
477   return obj->IsJSFunction();
478 }
479 
480 
IsCode()481 bool Object::IsCode() {
482   return Object::IsHeapObject()
483     && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
484 }
485 
486 
IsOddball()487 bool Object::IsOddball() {
488   return Object::IsHeapObject()
489     && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
490 }
491 
492 
IsJSGlobalPropertyCell()493 bool Object::IsJSGlobalPropertyCell() {
494   return Object::IsHeapObject()
495       && HeapObject::cast(this)->map()->instance_type()
496       == JS_GLOBAL_PROPERTY_CELL_TYPE;
497 }
498 
499 
IsSharedFunctionInfo()500 bool Object::IsSharedFunctionInfo() {
501   return Object::IsHeapObject() &&
502       (HeapObject::cast(this)->map()->instance_type() ==
503        SHARED_FUNCTION_INFO_TYPE);
504 }
505 
506 
IsJSValue()507 bool Object::IsJSValue() {
508   return Object::IsHeapObject()
509     && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
510 }
511 
512 
IsStringWrapper()513 bool Object::IsStringWrapper() {
514   return IsJSValue() && JSValue::cast(this)->value()->IsString();
515 }
516 
517 
IsProxy()518 bool Object::IsProxy() {
519   return Object::IsHeapObject()
520     && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
521 }
522 
523 
IsBoolean()524 bool Object::IsBoolean() {
525   return IsTrue() || IsFalse();
526 }
527 
528 
IsJSArray()529 bool Object::IsJSArray() {
530   return Object::IsHeapObject()
531     && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
532 }
533 
534 
IsJSRegExp()535 bool Object::IsJSRegExp() {
536   return Object::IsHeapObject()
537     && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
538 }
539 
540 
541 template <> inline bool Is<JSArray>(Object* obj) {
542   return obj->IsJSArray();
543 }
544 
545 
IsHashTable()546 bool Object::IsHashTable() {
547   return Object::IsHeapObject()
548     && HeapObject::cast(this)->map() == Heap::hash_table_map();
549 }
550 
551 
IsDictionary()552 bool Object::IsDictionary() {
553   return IsHashTable() && this != Heap::symbol_table();
554 }
555 
556 
IsSymbolTable()557 bool Object::IsSymbolTable() {
558   return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
559 }
560 
561 
IsCompilationCacheTable()562 bool Object::IsCompilationCacheTable() {
563   return IsHashTable();
564 }
565 
566 
IsMapCache()567 bool Object::IsMapCache() {
568   return IsHashTable();
569 }
570 
571 
IsPrimitive()572 bool Object::IsPrimitive() {
573   return IsOddball() || IsNumber() || IsString();
574 }
575 
576 
IsJSGlobalProxy()577 bool Object::IsJSGlobalProxy() {
578   bool result = IsHeapObject() &&
579                 (HeapObject::cast(this)->map()->instance_type() ==
580                  JS_GLOBAL_PROXY_TYPE);
581   ASSERT(!result || IsAccessCheckNeeded());
582   return result;
583 }
584 
585 
IsGlobalObject()586 bool Object::IsGlobalObject() {
587   if (!IsHeapObject()) return false;
588 
589   InstanceType type = HeapObject::cast(this)->map()->instance_type();
590   return type == JS_GLOBAL_OBJECT_TYPE ||
591          type == JS_BUILTINS_OBJECT_TYPE;
592 }
593 
594 
IsJSGlobalObject()595 bool Object::IsJSGlobalObject() {
596   return IsHeapObject() &&
597       (HeapObject::cast(this)->map()->instance_type() ==
598        JS_GLOBAL_OBJECT_TYPE);
599 }
600 
601 
IsJSBuiltinsObject()602 bool Object::IsJSBuiltinsObject() {
603   return IsHeapObject() &&
604       (HeapObject::cast(this)->map()->instance_type() ==
605        JS_BUILTINS_OBJECT_TYPE);
606 }
607 
608 
IsUndetectableObject()609 bool Object::IsUndetectableObject() {
610   return IsHeapObject()
611     && HeapObject::cast(this)->map()->is_undetectable();
612 }
613 
614 
IsAccessCheckNeeded()615 bool Object::IsAccessCheckNeeded() {
616   return IsHeapObject()
617     && HeapObject::cast(this)->map()->is_access_check_needed();
618 }
619 
620 
IsStruct()621 bool Object::IsStruct() {
622   if (!IsHeapObject()) return false;
623   switch (HeapObject::cast(this)->map()->instance_type()) {
624 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
625   STRUCT_LIST(MAKE_STRUCT_CASE)
626 #undef MAKE_STRUCT_CASE
627     default: return false;
628   }
629 }
630 
631 
632 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
633   bool Object::Is##Name() {                                      \
634     return Object::IsHeapObject()                                \
635       && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
636   }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)637   STRUCT_LIST(MAKE_STRUCT_PREDICATE)
638 #undef MAKE_STRUCT_PREDICATE
639 
640 
641 bool Object::IsUndefined() {
642   return this == Heap::undefined_value();
643 }
644 
645 
IsTheHole()646 bool Object::IsTheHole() {
647   return this == Heap::the_hole_value();
648 }
649 
650 
IsNull()651 bool Object::IsNull() {
652   return this == Heap::null_value();
653 }
654 
655 
IsTrue()656 bool Object::IsTrue() {
657   return this == Heap::true_value();
658 }
659 
660 
IsFalse()661 bool Object::IsFalse() {
662   return this == Heap::false_value();
663 }
664 
665 
Number()666 double Object::Number() {
667   ASSERT(IsNumber());
668   return IsSmi()
669     ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
670     : reinterpret_cast<HeapNumber*>(this)->value();
671 }
672 
673 
674 
ToSmi()675 Object* Object::ToSmi() {
676   if (IsSmi()) return this;
677   if (IsHeapNumber()) {
678     double value = HeapNumber::cast(this)->value();
679     int int_value = FastD2I(value);
680     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
681       return Smi::FromInt(int_value);
682     }
683   }
684   return Failure::Exception();
685 }
686 
687 
HasSpecificClassOf(String * name)688 bool Object::HasSpecificClassOf(String* name) {
689   return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
690 }
691 
692 
GetElement(uint32_t index)693 Object* Object::GetElement(uint32_t index) {
694   return GetElementWithReceiver(this, index);
695 }
696 
697 
GetProperty(String * key)698 Object* Object::GetProperty(String* key) {
699   PropertyAttributes attributes;
700   return GetPropertyWithReceiver(this, key, &attributes);
701 }
702 
703 
GetProperty(String * key,PropertyAttributes * attributes)704 Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
705   return GetPropertyWithReceiver(this, key, attributes);
706 }
707 
708 
709 #define FIELD_ADDR(p, offset) \
710   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
711 
712 #define READ_FIELD(p, offset) \
713   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
714 
715 #define WRITE_FIELD(p, offset, value) \
716   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
717 
718 
719 #define WRITE_BARRIER(object, offset) \
720   Heap::RecordWrite(object->address(), offset);
721 
722 // CONDITIONAL_WRITE_BARRIER must be issued after the actual
723 // write due to the assert validating the written value.
724 #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
725   if (mode == UPDATE_WRITE_BARRIER) { \
726     Heap::RecordWrite(object->address(), offset); \
727   } else { \
728     ASSERT(mode == SKIP_WRITE_BARRIER); \
729     ASSERT(Heap::InNewSpace(object) || \
730            !Heap::InNewSpace(READ_FIELD(object, offset))); \
731   }
732 
733 #define READ_DOUBLE_FIELD(p, offset) \
734   (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
735 
736 #define WRITE_DOUBLE_FIELD(p, offset, value) \
737   (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
738 
739 #define READ_INT_FIELD(p, offset) \
740   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
741 
742 #define WRITE_INT_FIELD(p, offset, value) \
743   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
744 
745 #define READ_INTPTR_FIELD(p, offset) \
746   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
747 
748 #define WRITE_INTPTR_FIELD(p, offset, value) \
749   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
750 
751 #define READ_UINT32_FIELD(p, offset) \
752   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
753 
754 #define WRITE_UINT32_FIELD(p, offset, value) \
755   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
756 
757 #define READ_SHORT_FIELD(p, offset) \
758   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
759 
760 #define WRITE_SHORT_FIELD(p, offset, value) \
761   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
762 
763 #define READ_BYTE_FIELD(p, offset) \
764   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
765 
766 #define WRITE_BYTE_FIELD(p, offset, value) \
767   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
768 
769 
RawField(HeapObject * obj,int byte_offset)770 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
771   return &READ_FIELD(obj, byte_offset);
772 }
773 
774 
value()775 int Smi::value() {
776   return Internals::SmiValue(this);
777 }
778 
779 
FromInt(int value)780 Smi* Smi::FromInt(int value) {
781   ASSERT(Smi::IsValid(value));
782   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
783   intptr_t tagged_value =
784       (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
785   return reinterpret_cast<Smi*>(tagged_value);
786 }
787 
788 
FromIntptr(intptr_t value)789 Smi* Smi::FromIntptr(intptr_t value) {
790   ASSERT(Smi::IsValid(value));
791   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
792   return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
793 }
794 
795 
type()796 Failure::Type Failure::type() const {
797   return static_cast<Type>(value() & kFailureTypeTagMask);
798 }
799 
800 
IsInternalError()801 bool Failure::IsInternalError() const {
802   return type() == INTERNAL_ERROR;
803 }
804 
805 
IsOutOfMemoryException()806 bool Failure::IsOutOfMemoryException() const {
807   return type() == OUT_OF_MEMORY_EXCEPTION;
808 }
809 
810 
requested()811 int Failure::requested() const {
812   const int kShiftBits =
813       kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
814   STATIC_ASSERT(kShiftBits >= 0);
815   ASSERT(type() == RETRY_AFTER_GC);
816   return static_cast<int>(value() >> kShiftBits);
817 }
818 
819 
allocation_space()820 AllocationSpace Failure::allocation_space() const {
821   ASSERT_EQ(RETRY_AFTER_GC, type());
822   return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
823                                       & kSpaceTagMask);
824 }
825 
826 
InternalError()827 Failure* Failure::InternalError() {
828   return Construct(INTERNAL_ERROR);
829 }
830 
831 
Exception()832 Failure* Failure::Exception() {
833   return Construct(EXCEPTION);
834 }
835 
836 
OutOfMemoryException()837 Failure* Failure::OutOfMemoryException() {
838   return Construct(OUT_OF_MEMORY_EXCEPTION);
839 }
840 
841 
value()842 intptr_t Failure::value() const {
843   return reinterpret_cast<intptr_t>(this) >> kFailureTagSize;
844 }
845 
846 
RetryAfterGC(int requested_bytes)847 Failure* Failure::RetryAfterGC(int requested_bytes) {
848   // Assert that the space encoding fits in the three bytes allotted for it.
849   ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
850   intptr_t requested = requested_bytes >> kObjectAlignmentBits;
851   int tag_bits = kSpaceTagSize + kFailureTypeTagSize;
852   if (((requested << tag_bits) >> tag_bits) != requested) {
853     // No room for entire requested size in the bits. Round down to
854     // maximally representable size.
855     requested = static_cast<intptr_t>(
856                     (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
857   }
858   int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
859   return Construct(RETRY_AFTER_GC, value);
860 }
861 
862 
Construct(Type type,intptr_t value)863 Failure* Failure::Construct(Type type, intptr_t value) {
864   intptr_t info = (static_cast<intptr_t>(value) << kFailureTypeTagSize) | type;
865   ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
866   return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
867 }
868 
869 
IsValid(intptr_t value)870 bool Smi::IsValid(intptr_t value) {
871 #ifdef DEBUG
872   bool in_range = (value >= kMinValue) && (value <= kMaxValue);
873 #endif
874 
875 #ifdef V8_TARGET_ARCH_X64
876   // To be representable as a long smi, the value must be a 32-bit integer.
877   bool result = (value == static_cast<int32_t>(value));
878 #else
879   // To be representable as an tagged small integer, the two
880   // most-significant bits of 'value' must be either 00 or 11 due to
881   // sign-extension. To check this we add 01 to the two
882   // most-significant bits, and check if the most-significant bit is 0
883   //
884   // CAUTION: The original code below:
885   // bool result = ((value + 0x40000000) & 0x80000000) == 0;
886   // may lead to incorrect results according to the C language spec, and
887   // in fact doesn't work correctly with gcc4.1.1 in some cases: The
888   // compiler may produce undefined results in case of signed integer
889   // overflow. The computation must be done w/ unsigned ints.
890   bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
891 #endif
892   ASSERT(result == in_range);
893   return result;
894 }
895 
896 
FromMap(Map * map)897 MapWord MapWord::FromMap(Map* map) {
898   return MapWord(reinterpret_cast<uintptr_t>(map));
899 }
900 
901 
ToMap()902 Map* MapWord::ToMap() {
903   return reinterpret_cast<Map*>(value_);
904 }
905 
906 
IsForwardingAddress()907 bool MapWord::IsForwardingAddress() {
908   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
909 }
910 
911 
FromForwardingAddress(HeapObject * object)912 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
913   Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
914   return MapWord(reinterpret_cast<uintptr_t>(raw));
915 }
916 
917 
ToForwardingAddress()918 HeapObject* MapWord::ToForwardingAddress() {
919   ASSERT(IsForwardingAddress());
920   return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
921 }
922 
923 
IsMarked()924 bool MapWord::IsMarked() {
925   return (value_ & kMarkingMask) == 0;
926 }
927 
928 
SetMark()929 void MapWord::SetMark() {
930   value_ &= ~kMarkingMask;
931 }
932 
933 
ClearMark()934 void MapWord::ClearMark() {
935   value_ |= kMarkingMask;
936 }
937 
938 
IsOverflowed()939 bool MapWord::IsOverflowed() {
940   return (value_ & kOverflowMask) != 0;
941 }
942 
943 
SetOverflow()944 void MapWord::SetOverflow() {
945   value_ |= kOverflowMask;
946 }
947 
948 
ClearOverflow()949 void MapWord::ClearOverflow() {
950   value_ &= ~kOverflowMask;
951 }
952 
953 
EncodeAddress(Address map_address,int offset)954 MapWord MapWord::EncodeAddress(Address map_address, int offset) {
955   // Offset is the distance in live bytes from the first live object in the
956   // same page. The offset between two objects in the same page should not
957   // exceed the object area size of a page.
958   ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
959 
960   uintptr_t compact_offset = offset >> kObjectAlignmentBits;
961   ASSERT(compact_offset < (1 << kForwardingOffsetBits));
962 
963   Page* map_page = Page::FromAddress(map_address);
964   ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
965 
966   uintptr_t map_page_offset =
967       map_page->Offset(map_address) >> kMapAlignmentBits;
968 
969   uintptr_t encoding =
970       (compact_offset << kForwardingOffsetShift) |
971       (map_page_offset << kMapPageOffsetShift) |
972       (map_page->mc_page_index << kMapPageIndexShift);
973   return MapWord(encoding);
974 }
975 
976 
DecodeMapAddress(MapSpace * map_space)977 Address MapWord::DecodeMapAddress(MapSpace* map_space) {
978   int map_page_index =
979       static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
980   ASSERT_MAP_PAGE_INDEX(map_page_index);
981 
982   int map_page_offset = static_cast<int>(
983       ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
984       kMapAlignmentBits);
985 
986   return (map_space->PageAddress(map_page_index) + map_page_offset);
987 }
988 
989 
DecodeOffset()990 int MapWord::DecodeOffset() {
991   // The offset field is represented in the kForwardingOffsetBits
992   // most-significant bits.
993   uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
994   ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
995   return static_cast<int>(offset);
996 }
997 
998 
FromEncodedAddress(Address address)999 MapWord MapWord::FromEncodedAddress(Address address) {
1000   return MapWord(reinterpret_cast<uintptr_t>(address));
1001 }
1002 
1003 
ToEncodedAddress()1004 Address MapWord::ToEncodedAddress() {
1005   return reinterpret_cast<Address>(value_);
1006 }
1007 
1008 
1009 #ifdef DEBUG
VerifyObjectField(int offset)1010 void HeapObject::VerifyObjectField(int offset) {
1011   VerifyPointer(READ_FIELD(this, offset));
1012 }
1013 #endif
1014 
1015 
map()1016 Map* HeapObject::map() {
1017   return map_word().ToMap();
1018 }
1019 
1020 
set_map(Map * value)1021 void HeapObject::set_map(Map* value) {
1022   set_map_word(MapWord::FromMap(value));
1023 }
1024 
1025 
map_word()1026 MapWord HeapObject::map_word() {
1027   return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1028 }
1029 
1030 
set_map_word(MapWord map_word)1031 void HeapObject::set_map_word(MapWord map_word) {
1032   // WRITE_FIELD does not update the remembered set, but there is no need
1033   // here.
1034   WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1035 }
1036 
1037 
FromAddress(Address address)1038 HeapObject* HeapObject::FromAddress(Address address) {
1039   ASSERT_TAG_ALIGNED(address);
1040   return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1041 }
1042 
1043 
address()1044 Address HeapObject::address() {
1045   return reinterpret_cast<Address>(this) - kHeapObjectTag;
1046 }
1047 
1048 
Size()1049 int HeapObject::Size() {
1050   return SizeFromMap(map());
1051 }
1052 
1053 
IteratePointers(ObjectVisitor * v,int start,int end)1054 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1055   v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1056                    reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1057 }
1058 
1059 
IteratePointer(ObjectVisitor * v,int offset)1060 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1061   v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1062 }
1063 
1064 
IsMarked()1065 bool HeapObject::IsMarked() {
1066   return map_word().IsMarked();
1067 }
1068 
1069 
SetMark()1070 void HeapObject::SetMark() {
1071   ASSERT(!IsMarked());
1072   MapWord first_word = map_word();
1073   first_word.SetMark();
1074   set_map_word(first_word);
1075 }
1076 
1077 
ClearMark()1078 void HeapObject::ClearMark() {
1079   ASSERT(IsMarked());
1080   MapWord first_word = map_word();
1081   first_word.ClearMark();
1082   set_map_word(first_word);
1083 }
1084 
1085 
IsOverflowed()1086 bool HeapObject::IsOverflowed() {
1087   return map_word().IsOverflowed();
1088 }
1089 
1090 
SetOverflow()1091 void HeapObject::SetOverflow() {
1092   MapWord first_word = map_word();
1093   first_word.SetOverflow();
1094   set_map_word(first_word);
1095 }
1096 
1097 
ClearOverflow()1098 void HeapObject::ClearOverflow() {
1099   ASSERT(IsOverflowed());
1100   MapWord first_word = map_word();
1101   first_word.ClearOverflow();
1102   set_map_word(first_word);
1103 }
1104 
1105 
value()1106 double HeapNumber::value() {
1107   return READ_DOUBLE_FIELD(this, kValueOffset);
1108 }
1109 
1110 
set_value(double value)1111 void HeapNumber::set_value(double value) {
1112   WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1113 }
1114 
1115 
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1116 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1117 
1118 
1119 Array* JSObject::elements() {
1120   Object* array = READ_FIELD(this, kElementsOffset);
1121   // In the assert below Dictionary is covered under FixedArray.
1122   ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1123          array->IsExternalArray());
1124   return reinterpret_cast<Array*>(array);
1125 }
1126 
1127 
set_elements(Array * value,WriteBarrierMode mode)1128 void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1129   // In the assert below Dictionary is covered under FixedArray.
1130   ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1131          value->IsExternalArray());
1132   WRITE_FIELD(this, kElementsOffset, value);
1133   CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1134 }
1135 
1136 
initialize_properties()1137 void JSObject::initialize_properties() {
1138   ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1139   WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1140 }
1141 
1142 
initialize_elements()1143 void JSObject::initialize_elements() {
1144   ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1145   WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1146 }
1147 
1148 
ACCESSORS(Oddball,to_string,String,kToStringOffset)1149 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1150 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1151 
1152 
1153 Object* JSGlobalPropertyCell::value() {
1154   return READ_FIELD(this, kValueOffset);
1155 }
1156 
1157 
set_value(Object * val,WriteBarrierMode ignored)1158 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1159   // The write barrier is not used for global property cells.
1160   ASSERT(!val->IsJSGlobalPropertyCell());
1161   WRITE_FIELD(this, kValueOffset, val);
1162 }
1163 
1164 
GetHeaderSize()1165 int JSObject::GetHeaderSize() {
1166   InstanceType type = map()->instance_type();
1167   // Check for the most common kind of JavaScript object before
1168   // falling into the generic switch. This speeds up the internal
1169   // field operations considerably on average.
1170   if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1171   switch (type) {
1172     case JS_GLOBAL_PROXY_TYPE:
1173       return JSGlobalProxy::kSize;
1174     case JS_GLOBAL_OBJECT_TYPE:
1175       return JSGlobalObject::kSize;
1176     case JS_BUILTINS_OBJECT_TYPE:
1177       return JSBuiltinsObject::kSize;
1178     case JS_FUNCTION_TYPE:
1179       return JSFunction::kSize;
1180     case JS_VALUE_TYPE:
1181       return JSValue::kSize;
1182     case JS_ARRAY_TYPE:
1183       return JSValue::kSize;
1184     case JS_REGEXP_TYPE:
1185       return JSValue::kSize;
1186     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1187       return JSObject::kHeaderSize;
1188     default:
1189       UNREACHABLE();
1190       return 0;
1191   }
1192 }
1193 
1194 
GetInternalFieldCount()1195 int JSObject::GetInternalFieldCount() {
1196   ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1197   // Make sure to adjust for the number of in-object properties. These
1198   // properties do contribute to the size, but are not internal fields.
1199   return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1200          map()->inobject_properties();
1201 }
1202 
1203 
GetInternalField(int index)1204 Object* JSObject::GetInternalField(int index) {
1205   ASSERT(index < GetInternalFieldCount() && index >= 0);
1206   // Internal objects do follow immediately after the header, whereas in-object
1207   // properties are at the end of the object. Therefore there is no need
1208   // to adjust the index here.
1209   return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1210 }
1211 
1212 
SetInternalField(int index,Object * value)1213 void JSObject::SetInternalField(int index, Object* value) {
1214   ASSERT(index < GetInternalFieldCount() && index >= 0);
1215   // Internal objects do follow immediately after the header, whereas in-object
1216   // properties are at the end of the object. Therefore there is no need
1217   // to adjust the index here.
1218   int offset = GetHeaderSize() + (kPointerSize * index);
1219   WRITE_FIELD(this, offset, value);
1220   WRITE_BARRIER(this, offset);
1221 }
1222 
1223 
1224 // Access fast-case object properties at index. The use of these routines
1225 // is needed to correctly distinguish between properties stored in-object and
1226 // properties stored in the properties array.
FastPropertyAt(int index)1227 Object* JSObject::FastPropertyAt(int index) {
1228   // Adjust for the number of properties stored in the object.
1229   index -= map()->inobject_properties();
1230   if (index < 0) {
1231     int offset = map()->instance_size() + (index * kPointerSize);
1232     return READ_FIELD(this, offset);
1233   } else {
1234     ASSERT(index < properties()->length());
1235     return properties()->get(index);
1236   }
1237 }
1238 
1239 
FastPropertyAtPut(int index,Object * value)1240 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1241   // Adjust for the number of properties stored in the object.
1242   index -= map()->inobject_properties();
1243   if (index < 0) {
1244     int offset = map()->instance_size() + (index * kPointerSize);
1245     WRITE_FIELD(this, offset, value);
1246     WRITE_BARRIER(this, offset);
1247   } else {
1248     ASSERT(index < properties()->length());
1249     properties()->set(index, value);
1250   }
1251   return value;
1252 }
1253 
1254 
InObjectPropertyAt(int index)1255 Object* JSObject::InObjectPropertyAt(int index) {
1256   // Adjust for the number of properties stored in the object.
1257   index -= map()->inobject_properties();
1258   ASSERT(index < 0);
1259   int offset = map()->instance_size() + (index * kPointerSize);
1260   return READ_FIELD(this, offset);
1261 }
1262 
1263 
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1264 Object* JSObject::InObjectPropertyAtPut(int index,
1265                                         Object* value,
1266                                         WriteBarrierMode mode) {
1267   // Adjust for the number of properties stored in the object.
1268   index -= map()->inobject_properties();
1269   ASSERT(index < 0);
1270   int offset = map()->instance_size() + (index * kPointerSize);
1271   WRITE_FIELD(this, offset, value);
1272   CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1273   return value;
1274 }
1275 
1276 
1277 
InitializeBody(int object_size)1278 void JSObject::InitializeBody(int object_size) {
1279   Object* value = Heap::undefined_value();
1280   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1281     WRITE_FIELD(this, offset, value);
1282   }
1283 }
1284 
1285 
InitializeBody(int object_size)1286 void Struct::InitializeBody(int object_size) {
1287   Object* value = Heap::undefined_value();
1288   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1289     WRITE_FIELD(this, offset, value);
1290   }
1291 }
1292 
1293 
HasFastProperties()1294 bool JSObject::HasFastProperties() {
1295   return !properties()->IsDictionary();
1296 }
1297 
1298 
IndexFromObject(Object * object,uint32_t * index)1299 bool Array::IndexFromObject(Object* object, uint32_t* index) {
1300   if (object->IsSmi()) {
1301     int value = Smi::cast(object)->value();
1302     if (value < 0) return false;
1303     *index = value;
1304     return true;
1305   }
1306   if (object->IsHeapNumber()) {
1307     double value = HeapNumber::cast(object)->value();
1308     uint32_t uint_value = static_cast<uint32_t>(value);
1309     if (value == static_cast<double>(uint_value)) {
1310       *index = uint_value;
1311       return true;
1312     }
1313   }
1314   return false;
1315 }
1316 
1317 
IsStringObjectWithCharacterAt(uint32_t index)1318 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1319   if (!this->IsJSValue()) return false;
1320 
1321   JSValue* js_value = JSValue::cast(this);
1322   if (!js_value->value()->IsString()) return false;
1323 
1324   String* str = String::cast(js_value->value());
1325   if (index >= (uint32_t)str->length()) return false;
1326 
1327   return true;
1328 }
1329 
1330 
get(int index)1331 Object* FixedArray::get(int index) {
1332   ASSERT(index >= 0 && index < this->length());
1333   return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1334 }
1335 
1336 
set(int index,Smi * value)1337 void FixedArray::set(int index, Smi* value) {
1338   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1339   int offset = kHeaderSize + index * kPointerSize;
1340   WRITE_FIELD(this, offset, value);
1341 }
1342 
1343 
set(int index,Object * value)1344 void FixedArray::set(int index, Object* value) {
1345   ASSERT(index >= 0 && index < this->length());
1346   int offset = kHeaderSize + index * kPointerSize;
1347   WRITE_FIELD(this, offset, value);
1348   WRITE_BARRIER(this, offset);
1349 }
1350 
1351 
GetWriteBarrierMode(const AssertNoAllocation &)1352 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1353   if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1354   return UPDATE_WRITE_BARRIER;
1355 }
1356 
1357 
set(int index,Object * value,WriteBarrierMode mode)1358 void FixedArray::set(int index,
1359                      Object* value,
1360                      WriteBarrierMode mode) {
1361   ASSERT(index >= 0 && index < this->length());
1362   int offset = kHeaderSize + index * kPointerSize;
1363   WRITE_FIELD(this, offset, value);
1364   CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1365 }
1366 
1367 
fast_set(FixedArray * array,int index,Object * value)1368 void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1369   ASSERT(index >= 0 && index < array->length());
1370   ASSERT(!Heap::InNewSpace(value));
1371   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1372 }
1373 
1374 
set_undefined(int index)1375 void FixedArray::set_undefined(int index) {
1376   ASSERT(index >= 0 && index < this->length());
1377   ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1378   WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1379               Heap::undefined_value());
1380 }
1381 
1382 
set_null(int index)1383 void FixedArray::set_null(int index) {
1384   ASSERT(index >= 0 && index < this->length());
1385   ASSERT(!Heap::InNewSpace(Heap::null_value()));
1386   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1387 }
1388 
1389 
set_the_hole(int index)1390 void FixedArray::set_the_hole(int index) {
1391   ASSERT(index >= 0 && index < this->length());
1392   ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1393   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1394 }
1395 
1396 
IsEmpty()1397 bool DescriptorArray::IsEmpty() {
1398   ASSERT(this == Heap::empty_descriptor_array() ||
1399          this->length() > 2);
1400   return this == Heap::empty_descriptor_array();
1401 }
1402 
1403 
fast_swap(FixedArray * array,int first,int second)1404 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1405   Object* tmp = array->get(first);
1406   fast_set(array, first, array->get(second));
1407   fast_set(array, second, tmp);
1408 }
1409 
1410 
Search(String * name)1411 int DescriptorArray::Search(String* name) {
1412   SLOW_ASSERT(IsSortedNoDuplicates());
1413 
1414   // Check for empty descriptor array.
1415   int nof = number_of_descriptors();
1416   if (nof == 0) return kNotFound;
1417 
1418   // Fast case: do linear search for small arrays.
1419   const int kMaxElementsForLinearSearch = 8;
1420   if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1421     return LinearSearch(name, nof);
1422   }
1423 
1424   // Slow case: perform binary search.
1425   return BinarySearch(name, 0, nof - 1);
1426 }
1427 
1428 
GetKey(int descriptor_number)1429 String* DescriptorArray::GetKey(int descriptor_number) {
1430   ASSERT(descriptor_number < number_of_descriptors());
1431   return String::cast(get(ToKeyIndex(descriptor_number)));
1432 }
1433 
1434 
GetValue(int descriptor_number)1435 Object* DescriptorArray::GetValue(int descriptor_number) {
1436   ASSERT(descriptor_number < number_of_descriptors());
1437   return GetContentArray()->get(ToValueIndex(descriptor_number));
1438 }
1439 
1440 
GetDetails(int descriptor_number)1441 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1442   ASSERT(descriptor_number < number_of_descriptors());
1443   return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1444 }
1445 
1446 
GetType(int descriptor_number)1447 PropertyType DescriptorArray::GetType(int descriptor_number) {
1448   ASSERT(descriptor_number < number_of_descriptors());
1449   return PropertyDetails(GetDetails(descriptor_number)).type();
1450 }
1451 
1452 
GetFieldIndex(int descriptor_number)1453 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1454   return Descriptor::IndexFromValue(GetValue(descriptor_number));
1455 }
1456 
1457 
GetConstantFunction(int descriptor_number)1458 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1459   return JSFunction::cast(GetValue(descriptor_number));
1460 }
1461 
1462 
GetCallbacksObject(int descriptor_number)1463 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1464   ASSERT(GetType(descriptor_number) == CALLBACKS);
1465   return GetValue(descriptor_number);
1466 }
1467 
1468 
GetCallbacks(int descriptor_number)1469 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1470   ASSERT(GetType(descriptor_number) == CALLBACKS);
1471   Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1472   return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1473 }
1474 
1475 
IsProperty(int descriptor_number)1476 bool DescriptorArray::IsProperty(int descriptor_number) {
1477   return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1478 }
1479 
1480 
IsTransition(int descriptor_number)1481 bool DescriptorArray::IsTransition(int descriptor_number) {
1482   PropertyType t = GetType(descriptor_number);
1483   return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1484 }
1485 
1486 
IsNullDescriptor(int descriptor_number)1487 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1488   return GetType(descriptor_number) == NULL_DESCRIPTOR;
1489 }
1490 
1491 
IsDontEnum(int descriptor_number)1492 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1493   return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1494 }
1495 
1496 
Get(int descriptor_number,Descriptor * desc)1497 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1498   desc->Init(GetKey(descriptor_number),
1499              GetValue(descriptor_number),
1500              GetDetails(descriptor_number));
1501 }
1502 
1503 
Set(int descriptor_number,Descriptor * desc)1504 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1505   // Range check.
1506   ASSERT(descriptor_number < number_of_descriptors());
1507 
1508   // Make sure none of the elements in desc are in new space.
1509   ASSERT(!Heap::InNewSpace(desc->GetKey()));
1510   ASSERT(!Heap::InNewSpace(desc->GetValue()));
1511 
1512   fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1513   FixedArray* content_array = GetContentArray();
1514   fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1515   fast_set(content_array, ToDetailsIndex(descriptor_number),
1516            desc->GetDetails().AsSmi());
1517 }
1518 
1519 
CopyFrom(int index,DescriptorArray * src,int src_index)1520 void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1521   Descriptor desc;
1522   src->Get(src_index, &desc);
1523   Set(index, &desc);
1524 }
1525 
1526 
Swap(int first,int second)1527 void DescriptorArray::Swap(int first, int second) {
1528   fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1529   FixedArray* content_array = GetContentArray();
1530   fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1531   fast_swap(content_array, ToDetailsIndex(first),  ToDetailsIndex(second));
1532 }
1533 
1534 
requires_slow_elements()1535 bool NumberDictionary::requires_slow_elements() {
1536   Object* max_index_object = get(kMaxNumberKeyIndex);
1537   if (!max_index_object->IsSmi()) return false;
1538   return 0 !=
1539       (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1540 }
1541 
max_number_key()1542 uint32_t NumberDictionary::max_number_key() {
1543   ASSERT(!requires_slow_elements());
1544   Object* max_index_object = get(kMaxNumberKeyIndex);
1545   if (!max_index_object->IsSmi()) return 0;
1546   uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1547   return value >> kRequiresSlowElementsTagSize;
1548 }
1549 
set_requires_slow_elements()1550 void NumberDictionary::set_requires_slow_elements() {
1551   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
1552 }
1553 
1554 
1555 // ------------------------------------
1556 // Cast operations
1557 
1558 
1559 CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(DescriptorArray)1560 CAST_ACCESSOR(DescriptorArray)
1561 CAST_ACCESSOR(SymbolTable)
1562 CAST_ACCESSOR(CompilationCacheTable)
1563 CAST_ACCESSOR(MapCache)
1564 CAST_ACCESSOR(String)
1565 CAST_ACCESSOR(SeqString)
1566 CAST_ACCESSOR(SeqAsciiString)
1567 CAST_ACCESSOR(SeqTwoByteString)
1568 CAST_ACCESSOR(ConsString)
1569 CAST_ACCESSOR(ExternalString)
1570 CAST_ACCESSOR(ExternalAsciiString)
1571 CAST_ACCESSOR(ExternalTwoByteString)
1572 CAST_ACCESSOR(JSObject)
1573 CAST_ACCESSOR(Smi)
1574 CAST_ACCESSOR(Failure)
1575 CAST_ACCESSOR(HeapObject)
1576 CAST_ACCESSOR(HeapNumber)
1577 CAST_ACCESSOR(Oddball)
1578 CAST_ACCESSOR(JSGlobalPropertyCell)
1579 CAST_ACCESSOR(SharedFunctionInfo)
1580 CAST_ACCESSOR(Map)
1581 CAST_ACCESSOR(JSFunction)
1582 CAST_ACCESSOR(GlobalObject)
1583 CAST_ACCESSOR(JSGlobalProxy)
1584 CAST_ACCESSOR(JSGlobalObject)
1585 CAST_ACCESSOR(JSBuiltinsObject)
1586 CAST_ACCESSOR(Code)
1587 CAST_ACCESSOR(JSArray)
1588 CAST_ACCESSOR(JSRegExp)
1589 CAST_ACCESSOR(Proxy)
1590 CAST_ACCESSOR(ByteArray)
1591 CAST_ACCESSOR(PixelArray)
1592 CAST_ACCESSOR(ExternalArray)
1593 CAST_ACCESSOR(ExternalByteArray)
1594 CAST_ACCESSOR(ExternalUnsignedByteArray)
1595 CAST_ACCESSOR(ExternalShortArray)
1596 CAST_ACCESSOR(ExternalUnsignedShortArray)
1597 CAST_ACCESSOR(ExternalIntArray)
1598 CAST_ACCESSOR(ExternalUnsignedIntArray)
1599 CAST_ACCESSOR(ExternalFloatArray)
1600 CAST_ACCESSOR(Struct)
1601 
1602 
1603 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1604   STRUCT_LIST(MAKE_STRUCT_CAST)
1605 #undef MAKE_STRUCT_CAST
1606 
1607 
1608 template <typename Shape, typename Key>
1609 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1610   ASSERT(obj->IsHashTable());
1611   return reinterpret_cast<HashTable*>(obj);
1612 }
1613 
1614 
INT_ACCESSORS(Array,length,kLengthOffset)1615 INT_ACCESSORS(Array, length, kLengthOffset)
1616 
1617 
1618 INT_ACCESSORS(String, length, kLengthOffset)
1619 
1620 
1621 uint32_t String::hash_field() {
1622   return READ_UINT32_FIELD(this, kHashFieldOffset);
1623 }
1624 
1625 
set_hash_field(uint32_t value)1626 void String::set_hash_field(uint32_t value) {
1627   WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1628 }
1629 
1630 
Equals(String * other)1631 bool String::Equals(String* other) {
1632   if (other == this) return true;
1633   if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1634     return false;
1635   }
1636   return SlowEquals(other);
1637 }
1638 
1639 
TryFlattenIfNotFlat()1640 Object* String::TryFlattenIfNotFlat() {
1641   // We don't need to flatten strings that are already flat.  Since this code
1642   // is inlined, it can be helpful in the flat case to not call out to Flatten.
1643   if (!IsFlat()) {
1644     return TryFlatten();
1645   }
1646   return this;
1647 }
1648 
1649 
Get(int index)1650 uint16_t String::Get(int index) {
1651   ASSERT(index >= 0 && index < length());
1652   switch (StringShape(this).full_representation_tag()) {
1653     case kSeqStringTag | kAsciiStringTag:
1654       return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1655     case kSeqStringTag | kTwoByteStringTag:
1656       return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1657     case kConsStringTag | kAsciiStringTag:
1658     case kConsStringTag | kTwoByteStringTag:
1659       return ConsString::cast(this)->ConsStringGet(index);
1660     case kExternalStringTag | kAsciiStringTag:
1661       return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1662     case kExternalStringTag | kTwoByteStringTag:
1663       return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1664     default:
1665       break;
1666   }
1667 
1668   UNREACHABLE();
1669   return 0;
1670 }
1671 
1672 
Set(int index,uint16_t value)1673 void String::Set(int index, uint16_t value) {
1674   ASSERT(index >= 0 && index < length());
1675   ASSERT(StringShape(this).IsSequential());
1676 
1677   return this->IsAsciiRepresentation()
1678       ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1679       : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1680 }
1681 
1682 
IsFlat()1683 bool String::IsFlat() {
1684   switch (StringShape(this).representation_tag()) {
1685     case kConsStringTag: {
1686       String* second = ConsString::cast(this)->second();
1687       // Only flattened strings have second part empty.
1688       return second->length() == 0;
1689     }
1690     default:
1691       return true;
1692   }
1693 }
1694 
1695 
SeqAsciiStringGet(int index)1696 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1697   ASSERT(index >= 0 && index < length());
1698   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1699 }
1700 
1701 
SeqAsciiStringSet(int index,uint16_t value)1702 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1703   ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1704   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1705                    static_cast<byte>(value));
1706 }
1707 
1708 
GetCharsAddress()1709 Address SeqAsciiString::GetCharsAddress() {
1710   return FIELD_ADDR(this, kHeaderSize);
1711 }
1712 
1713 
GetChars()1714 char* SeqAsciiString::GetChars() {
1715   return reinterpret_cast<char*>(GetCharsAddress());
1716 }
1717 
1718 
GetCharsAddress()1719 Address SeqTwoByteString::GetCharsAddress() {
1720   return FIELD_ADDR(this, kHeaderSize);
1721 }
1722 
1723 
GetChars()1724 uc16* SeqTwoByteString::GetChars() {
1725   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1726 }
1727 
1728 
SeqTwoByteStringGet(int index)1729 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1730   ASSERT(index >= 0 && index < length());
1731   return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1732 }
1733 
1734 
SeqTwoByteStringSet(int index,uint16_t value)1735 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1736   ASSERT(index >= 0 && index < length());
1737   WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1738 }
1739 
1740 
SeqTwoByteStringSize(InstanceType instance_type)1741 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
1742   uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1743   return SizeFor(length);
1744 }
1745 
1746 
SeqAsciiStringSize(InstanceType instance_type)1747 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
1748   uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1749   return SizeFor(length);
1750 }
1751 
1752 
first()1753 String* ConsString::first() {
1754   return String::cast(READ_FIELD(this, kFirstOffset));
1755 }
1756 
1757 
unchecked_first()1758 Object* ConsString::unchecked_first() {
1759   return READ_FIELD(this, kFirstOffset);
1760 }
1761 
1762 
set_first(String * value,WriteBarrierMode mode)1763 void ConsString::set_first(String* value, WriteBarrierMode mode) {
1764   WRITE_FIELD(this, kFirstOffset, value);
1765   CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1766 }
1767 
1768 
second()1769 String* ConsString::second() {
1770   return String::cast(READ_FIELD(this, kSecondOffset));
1771 }
1772 
1773 
unchecked_second()1774 Object* ConsString::unchecked_second() {
1775   return READ_FIELD(this, kSecondOffset);
1776 }
1777 
1778 
set_second(String * value,WriteBarrierMode mode)1779 void ConsString::set_second(String* value, WriteBarrierMode mode) {
1780   WRITE_FIELD(this, kSecondOffset, value);
1781   CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1782 }
1783 
1784 
resource()1785 ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1786   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1787 }
1788 
1789 
set_resource(ExternalAsciiString::Resource * resource)1790 void ExternalAsciiString::set_resource(
1791     ExternalAsciiString::Resource* resource) {
1792   *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1793 }
1794 
1795 
resource()1796 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1797   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1798 }
1799 
1800 
set_resource(ExternalTwoByteString::Resource * resource)1801 void ExternalTwoByteString::set_resource(
1802     ExternalTwoByteString::Resource* resource) {
1803   *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1804 }
1805 
1806 
get(int index)1807 byte ByteArray::get(int index) {
1808   ASSERT(index >= 0 && index < this->length());
1809   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1810 }
1811 
1812 
set(int index,byte value)1813 void ByteArray::set(int index, byte value) {
1814   ASSERT(index >= 0 && index < this->length());
1815   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1816 }
1817 
1818 
get_int(int index)1819 int ByteArray::get_int(int index) {
1820   ASSERT(index >= 0 && (index * kIntSize) < this->length());
1821   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1822 }
1823 
1824 
FromDataStartAddress(Address address)1825 ByteArray* ByteArray::FromDataStartAddress(Address address) {
1826   ASSERT_TAG_ALIGNED(address);
1827   return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1828 }
1829 
1830 
GetDataStartAddress()1831 Address ByteArray::GetDataStartAddress() {
1832   return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1833 }
1834 
1835 
external_pointer()1836 uint8_t* PixelArray::external_pointer() {
1837   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1838   return reinterpret_cast<uint8_t*>(ptr);
1839 }
1840 
1841 
set_external_pointer(uint8_t * value,WriteBarrierMode mode)1842 void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1843   intptr_t ptr = reinterpret_cast<intptr_t>(value);
1844   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1845 }
1846 
1847 
get(int index)1848 uint8_t PixelArray::get(int index) {
1849   ASSERT((index >= 0) && (index < this->length()));
1850   uint8_t* ptr = external_pointer();
1851   return ptr[index];
1852 }
1853 
1854 
set(int index,uint8_t value)1855 void PixelArray::set(int index, uint8_t value) {
1856   ASSERT((index >= 0) && (index < this->length()));
1857   uint8_t* ptr = external_pointer();
1858   ptr[index] = value;
1859 }
1860 
1861 
external_pointer()1862 void* ExternalArray::external_pointer() {
1863   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1864   return reinterpret_cast<void*>(ptr);
1865 }
1866 
1867 
set_external_pointer(void * value,WriteBarrierMode mode)1868 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1869   intptr_t ptr = reinterpret_cast<intptr_t>(value);
1870   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1871 }
1872 
1873 
get(int index)1874 int8_t ExternalByteArray::get(int index) {
1875   ASSERT((index >= 0) && (index < this->length()));
1876   int8_t* ptr = static_cast<int8_t*>(external_pointer());
1877   return ptr[index];
1878 }
1879 
1880 
set(int index,int8_t value)1881 void ExternalByteArray::set(int index, int8_t value) {
1882   ASSERT((index >= 0) && (index < this->length()));
1883   int8_t* ptr = static_cast<int8_t*>(external_pointer());
1884   ptr[index] = value;
1885 }
1886 
1887 
get(int index)1888 uint8_t ExternalUnsignedByteArray::get(int index) {
1889   ASSERT((index >= 0) && (index < this->length()));
1890   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1891   return ptr[index];
1892 }
1893 
1894 
set(int index,uint8_t value)1895 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1896   ASSERT((index >= 0) && (index < this->length()));
1897   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1898   ptr[index] = value;
1899 }
1900 
1901 
get(int index)1902 int16_t ExternalShortArray::get(int index) {
1903   ASSERT((index >= 0) && (index < this->length()));
1904   int16_t* ptr = static_cast<int16_t*>(external_pointer());
1905   return ptr[index];
1906 }
1907 
1908 
set(int index,int16_t value)1909 void ExternalShortArray::set(int index, int16_t value) {
1910   ASSERT((index >= 0) && (index < this->length()));
1911   int16_t* ptr = static_cast<int16_t*>(external_pointer());
1912   ptr[index] = value;
1913 }
1914 
1915 
get(int index)1916 uint16_t ExternalUnsignedShortArray::get(int index) {
1917   ASSERT((index >= 0) && (index < this->length()));
1918   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1919   return ptr[index];
1920 }
1921 
1922 
set(int index,uint16_t value)1923 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1924   ASSERT((index >= 0) && (index < this->length()));
1925   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1926   ptr[index] = value;
1927 }
1928 
1929 
get(int index)1930 int32_t ExternalIntArray::get(int index) {
1931   ASSERT((index >= 0) && (index < this->length()));
1932   int32_t* ptr = static_cast<int32_t*>(external_pointer());
1933   return ptr[index];
1934 }
1935 
1936 
set(int index,int32_t value)1937 void ExternalIntArray::set(int index, int32_t value) {
1938   ASSERT((index >= 0) && (index < this->length()));
1939   int32_t* ptr = static_cast<int32_t*>(external_pointer());
1940   ptr[index] = value;
1941 }
1942 
1943 
get(int index)1944 uint32_t ExternalUnsignedIntArray::get(int index) {
1945   ASSERT((index >= 0) && (index < this->length()));
1946   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1947   return ptr[index];
1948 }
1949 
1950 
set(int index,uint32_t value)1951 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
1952   ASSERT((index >= 0) && (index < this->length()));
1953   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1954   ptr[index] = value;
1955 }
1956 
1957 
get(int index)1958 float ExternalFloatArray::get(int index) {
1959   ASSERT((index >= 0) && (index < this->length()));
1960   float* ptr = static_cast<float*>(external_pointer());
1961   return ptr[index];
1962 }
1963 
1964 
set(int index,float value)1965 void ExternalFloatArray::set(int index, float value) {
1966   ASSERT((index >= 0) && (index < this->length()));
1967   float* ptr = static_cast<float*>(external_pointer());
1968   ptr[index] = value;
1969 }
1970 
1971 
instance_size()1972 int Map::instance_size() {
1973   return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1974 }
1975 
1976 
inobject_properties()1977 int Map::inobject_properties() {
1978   return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
1979 }
1980 
1981 
pre_allocated_property_fields()1982 int Map::pre_allocated_property_fields() {
1983   return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1984 }
1985 
1986 
SizeFromMap(Map * map)1987 int HeapObject::SizeFromMap(Map* map) {
1988   InstanceType instance_type = map->instance_type();
1989   // Only inline the most frequent cases.
1990   if (instance_type == JS_OBJECT_TYPE ||
1991       (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1992       (kStringTag | kConsStringTag) ||
1993       instance_type == JS_ARRAY_TYPE) return map->instance_size();
1994   if (instance_type == FIXED_ARRAY_TYPE) {
1995     return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1996   }
1997   if (instance_type == BYTE_ARRAY_TYPE) {
1998     return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1999   }
2000   // Otherwise do the general size computation.
2001   return SlowSizeFromMap(map);
2002 }
2003 
2004 
set_instance_size(int value)2005 void Map::set_instance_size(int value) {
2006   ASSERT_EQ(0, value & (kPointerSize - 1));
2007   value >>= kPointerSizeLog2;
2008   ASSERT(0 <= value && value < 256);
2009   WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2010 }
2011 
2012 
set_inobject_properties(int value)2013 void Map::set_inobject_properties(int value) {
2014   ASSERT(0 <= value && value < 256);
2015   WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2016 }
2017 
2018 
set_pre_allocated_property_fields(int value)2019 void Map::set_pre_allocated_property_fields(int value) {
2020   ASSERT(0 <= value && value < 256);
2021   WRITE_BYTE_FIELD(this,
2022                    kPreAllocatedPropertyFieldsOffset,
2023                    static_cast<byte>(value));
2024 }
2025 
2026 
instance_type()2027 InstanceType Map::instance_type() {
2028   return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2029 }
2030 
2031 
set_instance_type(InstanceType value)2032 void Map::set_instance_type(InstanceType value) {
2033   ASSERT(0 <= value && value < 256);
2034   WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2035 }
2036 
2037 
unused_property_fields()2038 int Map::unused_property_fields() {
2039   return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2040 }
2041 
2042 
set_unused_property_fields(int value)2043 void Map::set_unused_property_fields(int value) {
2044   WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2045 }
2046 
2047 
bit_field()2048 byte Map::bit_field() {
2049   return READ_BYTE_FIELD(this, kBitFieldOffset);
2050 }
2051 
2052 
set_bit_field(byte value)2053 void Map::set_bit_field(byte value) {
2054   WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2055 }
2056 
2057 
bit_field2()2058 byte Map::bit_field2() {
2059   return READ_BYTE_FIELD(this, kBitField2Offset);
2060 }
2061 
2062 
set_bit_field2(byte value)2063 void Map::set_bit_field2(byte value) {
2064   WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2065 }
2066 
2067 
set_non_instance_prototype(bool value)2068 void Map::set_non_instance_prototype(bool value) {
2069   if (value) {
2070     set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2071   } else {
2072     set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2073   }
2074 }
2075 
2076 
has_non_instance_prototype()2077 bool Map::has_non_instance_prototype() {
2078   return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2079 }
2080 
2081 
set_is_access_check_needed(bool access_check_needed)2082 void Map::set_is_access_check_needed(bool access_check_needed) {
2083   if (access_check_needed) {
2084     set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2085   } else {
2086     set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2087   }
2088 }
2089 
2090 
is_access_check_needed()2091 bool Map::is_access_check_needed() {
2092   return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2093 }
2094 
2095 
flags()2096 Code::Flags Code::flags() {
2097   return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2098 }
2099 
2100 
set_flags(Code::Flags flags)2101 void Code::set_flags(Code::Flags flags) {
2102   STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2103   // Make sure that all call stubs have an arguments count.
2104   ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2105          ExtractArgumentsCountFromFlags(flags) >= 0);
2106   WRITE_INT_FIELD(this, kFlagsOffset, flags);
2107 }
2108 
2109 
kind()2110 Code::Kind Code::kind() {
2111   return ExtractKindFromFlags(flags());
2112 }
2113 
2114 
ic_in_loop()2115 InLoopFlag Code::ic_in_loop() {
2116   return ExtractICInLoopFromFlags(flags());
2117 }
2118 
2119 
ic_state()2120 InlineCacheState Code::ic_state() {
2121   InlineCacheState result = ExtractICStateFromFlags(flags());
2122   // Only allow uninitialized or debugger states for non-IC code
2123   // objects. This is used in the debugger to determine whether or not
2124   // a call to code object has been replaced with a debug break call.
2125   ASSERT(is_inline_cache_stub() ||
2126          result == UNINITIALIZED ||
2127          result == DEBUG_BREAK ||
2128          result == DEBUG_PREPARE_STEP_IN);
2129   return result;
2130 }
2131 
2132 
type()2133 PropertyType Code::type() {
2134   ASSERT(ic_state() == MONOMORPHIC);
2135   return ExtractTypeFromFlags(flags());
2136 }
2137 
2138 
arguments_count()2139 int Code::arguments_count() {
2140   ASSERT(is_call_stub() || kind() == STUB);
2141   return ExtractArgumentsCountFromFlags(flags());
2142 }
2143 
2144 
major_key()2145 CodeStub::Major Code::major_key() {
2146   ASSERT(kind() == STUB);
2147   return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2148                                                       kStubMajorKeyOffset));
2149 }
2150 
2151 
set_major_key(CodeStub::Major major)2152 void Code::set_major_key(CodeStub::Major major) {
2153   ASSERT(kind() == STUB);
2154   ASSERT(0 <= major && major < 256);
2155   WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2156 }
2157 
2158 
is_inline_cache_stub()2159 bool Code::is_inline_cache_stub() {
2160   Kind kind = this->kind();
2161   return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2162 }
2163 
2164 
ComputeFlags(Kind kind,InLoopFlag in_loop,InlineCacheState ic_state,PropertyType type,int argc)2165 Code::Flags Code::ComputeFlags(Kind kind,
2166                                InLoopFlag in_loop,
2167                                InlineCacheState ic_state,
2168                                PropertyType type,
2169                                int argc) {
2170   // Compute the bit mask.
2171   int bits = kind << kFlagsKindShift;
2172   if (in_loop) bits |= kFlagsICInLoopMask;
2173   bits |= ic_state << kFlagsICStateShift;
2174   bits |= type << kFlagsTypeShift;
2175   bits |= argc << kFlagsArgumentsCountShift;
2176   // Cast to flags and validate result before returning it.
2177   Flags result = static_cast<Flags>(bits);
2178   ASSERT(ExtractKindFromFlags(result) == kind);
2179   ASSERT(ExtractICStateFromFlags(result) == ic_state);
2180   ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2181   ASSERT(ExtractTypeFromFlags(result) == type);
2182   ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2183   return result;
2184 }
2185 
2186 
ComputeMonomorphicFlags(Kind kind,PropertyType type,InLoopFlag in_loop,int argc)2187 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2188                                           PropertyType type,
2189                                           InLoopFlag in_loop,
2190                                           int argc) {
2191   return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
2192 }
2193 
2194 
ExtractKindFromFlags(Flags flags)2195 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2196   int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2197   return static_cast<Kind>(bits);
2198 }
2199 
2200 
ExtractICStateFromFlags(Flags flags)2201 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2202   int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2203   return static_cast<InlineCacheState>(bits);
2204 }
2205 
2206 
ExtractICInLoopFromFlags(Flags flags)2207 InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2208   int bits = (flags & kFlagsICInLoopMask);
2209   return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2210 }
2211 
2212 
ExtractTypeFromFlags(Flags flags)2213 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2214   int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2215   return static_cast<PropertyType>(bits);
2216 }
2217 
2218 
ExtractArgumentsCountFromFlags(Flags flags)2219 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2220   return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2221 }
2222 
2223 
RemoveTypeFromFlags(Flags flags)2224 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2225   int bits = flags & ~kFlagsTypeMask;
2226   return static_cast<Flags>(bits);
2227 }
2228 
2229 
GetCodeFromTargetAddress(Address address)2230 Code* Code::GetCodeFromTargetAddress(Address address) {
2231   HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2232   // GetCodeFromTargetAddress might be called when marking objects during mark
2233   // sweep. reinterpret_cast is therefore used instead of the more appropriate
2234   // Code::cast. Code::cast does not work when the object's map is
2235   // marked.
2236   Code* result = reinterpret_cast<Code*>(code);
2237   return result;
2238 }
2239 
2240 
prototype()2241 Object* Map::prototype() {
2242   return READ_FIELD(this, kPrototypeOffset);
2243 }
2244 
2245 
set_prototype(Object * value,WriteBarrierMode mode)2246 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2247   ASSERT(value->IsNull() || value->IsJSObject());
2248   WRITE_FIELD(this, kPrototypeOffset, value);
2249   CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2250 }
2251 
2252 
ACCESSORS(Map,instance_descriptors,DescriptorArray,kInstanceDescriptorsOffset)2253 ACCESSORS(Map, instance_descriptors, DescriptorArray,
2254           kInstanceDescriptorsOffset)
2255 ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2256 ACCESSORS(Map, constructor, Object, kConstructorOffset)
2257 
2258 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2259 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2260 
2261 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2262 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2263 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2264 
2265 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2266 
2267 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2268 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2269 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2270 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2271 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2272 ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
2273 
2274 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2275 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2276 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2277 
2278 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2279 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2280 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2281 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2282 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2283 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2284 
2285 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2286 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2287 
2288 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2289 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2290 
2291 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2292 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2293 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2294           kPropertyAccessorsOffset)
2295 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2296           kPrototypeTemplateOffset)
2297 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2298 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2299           kNamedPropertyHandlerOffset)
2300 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2301           kIndexedPropertyHandlerOffset)
2302 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2303           kInstanceTemplateOffset)
2304 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2305 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2306 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2307           kInstanceCallHandlerOffset)
2308 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2309           kAccessCheckInfoOffset)
2310 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2311 
2312 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2313 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2314           kInternalFieldCountOffset)
2315 
2316 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2317 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2318 
2319 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2320 
2321 ACCESSORS(Script, source, Object, kSourceOffset)
2322 ACCESSORS(Script, name, Object, kNameOffset)
2323 ACCESSORS(Script, id, Object, kIdOffset)
2324 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2325 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2326 ACCESSORS(Script, data, Object, kDataOffset)
2327 ACCESSORS(Script, context_data, Object, kContextOffset)
2328 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2329 ACCESSORS(Script, type, Smi, kTypeOffset)
2330 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2331 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
2332 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
2333 ACCESSORS(Script, eval_from_instructions_offset, Smi,
2334           kEvalFrominstructionsOffsetOffset)
2335 
2336 #ifdef ENABLE_DEBUGGER_SUPPORT
2337 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2338 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2339 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2340 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2341 
2342 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2343 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2344 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2345 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2346 #endif
2347 
2348 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2349 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2350 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2351           kInstanceClassNameOffset)
2352 ACCESSORS(SharedFunctionInfo, function_data, Object,
2353           kExternalReferenceDataOffset)
2354 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2355 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2356 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2357 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2358           kThisPropertyAssignmentsOffset)
2359 
2360 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2361                kHiddenPrototypeBit)
2362 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2363 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2364                kNeedsAccessCheckBit)
2365 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2366                kIsExpressionBit)
2367 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2368                kIsTopLevelBit)
2369 BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2370             has_only_simple_this_property_assignments,
2371             kHasOnlySimpleThisPropertyAssignments)
2372 BOOL_ACCESSORS(SharedFunctionInfo,
2373                compiler_hints,
2374                try_full_codegen,
2375                kTryFullCodegen)
2376 
2377 INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2378 INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2379               kFormalParameterCountOffset)
2380 INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2381               kExpectedNofPropertiesOffset)
2382 INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2383               kStartPositionAndTypeOffset)
2384 INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2385 INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2386               kFunctionTokenPositionOffset)
2387 INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2388               kCompilerHintsOffset)
2389 INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2390               kThisPropertyAssignmentsCountOffset)
2391 
2392 
2393 bool Script::HasValidSource() {
2394   Object* src = this->source();
2395   if (!src->IsString()) return true;
2396   String* src_str = String::cast(src);
2397   if (!StringShape(src_str).IsExternal()) return true;
2398   if (src_str->IsAsciiRepresentation()) {
2399     return ExternalAsciiString::cast(src)->resource() != NULL;
2400   } else if (src_str->IsTwoByteRepresentation()) {
2401     return ExternalTwoByteString::cast(src)->resource() != NULL;
2402   }
2403   return true;
2404 }
2405 
2406 
DontAdaptArguments()2407 void SharedFunctionInfo::DontAdaptArguments() {
2408   ASSERT(code()->kind() == Code::BUILTIN);
2409   set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2410 }
2411 
2412 
start_position()2413 int SharedFunctionInfo::start_position() {
2414   return start_position_and_type() >> kStartPositionShift;
2415 }
2416 
2417 
set_start_position(int start_position)2418 void SharedFunctionInfo::set_start_position(int start_position) {
2419   set_start_position_and_type((start_position << kStartPositionShift)
2420     | (start_position_and_type() & ~kStartPositionMask));
2421 }
2422 
2423 
code()2424 Code* SharedFunctionInfo::code() {
2425   return Code::cast(READ_FIELD(this, kCodeOffset));
2426 }
2427 
2428 
set_code(Code * value,WriteBarrierMode mode)2429 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2430   WRITE_FIELD(this, kCodeOffset, value);
2431   CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2432 }
2433 
2434 
is_compiled()2435 bool SharedFunctionInfo::is_compiled() {
2436   // TODO(1242782): Create a code kind for uncompiled code.
2437   return code()->kind() != Code::STUB;
2438 }
2439 
2440 
IsBoilerplate()2441 bool JSFunction::IsBoilerplate() {
2442   return map() == Heap::boilerplate_function_map();
2443 }
2444 
2445 
IsBuiltin()2446 bool JSFunction::IsBuiltin() {
2447   return context()->global()->IsJSBuiltinsObject();
2448 }
2449 
2450 
code()2451 Code* JSFunction::code() {
2452   return shared()->code();
2453 }
2454 
2455 
set_code(Code * value)2456 void JSFunction::set_code(Code* value) {
2457   shared()->set_code(value);
2458 }
2459 
2460 
context()2461 Context* JSFunction::context() {
2462   return Context::cast(READ_FIELD(this, kContextOffset));
2463 }
2464 
2465 
unchecked_context()2466 Object* JSFunction::unchecked_context() {
2467   return READ_FIELD(this, kContextOffset);
2468 }
2469 
2470 
set_context(Object * value)2471 void JSFunction::set_context(Object* value) {
2472   ASSERT(value == Heap::undefined_value() || value->IsContext());
2473   WRITE_FIELD(this, kContextOffset, value);
2474   WRITE_BARRIER(this, kContextOffset);
2475 }
2476 
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)2477 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2478           kPrototypeOrInitialMapOffset)
2479 
2480 
2481 Map* JSFunction::initial_map() {
2482   return Map::cast(prototype_or_initial_map());
2483 }
2484 
2485 
set_initial_map(Map * value)2486 void JSFunction::set_initial_map(Map* value) {
2487   set_prototype_or_initial_map(value);
2488 }
2489 
2490 
has_initial_map()2491 bool JSFunction::has_initial_map() {
2492   return prototype_or_initial_map()->IsMap();
2493 }
2494 
2495 
has_instance_prototype()2496 bool JSFunction::has_instance_prototype() {
2497   return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2498 }
2499 
2500 
has_prototype()2501 bool JSFunction::has_prototype() {
2502   return map()->has_non_instance_prototype() || has_instance_prototype();
2503 }
2504 
2505 
instance_prototype()2506 Object* JSFunction::instance_prototype() {
2507   ASSERT(has_instance_prototype());
2508   if (has_initial_map()) return initial_map()->prototype();
2509   // When there is no initial map and the prototype is a JSObject, the
2510   // initial map field is used for the prototype field.
2511   return prototype_or_initial_map();
2512 }
2513 
2514 
prototype()2515 Object* JSFunction::prototype() {
2516   ASSERT(has_prototype());
2517   // If the function's prototype property has been set to a non-JSObject
2518   // value, that value is stored in the constructor field of the map.
2519   if (map()->has_non_instance_prototype()) return map()->constructor();
2520   return instance_prototype();
2521 }
2522 
2523 
is_compiled()2524 bool JSFunction::is_compiled() {
2525   return shared()->is_compiled();
2526 }
2527 
2528 
NumberOfLiterals()2529 int JSFunction::NumberOfLiterals() {
2530   return literals()->length();
2531 }
2532 
2533 
javascript_builtin(Builtins::JavaScript id)2534 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2535   ASSERT(0 <= id && id < kJSBuiltinsCount);
2536   return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2537 }
2538 
2539 
set_javascript_builtin(Builtins::JavaScript id,Object * value)2540 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2541                                               Object* value) {
2542   ASSERT(0 <= id && id < kJSBuiltinsCount);
2543   WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2544   WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2545 }
2546 
2547 
proxy()2548 Address Proxy::proxy() {
2549   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2550 }
2551 
2552 
set_proxy(Address value)2553 void Proxy::set_proxy(Address value) {
2554   WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2555 }
2556 
2557 
ProxyIterateBody(ObjectVisitor * visitor)2558 void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2559   visitor->VisitExternalReference(
2560       reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2561 }
2562 
2563 
ACCESSORS(JSValue,value,Object,kValueOffset)2564 ACCESSORS(JSValue, value, Object, kValueOffset)
2565 
2566 
2567 JSValue* JSValue::cast(Object* obj) {
2568   ASSERT(obj->IsJSValue());
2569   ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2570   return reinterpret_cast<JSValue*>(obj);
2571 }
2572 
2573 
INT_ACCESSORS(Code,instruction_size,kInstructionSizeOffset)2574 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2575 INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2576 INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2577 
2578 
2579 byte* Code::instruction_start()  {
2580   return FIELD_ADDR(this, kHeaderSize);
2581 }
2582 
2583 
body_size()2584 int Code::body_size() {
2585   return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2586 }
2587 
2588 
relocation_start()2589 byte* Code::relocation_start() {
2590   return FIELD_ADDR(this, kHeaderSize + instruction_size());
2591 }
2592 
2593 
entry()2594 byte* Code::entry() {
2595   return instruction_start();
2596 }
2597 
2598 
contains(byte * pc)2599 bool Code::contains(byte* pc) {
2600   return (instruction_start() <= pc) &&
2601       (pc < instruction_start() + instruction_size());
2602 }
2603 
2604 
sinfo_start()2605 byte* Code::sinfo_start() {
2606   return FIELD_ADDR(this, kHeaderSize + body_size());
2607 }
2608 
2609 
ACCESSORS(JSArray,length,Object,kLengthOffset)2610 ACCESSORS(JSArray, length, Object, kLengthOffset)
2611 
2612 
2613 ACCESSORS(JSRegExp, data, Object, kDataOffset)
2614 
2615 
2616 JSRegExp::Type JSRegExp::TypeTag() {
2617   Object* data = this->data();
2618   if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2619   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2620   return static_cast<JSRegExp::Type>(smi->value());
2621 }
2622 
2623 
CaptureCount()2624 int JSRegExp::CaptureCount() {
2625   switch (TypeTag()) {
2626     case ATOM:
2627       return 0;
2628     case IRREGEXP:
2629       return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2630     default:
2631       UNREACHABLE();
2632       return -1;
2633   }
2634 }
2635 
2636 
GetFlags()2637 JSRegExp::Flags JSRegExp::GetFlags() {
2638   ASSERT(this->data()->IsFixedArray());
2639   Object* data = this->data();
2640   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2641   return Flags(smi->value());
2642 }
2643 
2644 
Pattern()2645 String* JSRegExp::Pattern() {
2646   ASSERT(this->data()->IsFixedArray());
2647   Object* data = this->data();
2648   String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2649   return pattern;
2650 }
2651 
2652 
DataAt(int index)2653 Object* JSRegExp::DataAt(int index) {
2654   ASSERT(TypeTag() != NOT_COMPILED);
2655   return FixedArray::cast(data())->get(index);
2656 }
2657 
2658 
SetDataAt(int index,Object * value)2659 void JSRegExp::SetDataAt(int index, Object* value) {
2660   ASSERT(TypeTag() != NOT_COMPILED);
2661   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
2662   FixedArray::cast(data())->set(index, value);
2663 }
2664 
2665 
GetElementsKind()2666 JSObject::ElementsKind JSObject::GetElementsKind() {
2667   Array* array = elements();
2668   if (array->IsFixedArray()) {
2669     // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2670     if (array->map() == Heap::fixed_array_map()) {
2671       return FAST_ELEMENTS;
2672     }
2673     ASSERT(array->IsDictionary());
2674     return DICTIONARY_ELEMENTS;
2675   }
2676   if (array->IsExternalArray()) {
2677     switch (array->map()->instance_type()) {
2678       case EXTERNAL_BYTE_ARRAY_TYPE:
2679         return EXTERNAL_BYTE_ELEMENTS;
2680       case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2681         return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2682       case EXTERNAL_SHORT_ARRAY_TYPE:
2683         return EXTERNAL_SHORT_ELEMENTS;
2684       case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2685         return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2686       case EXTERNAL_INT_ARRAY_TYPE:
2687         return EXTERNAL_INT_ELEMENTS;
2688       case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2689         return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2690       default:
2691         ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2692         return EXTERNAL_FLOAT_ELEMENTS;
2693     }
2694   }
2695   ASSERT(array->IsPixelArray());
2696   return PIXEL_ELEMENTS;
2697 }
2698 
2699 
HasFastElements()2700 bool JSObject::HasFastElements() {
2701   return GetElementsKind() == FAST_ELEMENTS;
2702 }
2703 
2704 
HasDictionaryElements()2705 bool JSObject::HasDictionaryElements() {
2706   return GetElementsKind() == DICTIONARY_ELEMENTS;
2707 }
2708 
2709 
HasPixelElements()2710 bool JSObject::HasPixelElements() {
2711   return GetElementsKind() == PIXEL_ELEMENTS;
2712 }
2713 
2714 
HasExternalArrayElements()2715 bool JSObject::HasExternalArrayElements() {
2716   return (HasExternalByteElements() ||
2717           HasExternalUnsignedByteElements() ||
2718           HasExternalShortElements() ||
2719           HasExternalUnsignedShortElements() ||
2720           HasExternalIntElements() ||
2721           HasExternalUnsignedIntElements() ||
2722           HasExternalFloatElements());
2723 }
2724 
2725 
HasExternalByteElements()2726 bool JSObject::HasExternalByteElements() {
2727   return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2728 }
2729 
2730 
HasExternalUnsignedByteElements()2731 bool JSObject::HasExternalUnsignedByteElements() {
2732   return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2733 }
2734 
2735 
HasExternalShortElements()2736 bool JSObject::HasExternalShortElements() {
2737   return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2738 }
2739 
2740 
HasExternalUnsignedShortElements()2741 bool JSObject::HasExternalUnsignedShortElements() {
2742   return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2743 }
2744 
2745 
HasExternalIntElements()2746 bool JSObject::HasExternalIntElements() {
2747   return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2748 }
2749 
2750 
HasExternalUnsignedIntElements()2751 bool JSObject::HasExternalUnsignedIntElements() {
2752   return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2753 }
2754 
2755 
HasExternalFloatElements()2756 bool JSObject::HasExternalFloatElements() {
2757   return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2758 }
2759 
2760 
HasNamedInterceptor()2761 bool JSObject::HasNamedInterceptor() {
2762   return map()->has_named_interceptor();
2763 }
2764 
2765 
HasIndexedInterceptor()2766 bool JSObject::HasIndexedInterceptor() {
2767   return map()->has_indexed_interceptor();
2768 }
2769 
2770 
property_dictionary()2771 StringDictionary* JSObject::property_dictionary() {
2772   ASSERT(!HasFastProperties());
2773   return StringDictionary::cast(properties());
2774 }
2775 
2776 
element_dictionary()2777 NumberDictionary* JSObject::element_dictionary() {
2778   ASSERT(HasDictionaryElements());
2779   return NumberDictionary::cast(elements());
2780 }
2781 
2782 
HasHashCode()2783 bool String::HasHashCode() {
2784   return (hash_field() & kHashComputedMask) != 0;
2785 }
2786 
2787 
Hash()2788 uint32_t String::Hash() {
2789   // Fast case: has hash code already been computed?
2790   uint32_t field = hash_field();
2791   if (field & kHashComputedMask) return field >> kHashShift;
2792   // Slow case: compute hash code and set it.
2793   return ComputeAndSetHash();
2794 }
2795 
2796 
StringHasher(int length)2797 StringHasher::StringHasher(int length)
2798   : length_(length),
2799     raw_running_hash_(0),
2800     array_index_(0),
2801     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2802     is_first_char_(true),
2803     is_valid_(true) { }
2804 
2805 
has_trivial_hash()2806 bool StringHasher::has_trivial_hash() {
2807   return length_ > String::kMaxHashCalcLength;
2808 }
2809 
2810 
AddCharacter(uc32 c)2811 void StringHasher::AddCharacter(uc32 c) {
2812   // Use the Jenkins one-at-a-time hash function to update the hash
2813   // for the given character.
2814   raw_running_hash_ += c;
2815   raw_running_hash_ += (raw_running_hash_ << 10);
2816   raw_running_hash_ ^= (raw_running_hash_ >> 6);
2817   // Incremental array index computation.
2818   if (is_array_index_) {
2819     if (c < '0' || c > '9') {
2820       is_array_index_ = false;
2821     } else {
2822       int d = c - '0';
2823       if (is_first_char_) {
2824         is_first_char_ = false;
2825         if (c == '0' && length_ > 1) {
2826           is_array_index_ = false;
2827           return;
2828         }
2829       }
2830       if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2831         is_array_index_ = false;
2832       } else {
2833         array_index_ = array_index_ * 10 + d;
2834       }
2835     }
2836   }
2837 }
2838 
2839 
AddCharacterNoIndex(uc32 c)2840 void StringHasher::AddCharacterNoIndex(uc32 c) {
2841   ASSERT(!is_array_index());
2842   raw_running_hash_ += c;
2843   raw_running_hash_ += (raw_running_hash_ << 10);
2844   raw_running_hash_ ^= (raw_running_hash_ >> 6);
2845 }
2846 
2847 
GetHash()2848 uint32_t StringHasher::GetHash() {
2849   // Get the calculated raw hash value and do some more bit ops to distribute
2850   // the hash further. Ensure that we never return zero as the hash value.
2851   uint32_t result = raw_running_hash_;
2852   result += (result << 3);
2853   result ^= (result >> 11);
2854   result += (result << 15);
2855   if (result == 0) {
2856     result = 27;
2857   }
2858   return result;
2859 }
2860 
2861 
AsArrayIndex(uint32_t * index)2862 bool String::AsArrayIndex(uint32_t* index) {
2863   uint32_t field = hash_field();
2864   if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
2865   return SlowAsArrayIndex(index);
2866 }
2867 
2868 
GetPrototype()2869 Object* JSObject::GetPrototype() {
2870   return JSObject::cast(this)->map()->prototype();
2871 }
2872 
2873 
GetPropertyAttribute(String * key)2874 PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2875   return GetPropertyAttributeWithReceiver(this, key);
2876 }
2877 
2878 // TODO(504): this may be useful in other places too where JSGlobalProxy
2879 // is used.
BypassGlobalProxy()2880 Object* JSObject::BypassGlobalProxy() {
2881   if (IsJSGlobalProxy()) {
2882     Object* proto = GetPrototype();
2883     if (proto->IsNull()) return Heap::undefined_value();
2884     ASSERT(proto->IsJSGlobalObject());
2885     return proto;
2886   }
2887   return this;
2888 }
2889 
2890 
HasHiddenPropertiesObject()2891 bool JSObject::HasHiddenPropertiesObject() {
2892   ASSERT(!IsJSGlobalProxy());
2893   return GetPropertyAttributePostInterceptor(this,
2894                                              Heap::hidden_symbol(),
2895                                              false) != ABSENT;
2896 }
2897 
2898 
GetHiddenPropertiesObject()2899 Object* JSObject::GetHiddenPropertiesObject() {
2900   ASSERT(!IsJSGlobalProxy());
2901   PropertyAttributes attributes;
2902   return GetLocalPropertyPostInterceptor(this,
2903                                          Heap::hidden_symbol(),
2904                                          &attributes);
2905 }
2906 
2907 
SetHiddenPropertiesObject(Object * hidden_obj)2908 Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
2909   ASSERT(!IsJSGlobalProxy());
2910   return SetPropertyPostInterceptor(Heap::hidden_symbol(),
2911                                     hidden_obj,
2912                                     DONT_ENUM);
2913 }
2914 
2915 
HasElement(uint32_t index)2916 bool JSObject::HasElement(uint32_t index) {
2917   return HasElementWithReceiver(this, index);
2918 }
2919 
2920 
all_can_read()2921 bool AccessorInfo::all_can_read() {
2922   return BooleanBit::get(flag(), kAllCanReadBit);
2923 }
2924 
2925 
set_all_can_read(bool value)2926 void AccessorInfo::set_all_can_read(bool value) {
2927   set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2928 }
2929 
2930 
all_can_write()2931 bool AccessorInfo::all_can_write() {
2932   return BooleanBit::get(flag(), kAllCanWriteBit);
2933 }
2934 
2935 
set_all_can_write(bool value)2936 void AccessorInfo::set_all_can_write(bool value) {
2937   set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2938 }
2939 
2940 
prohibits_overwriting()2941 bool AccessorInfo::prohibits_overwriting() {
2942   return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2943 }
2944 
2945 
set_prohibits_overwriting(bool value)2946 void AccessorInfo::set_prohibits_overwriting(bool value) {
2947   set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2948 }
2949 
2950 
property_attributes()2951 PropertyAttributes AccessorInfo::property_attributes() {
2952   return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2953 }
2954 
2955 
set_property_attributes(PropertyAttributes attributes)2956 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2957   ASSERT(AttributesField::is_valid(attributes));
2958   int rest_value = flag()->value() & ~AttributesField::mask();
2959   set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2960 }
2961 
2962 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)2963 void Dictionary<Shape, Key>::SetEntry(int entry,
2964                                       Object* key,
2965                                       Object* value,
2966                                       PropertyDetails details) {
2967   ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
2968   int index = HashTable<Shape, Key>::EntryToIndex(entry);
2969   AssertNoAllocation no_gc;
2970   WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
2971   FixedArray::set(index, key, mode);
2972   FixedArray::set(index+1, value, mode);
2973   FixedArray::fast_set(this, index+2, details.AsSmi());
2974 }
2975 
2976 
ClearCodeCache()2977 void Map::ClearCodeCache() {
2978   // No write barrier is needed since empty_fixed_array is not in new space.
2979   // Please note this function is used during marking:
2980   //  - MarkCompactCollector::MarkUnmarkedObject
2981   ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2982   WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
2983 }
2984 
2985 
EnsureSize(int required_size)2986 void JSArray::EnsureSize(int required_size) {
2987   ASSERT(HasFastElements());
2988   Array* elts = elements();
2989   const int kArraySizeThatFitsComfortablyInNewSpace = 128;
2990   if (elts->length() < required_size) {
2991     // Doubling in size would be overkill, but leave some slack to avoid
2992     // constantly growing.
2993     Expand(required_size + (required_size >> 3));
2994     // It's a performance benefit to keep a frequently used array in new-space.
2995   } else if (!Heap::new_space()->Contains(elts) &&
2996              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
2997     // Expand will allocate a new backing store in new space even if the size
2998     // we asked for isn't larger than what we had before.
2999     Expand(required_size);
3000   }
3001 }
3002 
3003 
set_length(Smi * length)3004 void JSArray::set_length(Smi* length) {
3005   set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3006 }
3007 
3008 
SetContent(FixedArray * storage)3009 void JSArray::SetContent(FixedArray* storage) {
3010   set_length(Smi::FromInt(storage->length()));
3011   set_elements(storage);
3012 }
3013 
3014 
Copy()3015 Object* FixedArray::Copy() {
3016   if (length() == 0) return this;
3017   return Heap::CopyFixedArray(this);
3018 }
3019 
3020 
3021 #undef CAST_ACCESSOR
3022 #undef INT_ACCESSORS
3023 #undef SMI_ACCESSORS
3024 #undef ACCESSORS
3025 #undef FIELD_ADDR
3026 #undef READ_FIELD
3027 #undef WRITE_FIELD
3028 #undef WRITE_BARRIER
3029 #undef CONDITIONAL_WRITE_BARRIER
3030 #undef READ_MEMADDR_FIELD
3031 #undef WRITE_MEMADDR_FIELD
3032 #undef READ_DOUBLE_FIELD
3033 #undef WRITE_DOUBLE_FIELD
3034 #undef READ_INT_FIELD
3035 #undef WRITE_INT_FIELD
3036 #undef READ_SHORT_FIELD
3037 #undef WRITE_SHORT_FIELD
3038 #undef READ_BYTE_FIELD
3039 #undef WRITE_BYTE_FIELD
3040 
3041 
3042 } }  // namespace v8::internal
3043 
3044 #endif  // V8_OBJECTS_INL_H_
3045