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