• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 "elements.h"
39 #include "objects.h"
40 #include "contexts.h"
41 #include "conversions-inl.h"
42 #include "heap.h"
43 #include "isolate.h"
44 #include "property.h"
45 #include "spaces.h"
46 #include "store-buffer.h"
47 #include "v8memory.h"
48 #include "factory.h"
49 #include "incremental-marking.h"
50 #include "transitions-inl.h"
51 
52 namespace v8 {
53 namespace internal {
54 
PropertyDetails(Smi * smi)55 PropertyDetails::PropertyDetails(Smi* smi) {
56   value_ = smi->value();
57 }
58 
59 
AsSmi()60 Smi* PropertyDetails::AsSmi() {
61   // Ensure the upper 2 bits have the same value by sign extending it. This is
62   // necessary to be able to use the 31st bit of the property details.
63   int value = value_ << 1;
64   return Smi::FromInt(value >> 1);
65 }
66 
67 
AsDeleted()68 PropertyDetails PropertyDetails::AsDeleted() {
69   Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
70   return PropertyDetails(smi);
71 }
72 
73 
74 #define TYPE_CHECKER(type, instancetype)                                \
75   bool Object::Is##type() {                                             \
76   return Object::IsHeapObject() &&                                      \
77       HeapObject::cast(this)->map()->instance_type() == instancetype;   \
78   }
79 
80 
81 #define CAST_ACCESSOR(type)                     \
82   type* type::cast(Object* object) {            \
83     SLOW_ASSERT(object->Is##type());            \
84     return reinterpret_cast<type*>(object);     \
85   }
86 
87 
88 #define INT_ACCESSORS(holder, name, offset)                             \
89   int holder::name() { return READ_INT_FIELD(this, offset); }           \
90   void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
91 
92 
93 #define ACCESSORS(holder, name, type, offset)                           \
94   type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
95   void holder::set_##name(type* value, WriteBarrierMode mode) {         \
96     WRITE_FIELD(this, offset, value);                                   \
97     CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);    \
98   }
99 
100 
101 // Getter that returns a tagged Smi and setter that writes a tagged Smi.
102 #define ACCESSORS_TO_SMI(holder, name, offset)                          \
103   Smi* holder::name() { return Smi::cast(READ_FIELD(this, offset)); }   \
104   void holder::set_##name(Smi* value, WriteBarrierMode mode) {          \
105     WRITE_FIELD(this, offset, value);                                   \
106   }
107 
108 
109 // Getter that returns a Smi as an int and writes an int as a Smi.
110 #define SMI_ACCESSORS(holder, name, offset)             \
111   int holder::name() {                                  \
112     Object* value = READ_FIELD(this, offset);           \
113     return Smi::cast(value)->value();                   \
114   }                                                     \
115   void holder::set_##name(int value) {                  \
116     WRITE_FIELD(this, offset, Smi::FromInt(value));     \
117   }
118 
119 
120 #define BOOL_GETTER(holder, field, name, offset)           \
121   bool holder::name() {                                    \
122     return BooleanBit::get(field(), offset);               \
123   }                                                        \
124 
125 
126 #define BOOL_ACCESSORS(holder, field, name, offset)        \
127   bool holder::name() {                                    \
128     return BooleanBit::get(field(), offset);               \
129   }                                                        \
130   void holder::set_##name(bool value) {                    \
131     set_##field(BooleanBit::set(field(), offset, value));  \
132   }
133 
134 
IsFixedArrayBase()135 bool Object::IsFixedArrayBase() {
136   return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray();
137 }
138 
139 
140 // External objects are not extensible, so the map check is enough.
IsExternal()141 bool Object::IsExternal() {
142   return Object::IsHeapObject() &&
143       HeapObject::cast(this)->map() ==
144       HeapObject::cast(this)->GetHeap()->external_map();
145 }
146 
147 
IsAccessorInfo()148 bool Object::IsAccessorInfo() {
149   return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
150 }
151 
152 
IsSmi()153 bool Object::IsSmi() {
154   return HAS_SMI_TAG(this);
155 }
156 
157 
IsHeapObject()158 bool Object::IsHeapObject() {
159   return Internals::HasHeapObjectTag(this);
160 }
161 
162 
NonFailureIsHeapObject()163 bool Object::NonFailureIsHeapObject() {
164   ASSERT(!this->IsFailure());
165   return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
166 }
167 
168 
TYPE_CHECKER(HeapNumber,HEAP_NUMBER_TYPE)169 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
170 TYPE_CHECKER(Symbol, SYMBOL_TYPE)
171 
172 
173 bool Object::IsString() {
174   return Object::IsHeapObject()
175     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
176 }
177 
178 
IsName()179 bool Object::IsName() {
180   return IsString() || IsSymbol();
181 }
182 
183 
IsUniqueName()184 bool Object::IsUniqueName() {
185   return IsInternalizedString() || IsSymbol();
186 }
187 
188 
IsSpecObject()189 bool Object::IsSpecObject() {
190   return Object::IsHeapObject()
191     && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
192 }
193 
194 
IsSpecFunction()195 bool Object::IsSpecFunction() {
196   if (!Object::IsHeapObject()) return false;
197   InstanceType type = HeapObject::cast(this)->map()->instance_type();
198   return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
199 }
200 
201 
IsInternalizedString()202 bool Object::IsInternalizedString() {
203   if (!this->IsHeapObject()) return false;
204   uint32_t type = HeapObject::cast(this)->map()->instance_type();
205   STATIC_ASSERT(kNotInternalizedTag != 0);
206   return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
207       (kStringTag | kInternalizedTag);
208 }
209 
210 
IsConsString()211 bool Object::IsConsString() {
212   if (!IsString()) return false;
213   return StringShape(String::cast(this)).IsCons();
214 }
215 
216 
IsSlicedString()217 bool Object::IsSlicedString() {
218   if (!IsString()) return false;
219   return StringShape(String::cast(this)).IsSliced();
220 }
221 
222 
IsSeqString()223 bool Object::IsSeqString() {
224   if (!IsString()) return false;
225   return StringShape(String::cast(this)).IsSequential();
226 }
227 
228 
IsSeqOneByteString()229 bool Object::IsSeqOneByteString() {
230   if (!IsString()) return false;
231   return StringShape(String::cast(this)).IsSequential() &&
232          String::cast(this)->IsOneByteRepresentation();
233 }
234 
235 
IsSeqTwoByteString()236 bool Object::IsSeqTwoByteString() {
237   if (!IsString()) return false;
238   return StringShape(String::cast(this)).IsSequential() &&
239          String::cast(this)->IsTwoByteRepresentation();
240 }
241 
242 
IsExternalString()243 bool Object::IsExternalString() {
244   if (!IsString()) return false;
245   return StringShape(String::cast(this)).IsExternal();
246 }
247 
248 
IsExternalAsciiString()249 bool Object::IsExternalAsciiString() {
250   if (!IsString()) return false;
251   return StringShape(String::cast(this)).IsExternal() &&
252          String::cast(this)->IsOneByteRepresentation();
253 }
254 
255 
IsExternalTwoByteString()256 bool Object::IsExternalTwoByteString() {
257   if (!IsString()) return false;
258   return StringShape(String::cast(this)).IsExternal() &&
259          String::cast(this)->IsTwoByteRepresentation();
260 }
261 
HasValidElements()262 bool Object::HasValidElements() {
263   // Dictionary is covered under FixedArray.
264   return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
265 }
266 
267 
AllocateNewStorageFor(Heap * heap,Representation representation)268 MaybeObject* Object::AllocateNewStorageFor(Heap* heap,
269                                            Representation representation) {
270   if (!FLAG_track_double_fields) return this;
271   if (!representation.IsDouble()) return this;
272   if (IsUninitialized()) {
273     return heap->AllocateHeapNumber(0);
274   }
275   return heap->AllocateHeapNumber(Number());
276 }
277 
278 
StringShape(String * str)279 StringShape::StringShape(String* str)
280   : type_(str->map()->instance_type()) {
281   set_valid();
282   ASSERT((type_ & kIsNotStringMask) == kStringTag);
283 }
284 
285 
StringShape(Map * map)286 StringShape::StringShape(Map* map)
287   : type_(map->instance_type()) {
288   set_valid();
289   ASSERT((type_ & kIsNotStringMask) == kStringTag);
290 }
291 
292 
StringShape(InstanceType t)293 StringShape::StringShape(InstanceType t)
294   : type_(static_cast<uint32_t>(t)) {
295   set_valid();
296   ASSERT((type_ & kIsNotStringMask) == kStringTag);
297 }
298 
299 
IsInternalized()300 bool StringShape::IsInternalized() {
301   ASSERT(valid());
302   STATIC_ASSERT(kNotInternalizedTag != 0);
303   return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
304       (kStringTag | kInternalizedTag);
305 }
306 
307 
IsOneByteRepresentation()308 bool String::IsOneByteRepresentation() {
309   uint32_t type = map()->instance_type();
310   return (type & kStringEncodingMask) == kOneByteStringTag;
311 }
312 
313 
IsTwoByteRepresentation()314 bool String::IsTwoByteRepresentation() {
315   uint32_t type = map()->instance_type();
316   return (type & kStringEncodingMask) == kTwoByteStringTag;
317 }
318 
319 
IsOneByteRepresentationUnderneath()320 bool String::IsOneByteRepresentationUnderneath() {
321   uint32_t type = map()->instance_type();
322   STATIC_ASSERT(kIsIndirectStringTag != 0);
323   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
324   ASSERT(IsFlat());
325   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
326     case kOneByteStringTag:
327       return true;
328     case kTwoByteStringTag:
329       return false;
330     default:  // Cons or sliced string.  Need to go deeper.
331       return GetUnderlying()->IsOneByteRepresentation();
332   }
333 }
334 
335 
IsTwoByteRepresentationUnderneath()336 bool String::IsTwoByteRepresentationUnderneath() {
337   uint32_t type = map()->instance_type();
338   STATIC_ASSERT(kIsIndirectStringTag != 0);
339   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
340   ASSERT(IsFlat());
341   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
342     case kOneByteStringTag:
343       return false;
344     case kTwoByteStringTag:
345       return true;
346     default:  // Cons or sliced string.  Need to go deeper.
347       return GetUnderlying()->IsTwoByteRepresentation();
348   }
349 }
350 
351 
HasOnlyOneByteChars()352 bool String::HasOnlyOneByteChars() {
353   uint32_t type = map()->instance_type();
354   return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
355          IsOneByteRepresentation();
356 }
357 
358 
IsCons()359 bool StringShape::IsCons() {
360   return (type_ & kStringRepresentationMask) == kConsStringTag;
361 }
362 
363 
IsSliced()364 bool StringShape::IsSliced() {
365   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
366 }
367 
368 
IsIndirect()369 bool StringShape::IsIndirect() {
370   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
371 }
372 
373 
IsExternal()374 bool StringShape::IsExternal() {
375   return (type_ & kStringRepresentationMask) == kExternalStringTag;
376 }
377 
378 
IsSequential()379 bool StringShape::IsSequential() {
380   return (type_ & kStringRepresentationMask) == kSeqStringTag;
381 }
382 
383 
representation_tag()384 StringRepresentationTag StringShape::representation_tag() {
385   uint32_t tag = (type_ & kStringRepresentationMask);
386   return static_cast<StringRepresentationTag>(tag);
387 }
388 
389 
encoding_tag()390 uint32_t StringShape::encoding_tag() {
391   return type_ & kStringEncodingMask;
392 }
393 
394 
full_representation_tag()395 uint32_t StringShape::full_representation_tag() {
396   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
397 }
398 
399 
400 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
401              Internals::kFullStringRepresentationMask);
402 
403 STATIC_CHECK(static_cast<uint32_t>(kStringEncodingMask) ==
404              Internals::kStringEncodingMask);
405 
406 
IsSequentialAscii()407 bool StringShape::IsSequentialAscii() {
408   return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
409 }
410 
411 
IsSequentialTwoByte()412 bool StringShape::IsSequentialTwoByte() {
413   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
414 }
415 
416 
IsExternalAscii()417 bool StringShape::IsExternalAscii() {
418   return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
419 }
420 
421 
422 STATIC_CHECK((kExternalStringTag | kOneByteStringTag) ==
423              Internals::kExternalAsciiRepresentationTag);
424 
425 STATIC_CHECK(v8::String::ASCII_ENCODING == kOneByteStringTag);
426 
427 
IsExternalTwoByte()428 bool StringShape::IsExternalTwoByte() {
429   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
430 }
431 
432 
433 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
434              Internals::kExternalTwoByteRepresentationTag);
435 
436 STATIC_CHECK(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
437 
Get(int index)438 uc32 FlatStringReader::Get(int index) {
439   ASSERT(0 <= index && index <= length_);
440   if (is_ascii_) {
441     return static_cast<const byte*>(start_)[index];
442   } else {
443     return static_cast<const uc16*>(start_)[index];
444   }
445 }
446 
447 
IsNumber()448 bool Object::IsNumber() {
449   return IsSmi() || IsHeapNumber();
450 }
451 
452 
TYPE_CHECKER(ByteArray,BYTE_ARRAY_TYPE)453 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
454 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
455 
456 
457 bool Object::IsFiller() {
458   if (!Object::IsHeapObject()) return false;
459   InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
460   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
461 }
462 
463 
TYPE_CHECKER(ExternalPixelArray,EXTERNAL_PIXEL_ARRAY_TYPE)464 TYPE_CHECKER(ExternalPixelArray, EXTERNAL_PIXEL_ARRAY_TYPE)
465 
466 
467 bool Object::IsExternalArray() {
468   if (!Object::IsHeapObject())
469     return false;
470   InstanceType instance_type =
471       HeapObject::cast(this)->map()->instance_type();
472   return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
473           instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
474 }
475 
476 
TYPE_CHECKER(ExternalByteArray,EXTERNAL_BYTE_ARRAY_TYPE)477 TYPE_CHECKER(ExternalByteArray, EXTERNAL_BYTE_ARRAY_TYPE)
478 TYPE_CHECKER(ExternalUnsignedByteArray, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
479 TYPE_CHECKER(ExternalShortArray, EXTERNAL_SHORT_ARRAY_TYPE)
480 TYPE_CHECKER(ExternalUnsignedShortArray, EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
481 TYPE_CHECKER(ExternalIntArray, EXTERNAL_INT_ARRAY_TYPE)
482 TYPE_CHECKER(ExternalUnsignedIntArray, EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
483 TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
484 TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
485 
486 
487 bool MaybeObject::IsFailure() {
488   return HAS_FAILURE_TAG(this);
489 }
490 
491 
IsRetryAfterGC()492 bool MaybeObject::IsRetryAfterGC() {
493   return HAS_FAILURE_TAG(this)
494     && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
495 }
496 
497 
IsOutOfMemory()498 bool MaybeObject::IsOutOfMemory() {
499   return HAS_FAILURE_TAG(this)
500       && Failure::cast(this)->IsOutOfMemoryException();
501 }
502 
503 
IsException()504 bool MaybeObject::IsException() {
505   return this == Failure::Exception();
506 }
507 
508 
IsTheHole()509 bool MaybeObject::IsTheHole() {
510   return !IsFailure() && ToObjectUnchecked()->IsTheHole();
511 }
512 
513 
IsUninitialized()514 bool MaybeObject::IsUninitialized() {
515   return !IsFailure() && ToObjectUnchecked()->IsUninitialized();
516 }
517 
518 
cast(MaybeObject * obj)519 Failure* Failure::cast(MaybeObject* obj) {
520   ASSERT(HAS_FAILURE_TAG(obj));
521   return reinterpret_cast<Failure*>(obj);
522 }
523 
524 
IsJSReceiver()525 bool Object::IsJSReceiver() {
526   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
527   return IsHeapObject() &&
528       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
529 }
530 
531 
IsJSObject()532 bool Object::IsJSObject() {
533   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
534   return IsHeapObject() &&
535       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
536 }
537 
538 
IsJSProxy()539 bool Object::IsJSProxy() {
540   if (!Object::IsHeapObject()) return false;
541   InstanceType type = HeapObject::cast(this)->map()->instance_type();
542   return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
543 }
544 
545 
TYPE_CHECKER(JSFunctionProxy,JS_FUNCTION_PROXY_TYPE)546 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
547 TYPE_CHECKER(JSSet, JS_SET_TYPE)
548 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
549 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
550 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
551 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
552 TYPE_CHECKER(Map, MAP_TYPE)
553 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
554 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
555 TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
556 
557 
558 bool Object::IsJSWeakCollection() {
559   return IsJSWeakMap() || IsJSWeakSet();
560 }
561 
562 
IsDescriptorArray()563 bool Object::IsDescriptorArray() {
564   return IsFixedArray();
565 }
566 
567 
IsTransitionArray()568 bool Object::IsTransitionArray() {
569   return IsFixedArray();
570 }
571 
572 
IsDeoptimizationInputData()573 bool Object::IsDeoptimizationInputData() {
574   // Must be a fixed array.
575   if (!IsFixedArray()) return false;
576 
577   // There's no sure way to detect the difference between a fixed array and
578   // a deoptimization data array.  Since this is used for asserts we can
579   // check that the length is zero or else the fixed size plus a multiple of
580   // the entry size.
581   int length = FixedArray::cast(this)->length();
582   if (length == 0) return true;
583 
584   length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
585   return length >= 0 &&
586       length % DeoptimizationInputData::kDeoptEntrySize == 0;
587 }
588 
589 
IsDeoptimizationOutputData()590 bool Object::IsDeoptimizationOutputData() {
591   if (!IsFixedArray()) return false;
592   // There's actually no way to see the difference between a fixed array and
593   // a deoptimization data array.  Since this is used for asserts we can check
594   // that the length is plausible though.
595   if (FixedArray::cast(this)->length() % 2 != 0) return false;
596   return true;
597 }
598 
599 
IsDependentCode()600 bool Object::IsDependentCode() {
601   if (!IsFixedArray()) return false;
602   // There's actually no way to see the difference between a fixed array and
603   // a dependent codes array.
604   return true;
605 }
606 
607 
IsTypeFeedbackCells()608 bool Object::IsTypeFeedbackCells() {
609   if (!IsFixedArray()) return false;
610   // There's actually no way to see the difference between a fixed array and
611   // a cache cells array.  Since this is used for asserts we can check that
612   // the length is plausible though.
613   if (FixedArray::cast(this)->length() % 2 != 0) return false;
614   return true;
615 }
616 
617 
IsContext()618 bool Object::IsContext() {
619   if (!Object::IsHeapObject()) return false;
620   Map* map = HeapObject::cast(this)->map();
621   Heap* heap = map->GetHeap();
622   return (map == heap->function_context_map() ||
623       map == heap->catch_context_map() ||
624       map == heap->with_context_map() ||
625       map == heap->native_context_map() ||
626       map == heap->block_context_map() ||
627       map == heap->module_context_map() ||
628       map == heap->global_context_map());
629 }
630 
631 
IsNativeContext()632 bool Object::IsNativeContext() {
633   return Object::IsHeapObject() &&
634       HeapObject::cast(this)->map() ==
635       HeapObject::cast(this)->GetHeap()->native_context_map();
636 }
637 
638 
IsScopeInfo()639 bool Object::IsScopeInfo() {
640   return Object::IsHeapObject() &&
641       HeapObject::cast(this)->map() ==
642       HeapObject::cast(this)->GetHeap()->scope_info_map();
643 }
644 
645 
TYPE_CHECKER(JSFunction,JS_FUNCTION_TYPE)646 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
647 
648 
649 template <> inline bool Is<JSFunction>(Object* obj) {
650   return obj->IsJSFunction();
651 }
652 
653 
TYPE_CHECKER(Code,CODE_TYPE)654 TYPE_CHECKER(Code, CODE_TYPE)
655 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
656 TYPE_CHECKER(Cell, CELL_TYPE)
657 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
658 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
659 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
660 TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
661 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
662 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
663 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
664 
665 
666 bool Object::IsStringWrapper() {
667   return IsJSValue() && JSValue::cast(this)->value()->IsString();
668 }
669 
670 
TYPE_CHECKER(Foreign,FOREIGN_TYPE)671 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
672 
673 
674 bool Object::IsBoolean() {
675   return IsOddball() &&
676       ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
677 }
678 
679 
TYPE_CHECKER(JSArray,JS_ARRAY_TYPE)680 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
681 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
682 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
683 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
684 
685 
686 bool Object::IsJSArrayBufferView() {
687   return IsJSDataView() || IsJSTypedArray();
688 }
689 
690 
TYPE_CHECKER(JSRegExp,JS_REGEXP_TYPE)691 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
692 
693 
694 template <> inline bool Is<JSArray>(Object* obj) {
695   return obj->IsJSArray();
696 }
697 
698 
IsHashTable()699 bool Object::IsHashTable() {
700   return Object::IsHeapObject() &&
701       HeapObject::cast(this)->map() ==
702       HeapObject::cast(this)->GetHeap()->hash_table_map();
703 }
704 
705 
IsDictionary()706 bool Object::IsDictionary() {
707   return IsHashTable() &&
708       this != HeapObject::cast(this)->GetHeap()->string_table();
709 }
710 
711 
IsStringTable()712 bool Object::IsStringTable() {
713   return IsHashTable() &&
714       this == HeapObject::cast(this)->GetHeap()->raw_unchecked_string_table();
715 }
716 
717 
IsJSFunctionResultCache()718 bool Object::IsJSFunctionResultCache() {
719   if (!IsFixedArray()) return false;
720   FixedArray* self = FixedArray::cast(this);
721   int length = self->length();
722   if (length < JSFunctionResultCache::kEntriesIndex) return false;
723   if ((length - JSFunctionResultCache::kEntriesIndex)
724       % JSFunctionResultCache::kEntrySize != 0) {
725     return false;
726   }
727 #ifdef VERIFY_HEAP
728   if (FLAG_verify_heap) {
729     reinterpret_cast<JSFunctionResultCache*>(this)->
730         JSFunctionResultCacheVerify();
731   }
732 #endif
733   return true;
734 }
735 
736 
IsNormalizedMapCache()737 bool Object::IsNormalizedMapCache() {
738   if (!IsFixedArray()) return false;
739   if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
740     return false;
741   }
742 #ifdef VERIFY_HEAP
743   if (FLAG_verify_heap) {
744     reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
745   }
746 #endif
747   return true;
748 }
749 
750 
IsCompilationCacheTable()751 bool Object::IsCompilationCacheTable() {
752   return IsHashTable();
753 }
754 
755 
IsCodeCacheHashTable()756 bool Object::IsCodeCacheHashTable() {
757   return IsHashTable();
758 }
759 
760 
IsPolymorphicCodeCacheHashTable()761 bool Object::IsPolymorphicCodeCacheHashTable() {
762   return IsHashTable();
763 }
764 
765 
IsMapCache()766 bool Object::IsMapCache() {
767   return IsHashTable();
768 }
769 
770 
IsObjectHashTable()771 bool Object::IsObjectHashTable() {
772   return IsHashTable();
773 }
774 
775 
IsPrimitive()776 bool Object::IsPrimitive() {
777   return IsOddball() || IsNumber() || IsString();
778 }
779 
780 
IsJSGlobalProxy()781 bool Object::IsJSGlobalProxy() {
782   bool result = IsHeapObject() &&
783                 (HeapObject::cast(this)->map()->instance_type() ==
784                  JS_GLOBAL_PROXY_TYPE);
785   ASSERT(!result || IsAccessCheckNeeded());
786   return result;
787 }
788 
789 
IsGlobalObject()790 bool Object::IsGlobalObject() {
791   if (!IsHeapObject()) return false;
792 
793   InstanceType type = HeapObject::cast(this)->map()->instance_type();
794   return type == JS_GLOBAL_OBJECT_TYPE ||
795          type == JS_BUILTINS_OBJECT_TYPE;
796 }
797 
798 
TYPE_CHECKER(JSGlobalObject,JS_GLOBAL_OBJECT_TYPE)799 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
800 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
801 
802 
803 bool Object::IsUndetectableObject() {
804   return IsHeapObject()
805     && HeapObject::cast(this)->map()->is_undetectable();
806 }
807 
808 
IsAccessCheckNeeded()809 bool Object::IsAccessCheckNeeded() {
810   return IsHeapObject()
811     && HeapObject::cast(this)->map()->is_access_check_needed();
812 }
813 
814 
IsStruct()815 bool Object::IsStruct() {
816   if (!IsHeapObject()) return false;
817   switch (HeapObject::cast(this)->map()->instance_type()) {
818 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
819   STRUCT_LIST(MAKE_STRUCT_CASE)
820 #undef MAKE_STRUCT_CASE
821     default: return false;
822   }
823 }
824 
825 
826 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
827   bool Object::Is##Name() {                                      \
828     return Object::IsHeapObject()                                \
829       && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
830   }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)831   STRUCT_LIST(MAKE_STRUCT_PREDICATE)
832 #undef MAKE_STRUCT_PREDICATE
833 
834 
835 bool Object::IsUndefined() {
836   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
837 }
838 
839 
IsNull()840 bool Object::IsNull() {
841   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
842 }
843 
844 
IsTheHole()845 bool Object::IsTheHole() {
846   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
847 }
848 
849 
IsUninitialized()850 bool Object::IsUninitialized() {
851   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
852 }
853 
854 
IsTrue()855 bool Object::IsTrue() {
856   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
857 }
858 
859 
IsFalse()860 bool Object::IsFalse() {
861   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
862 }
863 
864 
IsArgumentsMarker()865 bool Object::IsArgumentsMarker() {
866   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
867 }
868 
869 
Number()870 double Object::Number() {
871   ASSERT(IsNumber());
872   return IsSmi()
873     ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
874     : reinterpret_cast<HeapNumber*>(this)->value();
875 }
876 
877 
IsNaN()878 bool Object::IsNaN() {
879   return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
880 }
881 
882 
ToSmi()883 MaybeObject* Object::ToSmi() {
884   if (IsSmi()) return this;
885   if (IsHeapNumber()) {
886     double value = HeapNumber::cast(this)->value();
887     int int_value = FastD2I(value);
888     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
889       return Smi::FromInt(int_value);
890     }
891   }
892   return Failure::Exception();
893 }
894 
895 
HasSpecificClassOf(String * name)896 bool Object::HasSpecificClassOf(String* name) {
897   return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
898 }
899 
900 
GetElement(Isolate * isolate,uint32_t index)901 MaybeObject* Object::GetElement(Isolate* isolate, uint32_t index) {
902   // GetElement can trigger a getter which can cause allocation.
903   // This was not always the case. This ASSERT is here to catch
904   // leftover incorrect uses.
905   ASSERT(AllowHeapAllocation::IsAllowed());
906   return GetElementWithReceiver(isolate, this, index);
907 }
908 
909 
GetElementNoExceptionThrown(Isolate * isolate,uint32_t index)910 Object* Object::GetElementNoExceptionThrown(Isolate* isolate, uint32_t index) {
911   MaybeObject* maybe = GetElementWithReceiver(isolate, this, index);
912   ASSERT(!maybe->IsFailure());
913   Object* result = NULL;  // Initialization to please compiler.
914   maybe->ToObject(&result);
915   return result;
916 }
917 
918 
GetProperty(Name * key)919 MaybeObject* Object::GetProperty(Name* key) {
920   PropertyAttributes attributes;
921   return GetPropertyWithReceiver(this, key, &attributes);
922 }
923 
924 
GetProperty(Name * key,PropertyAttributes * attributes)925 MaybeObject* Object::GetProperty(Name* key, PropertyAttributes* attributes) {
926   return GetPropertyWithReceiver(this, key, attributes);
927 }
928 
929 
930 #define FIELD_ADDR(p, offset) \
931   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
932 
933 #define READ_FIELD(p, offset) \
934   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
935 
936 #define WRITE_FIELD(p, offset, value) \
937   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
938 
939 #define WRITE_BARRIER(heap, object, offset, value)                      \
940   heap->incremental_marking()->RecordWrite(                             \
941       object, HeapObject::RawField(object, offset), value);             \
942   if (heap->InNewSpace(value)) {                                        \
943     heap->RecordWrite(object->address(), offset);                       \
944   }
945 
946 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode)    \
947   if (mode == UPDATE_WRITE_BARRIER) {                                   \
948     heap->incremental_marking()->RecordWrite(                           \
949       object, HeapObject::RawField(object, offset), value);             \
950     if (heap->InNewSpace(value)) {                                      \
951       heap->RecordWrite(object->address(), offset);                     \
952     }                                                                   \
953   }
954 
955 #ifndef V8_TARGET_ARCH_MIPS
956   #define READ_DOUBLE_FIELD(p, offset) \
957     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
958 #else  // V8_TARGET_ARCH_MIPS
959   // Prevent gcc from using load-double (mips ldc1) on (possibly)
960   // non-64-bit aligned HeapNumber::value.
read_double_field(void * p,int offset)961   static inline double read_double_field(void* p, int offset) {
962     union conversion {
963       double d;
964       uint32_t u[2];
965     } c;
966     c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
967     c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
968     return c.d;
969   }
970   #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
971 #endif  // V8_TARGET_ARCH_MIPS
972 
973 #ifndef V8_TARGET_ARCH_MIPS
974   #define WRITE_DOUBLE_FIELD(p, offset, value) \
975     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
976 #else  // V8_TARGET_ARCH_MIPS
977   // Prevent gcc from using store-double (mips sdc1) on (possibly)
978   // non-64-bit aligned HeapNumber::value.
write_double_field(void * p,int offset,double value)979   static inline void write_double_field(void* p, int offset,
980                                         double value) {
981     union conversion {
982       double d;
983       uint32_t u[2];
984     } c;
985     c.d = value;
986     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
987     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
988   }
989   #define WRITE_DOUBLE_FIELD(p, offset, value) \
990     write_double_field(p, offset, value)
991 #endif  // V8_TARGET_ARCH_MIPS
992 
993 
994 #define READ_INT_FIELD(p, offset) \
995   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
996 
997 #define WRITE_INT_FIELD(p, offset, value) \
998   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
999 
1000 #define READ_INTPTR_FIELD(p, offset) \
1001   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
1002 
1003 #define WRITE_INTPTR_FIELD(p, offset, value) \
1004   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
1005 
1006 #define READ_UINT32_FIELD(p, offset) \
1007   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
1008 
1009 #define WRITE_UINT32_FIELD(p, offset, value) \
1010   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
1011 
1012 #define READ_INT32_FIELD(p, offset) \
1013   (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)))
1014 
1015 #define WRITE_INT32_FIELD(p, offset, value) \
1016   (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
1017 
1018 #define READ_INT64_FIELD(p, offset) \
1019   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)))
1020 
1021 #define WRITE_INT64_FIELD(p, offset, value) \
1022   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
1023 
1024 #define READ_SHORT_FIELD(p, offset) \
1025   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
1026 
1027 #define WRITE_SHORT_FIELD(p, offset, value) \
1028   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
1029 
1030 #define READ_BYTE_FIELD(p, offset) \
1031   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
1032 
1033 #define WRITE_BYTE_FIELD(p, offset, value) \
1034   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
1035 
1036 
RawField(HeapObject * obj,int byte_offset)1037 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
1038   return &READ_FIELD(obj, byte_offset);
1039 }
1040 
1041 
value()1042 int Smi::value() {
1043   return Internals::SmiValue(this);
1044 }
1045 
1046 
FromInt(int value)1047 Smi* Smi::FromInt(int value) {
1048   ASSERT(Smi::IsValid(value));
1049   return reinterpret_cast<Smi*>(Internals::IntToSmi(value));
1050 }
1051 
1052 
FromIntptr(intptr_t value)1053 Smi* Smi::FromIntptr(intptr_t value) {
1054   ASSERT(Smi::IsValid(value));
1055   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
1056   return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
1057 }
1058 
1059 
type()1060 Failure::Type Failure::type() const {
1061   return static_cast<Type>(value() & kFailureTypeTagMask);
1062 }
1063 
1064 
IsInternalError()1065 bool Failure::IsInternalError() const {
1066   return type() == INTERNAL_ERROR;
1067 }
1068 
1069 
IsOutOfMemoryException()1070 bool Failure::IsOutOfMemoryException() const {
1071   return type() == OUT_OF_MEMORY_EXCEPTION;
1072 }
1073 
1074 
allocation_space()1075 AllocationSpace Failure::allocation_space() const {
1076   ASSERT_EQ(RETRY_AFTER_GC, type());
1077   return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1078                                       & kSpaceTagMask);
1079 }
1080 
1081 
InternalError()1082 Failure* Failure::InternalError() {
1083   return Construct(INTERNAL_ERROR);
1084 }
1085 
1086 
Exception()1087 Failure* Failure::Exception() {
1088   return Construct(EXCEPTION);
1089 }
1090 
1091 
OutOfMemoryException(intptr_t value)1092 Failure* Failure::OutOfMemoryException(intptr_t value) {
1093   return Construct(OUT_OF_MEMORY_EXCEPTION, value);
1094 }
1095 
1096 
value()1097 intptr_t Failure::value() const {
1098   return static_cast<intptr_t>(
1099       reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
1100 }
1101 
1102 
RetryAfterGC()1103 Failure* Failure::RetryAfterGC() {
1104   return RetryAfterGC(NEW_SPACE);
1105 }
1106 
1107 
RetryAfterGC(AllocationSpace space)1108 Failure* Failure::RetryAfterGC(AllocationSpace space) {
1109   ASSERT((space & ~kSpaceTagMask) == 0);
1110   return Construct(RETRY_AFTER_GC, space);
1111 }
1112 
1113 
Construct(Type type,intptr_t value)1114 Failure* Failure::Construct(Type type, intptr_t value) {
1115   uintptr_t info =
1116       (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
1117   ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
1118   // Fill the unused bits with a pattern that's easy to recognize in crash
1119   // dumps.
1120   static const int kFailureMagicPattern = 0x0BAD0000;
1121   return reinterpret_cast<Failure*>(
1122       (info << kFailureTagSize) | kFailureTag | kFailureMagicPattern);
1123 }
1124 
1125 
IsValid(intptr_t value)1126 bool Smi::IsValid(intptr_t value) {
1127   bool result = Internals::IsValidSmi(value);
1128   ASSERT_EQ(result, value >= kMinValue && value <= kMaxValue);
1129   return result;
1130 }
1131 
1132 
FromMap(Map * map)1133 MapWord MapWord::FromMap(Map* map) {
1134   return MapWord(reinterpret_cast<uintptr_t>(map));
1135 }
1136 
1137 
ToMap()1138 Map* MapWord::ToMap() {
1139   return reinterpret_cast<Map*>(value_);
1140 }
1141 
1142 
IsForwardingAddress()1143 bool MapWord::IsForwardingAddress() {
1144   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1145 }
1146 
1147 
FromForwardingAddress(HeapObject * object)1148 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1149   Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1150   return MapWord(reinterpret_cast<uintptr_t>(raw));
1151 }
1152 
1153 
ToForwardingAddress()1154 HeapObject* MapWord::ToForwardingAddress() {
1155   ASSERT(IsForwardingAddress());
1156   return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1157 }
1158 
1159 
1160 #ifdef VERIFY_HEAP
VerifyObjectField(int offset)1161 void HeapObject::VerifyObjectField(int offset) {
1162   VerifyPointer(READ_FIELD(this, offset));
1163 }
1164 
VerifySmiField(int offset)1165 void HeapObject::VerifySmiField(int offset) {
1166   CHECK(READ_FIELD(this, offset)->IsSmi());
1167 }
1168 #endif
1169 
1170 
GetHeap()1171 Heap* HeapObject::GetHeap() {
1172   Heap* heap =
1173       MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1174   SLOW_ASSERT(heap != NULL);
1175   return heap;
1176 }
1177 
1178 
GetIsolate()1179 Isolate* HeapObject::GetIsolate() {
1180   return GetHeap()->isolate();
1181 }
1182 
1183 
map()1184 Map* HeapObject::map() {
1185   return map_word().ToMap();
1186 }
1187 
1188 
set_map(Map * value)1189 void HeapObject::set_map(Map* value) {
1190   set_map_word(MapWord::FromMap(value));
1191   if (value != NULL) {
1192     // TODO(1600) We are passing NULL as a slot because maps can never be on
1193     // evacuation candidate.
1194     value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1195   }
1196 }
1197 
1198 
1199 // Unsafe accessor omitting write barrier.
set_map_no_write_barrier(Map * value)1200 void HeapObject::set_map_no_write_barrier(Map* value) {
1201   set_map_word(MapWord::FromMap(value));
1202 }
1203 
1204 
map_word()1205 MapWord HeapObject::map_word() {
1206   return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1207 }
1208 
1209 
set_map_word(MapWord map_word)1210 void HeapObject::set_map_word(MapWord map_word) {
1211   // WRITE_FIELD does not invoke write barrier, but there is no need
1212   // here.
1213   WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1214 }
1215 
1216 
FromAddress(Address address)1217 HeapObject* HeapObject::FromAddress(Address address) {
1218   ASSERT_TAG_ALIGNED(address);
1219   return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1220 }
1221 
1222 
address()1223 Address HeapObject::address() {
1224   return reinterpret_cast<Address>(this) - kHeapObjectTag;
1225 }
1226 
1227 
Size()1228 int HeapObject::Size() {
1229   return SizeFromMap(map());
1230 }
1231 
1232 
IteratePointers(ObjectVisitor * v,int start,int end)1233 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1234   v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1235                    reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1236 }
1237 
1238 
IteratePointer(ObjectVisitor * v,int offset)1239 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1240   v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1241 }
1242 
1243 
value()1244 double HeapNumber::value() {
1245   return READ_DOUBLE_FIELD(this, kValueOffset);
1246 }
1247 
1248 
set_value(double value)1249 void HeapNumber::set_value(double value) {
1250   WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1251 }
1252 
1253 
get_exponent()1254 int HeapNumber::get_exponent() {
1255   return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1256           kExponentShift) - kExponentBias;
1257 }
1258 
1259 
get_sign()1260 int HeapNumber::get_sign() {
1261   return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1262 }
1263 
1264 
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1265 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1266 
1267 
1268 Object** FixedArray::GetFirstElementAddress() {
1269   return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1270 }
1271 
1272 
ContainsOnlySmisOrHoles()1273 bool FixedArray::ContainsOnlySmisOrHoles() {
1274   Object* the_hole = GetHeap()->the_hole_value();
1275   Object** current = GetFirstElementAddress();
1276   for (int i = 0; i < length(); ++i) {
1277     Object* candidate = *current++;
1278     if (!candidate->IsSmi() && candidate != the_hole) return false;
1279   }
1280   return true;
1281 }
1282 
1283 
elements()1284 FixedArrayBase* JSObject::elements() {
1285   Object* array = READ_FIELD(this, kElementsOffset);
1286   return static_cast<FixedArrayBase*>(array);
1287 }
1288 
1289 
ValidateElements()1290 void JSObject::ValidateElements() {
1291 #ifdef ENABLE_SLOW_ASSERTS
1292   if (FLAG_enable_slow_asserts) {
1293     ElementsAccessor* accessor = GetElementsAccessor();
1294     accessor->Validate(this);
1295   }
1296 #endif
1297 }
1298 
1299 
ShouldTrackAllocationInfo()1300 bool JSObject::ShouldTrackAllocationInfo() {
1301   if (AllocationSite::CanTrack(map()->instance_type())) {
1302     if (!IsJSArray()) {
1303       return true;
1304     }
1305 
1306     return AllocationSite::GetMode(GetElementsKind()) ==
1307         TRACK_ALLOCATION_SITE;
1308   }
1309   return false;
1310 }
1311 
1312 
Initialize()1313 void AllocationSite::Initialize() {
1314   set_transition_info(Smi::FromInt(0));
1315   SetElementsKind(GetInitialFastElementsKind());
1316   set_nested_site(Smi::FromInt(0));
1317   set_memento_create_count(Smi::FromInt(0));
1318   set_memento_found_count(Smi::FromInt(0));
1319   set_pretenure_decision(Smi::FromInt(0));
1320   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1321                      SKIP_WRITE_BARRIER);
1322 }
1323 
1324 
MarkZombie()1325 void AllocationSite::MarkZombie() {
1326   ASSERT(!IsZombie());
1327   set_pretenure_decision(Smi::FromInt(kZombie));
1328   // Clear all non-smi fields
1329   set_transition_info(Smi::FromInt(0));
1330   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1331                      SKIP_WRITE_BARRIER);
1332 }
1333 
1334 
1335 // Heuristic: We only need to create allocation site info if the boilerplate
1336 // elements kind is the initial elements kind.
GetMode(ElementsKind boilerplate_elements_kind)1337 AllocationSiteMode AllocationSite::GetMode(
1338     ElementsKind boilerplate_elements_kind) {
1339   if (FLAG_track_allocation_sites &&
1340       IsFastSmiElementsKind(boilerplate_elements_kind)) {
1341     return TRACK_ALLOCATION_SITE;
1342   }
1343 
1344   return DONT_TRACK_ALLOCATION_SITE;
1345 }
1346 
1347 
GetMode(ElementsKind from,ElementsKind to)1348 AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
1349                                            ElementsKind to) {
1350   if (FLAG_track_allocation_sites &&
1351       IsFastSmiElementsKind(from) &&
1352       IsMoreGeneralElementsKindTransition(from, to)) {
1353     return TRACK_ALLOCATION_SITE;
1354   }
1355 
1356   return DONT_TRACK_ALLOCATION_SITE;
1357 }
1358 
1359 
CanTrack(InstanceType type)1360 inline bool AllocationSite::CanTrack(InstanceType type) {
1361   if (FLAG_allocation_site_pretenuring) {
1362     return type == JS_ARRAY_TYPE || type == JS_OBJECT_TYPE;
1363   }
1364   return type == JS_ARRAY_TYPE;
1365 }
1366 
1367 
ToDependencyGroup(Reason reason)1368 inline DependentCode::DependencyGroup AllocationSite::ToDependencyGroup(
1369     Reason reason) {
1370   switch (reason) {
1371     case TENURING:
1372       return DependentCode::kAllocationSiteTenuringChangedGroup;
1373       break;
1374     case TRANSITIONS:
1375       return DependentCode::kAllocationSiteTransitionChangedGroup;
1376       break;
1377   }
1378   UNREACHABLE();
1379   return DependentCode::kAllocationSiteTransitionChangedGroup;
1380 }
1381 
1382 
IncrementMementoFoundCount()1383 inline void AllocationSite::IncrementMementoFoundCount() {
1384   int value = memento_found_count()->value();
1385   set_memento_found_count(Smi::FromInt(value + 1));
1386 }
1387 
1388 
IncrementMementoCreateCount()1389 inline void AllocationSite::IncrementMementoCreateCount() {
1390   ASSERT(FLAG_allocation_site_pretenuring);
1391   int value = memento_create_count()->value();
1392   set_memento_create_count(Smi::FromInt(value + 1));
1393 }
1394 
1395 
DigestPretenuringFeedback()1396 inline bool AllocationSite::DigestPretenuringFeedback() {
1397   bool decision_made = false;
1398   if (!PretenuringDecisionMade()) {
1399     int create_count = memento_create_count()->value();
1400     if (create_count >= kPretenureMinimumCreated) {
1401       int found_count = memento_found_count()->value();
1402       double ratio = static_cast<double>(found_count) / create_count;
1403       if (FLAG_trace_track_allocation_sites) {
1404         PrintF("AllocationSite: %p (created, found, ratio) (%d, %d, %f)\n",
1405                static_cast<void*>(this), create_count, found_count, ratio);
1406       }
1407       int result = ratio >= kPretenureRatio ? kTenure : kDontTenure;
1408       set_pretenure_decision(Smi::FromInt(result));
1409       decision_made = true;
1410       // TODO(mvstanton): if the decision represents a change, any dependent
1411       // code registered for pretenuring changes should be deopted.
1412     }
1413   }
1414 
1415   // Clear feedback calculation fields until the next gc.
1416   set_memento_found_count(Smi::FromInt(0));
1417   set_memento_create_count(Smi::FromInt(0));
1418   return decision_made;
1419 }
1420 
1421 
EnsureCanContainHeapObjectElements(Handle<JSObject> object)1422 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1423   object->ValidateElements();
1424   ElementsKind elements_kind = object->map()->elements_kind();
1425   if (!IsFastObjectElementsKind(elements_kind)) {
1426     if (IsFastHoleyElementsKind(elements_kind)) {
1427       TransitionElementsKind(object, FAST_HOLEY_ELEMENTS);
1428     } else {
1429       TransitionElementsKind(object, FAST_ELEMENTS);
1430     }
1431   }
1432 }
1433 
1434 
EnsureCanContainElements(Object ** objects,uint32_t count,EnsureElementsMode mode)1435 MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1436                                                 uint32_t count,
1437                                                 EnsureElementsMode mode) {
1438   ElementsKind current_kind = map()->elements_kind();
1439   ElementsKind target_kind = current_kind;
1440   ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1441   bool is_holey = IsFastHoleyElementsKind(current_kind);
1442   if (current_kind == FAST_HOLEY_ELEMENTS) return this;
1443   Heap* heap = GetHeap();
1444   Object* the_hole = heap->the_hole_value();
1445   for (uint32_t i = 0; i < count; ++i) {
1446     Object* current = *objects++;
1447     if (current == the_hole) {
1448       is_holey = true;
1449       target_kind = GetHoleyElementsKind(target_kind);
1450     } else if (!current->IsSmi()) {
1451       if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1452         if (IsFastSmiElementsKind(target_kind)) {
1453           if (is_holey) {
1454             target_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
1455           } else {
1456             target_kind = FAST_DOUBLE_ELEMENTS;
1457           }
1458         }
1459       } else if (is_holey) {
1460         target_kind = FAST_HOLEY_ELEMENTS;
1461         break;
1462       } else {
1463         target_kind = FAST_ELEMENTS;
1464       }
1465     }
1466   }
1467 
1468   if (target_kind != current_kind) {
1469     return TransitionElementsKind(target_kind);
1470   }
1471   return this;
1472 }
1473 
1474 
EnsureCanContainElements(FixedArrayBase * elements,uint32_t length,EnsureElementsMode mode)1475 MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements,
1476                                                 uint32_t length,
1477                                                 EnsureElementsMode mode) {
1478   if (elements->map() != GetHeap()->fixed_double_array_map()) {
1479     ASSERT(elements->map() == GetHeap()->fixed_array_map() ||
1480            elements->map() == GetHeap()->fixed_cow_array_map());
1481     if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1482       mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1483     }
1484     Object** objects = FixedArray::cast(elements)->GetFirstElementAddress();
1485     return EnsureCanContainElements(objects, length, mode);
1486   }
1487 
1488   ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1489   if (GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) {
1490     return TransitionElementsKind(FAST_HOLEY_DOUBLE_ELEMENTS);
1491   } else if (GetElementsKind() == FAST_SMI_ELEMENTS) {
1492     FixedDoubleArray* double_array = FixedDoubleArray::cast(elements);
1493     for (uint32_t i = 0; i < length; ++i) {
1494       if (double_array->is_the_hole(i)) {
1495         return TransitionElementsKind(FAST_HOLEY_DOUBLE_ELEMENTS);
1496       }
1497     }
1498     return TransitionElementsKind(FAST_DOUBLE_ELEMENTS);
1499   }
1500 
1501   return this;
1502 }
1503 
1504 
GetElementsTransitionMap(Isolate * isolate,ElementsKind to_kind)1505 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate,
1506                                                 ElementsKind to_kind) {
1507   Map* current_map = map();
1508   ElementsKind from_kind = current_map->elements_kind();
1509   if (from_kind == to_kind) return current_map;
1510 
1511   Context* native_context = isolate->context()->native_context();
1512   Object* maybe_array_maps = native_context->js_array_maps();
1513   if (maybe_array_maps->IsFixedArray()) {
1514     FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
1515     if (array_maps->get(from_kind) == current_map) {
1516       Object* maybe_transitioned_map = array_maps->get(to_kind);
1517       if (maybe_transitioned_map->IsMap()) {
1518         return Map::cast(maybe_transitioned_map);
1519       }
1520     }
1521   }
1522 
1523   return GetElementsTransitionMapSlow(to_kind);
1524 }
1525 
1526 
set_map_and_elements(Map * new_map,FixedArrayBase * value,WriteBarrierMode mode)1527 void JSObject::set_map_and_elements(Map* new_map,
1528                                     FixedArrayBase* value,
1529                                     WriteBarrierMode mode) {
1530   ASSERT(value->HasValidElements());
1531   if (new_map != NULL) {
1532     if (mode == UPDATE_WRITE_BARRIER) {
1533       set_map(new_map);
1534     } else {
1535       ASSERT(mode == SKIP_WRITE_BARRIER);
1536       set_map_no_write_barrier(new_map);
1537     }
1538   }
1539   ASSERT((map()->has_fast_smi_or_object_elements() ||
1540           (value == GetHeap()->empty_fixed_array())) ==
1541          (value->map() == GetHeap()->fixed_array_map() ||
1542           value->map() == GetHeap()->fixed_cow_array_map()));
1543   ASSERT((value == GetHeap()->empty_fixed_array()) ||
1544          (map()->has_fast_double_elements() == value->IsFixedDoubleArray()));
1545   WRITE_FIELD(this, kElementsOffset, value);
1546   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1547 }
1548 
1549 
set_elements(FixedArrayBase * value,WriteBarrierMode mode)1550 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1551   set_map_and_elements(NULL, value, mode);
1552 }
1553 
1554 
initialize_properties()1555 void JSObject::initialize_properties() {
1556   ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1557   WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1558 }
1559 
1560 
initialize_elements()1561 void JSObject::initialize_elements() {
1562   if (map()->has_fast_smi_or_object_elements() ||
1563       map()->has_fast_double_elements()) {
1564     ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1565     WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
1566   } else if (map()->has_external_array_elements()) {
1567     ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(map());
1568     ASSERT(!GetHeap()->InNewSpace(empty_array));
1569     WRITE_FIELD(this, kElementsOffset, empty_array);
1570   } else {
1571     UNREACHABLE();
1572   }
1573 }
1574 
1575 
ResetElements()1576 MaybeObject* JSObject::ResetElements() {
1577   if (map()->is_observed()) {
1578     // Maintain invariant that observed elements are always in dictionary mode.
1579     SeededNumberDictionary* dictionary;
1580     MaybeObject* maybe = SeededNumberDictionary::Allocate(GetHeap(), 0);
1581     if (!maybe->To(&dictionary)) return maybe;
1582     if (map() == GetHeap()->non_strict_arguments_elements_map()) {
1583       FixedArray::cast(elements())->set(1, dictionary);
1584     } else {
1585       set_elements(dictionary);
1586     }
1587     return this;
1588   }
1589 
1590   ElementsKind elements_kind = GetInitialFastElementsKind();
1591   if (!FLAG_smi_only_arrays) {
1592     elements_kind = FastSmiToObjectElementsKind(elements_kind);
1593   }
1594   MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
1595   Map* map;
1596   if (!maybe->To(&map)) return maybe;
1597   set_map(map);
1598   initialize_elements();
1599 
1600   return this;
1601 }
1602 
1603 
ExpectedTransitionKey(Handle<Map> map)1604 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) {
1605   DisallowHeapAllocation no_gc;
1606   if (!map->HasTransitionArray()) return Handle<String>::null();
1607   TransitionArray* transitions = map->transitions();
1608   if (!transitions->IsSimpleTransition()) return Handle<String>::null();
1609   int transition = TransitionArray::kSimpleTransitionIndex;
1610   PropertyDetails details = transitions->GetTargetDetails(transition);
1611   Name* name = transitions->GetKey(transition);
1612   if (details.type() != FIELD) return Handle<String>::null();
1613   if (details.attributes() != NONE) return Handle<String>::null();
1614   if (!name->IsString()) return Handle<String>::null();
1615   return Handle<String>(String::cast(name));
1616 }
1617 
1618 
ExpectedTransitionTarget(Handle<Map> map)1619 Handle<Map> JSObject::ExpectedTransitionTarget(Handle<Map> map) {
1620   ASSERT(!ExpectedTransitionKey(map).is_null());
1621   return Handle<Map>(map->transitions()->GetTarget(
1622       TransitionArray::kSimpleTransitionIndex));
1623 }
1624 
1625 
FindTransitionToField(Handle<Map> map,Handle<Name> key)1626 Handle<Map> JSObject::FindTransitionToField(Handle<Map> map, Handle<Name> key) {
1627   DisallowHeapAllocation no_allocation;
1628   if (!map->HasTransitionArray()) return Handle<Map>::null();
1629   TransitionArray* transitions = map->transitions();
1630   int transition = transitions->Search(*key);
1631   if (transition == TransitionArray::kNotFound) return Handle<Map>::null();
1632   PropertyDetails target_details = transitions->GetTargetDetails(transition);
1633   if (target_details.type() != FIELD) return Handle<Map>::null();
1634   if (target_details.attributes() != NONE) return Handle<Map>::null();
1635   return Handle<Map>(transitions->GetTarget(transition));
1636 }
1637 
1638 
ACCESSORS(Oddball,to_string,String,kToStringOffset)1639 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1640 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1641 
1642 
1643 byte Oddball::kind() {
1644   return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1645 }
1646 
1647 
set_kind(byte value)1648 void Oddball::set_kind(byte value) {
1649   WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1650 }
1651 
1652 
value()1653 Object* Cell::value() {
1654   return READ_FIELD(this, kValueOffset);
1655 }
1656 
1657 
set_value(Object * val,WriteBarrierMode ignored)1658 void Cell::set_value(Object* val, WriteBarrierMode ignored) {
1659   // The write barrier is not used for global property cells.
1660   ASSERT(!val->IsPropertyCell() && !val->IsCell());
1661   WRITE_FIELD(this, kValueOffset, val);
1662 }
1663 
ACCESSORS(PropertyCell,dependent_code,DependentCode,kDependentCodeOffset)1664 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1665 
1666 Object* PropertyCell::type_raw() {
1667   return READ_FIELD(this, kTypeOffset);
1668 }
1669 
1670 
set_type_raw(Object * val,WriteBarrierMode ignored)1671 void PropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
1672   WRITE_FIELD(this, kTypeOffset, val);
1673 }
1674 
1675 
GetHeaderSize()1676 int JSObject::GetHeaderSize() {
1677   InstanceType type = map()->instance_type();
1678   // Check for the most common kind of JavaScript object before
1679   // falling into the generic switch. This speeds up the internal
1680   // field operations considerably on average.
1681   if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1682   switch (type) {
1683     case JS_GENERATOR_OBJECT_TYPE:
1684       return JSGeneratorObject::kSize;
1685     case JS_MODULE_TYPE:
1686       return JSModule::kSize;
1687     case JS_GLOBAL_PROXY_TYPE:
1688       return JSGlobalProxy::kSize;
1689     case JS_GLOBAL_OBJECT_TYPE:
1690       return JSGlobalObject::kSize;
1691     case JS_BUILTINS_OBJECT_TYPE:
1692       return JSBuiltinsObject::kSize;
1693     case JS_FUNCTION_TYPE:
1694       return JSFunction::kSize;
1695     case JS_VALUE_TYPE:
1696       return JSValue::kSize;
1697     case JS_DATE_TYPE:
1698       return JSDate::kSize;
1699     case JS_ARRAY_TYPE:
1700       return JSArray::kSize;
1701     case JS_ARRAY_BUFFER_TYPE:
1702       return JSArrayBuffer::kSize;
1703     case JS_TYPED_ARRAY_TYPE:
1704       return JSTypedArray::kSize;
1705     case JS_DATA_VIEW_TYPE:
1706       return JSDataView::kSize;
1707     case JS_SET_TYPE:
1708       return JSSet::kSize;
1709     case JS_MAP_TYPE:
1710       return JSMap::kSize;
1711     case JS_WEAK_MAP_TYPE:
1712       return JSWeakMap::kSize;
1713     case JS_WEAK_SET_TYPE:
1714       return JSWeakSet::kSize;
1715     case JS_REGEXP_TYPE:
1716       return JSRegExp::kSize;
1717     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1718       return JSObject::kHeaderSize;
1719     case JS_MESSAGE_OBJECT_TYPE:
1720       return JSMessageObject::kSize;
1721     default:
1722       // TODO(jkummerow): Re-enable this. Blink currently hits this
1723       // from its CustomElementConstructorBuilder.
1724       // UNREACHABLE();
1725       return 0;
1726   }
1727 }
1728 
1729 
GetInternalFieldCount()1730 int JSObject::GetInternalFieldCount() {
1731   ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1732   // Make sure to adjust for the number of in-object properties. These
1733   // properties do contribute to the size, but are not internal fields.
1734   return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1735          map()->inobject_properties();
1736 }
1737 
1738 
GetInternalFieldOffset(int index)1739 int JSObject::GetInternalFieldOffset(int index) {
1740   ASSERT(index < GetInternalFieldCount() && index >= 0);
1741   return GetHeaderSize() + (kPointerSize * index);
1742 }
1743 
1744 
GetInternalField(int index)1745 Object* JSObject::GetInternalField(int index) {
1746   ASSERT(index < GetInternalFieldCount() && index >= 0);
1747   // Internal objects do follow immediately after the header, whereas in-object
1748   // properties are at the end of the object. Therefore there is no need
1749   // to adjust the index here.
1750   return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1751 }
1752 
1753 
SetInternalField(int index,Object * value)1754 void JSObject::SetInternalField(int index, Object* value) {
1755   ASSERT(index < GetInternalFieldCount() && index >= 0);
1756   // Internal objects do follow immediately after the header, whereas in-object
1757   // properties are at the end of the object. Therefore there is no need
1758   // to adjust the index here.
1759   int offset = GetHeaderSize() + (kPointerSize * index);
1760   WRITE_FIELD(this, offset, value);
1761   WRITE_BARRIER(GetHeap(), this, offset, value);
1762 }
1763 
1764 
SetInternalField(int index,Smi * value)1765 void JSObject::SetInternalField(int index, Smi* value) {
1766   ASSERT(index < GetInternalFieldCount() && index >= 0);
1767   // Internal objects do follow immediately after the header, whereas in-object
1768   // properties are at the end of the object. Therefore there is no need
1769   // to adjust the index here.
1770   int offset = GetHeaderSize() + (kPointerSize * index);
1771   WRITE_FIELD(this, offset, value);
1772 }
1773 
1774 
FastPropertyAt(Representation representation,int index)1775 MaybeObject* JSObject::FastPropertyAt(Representation representation,
1776                                       int index) {
1777   Object* raw_value = RawFastPropertyAt(index);
1778   return raw_value->AllocateNewStorageFor(GetHeap(), representation);
1779 }
1780 
1781 
1782 // Access fast-case object properties at index. The use of these routines
1783 // is needed to correctly distinguish between properties stored in-object and
1784 // properties stored in the properties array.
RawFastPropertyAt(int index)1785 Object* JSObject::RawFastPropertyAt(int index) {
1786   // Adjust for the number of properties stored in the object.
1787   index -= map()->inobject_properties();
1788   if (index < 0) {
1789     int offset = map()->instance_size() + (index * kPointerSize);
1790     return READ_FIELD(this, offset);
1791   } else {
1792     ASSERT(index < properties()->length());
1793     return properties()->get(index);
1794   }
1795 }
1796 
1797 
FastPropertyAtPut(int index,Object * value)1798 void JSObject::FastPropertyAtPut(int index, Object* value) {
1799   // Adjust for the number of properties stored in the object.
1800   index -= map()->inobject_properties();
1801   if (index < 0) {
1802     int offset = map()->instance_size() + (index * kPointerSize);
1803     WRITE_FIELD(this, offset, value);
1804     WRITE_BARRIER(GetHeap(), this, offset, value);
1805   } else {
1806     ASSERT(index < properties()->length());
1807     properties()->set(index, value);
1808   }
1809 }
1810 
1811 
GetInObjectPropertyOffset(int index)1812 int JSObject::GetInObjectPropertyOffset(int index) {
1813   // Adjust for the number of properties stored in the object.
1814   index -= map()->inobject_properties();
1815   ASSERT(index < 0);
1816   return map()->instance_size() + (index * kPointerSize);
1817 }
1818 
1819 
InObjectPropertyAt(int index)1820 Object* JSObject::InObjectPropertyAt(int index) {
1821   // Adjust for the number of properties stored in the object.
1822   index -= map()->inobject_properties();
1823   ASSERT(index < 0);
1824   int offset = map()->instance_size() + (index * kPointerSize);
1825   return READ_FIELD(this, offset);
1826 }
1827 
1828 
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1829 Object* JSObject::InObjectPropertyAtPut(int index,
1830                                         Object* value,
1831                                         WriteBarrierMode mode) {
1832   // Adjust for the number of properties stored in the object.
1833   index -= map()->inobject_properties();
1834   ASSERT(index < 0);
1835   int offset = map()->instance_size() + (index * kPointerSize);
1836   WRITE_FIELD(this, offset, value);
1837   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1838   return value;
1839 }
1840 
1841 
1842 
InitializeBody(Map * map,Object * pre_allocated_value,Object * filler_value)1843 void JSObject::InitializeBody(Map* map,
1844                               Object* pre_allocated_value,
1845                               Object* filler_value) {
1846   ASSERT(!filler_value->IsHeapObject() ||
1847          !GetHeap()->InNewSpace(filler_value));
1848   ASSERT(!pre_allocated_value->IsHeapObject() ||
1849          !GetHeap()->InNewSpace(pre_allocated_value));
1850   int size = map->instance_size();
1851   int offset = kHeaderSize;
1852   if (filler_value != pre_allocated_value) {
1853     int pre_allocated = map->pre_allocated_property_fields();
1854     ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1855     for (int i = 0; i < pre_allocated; i++) {
1856       WRITE_FIELD(this, offset, pre_allocated_value);
1857       offset += kPointerSize;
1858     }
1859   }
1860   while (offset < size) {
1861     WRITE_FIELD(this, offset, filler_value);
1862     offset += kPointerSize;
1863   }
1864 }
1865 
1866 
HasFastProperties()1867 bool JSObject::HasFastProperties() {
1868   ASSERT(properties()->IsDictionary() == map()->is_dictionary_map());
1869   return !properties()->IsDictionary();
1870 }
1871 
1872 
TooManyFastProperties(StoreFromKeyed store_mode)1873 bool JSObject::TooManyFastProperties(StoreFromKeyed store_mode) {
1874   // Allow extra fast properties if the object has more than
1875   // kFastPropertiesSoftLimit in-object properties. When this is the case, it is
1876   // very unlikely that the object is being used as a dictionary and there is a
1877   // good chance that allowing more map transitions will be worth it.
1878   Map* map = this->map();
1879   if (map->unused_property_fields() != 0) return false;
1880 
1881   int inobject = map->inobject_properties();
1882 
1883   int limit;
1884   if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED) {
1885     limit = Max(inobject, kMaxFastProperties);
1886   } else {
1887     limit = Max(inobject, kFastPropertiesSoftLimit);
1888   }
1889   return properties()->length() > limit;
1890 }
1891 
1892 
InitializeBody(int object_size)1893 void Struct::InitializeBody(int object_size) {
1894   Object* value = GetHeap()->undefined_value();
1895   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1896     WRITE_FIELD(this, offset, value);
1897   }
1898 }
1899 
1900 
ToArrayIndex(uint32_t * index)1901 bool Object::ToArrayIndex(uint32_t* index) {
1902   if (IsSmi()) {
1903     int value = Smi::cast(this)->value();
1904     if (value < 0) return false;
1905     *index = value;
1906     return true;
1907   }
1908   if (IsHeapNumber()) {
1909     double value = HeapNumber::cast(this)->value();
1910     uint32_t uint_value = static_cast<uint32_t>(value);
1911     if (value == static_cast<double>(uint_value)) {
1912       *index = uint_value;
1913       return true;
1914     }
1915   }
1916   return false;
1917 }
1918 
1919 
IsStringObjectWithCharacterAt(uint32_t index)1920 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1921   if (!this->IsJSValue()) return false;
1922 
1923   JSValue* js_value = JSValue::cast(this);
1924   if (!js_value->value()->IsString()) return false;
1925 
1926   String* str = String::cast(js_value->value());
1927   if (index >= static_cast<uint32_t>(str->length())) return false;
1928 
1929   return true;
1930 }
1931 
1932 
1933 
VerifyApiCallResultType()1934 void Object::VerifyApiCallResultType() {
1935 #if ENABLE_EXTRA_CHECKS
1936   if (!(IsSmi() ||
1937         IsString() ||
1938         IsSpecObject() ||
1939         IsHeapNumber() ||
1940         IsUndefined() ||
1941         IsTrue() ||
1942         IsFalse() ||
1943         IsNull())) {
1944     FATAL("API call returned invalid object");
1945   }
1946 #endif  // ENABLE_EXTRA_CHECKS
1947 }
1948 
1949 
cast(Object * object)1950 FixedArrayBase* FixedArrayBase::cast(Object* object) {
1951   ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray() ||
1952          object->IsConstantPoolArray());
1953   return reinterpret_cast<FixedArrayBase*>(object);
1954 }
1955 
1956 
get(int index)1957 Object* FixedArray::get(int index) {
1958   SLOW_ASSERT(index >= 0 && index < this->length());
1959   return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1960 }
1961 
1962 
is_the_hole(int index)1963 bool FixedArray::is_the_hole(int index) {
1964   return get(index) == GetHeap()->the_hole_value();
1965 }
1966 
1967 
set(int index,Smi * value)1968 void FixedArray::set(int index, Smi* value) {
1969   ASSERT(map() != GetHeap()->fixed_cow_array_map());
1970   ASSERT(index >= 0 && index < this->length());
1971   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1972   int offset = kHeaderSize + index * kPointerSize;
1973   WRITE_FIELD(this, offset, value);
1974 }
1975 
1976 
set(int index,Object * value)1977 void FixedArray::set(int index, Object* value) {
1978   ASSERT(map() != GetHeap()->fixed_cow_array_map());
1979   ASSERT(index >= 0 && index < this->length());
1980   int offset = kHeaderSize + index * kPointerSize;
1981   WRITE_FIELD(this, offset, value);
1982   WRITE_BARRIER(GetHeap(), this, offset, value);
1983 }
1984 
1985 
is_the_hole_nan(double value)1986 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1987   return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1988 }
1989 
1990 
hole_nan_as_double()1991 inline double FixedDoubleArray::hole_nan_as_double() {
1992   return BitCast<double, uint64_t>(kHoleNanInt64);
1993 }
1994 
1995 
canonical_not_the_hole_nan_as_double()1996 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1997   ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1998   ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1999   return OS::nan_value();
2000 }
2001 
2002 
get_scalar(int index)2003 double FixedDoubleArray::get_scalar(int index) {
2004   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2005          map() != GetHeap()->fixed_array_map());
2006   ASSERT(index >= 0 && index < this->length());
2007   double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
2008   ASSERT(!is_the_hole_nan(result));
2009   return result;
2010 }
2011 
get_representation(int index)2012 int64_t FixedDoubleArray::get_representation(int index) {
2013   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2014          map() != GetHeap()->fixed_array_map());
2015   ASSERT(index >= 0 && index < this->length());
2016   return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
2017 }
2018 
get(int index)2019 MaybeObject* FixedDoubleArray::get(int index) {
2020   if (is_the_hole(index)) {
2021     return GetHeap()->the_hole_value();
2022   } else {
2023     return GetHeap()->NumberFromDouble(get_scalar(index));
2024   }
2025 }
2026 
2027 
set(int index,double value)2028 void FixedDoubleArray::set(int index, double value) {
2029   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2030          map() != GetHeap()->fixed_array_map());
2031   int offset = kHeaderSize + index * kDoubleSize;
2032   if (std::isnan(value)) value = canonical_not_the_hole_nan_as_double();
2033   WRITE_DOUBLE_FIELD(this, offset, value);
2034 }
2035 
2036 
set_the_hole(int index)2037 void FixedDoubleArray::set_the_hole(int index) {
2038   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2039          map() != GetHeap()->fixed_array_map());
2040   int offset = kHeaderSize + index * kDoubleSize;
2041   WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
2042 }
2043 
2044 
is_the_hole(int index)2045 bool FixedDoubleArray::is_the_hole(int index) {
2046   int offset = kHeaderSize + index * kDoubleSize;
2047   return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
2048 }
2049 
2050 
SMI_ACCESSORS(ConstantPoolArray,first_ptr_index,kFirstPointerIndexOffset)2051 SMI_ACCESSORS(ConstantPoolArray, first_ptr_index, kFirstPointerIndexOffset)
2052 SMI_ACCESSORS(ConstantPoolArray, first_int32_index, kFirstInt32IndexOffset)
2053 
2054 
2055 int ConstantPoolArray::first_int64_index() {
2056   return 0;
2057 }
2058 
2059 
count_of_int64_entries()2060 int ConstantPoolArray::count_of_int64_entries() {
2061   return first_ptr_index();
2062 }
2063 
2064 
count_of_ptr_entries()2065 int ConstantPoolArray::count_of_ptr_entries() {
2066   return first_int32_index() - first_ptr_index();
2067 }
2068 
2069 
count_of_int32_entries()2070 int ConstantPoolArray::count_of_int32_entries() {
2071   return length() - first_int32_index();
2072 }
2073 
2074 
SetEntryCounts(int number_of_int64_entries,int number_of_ptr_entries,int number_of_int32_entries)2075 void ConstantPoolArray::SetEntryCounts(int number_of_int64_entries,
2076                                        int number_of_ptr_entries,
2077                                        int number_of_int32_entries) {
2078   set_first_ptr_index(number_of_int64_entries);
2079   set_first_int32_index(number_of_int64_entries + number_of_ptr_entries);
2080   set_length(number_of_int64_entries + number_of_ptr_entries +
2081              number_of_int32_entries);
2082 }
2083 
2084 
get_int64_entry(int index)2085 int64_t ConstantPoolArray::get_int64_entry(int index) {
2086   ASSERT(map() == GetHeap()->constant_pool_array_map());
2087   ASSERT(index >= 0 && index < first_ptr_index());
2088   return READ_INT64_FIELD(this, OffsetOfElementAt(index));
2089 }
2090 
get_int64_entry_as_double(int index)2091 double ConstantPoolArray::get_int64_entry_as_double(int index) {
2092   STATIC_ASSERT(kDoubleSize == kInt64Size);
2093   ASSERT(map() == GetHeap()->constant_pool_array_map());
2094   ASSERT(index >= 0 && index < first_ptr_index());
2095   return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
2096 }
2097 
2098 
get_ptr_entry(int index)2099 Object* ConstantPoolArray::get_ptr_entry(int index) {
2100   ASSERT(map() == GetHeap()->constant_pool_array_map());
2101   ASSERT(index >= first_ptr_index() && index < first_int32_index());
2102   return READ_FIELD(this, OffsetOfElementAt(index));
2103 }
2104 
2105 
get_int32_entry(int index)2106 int32_t ConstantPoolArray::get_int32_entry(int index) {
2107   ASSERT(map() == GetHeap()->constant_pool_array_map());
2108   ASSERT(index >= first_int32_index() && index < length());
2109   return READ_INT32_FIELD(this, OffsetOfElementAt(index));
2110 }
2111 
2112 
set(int index,Object * value)2113 void ConstantPoolArray::set(int index, Object* value) {
2114   ASSERT(map() == GetHeap()->constant_pool_array_map());
2115   ASSERT(index >= first_ptr_index() && index < first_int32_index());
2116   WRITE_FIELD(this, OffsetOfElementAt(index), value);
2117   WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
2118 }
2119 
2120 
set(int index,int64_t value)2121 void ConstantPoolArray::set(int index, int64_t value) {
2122   ASSERT(map() == GetHeap()->constant_pool_array_map());
2123   ASSERT(index >= first_int64_index() && index < first_ptr_index());
2124   WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
2125 }
2126 
2127 
set(int index,double value)2128 void ConstantPoolArray::set(int index, double value) {
2129   STATIC_ASSERT(kDoubleSize == kInt64Size);
2130   ASSERT(map() == GetHeap()->constant_pool_array_map());
2131   ASSERT(index >= first_int64_index() && index < first_ptr_index());
2132   WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
2133 }
2134 
2135 
set(int index,int32_t value)2136 void ConstantPoolArray::set(int index, int32_t value) {
2137   ASSERT(map() == GetHeap()->constant_pool_array_map());
2138   ASSERT(index >= this->first_int32_index() && index < length());
2139   WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value);
2140 }
2141 
2142 
GetWriteBarrierMode(const DisallowHeapAllocation & promise)2143 WriteBarrierMode HeapObject::GetWriteBarrierMode(
2144     const DisallowHeapAllocation& promise) {
2145   Heap* heap = GetHeap();
2146   if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
2147   if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
2148   return UPDATE_WRITE_BARRIER;
2149 }
2150 
2151 
set(int index,Object * value,WriteBarrierMode mode)2152 void FixedArray::set(int index,
2153                      Object* value,
2154                      WriteBarrierMode mode) {
2155   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2156   ASSERT(index >= 0 && index < this->length());
2157   int offset = kHeaderSize + index * kPointerSize;
2158   WRITE_FIELD(this, offset, value);
2159   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
2160 }
2161 
2162 
NoIncrementalWriteBarrierSet(FixedArray * array,int index,Object * value)2163 void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
2164                                               int index,
2165                                               Object* value) {
2166   ASSERT(array->map() != array->GetHeap()->fixed_cow_array_map());
2167   ASSERT(index >= 0 && index < array->length());
2168   int offset = kHeaderSize + index * kPointerSize;
2169   WRITE_FIELD(array, offset, value);
2170   Heap* heap = array->GetHeap();
2171   if (heap->InNewSpace(value)) {
2172     heap->RecordWrite(array->address(), offset);
2173   }
2174 }
2175 
2176 
NoWriteBarrierSet(FixedArray * array,int index,Object * value)2177 void FixedArray::NoWriteBarrierSet(FixedArray* array,
2178                                    int index,
2179                                    Object* value) {
2180   ASSERT(array->map() != array->GetHeap()->fixed_cow_array_map());
2181   ASSERT(index >= 0 && index < array->length());
2182   ASSERT(!array->GetHeap()->InNewSpace(value));
2183   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
2184 }
2185 
2186 
set_undefined(int index)2187 void FixedArray::set_undefined(int index) {
2188   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2189   ASSERT(index >= 0 && index < this->length());
2190   ASSERT(!GetHeap()->InNewSpace(GetHeap()->undefined_value()));
2191   WRITE_FIELD(this,
2192               kHeaderSize + index * kPointerSize,
2193               GetHeap()->undefined_value());
2194 }
2195 
2196 
set_null(int index)2197 void FixedArray::set_null(int index) {
2198   ASSERT(index >= 0 && index < this->length());
2199   ASSERT(!GetHeap()->InNewSpace(GetHeap()->null_value()));
2200   WRITE_FIELD(this,
2201               kHeaderSize + index * kPointerSize,
2202               GetHeap()->null_value());
2203 }
2204 
2205 
set_the_hole(int index)2206 void FixedArray::set_the_hole(int index) {
2207   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2208   ASSERT(index >= 0 && index < this->length());
2209   ASSERT(!GetHeap()->InNewSpace(GetHeap()->the_hole_value()));
2210   WRITE_FIELD(this,
2211               kHeaderSize + index * kPointerSize,
2212               GetHeap()->the_hole_value());
2213 }
2214 
2215 
data_start()2216 double* FixedDoubleArray::data_start() {
2217   return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
2218 }
2219 
2220 
data_start()2221 Object** FixedArray::data_start() {
2222   return HeapObject::RawField(this, kHeaderSize);
2223 }
2224 
2225 
IsEmpty()2226 bool DescriptorArray::IsEmpty() {
2227   ASSERT(length() >= kFirstIndex ||
2228          this == GetHeap()->empty_descriptor_array());
2229   return length() < kFirstIndex;
2230 }
2231 
2232 
SetNumberOfDescriptors(int number_of_descriptors)2233 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
2234   WRITE_FIELD(
2235       this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
2236 }
2237 
2238 
2239 // Perform a binary search in a fixed array. Low and high are entry indices. If
2240 // there are three entries in this array it should be called with low=0 and
2241 // high=2.
2242 template<SearchMode search_mode, typename T>
BinarySearch(T * array,Name * name,int low,int high,int valid_entries)2243 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
2244   uint32_t hash = name->Hash();
2245   int limit = high;
2246 
2247   ASSERT(low <= high);
2248 
2249   while (low != high) {
2250     int mid = (low + high) / 2;
2251     Name* mid_name = array->GetSortedKey(mid);
2252     uint32_t mid_hash = mid_name->Hash();
2253 
2254     if (mid_hash >= hash) {
2255       high = mid;
2256     } else {
2257       low = mid + 1;
2258     }
2259   }
2260 
2261   for (; low <= limit; ++low) {
2262     int sort_index = array->GetSortedKeyIndex(low);
2263     Name* entry = array->GetKey(sort_index);
2264     if (entry->Hash() != hash) break;
2265     if (entry->Equals(name)) {
2266       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
2267         return sort_index;
2268       }
2269       return T::kNotFound;
2270     }
2271   }
2272 
2273   return T::kNotFound;
2274 }
2275 
2276 
2277 // Perform a linear search in this fixed array. len is the number of entry
2278 // indices that are valid.
2279 template<SearchMode search_mode, typename T>
LinearSearch(T * array,Name * name,int len,int valid_entries)2280 int LinearSearch(T* array, Name* name, int len, int valid_entries) {
2281   uint32_t hash = name->Hash();
2282   if (search_mode == ALL_ENTRIES) {
2283     for (int number = 0; number < len; number++) {
2284       int sorted_index = array->GetSortedKeyIndex(number);
2285       Name* entry = array->GetKey(sorted_index);
2286       uint32_t current_hash = entry->Hash();
2287       if (current_hash > hash) break;
2288       if (current_hash == hash && entry->Equals(name)) return sorted_index;
2289     }
2290   } else {
2291     ASSERT(len >= valid_entries);
2292     for (int number = 0; number < valid_entries; number++) {
2293       Name* entry = array->GetKey(number);
2294       uint32_t current_hash = entry->Hash();
2295       if (current_hash == hash && entry->Equals(name)) return number;
2296     }
2297   }
2298   return T::kNotFound;
2299 }
2300 
2301 
2302 template<SearchMode search_mode, typename T>
Search(T * array,Name * name,int valid_entries)2303 int Search(T* array, Name* name, int valid_entries) {
2304   if (search_mode == VALID_ENTRIES) {
2305     SLOW_ASSERT(array->IsSortedNoDuplicates(valid_entries));
2306   } else {
2307     SLOW_ASSERT(array->IsSortedNoDuplicates());
2308   }
2309 
2310   int nof = array->number_of_entries();
2311   if (nof == 0) return T::kNotFound;
2312 
2313   // Fast case: do linear search for small arrays.
2314   const int kMaxElementsForLinearSearch = 8;
2315   if ((search_mode == ALL_ENTRIES &&
2316        nof <= kMaxElementsForLinearSearch) ||
2317       (search_mode == VALID_ENTRIES &&
2318        valid_entries <= (kMaxElementsForLinearSearch * 3))) {
2319     return LinearSearch<search_mode>(array, name, nof, valid_entries);
2320   }
2321 
2322   // Slow case: perform binary search.
2323   return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries);
2324 }
2325 
2326 
Search(Name * name,int valid_descriptors)2327 int DescriptorArray::Search(Name* name, int valid_descriptors) {
2328   return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
2329 }
2330 
2331 
SearchWithCache(Name * name,Map * map)2332 int DescriptorArray::SearchWithCache(Name* name, Map* map) {
2333   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2334   if (number_of_own_descriptors == 0) return kNotFound;
2335 
2336   DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2337   int number = cache->Lookup(map, name);
2338 
2339   if (number == DescriptorLookupCache::kAbsent) {
2340     number = Search(name, number_of_own_descriptors);
2341     cache->Update(map, name, number);
2342   }
2343 
2344   return number;
2345 }
2346 
2347 
GetLastDescriptorDetails()2348 PropertyDetails Map::GetLastDescriptorDetails() {
2349   return instance_descriptors()->GetDetails(LastAdded());
2350 }
2351 
2352 
LookupDescriptor(JSObject * holder,Name * name,LookupResult * result)2353 void Map::LookupDescriptor(JSObject* holder,
2354                            Name* name,
2355                            LookupResult* result) {
2356   DescriptorArray* descriptors = this->instance_descriptors();
2357   int number = descriptors->SearchWithCache(name, this);
2358   if (number == DescriptorArray::kNotFound) return result->NotFound();
2359   result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2360 }
2361 
2362 
LookupTransition(JSObject * holder,Name * name,LookupResult * result)2363 void Map::LookupTransition(JSObject* holder,
2364                            Name* name,
2365                            LookupResult* result) {
2366   if (HasTransitionArray()) {
2367     TransitionArray* transition_array = transitions();
2368     int number = transition_array->Search(name);
2369     if (number != TransitionArray::kNotFound) {
2370       return result->TransitionResult(
2371           holder, transition_array->GetTarget(number));
2372     }
2373   }
2374   result->NotFound();
2375 }
2376 
2377 
GetKeySlot(int descriptor_number)2378 Object** DescriptorArray::GetKeySlot(int descriptor_number) {
2379   ASSERT(descriptor_number < number_of_descriptors());
2380   return HeapObject::RawField(
2381       reinterpret_cast<HeapObject*>(this),
2382       OffsetOfElementAt(ToKeyIndex(descriptor_number)));
2383 }
2384 
2385 
GetDescriptorStartSlot(int descriptor_number)2386 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
2387   return GetKeySlot(descriptor_number);
2388 }
2389 
2390 
GetDescriptorEndSlot(int descriptor_number)2391 Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
2392   return GetValueSlot(descriptor_number - 1) + 1;
2393 }
2394 
2395 
GetKey(int descriptor_number)2396 Name* DescriptorArray::GetKey(int descriptor_number) {
2397   ASSERT(descriptor_number < number_of_descriptors());
2398   return Name::cast(get(ToKeyIndex(descriptor_number)));
2399 }
2400 
2401 
GetSortedKeyIndex(int descriptor_number)2402 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
2403   return GetDetails(descriptor_number).pointer();
2404 }
2405 
2406 
GetSortedKey(int descriptor_number)2407 Name* DescriptorArray::GetSortedKey(int descriptor_number) {
2408   return GetKey(GetSortedKeyIndex(descriptor_number));
2409 }
2410 
2411 
SetSortedKey(int descriptor_index,int pointer)2412 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
2413   PropertyDetails details = GetDetails(descriptor_index);
2414   set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
2415 }
2416 
2417 
SetRepresentation(int descriptor_index,Representation representation)2418 void DescriptorArray::SetRepresentation(int descriptor_index,
2419                                         Representation representation) {
2420   ASSERT(!representation.IsNone());
2421   PropertyDetails details = GetDetails(descriptor_index);
2422   set(ToDetailsIndex(descriptor_index),
2423       details.CopyWithRepresentation(representation).AsSmi());
2424 }
2425 
2426 
InitializeRepresentations(Representation representation)2427 void DescriptorArray::InitializeRepresentations(Representation representation) {
2428   int length = number_of_descriptors();
2429   for (int i = 0; i < length; i++) {
2430     SetRepresentation(i, representation);
2431   }
2432 }
2433 
2434 
GetValueSlot(int descriptor_number)2435 Object** DescriptorArray::GetValueSlot(int descriptor_number) {
2436   ASSERT(descriptor_number < number_of_descriptors());
2437   return HeapObject::RawField(
2438       reinterpret_cast<HeapObject*>(this),
2439       OffsetOfElementAt(ToValueIndex(descriptor_number)));
2440 }
2441 
2442 
GetValue(int descriptor_number)2443 Object* DescriptorArray::GetValue(int descriptor_number) {
2444   ASSERT(descriptor_number < number_of_descriptors());
2445   return get(ToValueIndex(descriptor_number));
2446 }
2447 
2448 
GetDetails(int descriptor_number)2449 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
2450   ASSERT(descriptor_number < number_of_descriptors());
2451   Object* details = get(ToDetailsIndex(descriptor_number));
2452   return PropertyDetails(Smi::cast(details));
2453 }
2454 
2455 
GetType(int descriptor_number)2456 PropertyType DescriptorArray::GetType(int descriptor_number) {
2457   return GetDetails(descriptor_number).type();
2458 }
2459 
2460 
GetFieldIndex(int descriptor_number)2461 int DescriptorArray::GetFieldIndex(int descriptor_number) {
2462   ASSERT(GetDetails(descriptor_number).type() == FIELD);
2463   return GetDetails(descriptor_number).field_index();
2464 }
2465 
2466 
GetConstant(int descriptor_number)2467 Object* DescriptorArray::GetConstant(int descriptor_number) {
2468   return GetValue(descriptor_number);
2469 }
2470 
2471 
GetCallbacksObject(int descriptor_number)2472 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
2473   ASSERT(GetType(descriptor_number) == CALLBACKS);
2474   return GetValue(descriptor_number);
2475 }
2476 
2477 
GetCallbacks(int descriptor_number)2478 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
2479   ASSERT(GetType(descriptor_number) == CALLBACKS);
2480   Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
2481   return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
2482 }
2483 
2484 
Get(int descriptor_number,Descriptor * desc)2485 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2486   desc->Init(GetKey(descriptor_number),
2487              GetValue(descriptor_number),
2488              GetDetails(descriptor_number));
2489 }
2490 
2491 
Set(int descriptor_number,Descriptor * desc,const WhitenessWitness &)2492 void DescriptorArray::Set(int descriptor_number,
2493                           Descriptor* desc,
2494                           const WhitenessWitness&) {
2495   // Range check.
2496   ASSERT(descriptor_number < number_of_descriptors());
2497 
2498   NoIncrementalWriteBarrierSet(this,
2499                                ToKeyIndex(descriptor_number),
2500                                desc->GetKey());
2501   NoIncrementalWriteBarrierSet(this,
2502                                ToValueIndex(descriptor_number),
2503                                desc->GetValue());
2504   NoIncrementalWriteBarrierSet(this,
2505                                ToDetailsIndex(descriptor_number),
2506                                desc->GetDetails().AsSmi());
2507 }
2508 
2509 
Set(int descriptor_number,Descriptor * desc)2510 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
2511   // Range check.
2512   ASSERT(descriptor_number < number_of_descriptors());
2513 
2514   set(ToKeyIndex(descriptor_number), desc->GetKey());
2515   set(ToValueIndex(descriptor_number), desc->GetValue());
2516   set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
2517 }
2518 
2519 
Append(Descriptor * desc,const WhitenessWitness & witness)2520 void DescriptorArray::Append(Descriptor* desc,
2521                              const WhitenessWitness& witness) {
2522   int descriptor_number = number_of_descriptors();
2523   SetNumberOfDescriptors(descriptor_number + 1);
2524   Set(descriptor_number, desc, witness);
2525 
2526   uint32_t hash = desc->GetKey()->Hash();
2527 
2528   int insertion;
2529 
2530   for (insertion = descriptor_number; insertion > 0; --insertion) {
2531     Name* key = GetSortedKey(insertion - 1);
2532     if (key->Hash() <= hash) break;
2533     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
2534   }
2535 
2536   SetSortedKey(insertion, descriptor_number);
2537 }
2538 
2539 
Append(Descriptor * desc)2540 void DescriptorArray::Append(Descriptor* desc) {
2541   int descriptor_number = number_of_descriptors();
2542   SetNumberOfDescriptors(descriptor_number + 1);
2543   Set(descriptor_number, desc);
2544 
2545   uint32_t hash = desc->GetKey()->Hash();
2546 
2547   int insertion;
2548 
2549   for (insertion = descriptor_number; insertion > 0; --insertion) {
2550     Name* key = GetSortedKey(insertion - 1);
2551     if (key->Hash() <= hash) break;
2552     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
2553   }
2554 
2555   SetSortedKey(insertion, descriptor_number);
2556 }
2557 
2558 
SwapSortedKeys(int first,int second)2559 void DescriptorArray::SwapSortedKeys(int first, int second) {
2560   int first_key = GetSortedKeyIndex(first);
2561   SetSortedKey(first, GetSortedKeyIndex(second));
2562   SetSortedKey(second, first_key);
2563 }
2564 
2565 
WhitenessWitness(FixedArray * array)2566 DescriptorArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
2567     : marking_(array->GetHeap()->incremental_marking()) {
2568   marking_->EnterNoMarkingScope();
2569   ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
2570 }
2571 
2572 
~WhitenessWitness()2573 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
2574   marking_->LeaveNoMarkingScope();
2575 }
2576 
2577 
2578 template<typename Shape, typename Key>
ComputeCapacity(int at_least_space_for)2579 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2580   const int kMinCapacity = 32;
2581   int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2582   if (capacity < kMinCapacity) {
2583     capacity = kMinCapacity;  // Guarantee min capacity.
2584   }
2585   return capacity;
2586 }
2587 
2588 
2589 template<typename Shape, typename Key>
FindEntry(Key key)2590 int HashTable<Shape, Key>::FindEntry(Key key) {
2591   return FindEntry(GetIsolate(), key);
2592 }
2593 
2594 
2595 // Find entry for key otherwise return kNotFound.
2596 template<typename Shape, typename Key>
FindEntry(Isolate * isolate,Key key)2597 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2598   uint32_t capacity = Capacity();
2599   uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
2600   uint32_t count = 1;
2601   // EnsureCapacity will guarantee the hash table is never full.
2602   while (true) {
2603     Object* element = KeyAt(entry);
2604     // Empty entry. Uses raw unchecked accessors because it is called by the
2605     // string table during bootstrapping.
2606     if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
2607     if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
2608         Shape::IsMatch(key, element)) return entry;
2609     entry = NextProbe(entry, count++, capacity);
2610   }
2611   return kNotFound;
2612 }
2613 
2614 
requires_slow_elements()2615 bool SeededNumberDictionary::requires_slow_elements() {
2616   Object* max_index_object = get(kMaxNumberKeyIndex);
2617   if (!max_index_object->IsSmi()) return false;
2618   return 0 !=
2619       (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2620 }
2621 
max_number_key()2622 uint32_t SeededNumberDictionary::max_number_key() {
2623   ASSERT(!requires_slow_elements());
2624   Object* max_index_object = get(kMaxNumberKeyIndex);
2625   if (!max_index_object->IsSmi()) return 0;
2626   uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2627   return value >> kRequiresSlowElementsTagSize;
2628 }
2629 
set_requires_slow_elements()2630 void SeededNumberDictionary::set_requires_slow_elements() {
2631   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2632 }
2633 
2634 
2635 // ------------------------------------
2636 // Cast operations
2637 
2638 
2639 CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedDoubleArray)2640 CAST_ACCESSOR(FixedDoubleArray)
2641 CAST_ACCESSOR(ConstantPoolArray)
2642 CAST_ACCESSOR(DescriptorArray)
2643 CAST_ACCESSOR(DeoptimizationInputData)
2644 CAST_ACCESSOR(DeoptimizationOutputData)
2645 CAST_ACCESSOR(DependentCode)
2646 CAST_ACCESSOR(TypeFeedbackCells)
2647 CAST_ACCESSOR(StringTable)
2648 CAST_ACCESSOR(JSFunctionResultCache)
2649 CAST_ACCESSOR(NormalizedMapCache)
2650 CAST_ACCESSOR(ScopeInfo)
2651 CAST_ACCESSOR(CompilationCacheTable)
2652 CAST_ACCESSOR(CodeCacheHashTable)
2653 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
2654 CAST_ACCESSOR(MapCache)
2655 CAST_ACCESSOR(String)
2656 CAST_ACCESSOR(SeqString)
2657 CAST_ACCESSOR(SeqOneByteString)
2658 CAST_ACCESSOR(SeqTwoByteString)
2659 CAST_ACCESSOR(SlicedString)
2660 CAST_ACCESSOR(ConsString)
2661 CAST_ACCESSOR(ExternalString)
2662 CAST_ACCESSOR(ExternalAsciiString)
2663 CAST_ACCESSOR(ExternalTwoByteString)
2664 CAST_ACCESSOR(Symbol)
2665 CAST_ACCESSOR(Name)
2666 CAST_ACCESSOR(JSReceiver)
2667 CAST_ACCESSOR(JSObject)
2668 CAST_ACCESSOR(Smi)
2669 CAST_ACCESSOR(HeapObject)
2670 CAST_ACCESSOR(HeapNumber)
2671 CAST_ACCESSOR(Oddball)
2672 CAST_ACCESSOR(Cell)
2673 CAST_ACCESSOR(PropertyCell)
2674 CAST_ACCESSOR(SharedFunctionInfo)
2675 CAST_ACCESSOR(Map)
2676 CAST_ACCESSOR(JSFunction)
2677 CAST_ACCESSOR(GlobalObject)
2678 CAST_ACCESSOR(JSGlobalProxy)
2679 CAST_ACCESSOR(JSGlobalObject)
2680 CAST_ACCESSOR(JSBuiltinsObject)
2681 CAST_ACCESSOR(Code)
2682 CAST_ACCESSOR(JSArray)
2683 CAST_ACCESSOR(JSArrayBuffer)
2684 CAST_ACCESSOR(JSArrayBufferView)
2685 CAST_ACCESSOR(JSTypedArray)
2686 CAST_ACCESSOR(JSDataView)
2687 CAST_ACCESSOR(JSRegExp)
2688 CAST_ACCESSOR(JSProxy)
2689 CAST_ACCESSOR(JSFunctionProxy)
2690 CAST_ACCESSOR(JSSet)
2691 CAST_ACCESSOR(JSMap)
2692 CAST_ACCESSOR(JSWeakMap)
2693 CAST_ACCESSOR(JSWeakSet)
2694 CAST_ACCESSOR(Foreign)
2695 CAST_ACCESSOR(ByteArray)
2696 CAST_ACCESSOR(FreeSpace)
2697 CAST_ACCESSOR(ExternalArray)
2698 CAST_ACCESSOR(ExternalByteArray)
2699 CAST_ACCESSOR(ExternalUnsignedByteArray)
2700 CAST_ACCESSOR(ExternalShortArray)
2701 CAST_ACCESSOR(ExternalUnsignedShortArray)
2702 CAST_ACCESSOR(ExternalIntArray)
2703 CAST_ACCESSOR(ExternalUnsignedIntArray)
2704 CAST_ACCESSOR(ExternalFloatArray)
2705 CAST_ACCESSOR(ExternalDoubleArray)
2706 CAST_ACCESSOR(ExternalPixelArray)
2707 CAST_ACCESSOR(Struct)
2708 CAST_ACCESSOR(AccessorInfo)
2709 
2710 
2711 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2712   STRUCT_LIST(MAKE_STRUCT_CAST)
2713 #undef MAKE_STRUCT_CAST
2714 
2715 
2716 template <typename Shape, typename Key>
2717 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2718   ASSERT(obj->IsHashTable());
2719   return reinterpret_cast<HashTable*>(obj);
2720 }
2721 
2722 
SMI_ACCESSORS(FixedArrayBase,length,kLengthOffset)2723 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
2724 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2725 
2726 SMI_ACCESSORS(String, length, kLengthOffset)
2727 
2728 
2729 uint32_t Name::hash_field() {
2730   return READ_UINT32_FIELD(this, kHashFieldOffset);
2731 }
2732 
2733 
set_hash_field(uint32_t value)2734 void Name::set_hash_field(uint32_t value) {
2735   WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
2736 #if V8_HOST_ARCH_64_BIT
2737   WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2738 #endif
2739 }
2740 
2741 
Equals(Name * other)2742 bool Name::Equals(Name* other) {
2743   if (other == this) return true;
2744   if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
2745       this->IsSymbol() || other->IsSymbol()) {
2746     return false;
2747   }
2748   return String::cast(this)->SlowEquals(String::cast(other));
2749 }
2750 
2751 
ACCESSORS(Symbol,name,Object,kNameOffset)2752 ACCESSORS(Symbol, name, Object, kNameOffset)
2753 ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
2754 BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
2755 
2756 
2757 bool String::Equals(String* other) {
2758   if (other == this) return true;
2759   if (this->IsInternalizedString() && other->IsInternalizedString()) {
2760     return false;
2761   }
2762   return SlowEquals(other);
2763 }
2764 
2765 
TryFlatten(PretenureFlag pretenure)2766 MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
2767   if (!StringShape(this).IsCons()) return this;
2768   ConsString* cons = ConsString::cast(this);
2769   if (cons->IsFlat()) return cons->first();
2770   return SlowTryFlatten(pretenure);
2771 }
2772 
2773 
TryFlattenGetString(PretenureFlag pretenure)2774 String* String::TryFlattenGetString(PretenureFlag pretenure) {
2775   MaybeObject* flat = TryFlatten(pretenure);
2776   Object* successfully_flattened;
2777   if (!flat->ToObject(&successfully_flattened)) return this;
2778   return String::cast(successfully_flattened);
2779 }
2780 
2781 
Get(int index)2782 uint16_t String::Get(int index) {
2783   ASSERT(index >= 0 && index < length());
2784   switch (StringShape(this).full_representation_tag()) {
2785     case kSeqStringTag | kOneByteStringTag:
2786       return SeqOneByteString::cast(this)->SeqOneByteStringGet(index);
2787     case kSeqStringTag | kTwoByteStringTag:
2788       return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2789     case kConsStringTag | kOneByteStringTag:
2790     case kConsStringTag | kTwoByteStringTag:
2791       return ConsString::cast(this)->ConsStringGet(index);
2792     case kExternalStringTag | kOneByteStringTag:
2793       return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2794     case kExternalStringTag | kTwoByteStringTag:
2795       return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
2796     case kSlicedStringTag | kOneByteStringTag:
2797     case kSlicedStringTag | kTwoByteStringTag:
2798       return SlicedString::cast(this)->SlicedStringGet(index);
2799     default:
2800       break;
2801   }
2802 
2803   UNREACHABLE();
2804   return 0;
2805 }
2806 
2807 
Set(int index,uint16_t value)2808 void String::Set(int index, uint16_t value) {
2809   ASSERT(index >= 0 && index < length());
2810   ASSERT(StringShape(this).IsSequential());
2811 
2812   return this->IsOneByteRepresentation()
2813       ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value)
2814       : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2815 }
2816 
2817 
IsFlat()2818 bool String::IsFlat() {
2819   if (!StringShape(this).IsCons()) return true;
2820   return ConsString::cast(this)->second()->length() == 0;
2821 }
2822 
2823 
GetUnderlying()2824 String* String::GetUnderlying() {
2825   // Giving direct access to underlying string only makes sense if the
2826   // wrapping string is already flattened.
2827   ASSERT(this->IsFlat());
2828   ASSERT(StringShape(this).IsIndirect());
2829   STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2830   const int kUnderlyingOffset = SlicedString::kParentOffset;
2831   return String::cast(READ_FIELD(this, kUnderlyingOffset));
2832 }
2833 
2834 
2835 template<class Visitor, class ConsOp>
Visit(String * string,unsigned offset,Visitor & visitor,ConsOp & cons_op,int32_t type,unsigned length)2836 void String::Visit(
2837     String* string,
2838     unsigned offset,
2839     Visitor& visitor,
2840     ConsOp& cons_op,
2841     int32_t type,
2842     unsigned length) {
2843   ASSERT(length == static_cast<unsigned>(string->length()));
2844   ASSERT(offset <= length);
2845   unsigned slice_offset = offset;
2846   while (true) {
2847     ASSERT(type == string->map()->instance_type());
2848 
2849     switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
2850       case kSeqStringTag | kOneByteStringTag:
2851         visitor.VisitOneByteString(
2852             SeqOneByteString::cast(string)->GetChars() + slice_offset,
2853             length - offset);
2854         return;
2855 
2856       case kSeqStringTag | kTwoByteStringTag:
2857         visitor.VisitTwoByteString(
2858             SeqTwoByteString::cast(string)->GetChars() + slice_offset,
2859             length - offset);
2860         return;
2861 
2862       case kExternalStringTag | kOneByteStringTag:
2863         visitor.VisitOneByteString(
2864             ExternalAsciiString::cast(string)->GetChars() + slice_offset,
2865             length - offset);
2866         return;
2867 
2868       case kExternalStringTag | kTwoByteStringTag:
2869         visitor.VisitTwoByteString(
2870             ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
2871             length - offset);
2872         return;
2873 
2874       case kSlicedStringTag | kOneByteStringTag:
2875       case kSlicedStringTag | kTwoByteStringTag: {
2876         SlicedString* slicedString = SlicedString::cast(string);
2877         slice_offset += slicedString->offset();
2878         string = slicedString->parent();
2879         type = string->map()->instance_type();
2880         continue;
2881       }
2882 
2883       case kConsStringTag | kOneByteStringTag:
2884       case kConsStringTag | kTwoByteStringTag:
2885         string = cons_op.Operate(string, &offset, &type, &length);
2886         if (string == NULL) return;
2887         slice_offset = offset;
2888         ASSERT(length == static_cast<unsigned>(string->length()));
2889         continue;
2890 
2891       default:
2892         UNREACHABLE();
2893         return;
2894     }
2895   }
2896 }
2897 
2898 
2899 // TODO(dcarney): Remove this class after conversion to VisitFlat.
2900 class ConsStringCaptureOp {
2901  public:
ConsStringCaptureOp()2902   inline ConsStringCaptureOp() : cons_string_(NULL) {}
Operate(String * string,unsigned *,int32_t *,unsigned *)2903   inline String* Operate(String* string, unsigned*, int32_t*, unsigned*) {
2904     cons_string_ = ConsString::cast(string);
2905     return NULL;
2906   }
2907   ConsString* cons_string_;
2908 };
2909 
2910 
2911 template<class Visitor>
VisitFlat(Visitor * visitor,String * string,int offset,int length,int32_t type)2912 ConsString* String::VisitFlat(Visitor* visitor,
2913                               String* string,
2914                               int offset,
2915                               int length,
2916                               int32_t type) {
2917   ASSERT(length >= 0 && length == string->length());
2918   ASSERT(offset >= 0 && offset <= length);
2919   ConsStringCaptureOp op;
2920   Visit(string, offset, *visitor, op, type, static_cast<unsigned>(length));
2921   return op.cons_string_;
2922 }
2923 
2924 
SeqOneByteStringGet(int index)2925 uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
2926   ASSERT(index >= 0 && index < length());
2927   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2928 }
2929 
2930 
SeqOneByteStringSet(int index,uint16_t value)2931 void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
2932   ASSERT(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
2933   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2934                    static_cast<byte>(value));
2935 }
2936 
2937 
GetCharsAddress()2938 Address SeqOneByteString::GetCharsAddress() {
2939   return FIELD_ADDR(this, kHeaderSize);
2940 }
2941 
2942 
GetChars()2943 uint8_t* SeqOneByteString::GetChars() {
2944   return reinterpret_cast<uint8_t*>(GetCharsAddress());
2945 }
2946 
2947 
GetCharsAddress()2948 Address SeqTwoByteString::GetCharsAddress() {
2949   return FIELD_ADDR(this, kHeaderSize);
2950 }
2951 
2952 
GetChars()2953 uc16* SeqTwoByteString::GetChars() {
2954   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2955 }
2956 
2957 
SeqTwoByteStringGet(int index)2958 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2959   ASSERT(index >= 0 && index < length());
2960   return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2961 }
2962 
2963 
SeqTwoByteStringSet(int index,uint16_t value)2964 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2965   ASSERT(index >= 0 && index < length());
2966   WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2967 }
2968 
2969 
SeqTwoByteStringSize(InstanceType instance_type)2970 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
2971   return SizeFor(length());
2972 }
2973 
2974 
SeqOneByteStringSize(InstanceType instance_type)2975 int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
2976   return SizeFor(length());
2977 }
2978 
2979 
parent()2980 String* SlicedString::parent() {
2981   return String::cast(READ_FIELD(this, kParentOffset));
2982 }
2983 
2984 
set_parent(String * parent,WriteBarrierMode mode)2985 void SlicedString::set_parent(String* parent, WriteBarrierMode mode) {
2986   ASSERT(parent->IsSeqString() || parent->IsExternalString());
2987   WRITE_FIELD(this, kParentOffset, parent);
2988   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode);
2989 }
2990 
2991 
SMI_ACCESSORS(SlicedString,offset,kOffsetOffset)2992 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2993 
2994 
2995 String* ConsString::first() {
2996   return String::cast(READ_FIELD(this, kFirstOffset));
2997 }
2998 
2999 
unchecked_first()3000 Object* ConsString::unchecked_first() {
3001   return READ_FIELD(this, kFirstOffset);
3002 }
3003 
3004 
set_first(String * value,WriteBarrierMode mode)3005 void ConsString::set_first(String* value, WriteBarrierMode mode) {
3006   WRITE_FIELD(this, kFirstOffset, value);
3007   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
3008 }
3009 
3010 
second()3011 String* ConsString::second() {
3012   return String::cast(READ_FIELD(this, kSecondOffset));
3013 }
3014 
3015 
unchecked_second()3016 Object* ConsString::unchecked_second() {
3017   return READ_FIELD(this, kSecondOffset);
3018 }
3019 
3020 
set_second(String * value,WriteBarrierMode mode)3021 void ConsString::set_second(String* value, WriteBarrierMode mode) {
3022   WRITE_FIELD(this, kSecondOffset, value);
3023   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
3024 }
3025 
3026 
is_short()3027 bool ExternalString::is_short() {
3028   InstanceType type = map()->instance_type();
3029   return (type & kShortExternalStringMask) == kShortExternalStringTag;
3030 }
3031 
3032 
resource()3033 const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
3034   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3035 }
3036 
3037 
update_data_cache()3038 void ExternalAsciiString::update_data_cache() {
3039   if (is_short()) return;
3040   const char** data_field =
3041       reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
3042   *data_field = resource()->data();
3043 }
3044 
3045 
set_resource(const ExternalAsciiString::Resource * resource)3046 void ExternalAsciiString::set_resource(
3047     const ExternalAsciiString::Resource* resource) {
3048   *reinterpret_cast<const Resource**>(
3049       FIELD_ADDR(this, kResourceOffset)) = resource;
3050   if (resource != NULL) update_data_cache();
3051 }
3052 
3053 
GetChars()3054 const uint8_t* ExternalAsciiString::GetChars() {
3055   return reinterpret_cast<const uint8_t*>(resource()->data());
3056 }
3057 
3058 
ExternalAsciiStringGet(int index)3059 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
3060   ASSERT(index >= 0 && index < length());
3061   return GetChars()[index];
3062 }
3063 
3064 
resource()3065 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
3066   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3067 }
3068 
3069 
update_data_cache()3070 void ExternalTwoByteString::update_data_cache() {
3071   if (is_short()) return;
3072   const uint16_t** data_field =
3073       reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
3074   *data_field = resource()->data();
3075 }
3076 
3077 
set_resource(const ExternalTwoByteString::Resource * resource)3078 void ExternalTwoByteString::set_resource(
3079     const ExternalTwoByteString::Resource* resource) {
3080   *reinterpret_cast<const Resource**>(
3081       FIELD_ADDR(this, kResourceOffset)) = resource;
3082   if (resource != NULL) update_data_cache();
3083 }
3084 
3085 
GetChars()3086 const uint16_t* ExternalTwoByteString::GetChars() {
3087   return resource()->data();
3088 }
3089 
3090 
ExternalTwoByteStringGet(int index)3091 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
3092   ASSERT(index >= 0 && index < length());
3093   return GetChars()[index];
3094 }
3095 
3096 
ExternalTwoByteStringGetData(unsigned start)3097 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
3098       unsigned start) {
3099   return GetChars() + start;
3100 }
3101 
3102 
Operate(String *,unsigned *,int32_t *,unsigned *)3103 String* ConsStringNullOp::Operate(String*, unsigned*, int32_t*, unsigned*) {
3104   return NULL;
3105 }
3106 
3107 
OffsetForDepth(unsigned depth)3108 unsigned ConsStringIteratorOp::OffsetForDepth(unsigned depth) {
3109   return depth & kDepthMask;
3110 }
3111 
3112 
PushLeft(ConsString * string)3113 void ConsStringIteratorOp::PushLeft(ConsString* string) {
3114   frames_[depth_++ & kDepthMask] = string;
3115 }
3116 
3117 
PushRight(ConsString * string)3118 void ConsStringIteratorOp::PushRight(ConsString* string) {
3119   // Inplace update.
3120   frames_[(depth_-1) & kDepthMask] = string;
3121 }
3122 
3123 
AdjustMaximumDepth()3124 void ConsStringIteratorOp::AdjustMaximumDepth() {
3125   if (depth_ > maximum_depth_) maximum_depth_ = depth_;
3126 }
3127 
3128 
Pop()3129 void ConsStringIteratorOp::Pop() {
3130   ASSERT(depth_ > 0);
3131   ASSERT(depth_ <= maximum_depth_);
3132   depth_--;
3133 }
3134 
3135 
HasMore()3136 bool ConsStringIteratorOp::HasMore() {
3137   return depth_ != 0;
3138 }
3139 
3140 
Reset()3141 void ConsStringIteratorOp::Reset() {
3142   depth_ = 0;
3143 }
3144 
3145 
ContinueOperation(int32_t * type_out,unsigned * length_out)3146 String* ConsStringIteratorOp::ContinueOperation(int32_t* type_out,
3147                                                 unsigned* length_out) {
3148   bool blew_stack = false;
3149   String* string = NextLeaf(&blew_stack, type_out, length_out);
3150   // String found.
3151   if (string != NULL) {
3152     // Verify output.
3153     ASSERT(*length_out == static_cast<unsigned>(string->length()));
3154     ASSERT(*type_out == string->map()->instance_type());
3155     return string;
3156   }
3157   // Traversal complete.
3158   if (!blew_stack) return NULL;
3159   // Restart search from root.
3160   unsigned offset_out;
3161   string = Search(&offset_out, type_out, length_out);
3162   // Verify output.
3163   ASSERT(string == NULL || offset_out == 0);
3164   ASSERT(string == NULL ||
3165          *length_out == static_cast<unsigned>(string->length()));
3166   ASSERT(string == NULL || *type_out == string->map()->instance_type());
3167   return string;
3168 }
3169 
3170 
GetNext()3171 uint16_t StringCharacterStream::GetNext() {
3172   ASSERT(buffer8_ != NULL && end_ != NULL);
3173   // Advance cursor if needed.
3174   // TODO(dcarney): Ensure uses of the api call HasMore first and avoid this.
3175   if (buffer8_ == end_) HasMore();
3176   ASSERT(buffer8_ < end_);
3177   return is_one_byte_ ? *buffer8_++ : *buffer16_++;
3178 }
3179 
3180 
StringCharacterStream(String * string,ConsStringIteratorOp * op,unsigned offset)3181 StringCharacterStream::StringCharacterStream(String* string,
3182                                              ConsStringIteratorOp* op,
3183                                              unsigned offset)
3184   : is_one_byte_(false),
3185     op_(op) {
3186   Reset(string, offset);
3187 }
3188 
3189 
Reset(String * string,unsigned offset)3190 void StringCharacterStream::Reset(String* string, unsigned offset) {
3191   op_->Reset();
3192   buffer8_ = NULL;
3193   end_ = NULL;
3194   int32_t type = string->map()->instance_type();
3195   unsigned length = string->length();
3196   String::Visit(string, offset, *this, *op_, type, length);
3197 }
3198 
3199 
HasMore()3200 bool StringCharacterStream::HasMore() {
3201   if (buffer8_ != end_) return true;
3202   if (!op_->HasMore()) return false;
3203   unsigned length;
3204   int32_t type;
3205   String* string = op_->ContinueOperation(&type, &length);
3206   if (string == NULL) return false;
3207   ASSERT(!string->IsConsString());
3208   ASSERT(string->length() != 0);
3209   ConsStringNullOp null_op;
3210   String::Visit(string, 0, *this, null_op, type, length);
3211   ASSERT(buffer8_ != end_);
3212   return true;
3213 }
3214 
3215 
VisitOneByteString(const uint8_t * chars,unsigned length)3216 void StringCharacterStream::VisitOneByteString(
3217     const uint8_t* chars, unsigned length) {
3218   is_one_byte_ = true;
3219   buffer8_ = chars;
3220   end_ = chars + length;
3221 }
3222 
3223 
VisitTwoByteString(const uint16_t * chars,unsigned length)3224 void StringCharacterStream::VisitTwoByteString(
3225     const uint16_t* chars, unsigned length) {
3226   is_one_byte_ = false;
3227   buffer16_ = chars;
3228   end_ = reinterpret_cast<const uint8_t*>(chars + length);
3229 }
3230 
3231 
MakeZeroSize()3232 void JSFunctionResultCache::MakeZeroSize() {
3233   set_finger_index(kEntriesIndex);
3234   set_size(kEntriesIndex);
3235 }
3236 
3237 
Clear()3238 void JSFunctionResultCache::Clear() {
3239   int cache_size = size();
3240   Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
3241   MemsetPointer(entries_start,
3242                 GetHeap()->the_hole_value(),
3243                 cache_size - kEntriesIndex);
3244   MakeZeroSize();
3245 }
3246 
3247 
size()3248 int JSFunctionResultCache::size() {
3249   return Smi::cast(get(kCacheSizeIndex))->value();
3250 }
3251 
3252 
set_size(int size)3253 void JSFunctionResultCache::set_size(int size) {
3254   set(kCacheSizeIndex, Smi::FromInt(size));
3255 }
3256 
3257 
finger_index()3258 int JSFunctionResultCache::finger_index() {
3259   return Smi::cast(get(kFingerIndex))->value();
3260 }
3261 
3262 
set_finger_index(int finger_index)3263 void JSFunctionResultCache::set_finger_index(int finger_index) {
3264   set(kFingerIndex, Smi::FromInt(finger_index));
3265 }
3266 
3267 
get(int index)3268 byte ByteArray::get(int index) {
3269   ASSERT(index >= 0 && index < this->length());
3270   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3271 }
3272 
3273 
set(int index,byte value)3274 void ByteArray::set(int index, byte value) {
3275   ASSERT(index >= 0 && index < this->length());
3276   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
3277 }
3278 
3279 
get_int(int index)3280 int ByteArray::get_int(int index) {
3281   ASSERT(index >= 0 && (index * kIntSize) < this->length());
3282   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
3283 }
3284 
3285 
FromDataStartAddress(Address address)3286 ByteArray* ByteArray::FromDataStartAddress(Address address) {
3287   ASSERT_TAG_ALIGNED(address);
3288   return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
3289 }
3290 
3291 
GetDataStartAddress()3292 Address ByteArray::GetDataStartAddress() {
3293   return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
3294 }
3295 
3296 
external_pixel_pointer()3297 uint8_t* ExternalPixelArray::external_pixel_pointer() {
3298   return reinterpret_cast<uint8_t*>(external_pointer());
3299 }
3300 
3301 
get_scalar(int index)3302 uint8_t ExternalPixelArray::get_scalar(int index) {
3303   ASSERT((index >= 0) && (index < this->length()));
3304   uint8_t* ptr = external_pixel_pointer();
3305   return ptr[index];
3306 }
3307 
3308 
get(int index)3309 MaybeObject* ExternalPixelArray::get(int index) {
3310   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3311 }
3312 
3313 
set(int index,uint8_t value)3314 void ExternalPixelArray::set(int index, uint8_t value) {
3315   ASSERT((index >= 0) && (index < this->length()));
3316   uint8_t* ptr = external_pixel_pointer();
3317   ptr[index] = value;
3318 }
3319 
3320 
external_pointer()3321 void* ExternalArray::external_pointer() {
3322   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
3323   return reinterpret_cast<void*>(ptr);
3324 }
3325 
3326 
set_external_pointer(void * value,WriteBarrierMode mode)3327 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
3328   intptr_t ptr = reinterpret_cast<intptr_t>(value);
3329   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
3330 }
3331 
3332 
get_scalar(int index)3333 int8_t ExternalByteArray::get_scalar(int index) {
3334   ASSERT((index >= 0) && (index < this->length()));
3335   int8_t* ptr = static_cast<int8_t*>(external_pointer());
3336   return ptr[index];
3337 }
3338 
3339 
get(int index)3340 MaybeObject* ExternalByteArray::get(int index) {
3341   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3342 }
3343 
3344 
set(int index,int8_t value)3345 void ExternalByteArray::set(int index, int8_t value) {
3346   ASSERT((index >= 0) && (index < this->length()));
3347   int8_t* ptr = static_cast<int8_t*>(external_pointer());
3348   ptr[index] = value;
3349 }
3350 
3351 
get_scalar(int index)3352 uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
3353   ASSERT((index >= 0) && (index < this->length()));
3354   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3355   return ptr[index];
3356 }
3357 
3358 
get(int index)3359 MaybeObject* ExternalUnsignedByteArray::get(int index) {
3360   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3361 }
3362 
3363 
set(int index,uint8_t value)3364 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
3365   ASSERT((index >= 0) && (index < this->length()));
3366   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3367   ptr[index] = value;
3368 }
3369 
3370 
get_scalar(int index)3371 int16_t ExternalShortArray::get_scalar(int index) {
3372   ASSERT((index >= 0) && (index < this->length()));
3373   int16_t* ptr = static_cast<int16_t*>(external_pointer());
3374   return ptr[index];
3375 }
3376 
3377 
get(int index)3378 MaybeObject* ExternalShortArray::get(int index) {
3379   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3380 }
3381 
3382 
set(int index,int16_t value)3383 void ExternalShortArray::set(int index, int16_t value) {
3384   ASSERT((index >= 0) && (index < this->length()));
3385   int16_t* ptr = static_cast<int16_t*>(external_pointer());
3386   ptr[index] = value;
3387 }
3388 
3389 
get_scalar(int index)3390 uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
3391   ASSERT((index >= 0) && (index < this->length()));
3392   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3393   return ptr[index];
3394 }
3395 
3396 
get(int index)3397 MaybeObject* ExternalUnsignedShortArray::get(int index) {
3398   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3399 }
3400 
3401 
set(int index,uint16_t value)3402 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
3403   ASSERT((index >= 0) && (index < this->length()));
3404   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3405   ptr[index] = value;
3406 }
3407 
3408 
get_scalar(int index)3409 int32_t ExternalIntArray::get_scalar(int index) {
3410   ASSERT((index >= 0) && (index < this->length()));
3411   int32_t* ptr = static_cast<int32_t*>(external_pointer());
3412   return ptr[index];
3413 }
3414 
3415 
get(int index)3416 MaybeObject* ExternalIntArray::get(int index) {
3417     return GetHeap()->NumberFromInt32(get_scalar(index));
3418 }
3419 
3420 
set(int index,int32_t value)3421 void ExternalIntArray::set(int index, int32_t value) {
3422   ASSERT((index >= 0) && (index < this->length()));
3423   int32_t* ptr = static_cast<int32_t*>(external_pointer());
3424   ptr[index] = value;
3425 }
3426 
3427 
get_scalar(int index)3428 uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
3429   ASSERT((index >= 0) && (index < this->length()));
3430   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3431   return ptr[index];
3432 }
3433 
3434 
get(int index)3435 MaybeObject* ExternalUnsignedIntArray::get(int index) {
3436     return GetHeap()->NumberFromUint32(get_scalar(index));
3437 }
3438 
3439 
set(int index,uint32_t value)3440 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
3441   ASSERT((index >= 0) && (index < this->length()));
3442   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3443   ptr[index] = value;
3444 }
3445 
3446 
get_scalar(int index)3447 float ExternalFloatArray::get_scalar(int index) {
3448   ASSERT((index >= 0) && (index < this->length()));
3449   float* ptr = static_cast<float*>(external_pointer());
3450   return ptr[index];
3451 }
3452 
3453 
get(int index)3454 MaybeObject* ExternalFloatArray::get(int index) {
3455     return GetHeap()->NumberFromDouble(get_scalar(index));
3456 }
3457 
3458 
set(int index,float value)3459 void ExternalFloatArray::set(int index, float value) {
3460   ASSERT((index >= 0) && (index < this->length()));
3461   float* ptr = static_cast<float*>(external_pointer());
3462   ptr[index] = value;
3463 }
3464 
3465 
get_scalar(int index)3466 double ExternalDoubleArray::get_scalar(int index) {
3467   ASSERT((index >= 0) && (index < this->length()));
3468   double* ptr = static_cast<double*>(external_pointer());
3469   return ptr[index];
3470 }
3471 
3472 
get(int index)3473 MaybeObject* ExternalDoubleArray::get(int index) {
3474     return GetHeap()->NumberFromDouble(get_scalar(index));
3475 }
3476 
3477 
set(int index,double value)3478 void ExternalDoubleArray::set(int index, double value) {
3479   ASSERT((index >= 0) && (index < this->length()));
3480   double* ptr = static_cast<double*>(external_pointer());
3481   ptr[index] = value;
3482 }
3483 
3484 
visitor_id()3485 int Map::visitor_id() {
3486   return READ_BYTE_FIELD(this, kVisitorIdOffset);
3487 }
3488 
3489 
set_visitor_id(int id)3490 void Map::set_visitor_id(int id) {
3491   ASSERT(0 <= id && id < 256);
3492   WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
3493 }
3494 
3495 
instance_size()3496 int Map::instance_size() {
3497   return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
3498 }
3499 
3500 
inobject_properties()3501 int Map::inobject_properties() {
3502   return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
3503 }
3504 
3505 
pre_allocated_property_fields()3506 int Map::pre_allocated_property_fields() {
3507   return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
3508 }
3509 
3510 
SizeFromMap(Map * map)3511 int HeapObject::SizeFromMap(Map* map) {
3512   int instance_size = map->instance_size();
3513   if (instance_size != kVariableSizeSentinel) return instance_size;
3514   // Only inline the most frequent cases.
3515   int instance_type = static_cast<int>(map->instance_type());
3516   if (instance_type == FIXED_ARRAY_TYPE) {
3517     return FixedArray::BodyDescriptor::SizeOf(map, this);
3518   }
3519   if (instance_type == ASCII_STRING_TYPE ||
3520       instance_type == ASCII_INTERNALIZED_STRING_TYPE) {
3521     return SeqOneByteString::SizeFor(
3522         reinterpret_cast<SeqOneByteString*>(this)->length());
3523   }
3524   if (instance_type == BYTE_ARRAY_TYPE) {
3525     return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
3526   }
3527   if (instance_type == FREE_SPACE_TYPE) {
3528     return reinterpret_cast<FreeSpace*>(this)->size();
3529   }
3530   if (instance_type == STRING_TYPE ||
3531       instance_type == INTERNALIZED_STRING_TYPE) {
3532     return SeqTwoByteString::SizeFor(
3533         reinterpret_cast<SeqTwoByteString*>(this)->length());
3534   }
3535   if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
3536     return FixedDoubleArray::SizeFor(
3537         reinterpret_cast<FixedDoubleArray*>(this)->length());
3538   }
3539   if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
3540     return ConstantPoolArray::SizeFor(
3541         reinterpret_cast<ConstantPoolArray*>(this)->count_of_int64_entries(),
3542         reinterpret_cast<ConstantPoolArray*>(this)->count_of_ptr_entries(),
3543         reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
3544   }
3545   ASSERT(instance_type == CODE_TYPE);
3546   return reinterpret_cast<Code*>(this)->CodeSize();
3547 }
3548 
3549 
set_instance_size(int value)3550 void Map::set_instance_size(int value) {
3551   ASSERT_EQ(0, value & (kPointerSize - 1));
3552   value >>= kPointerSizeLog2;
3553   ASSERT(0 <= value && value < 256);
3554   WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
3555 }
3556 
3557 
set_inobject_properties(int value)3558 void Map::set_inobject_properties(int value) {
3559   ASSERT(0 <= value && value < 256);
3560   WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
3561 }
3562 
3563 
set_pre_allocated_property_fields(int value)3564 void Map::set_pre_allocated_property_fields(int value) {
3565   ASSERT(0 <= value && value < 256);
3566   WRITE_BYTE_FIELD(this,
3567                    kPreAllocatedPropertyFieldsOffset,
3568                    static_cast<byte>(value));
3569 }
3570 
3571 
instance_type()3572 InstanceType Map::instance_type() {
3573   return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
3574 }
3575 
3576 
set_instance_type(InstanceType value)3577 void Map::set_instance_type(InstanceType value) {
3578   WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
3579 }
3580 
3581 
unused_property_fields()3582 int Map::unused_property_fields() {
3583   return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
3584 }
3585 
3586 
set_unused_property_fields(int value)3587 void Map::set_unused_property_fields(int value) {
3588   WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
3589 }
3590 
3591 
bit_field()3592 byte Map::bit_field() {
3593   return READ_BYTE_FIELD(this, kBitFieldOffset);
3594 }
3595 
3596 
set_bit_field(byte value)3597 void Map::set_bit_field(byte value) {
3598   WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
3599 }
3600 
3601 
bit_field2()3602 byte Map::bit_field2() {
3603   return READ_BYTE_FIELD(this, kBitField2Offset);
3604 }
3605 
3606 
set_bit_field2(byte value)3607 void Map::set_bit_field2(byte value) {
3608   WRITE_BYTE_FIELD(this, kBitField2Offset, value);
3609 }
3610 
3611 
set_non_instance_prototype(bool value)3612 void Map::set_non_instance_prototype(bool value) {
3613   if (value) {
3614     set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
3615   } else {
3616     set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
3617   }
3618 }
3619 
3620 
has_non_instance_prototype()3621 bool Map::has_non_instance_prototype() {
3622   return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
3623 }
3624 
3625 
set_function_with_prototype(bool value)3626 void Map::set_function_with_prototype(bool value) {
3627   set_bit_field3(FunctionWithPrototype::update(bit_field3(), value));
3628 }
3629 
3630 
function_with_prototype()3631 bool Map::function_with_prototype() {
3632   return FunctionWithPrototype::decode(bit_field3());
3633 }
3634 
3635 
set_is_access_check_needed(bool access_check_needed)3636 void Map::set_is_access_check_needed(bool access_check_needed) {
3637   if (access_check_needed) {
3638     set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
3639   } else {
3640     set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
3641   }
3642 }
3643 
3644 
is_access_check_needed()3645 bool Map::is_access_check_needed() {
3646   return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
3647 }
3648 
3649 
set_is_extensible(bool value)3650 void Map::set_is_extensible(bool value) {
3651   if (value) {
3652     set_bit_field2(bit_field2() | (1 << kIsExtensible));
3653   } else {
3654     set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
3655   }
3656 }
3657 
is_extensible()3658 bool Map::is_extensible() {
3659   return ((1 << kIsExtensible) & bit_field2()) != 0;
3660 }
3661 
3662 
set_attached_to_shared_function_info(bool value)3663 void Map::set_attached_to_shared_function_info(bool value) {
3664   if (value) {
3665     set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
3666   } else {
3667     set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
3668   }
3669 }
3670 
attached_to_shared_function_info()3671 bool Map::attached_to_shared_function_info() {
3672   return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
3673 }
3674 
3675 
set_is_shared(bool value)3676 void Map::set_is_shared(bool value) {
3677   set_bit_field3(IsShared::update(bit_field3(), value));
3678 }
3679 
3680 
is_shared()3681 bool Map::is_shared() {
3682   return IsShared::decode(bit_field3());
3683 }
3684 
3685 
set_dictionary_map(bool value)3686 void Map::set_dictionary_map(bool value) {
3687   if (value) mark_unstable();
3688   set_bit_field3(DictionaryMap::update(bit_field3(), value));
3689 }
3690 
3691 
is_dictionary_map()3692 bool Map::is_dictionary_map() {
3693   return DictionaryMap::decode(bit_field3());
3694 }
3695 
3696 
flags()3697 Code::Flags Code::flags() {
3698   return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
3699 }
3700 
3701 
set_owns_descriptors(bool is_shared)3702 void Map::set_owns_descriptors(bool is_shared) {
3703   set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared));
3704 }
3705 
3706 
owns_descriptors()3707 bool Map::owns_descriptors() {
3708   return OwnsDescriptors::decode(bit_field3());
3709 }
3710 
3711 
set_has_instance_call_handler()3712 void Map::set_has_instance_call_handler() {
3713   set_bit_field3(HasInstanceCallHandler::update(bit_field3(), true));
3714 }
3715 
3716 
has_instance_call_handler()3717 bool Map::has_instance_call_handler() {
3718   return HasInstanceCallHandler::decode(bit_field3());
3719 }
3720 
3721 
deprecate()3722 void Map::deprecate() {
3723   set_bit_field3(Deprecated::update(bit_field3(), true));
3724 }
3725 
3726 
is_deprecated()3727 bool Map::is_deprecated() {
3728   if (!FLAG_track_fields) return false;
3729   return Deprecated::decode(bit_field3());
3730 }
3731 
3732 
set_migration_target(bool value)3733 void Map::set_migration_target(bool value) {
3734   set_bit_field3(IsMigrationTarget::update(bit_field3(), value));
3735 }
3736 
3737 
is_migration_target()3738 bool Map::is_migration_target() {
3739   if (!FLAG_track_fields) return false;
3740   return IsMigrationTarget::decode(bit_field3());
3741 }
3742 
3743 
freeze()3744 void Map::freeze() {
3745   set_bit_field3(IsFrozen::update(bit_field3(), true));
3746 }
3747 
3748 
is_frozen()3749 bool Map::is_frozen() {
3750   return IsFrozen::decode(bit_field3());
3751 }
3752 
3753 
mark_unstable()3754 void Map::mark_unstable() {
3755   set_bit_field3(IsUnstable::update(bit_field3(), true));
3756 }
3757 
3758 
is_stable()3759 bool Map::is_stable() {
3760   return !IsUnstable::decode(bit_field3());
3761 }
3762 
3763 
has_code_cache()3764 bool Map::has_code_cache() {
3765   return code_cache() != GetIsolate()->heap()->empty_fixed_array();
3766 }
3767 
3768 
CanBeDeprecated()3769 bool Map::CanBeDeprecated() {
3770   int descriptor = LastAdded();
3771   for (int i = 0; i <= descriptor; i++) {
3772     PropertyDetails details = instance_descriptors()->GetDetails(i);
3773     if (FLAG_track_fields && details.representation().IsNone()) {
3774       return true;
3775     }
3776     if (FLAG_track_fields && details.representation().IsSmi()) {
3777       return true;
3778     }
3779     if (FLAG_track_double_fields && details.representation().IsDouble()) {
3780       return true;
3781     }
3782     if (FLAG_track_heap_object_fields &&
3783         details.representation().IsHeapObject()) {
3784       return true;
3785     }
3786     if (FLAG_track_fields && details.type() == CONSTANT) {
3787       return true;
3788     }
3789   }
3790   return false;
3791 }
3792 
3793 
NotifyLeafMapLayoutChange()3794 void Map::NotifyLeafMapLayoutChange() {
3795   if (is_stable()) {
3796     mark_unstable();
3797     dependent_code()->DeoptimizeDependentCodeGroup(
3798         GetIsolate(),
3799         DependentCode::kPrototypeCheckGroup);
3800   }
3801 }
3802 
3803 
CanOmitMapChecks()3804 bool Map::CanOmitMapChecks() {
3805   return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
3806 }
3807 
3808 
number_of_entries(DependencyGroup group)3809 int DependentCode::number_of_entries(DependencyGroup group) {
3810   if (length() == 0) return 0;
3811   return Smi::cast(get(group))->value();
3812 }
3813 
3814 
set_number_of_entries(DependencyGroup group,int value)3815 void DependentCode::set_number_of_entries(DependencyGroup group, int value) {
3816   set(group, Smi::FromInt(value));
3817 }
3818 
3819 
is_code_at(int i)3820 bool DependentCode::is_code_at(int i) {
3821   return get(kCodesStartIndex + i)->IsCode();
3822 }
3823 
code_at(int i)3824 Code* DependentCode::code_at(int i) {
3825   return Code::cast(get(kCodesStartIndex + i));
3826 }
3827 
3828 
compilation_info_at(int i)3829 CompilationInfo* DependentCode::compilation_info_at(int i) {
3830   return reinterpret_cast<CompilationInfo*>(
3831       Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
3832 }
3833 
3834 
set_object_at(int i,Object * object)3835 void DependentCode::set_object_at(int i, Object* object) {
3836   set(kCodesStartIndex + i, object);
3837 }
3838 
3839 
object_at(int i)3840 Object* DependentCode::object_at(int i) {
3841   return get(kCodesStartIndex + i);
3842 }
3843 
3844 
slot_at(int i)3845 Object** DependentCode::slot_at(int i) {
3846   return HeapObject::RawField(
3847       this, FixedArray::OffsetOfElementAt(kCodesStartIndex + i));
3848 }
3849 
3850 
clear_at(int i)3851 void DependentCode::clear_at(int i) {
3852   set_undefined(kCodesStartIndex + i);
3853 }
3854 
3855 
copy(int from,int to)3856 void DependentCode::copy(int from, int to) {
3857   set(kCodesStartIndex + to, get(kCodesStartIndex + from));
3858 }
3859 
3860 
ExtendGroup(DependencyGroup group)3861 void DependentCode::ExtendGroup(DependencyGroup group) {
3862   GroupStartIndexes starts(this);
3863   for (int g = kGroupCount - 1; g > group; g--) {
3864     if (starts.at(g) < starts.at(g + 1)) {
3865       copy(starts.at(g), starts.at(g + 1));
3866     }
3867   }
3868 }
3869 
3870 
set_flags(Code::Flags flags)3871 void Code::set_flags(Code::Flags flags) {
3872   STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
3873   // Make sure that all call stubs have an arguments count.
3874   ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
3875           ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
3876          ExtractArgumentsCountFromFlags(flags) >= 0);
3877   WRITE_INT_FIELD(this, kFlagsOffset, flags);
3878 }
3879 
3880 
kind()3881 Code::Kind Code::kind() {
3882   return ExtractKindFromFlags(flags());
3883 }
3884 
3885 
ic_state()3886 InlineCacheState Code::ic_state() {
3887   InlineCacheState result = ExtractICStateFromFlags(flags());
3888   // Only allow uninitialized or debugger states for non-IC code
3889   // objects. This is used in the debugger to determine whether or not
3890   // a call to code object has been replaced with a debug break call.
3891   ASSERT(is_inline_cache_stub() ||
3892          result == UNINITIALIZED ||
3893          result == DEBUG_STUB);
3894   return result;
3895 }
3896 
3897 
extra_ic_state()3898 ExtraICState Code::extra_ic_state() {
3899   ASSERT((is_inline_cache_stub() && !needs_extended_extra_ic_state(kind()))
3900          || ic_state() == DEBUG_STUB);
3901   return ExtractExtraICStateFromFlags(flags());
3902 }
3903 
3904 
extended_extra_ic_state()3905 ExtraICState Code::extended_extra_ic_state() {
3906   ASSERT(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
3907   ASSERT(needs_extended_extra_ic_state(kind()));
3908   return ExtractExtendedExtraICStateFromFlags(flags());
3909 }
3910 
3911 
type()3912 Code::StubType Code::type() {
3913   return ExtractTypeFromFlags(flags());
3914 }
3915 
3916 
arguments_count()3917 int Code::arguments_count() {
3918   ASSERT(is_call_stub() || is_keyed_call_stub() ||
3919          kind() == STUB || is_handler());
3920   return ExtractArgumentsCountFromFlags(flags());
3921 }
3922 
3923 
3924 // For initialization.
set_raw_kind_specific_flags1(int value)3925 void Code::set_raw_kind_specific_flags1(int value) {
3926   WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value);
3927 }
3928 
3929 
set_raw_kind_specific_flags2(int value)3930 void Code::set_raw_kind_specific_flags2(int value) {
3931   WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value);
3932 }
3933 
3934 
is_crankshafted()3935 inline bool Code::is_crankshafted() {
3936   return IsCrankshaftedField::decode(
3937       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
3938 }
3939 
3940 
set_is_crankshafted(bool value)3941 inline void Code::set_is_crankshafted(bool value) {
3942   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
3943   int updated = IsCrankshaftedField::update(previous, value);
3944   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
3945 }
3946 
3947 
major_key()3948 int Code::major_key() {
3949   ASSERT(has_major_key());
3950   return StubMajorKeyField::decode(
3951       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
3952 }
3953 
3954 
set_major_key(int major)3955 void Code::set_major_key(int major) {
3956   ASSERT(has_major_key());
3957   ASSERT(0 <= major && major < 256);
3958   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
3959   int updated = StubMajorKeyField::update(previous, major);
3960   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
3961 }
3962 
3963 
has_major_key()3964 bool Code::has_major_key() {
3965   return kind() == STUB ||
3966       kind() == HANDLER ||
3967       kind() == BINARY_OP_IC ||
3968       kind() == COMPARE_IC ||
3969       kind() == COMPARE_NIL_IC ||
3970       kind() == LOAD_IC ||
3971       kind() == KEYED_LOAD_IC ||
3972       kind() == STORE_IC ||
3973       kind() == KEYED_STORE_IC ||
3974       kind() == KEYED_CALL_IC ||
3975       kind() == TO_BOOLEAN_IC;
3976 }
3977 
3978 
optimizable()3979 bool Code::optimizable() {
3980   ASSERT_EQ(FUNCTION, kind());
3981   return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
3982 }
3983 
3984 
set_optimizable(bool value)3985 void Code::set_optimizable(bool value) {
3986   ASSERT_EQ(FUNCTION, kind());
3987   WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
3988 }
3989 
3990 
has_deoptimization_support()3991 bool Code::has_deoptimization_support() {
3992   ASSERT_EQ(FUNCTION, kind());
3993   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3994   return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
3995 }
3996 
3997 
set_has_deoptimization_support(bool value)3998 void Code::set_has_deoptimization_support(bool value) {
3999   ASSERT_EQ(FUNCTION, kind());
4000   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4001   flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
4002   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4003 }
4004 
4005 
has_debug_break_slots()4006 bool Code::has_debug_break_slots() {
4007   ASSERT_EQ(FUNCTION, kind());
4008   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4009   return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
4010 }
4011 
4012 
set_has_debug_break_slots(bool value)4013 void Code::set_has_debug_break_slots(bool value) {
4014   ASSERT_EQ(FUNCTION, kind());
4015   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4016   flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
4017   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4018 }
4019 
4020 
is_compiled_optimizable()4021 bool Code::is_compiled_optimizable() {
4022   ASSERT_EQ(FUNCTION, kind());
4023   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4024   return FullCodeFlagsIsCompiledOptimizable::decode(flags);
4025 }
4026 
4027 
set_compiled_optimizable(bool value)4028 void Code::set_compiled_optimizable(bool value) {
4029   ASSERT_EQ(FUNCTION, kind());
4030   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4031   flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
4032   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4033 }
4034 
4035 
allow_osr_at_loop_nesting_level()4036 int Code::allow_osr_at_loop_nesting_level() {
4037   ASSERT_EQ(FUNCTION, kind());
4038   return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
4039 }
4040 
4041 
set_allow_osr_at_loop_nesting_level(int level)4042 void Code::set_allow_osr_at_loop_nesting_level(int level) {
4043   ASSERT_EQ(FUNCTION, kind());
4044   ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
4045   WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
4046 }
4047 
4048 
profiler_ticks()4049 int Code::profiler_ticks() {
4050   ASSERT_EQ(FUNCTION, kind());
4051   return READ_BYTE_FIELD(this, kProfilerTicksOffset);
4052 }
4053 
4054 
set_profiler_ticks(int ticks)4055 void Code::set_profiler_ticks(int ticks) {
4056   ASSERT_EQ(FUNCTION, kind());
4057   ASSERT(ticks < 256);
4058   WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
4059 }
4060 
4061 
stack_slots()4062 unsigned Code::stack_slots() {
4063   ASSERT(is_crankshafted());
4064   return StackSlotsField::decode(
4065       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4066 }
4067 
4068 
set_stack_slots(unsigned slots)4069 void Code::set_stack_slots(unsigned slots) {
4070   CHECK(slots <= (1 << kStackSlotsBitCount));
4071   ASSERT(is_crankshafted());
4072   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4073   int updated = StackSlotsField::update(previous, slots);
4074   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4075 }
4076 
4077 
safepoint_table_offset()4078 unsigned Code::safepoint_table_offset() {
4079   ASSERT(is_crankshafted());
4080   return SafepointTableOffsetField::decode(
4081       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4082 }
4083 
4084 
set_safepoint_table_offset(unsigned offset)4085 void Code::set_safepoint_table_offset(unsigned offset) {
4086   CHECK(offset <= (1 << kSafepointTableOffsetBitCount));
4087   ASSERT(is_crankshafted());
4088   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
4089   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4090   int updated = SafepointTableOffsetField::update(previous, offset);
4091   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4092 }
4093 
4094 
back_edge_table_offset()4095 unsigned Code::back_edge_table_offset() {
4096   ASSERT_EQ(FUNCTION, kind());
4097   return BackEdgeTableOffsetField::decode(
4098       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4099 }
4100 
4101 
set_back_edge_table_offset(unsigned offset)4102 void Code::set_back_edge_table_offset(unsigned offset) {
4103   ASSERT_EQ(FUNCTION, kind());
4104   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
4105   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4106   int updated = BackEdgeTableOffsetField::update(previous, offset);
4107   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4108 }
4109 
4110 
back_edges_patched_for_osr()4111 bool Code::back_edges_patched_for_osr() {
4112   ASSERT_EQ(FUNCTION, kind());
4113   return BackEdgesPatchedForOSRField::decode(
4114       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4115 }
4116 
4117 
set_back_edges_patched_for_osr(bool value)4118 void Code::set_back_edges_patched_for_osr(bool value) {
4119   ASSERT_EQ(FUNCTION, kind());
4120   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4121   int updated = BackEdgesPatchedForOSRField::update(previous, value);
4122   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4123 }
4124 
4125 
4126 
check_type()4127 CheckType Code::check_type() {
4128   ASSERT(is_call_stub() || is_keyed_call_stub());
4129   byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
4130   return static_cast<CheckType>(type);
4131 }
4132 
4133 
set_check_type(CheckType value)4134 void Code::set_check_type(CheckType value) {
4135   ASSERT(is_call_stub() || is_keyed_call_stub());
4136   WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
4137 }
4138 
4139 
to_boolean_state()4140 byte Code::to_boolean_state() {
4141   return extended_extra_ic_state();
4142 }
4143 
4144 
has_function_cache()4145 bool Code::has_function_cache() {
4146   ASSERT(kind() == STUB);
4147   return HasFunctionCacheField::decode(
4148       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4149 }
4150 
4151 
set_has_function_cache(bool flag)4152 void Code::set_has_function_cache(bool flag) {
4153   ASSERT(kind() == STUB);
4154   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4155   int updated = HasFunctionCacheField::update(previous, flag);
4156   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4157 }
4158 
4159 
marked_for_deoptimization()4160 bool Code::marked_for_deoptimization() {
4161   ASSERT(kind() == OPTIMIZED_FUNCTION);
4162   return MarkedForDeoptimizationField::decode(
4163       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4164 }
4165 
4166 
set_marked_for_deoptimization(bool flag)4167 void Code::set_marked_for_deoptimization(bool flag) {
4168   ASSERT(kind() == OPTIMIZED_FUNCTION);
4169   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4170   int updated = MarkedForDeoptimizationField::update(previous, flag);
4171   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4172 }
4173 
4174 
is_inline_cache_stub()4175 bool Code::is_inline_cache_stub() {
4176   Kind kind = this->kind();
4177   switch (kind) {
4178 #define CASE(name) case name: return true;
4179     IC_KIND_LIST(CASE)
4180 #undef CASE
4181     default: return false;
4182   }
4183 }
4184 
4185 
is_keyed_stub()4186 bool Code::is_keyed_stub() {
4187   return is_keyed_load_stub() || is_keyed_store_stub() || is_keyed_call_stub();
4188 }
4189 
4190 
is_debug_stub()4191 bool Code::is_debug_stub() {
4192   return ic_state() == DEBUG_STUB;
4193 }
4194 
4195 
ComputeFlags(Kind kind,InlineCacheState ic_state,ExtraICState extra_ic_state,StubType type,int argc,InlineCacheHolderFlag holder)4196 Code::Flags Code::ComputeFlags(Kind kind,
4197                                InlineCacheState ic_state,
4198                                ExtraICState extra_ic_state,
4199                                StubType type,
4200                                int argc,
4201                                InlineCacheHolderFlag holder) {
4202   ASSERT(argc <= Code::kMaxArguments);
4203   // Since the extended extra ic state overlaps with the argument count
4204   // for CALL_ICs, do so checks to make sure that they don't interfere.
4205   ASSERT((kind != Code::CALL_IC &&
4206           kind != Code::KEYED_CALL_IC) ||
4207          (ExtraICStateField::encode(extra_ic_state) | true));
4208   // Compute the bit mask.
4209   unsigned int bits = KindField::encode(kind)
4210       | ICStateField::encode(ic_state)
4211       | TypeField::encode(type)
4212       | ExtendedExtraICStateField::encode(extra_ic_state)
4213       | CacheHolderField::encode(holder);
4214   if (!Code::needs_extended_extra_ic_state(kind)) {
4215     bits |= (argc << kArgumentsCountShift);
4216   }
4217   return static_cast<Flags>(bits);
4218 }
4219 
4220 
ComputeMonomorphicFlags(Kind kind,ExtraICState extra_ic_state,InlineCacheHolderFlag holder,StubType type,int argc)4221 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
4222                                           ExtraICState extra_ic_state,
4223                                           InlineCacheHolderFlag holder,
4224                                           StubType type,
4225                                           int argc) {
4226   return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
4227 }
4228 
4229 
ExtractKindFromFlags(Flags flags)4230 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
4231   return KindField::decode(flags);
4232 }
4233 
4234 
ExtractICStateFromFlags(Flags flags)4235 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
4236   return ICStateField::decode(flags);
4237 }
4238 
4239 
ExtractExtraICStateFromFlags(Flags flags)4240 ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
4241   return ExtraICStateField::decode(flags);
4242 }
4243 
4244 
ExtractExtendedExtraICStateFromFlags(Flags flags)4245 ExtraICState Code::ExtractExtendedExtraICStateFromFlags(
4246     Flags flags) {
4247   return ExtendedExtraICStateField::decode(flags);
4248 }
4249 
4250 
ExtractTypeFromFlags(Flags flags)4251 Code::StubType Code::ExtractTypeFromFlags(Flags flags) {
4252   return TypeField::decode(flags);
4253 }
4254 
4255 
ExtractArgumentsCountFromFlags(Flags flags)4256 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
4257   return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
4258 }
4259 
4260 
ExtractCacheHolderFromFlags(Flags flags)4261 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
4262   return CacheHolderField::decode(flags);
4263 }
4264 
4265 
RemoveTypeFromFlags(Flags flags)4266 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
4267   int bits = flags & ~TypeField::kMask;
4268   return static_cast<Flags>(bits);
4269 }
4270 
4271 
GetCodeFromTargetAddress(Address address)4272 Code* Code::GetCodeFromTargetAddress(Address address) {
4273   HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
4274   // GetCodeFromTargetAddress might be called when marking objects during mark
4275   // sweep. reinterpret_cast is therefore used instead of the more appropriate
4276   // Code::cast. Code::cast does not work when the object's map is
4277   // marked.
4278   Code* result = reinterpret_cast<Code*>(code);
4279   return result;
4280 }
4281 
4282 
GetObjectFromEntryAddress(Address location_of_address)4283 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
4284   return HeapObject::
4285       FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
4286 }
4287 
4288 
prototype()4289 Object* Map::prototype() {
4290   return READ_FIELD(this, kPrototypeOffset);
4291 }
4292 
4293 
set_prototype(Object * value,WriteBarrierMode mode)4294 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
4295   ASSERT(value->IsNull() || value->IsJSReceiver());
4296   WRITE_FIELD(this, kPrototypeOffset, value);
4297   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
4298 }
4299 
4300 
4301 // If the descriptor is using the empty transition array, install a new empty
4302 // transition array that will have place for an element transition.
EnsureHasTransitionArray(Map * map)4303 static MaybeObject* EnsureHasTransitionArray(Map* map) {
4304   TransitionArray* transitions;
4305   MaybeObject* maybe_transitions;
4306   if (!map->HasTransitionArray()) {
4307     maybe_transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
4308     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4309     transitions->set_back_pointer_storage(map->GetBackPointer());
4310   } else if (!map->transitions()->IsFullTransitionArray()) {
4311     maybe_transitions = map->transitions()->ExtendToFullTransitionArray();
4312     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4313   } else {
4314     return map;
4315   }
4316   map->set_transitions(transitions);
4317   return transitions;
4318 }
4319 
4320 
InitializeDescriptors(DescriptorArray * descriptors)4321 void Map::InitializeDescriptors(DescriptorArray* descriptors) {
4322   int len = descriptors->number_of_descriptors();
4323   set_instance_descriptors(descriptors);
4324   SetNumberOfOwnDescriptors(len);
4325 }
4326 
4327 
ACCESSORS(Map,instance_descriptors,DescriptorArray,kDescriptorsOffset)4328 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
4329 
4330 
4331 void Map::set_bit_field3(uint32_t bits) {
4332   // Ensure the upper 2 bits have the same value by sign extending it. This is
4333   // necessary to be able to use the 31st bit.
4334   int value = bits << 1;
4335   WRITE_FIELD(this, kBitField3Offset, Smi::FromInt(value >> 1));
4336 }
4337 
4338 
bit_field3()4339 uint32_t Map::bit_field3() {
4340   Object* value = READ_FIELD(this, kBitField3Offset);
4341   return Smi::cast(value)->value();
4342 }
4343 
4344 
ClearTransitions(Heap * heap,WriteBarrierMode mode)4345 void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
4346   Object* back_pointer = GetBackPointer();
4347 
4348   if (Heap::ShouldZapGarbage() && HasTransitionArray()) {
4349     ZapTransitions();
4350   }
4351 
4352   WRITE_FIELD(this, kTransitionsOrBackPointerOffset, back_pointer);
4353   CONDITIONAL_WRITE_BARRIER(
4354       heap, this, kTransitionsOrBackPointerOffset, back_pointer, mode);
4355 }
4356 
4357 
AppendDescriptor(Descriptor * desc,const DescriptorArray::WhitenessWitness & witness)4358 void Map::AppendDescriptor(Descriptor* desc,
4359                            const DescriptorArray::WhitenessWitness& witness) {
4360   DescriptorArray* descriptors = instance_descriptors();
4361   int number_of_own_descriptors = NumberOfOwnDescriptors();
4362   ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
4363   descriptors->Append(desc, witness);
4364   SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
4365 }
4366 
4367 
GetBackPointer()4368 Object* Map::GetBackPointer() {
4369   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4370   if (object->IsDescriptorArray()) {
4371     return TransitionArray::cast(object)->back_pointer_storage();
4372   } else {
4373     ASSERT(object->IsMap() || object->IsUndefined());
4374     return object;
4375   }
4376 }
4377 
4378 
HasElementsTransition()4379 bool Map::HasElementsTransition() {
4380   return HasTransitionArray() && transitions()->HasElementsTransition();
4381 }
4382 
4383 
HasTransitionArray()4384 bool Map::HasTransitionArray() {
4385   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4386   return object->IsTransitionArray();
4387 }
4388 
4389 
elements_transition_map()4390 Map* Map::elements_transition_map() {
4391   int index = transitions()->Search(GetHeap()->elements_transition_symbol());
4392   return transitions()->GetTarget(index);
4393 }
4394 
4395 
CanHaveMoreTransitions()4396 bool Map::CanHaveMoreTransitions() {
4397   if (!HasTransitionArray()) return true;
4398   return FixedArray::SizeFor(transitions()->length() +
4399                              TransitionArray::kTransitionSize)
4400       <= Page::kMaxNonCodeHeapObjectSize;
4401 }
4402 
4403 
AddTransition(Name * key,Map * target,SimpleTransitionFlag flag)4404 MaybeObject* Map::AddTransition(Name* key,
4405                                 Map* target,
4406                                 SimpleTransitionFlag flag) {
4407   if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
4408   return TransitionArray::NewWith(flag, key, target, GetBackPointer());
4409 }
4410 
4411 
SetTransition(int transition_index,Map * target)4412 void Map::SetTransition(int transition_index, Map* target) {
4413   transitions()->SetTarget(transition_index, target);
4414 }
4415 
4416 
GetTransition(int transition_index)4417 Map* Map::GetTransition(int transition_index) {
4418   return transitions()->GetTarget(transition_index);
4419 }
4420 
4421 
set_elements_transition_map(Map * transitioned_map)4422 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
4423   TransitionArray* transitions;
4424   MaybeObject* maybe_transitions = AddTransition(
4425       GetHeap()->elements_transition_symbol(),
4426       transitioned_map,
4427       FULL_TRANSITION);
4428   if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4429   set_transitions(transitions);
4430   return transitions;
4431 }
4432 
4433 
GetPrototypeTransitions()4434 FixedArray* Map::GetPrototypeTransitions() {
4435   if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
4436   if (!transitions()->HasPrototypeTransitions()) {
4437     return GetHeap()->empty_fixed_array();
4438   }
4439   return transitions()->GetPrototypeTransitions();
4440 }
4441 
4442 
SetPrototypeTransitions(FixedArray * proto_transitions)4443 MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
4444   MaybeObject* allow_prototype = EnsureHasTransitionArray(this);
4445   if (allow_prototype->IsFailure()) return allow_prototype;
4446   int old_number_of_transitions = NumberOfProtoTransitions();
4447 #ifdef DEBUG
4448   if (HasPrototypeTransitions()) {
4449     ASSERT(GetPrototypeTransitions() != proto_transitions);
4450     ZapPrototypeTransitions();
4451   }
4452 #endif
4453   transitions()->SetPrototypeTransitions(proto_transitions);
4454   SetNumberOfProtoTransitions(old_number_of_transitions);
4455   return this;
4456 }
4457 
4458 
HasPrototypeTransitions()4459 bool Map::HasPrototypeTransitions() {
4460   return HasTransitionArray() && transitions()->HasPrototypeTransitions();
4461 }
4462 
4463 
transitions()4464 TransitionArray* Map::transitions() {
4465   ASSERT(HasTransitionArray());
4466   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4467   return TransitionArray::cast(object);
4468 }
4469 
4470 
set_transitions(TransitionArray * transition_array,WriteBarrierMode mode)4471 void Map::set_transitions(TransitionArray* transition_array,
4472                           WriteBarrierMode mode) {
4473   // Transition arrays are not shared. When one is replaced, it should not
4474   // keep referenced objects alive, so we zap it.
4475   // When there is another reference to the array somewhere (e.g. a handle),
4476   // not zapping turns from a waste of memory into a source of crashes.
4477   if (HasTransitionArray()) {
4478 #ifdef DEBUG
4479     for (int i = 0; i < transitions()->number_of_transitions(); i++) {
4480       Map* target = transitions()->GetTarget(i);
4481       if (target->instance_descriptors() == instance_descriptors()) {
4482         Name* key = transitions()->GetKey(i);
4483         int new_target_index = transition_array->Search(key);
4484         ASSERT(new_target_index != TransitionArray::kNotFound);
4485         ASSERT(transition_array->GetTarget(new_target_index) == target);
4486       }
4487     }
4488 #endif
4489     ASSERT(transitions() != transition_array);
4490     ZapTransitions();
4491   }
4492 
4493   WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array);
4494   CONDITIONAL_WRITE_BARRIER(
4495       GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode);
4496 }
4497 
4498 
init_back_pointer(Object * undefined)4499 void Map::init_back_pointer(Object* undefined) {
4500   ASSERT(undefined->IsUndefined());
4501   WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined);
4502 }
4503 
4504 
SetBackPointer(Object * value,WriteBarrierMode mode)4505 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
4506   ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE);
4507   ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) ||
4508          (value->IsMap() && GetBackPointer()->IsUndefined()));
4509   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4510   if (object->IsTransitionArray()) {
4511     TransitionArray::cast(object)->set_back_pointer_storage(value);
4512   } else {
4513     WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value);
4514     CONDITIONAL_WRITE_BARRIER(
4515         GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode);
4516   }
4517 }
4518 
4519 
4520 // Can either be Smi (no transitions), normal transition array, or a transition
4521 // array with the header overwritten as a Smi (thus iterating).
unchecked_transition_array()4522 TransitionArray* Map::unchecked_transition_array() {
4523   Object* object = *HeapObject::RawField(this,
4524                                          Map::kTransitionsOrBackPointerOffset);
4525   TransitionArray* transition_array = static_cast<TransitionArray*>(object);
4526   return transition_array;
4527 }
4528 
4529 
UncheckedPrototypeTransitions()4530 HeapObject* Map::UncheckedPrototypeTransitions() {
4531   ASSERT(HasTransitionArray());
4532   ASSERT(unchecked_transition_array()->HasPrototypeTransitions());
4533   return unchecked_transition_array()->UncheckedPrototypeTransitions();
4534 }
4535 
4536 
ACCESSORS(Map,code_cache,Object,kCodeCacheOffset)4537 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
4538 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
4539 ACCESSORS(Map, constructor, Object, kConstructorOffset)
4540 
4541 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
4542 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
4543 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
4544 
4545 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
4546 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset)
4547 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
4548 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
4549 
4550 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
4551 
4552 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
4553 ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
4554 ACCESSORS(AccessorInfo, expected_receiver_type, Object,
4555           kExpectedReceiverTypeOffset)
4556 
4557 ACCESSORS(DeclaredAccessorDescriptor, serialized_data, ByteArray,
4558           kSerializedDataOffset)
4559 
4560 ACCESSORS(DeclaredAccessorInfo, descriptor, DeclaredAccessorDescriptor,
4561           kDescriptorOffset)
4562 
4563 ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset)
4564 ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
4565 ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
4566 
4567 ACCESSORS(Box, value, Object, kValueOffset)
4568 
4569 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
4570 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
4571 ACCESSORS_TO_SMI(AccessorPair, access_flags, kAccessFlagsOffset)
4572 
4573 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
4574 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
4575 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
4576 
4577 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
4578 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
4579 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
4580 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
4581 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
4582 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
4583 
4584 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
4585 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
4586 
4587 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
4588 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
4589 ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
4590 
4591 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
4592 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
4593 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
4594           kPrototypeTemplateOffset)
4595 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
4596 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
4597           kNamedPropertyHandlerOffset)
4598 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
4599           kIndexedPropertyHandlerOffset)
4600 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
4601           kInstanceTemplateOffset)
4602 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
4603 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
4604 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
4605           kInstanceCallHandlerOffset)
4606 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
4607           kAccessCheckInfoOffset)
4608 ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
4609 
4610 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
4611 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
4612           kInternalFieldCountOffset)
4613 
4614 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
4615 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
4616 
4617 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
4618 
4619 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
4620 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
4621 ACCESSORS_TO_SMI(AllocationSite, memento_found_count, kMementoFoundCountOffset)
4622 ACCESSORS_TO_SMI(AllocationSite, memento_create_count,
4623                  kMementoCreateCountOffset)
4624 ACCESSORS_TO_SMI(AllocationSite, pretenure_decision, kPretenureDecisionOffset)
4625 ACCESSORS(AllocationSite, dependent_code, DependentCode,
4626           kDependentCodeOffset)
4627 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
4628 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
4629 
4630 ACCESSORS(Script, source, Object, kSourceOffset)
4631 ACCESSORS(Script, name, Object, kNameOffset)
4632 ACCESSORS(Script, id, Smi, kIdOffset)
4633 ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
4634 ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
4635 ACCESSORS(Script, data, Object, kDataOffset)
4636 ACCESSORS(Script, context_data, Object, kContextOffset)
4637 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
4638 ACCESSORS_TO_SMI(Script, type, kTypeOffset)
4639 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
4640 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
4641 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
4642                  kEvalFrominstructionsOffsetOffset)
4643 ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
4644 BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
4645 
4646 Script::CompilationType Script::compilation_type() {
4647   return BooleanBit::get(flags(), kCompilationTypeBit) ?
4648       COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST;
4649 }
set_compilation_type(CompilationType type)4650 void Script::set_compilation_type(CompilationType type) {
4651   set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
4652       type == COMPILATION_TYPE_EVAL));
4653 }
compilation_state()4654 Script::CompilationState Script::compilation_state() {
4655   return BooleanBit::get(flags(), kCompilationStateBit) ?
4656       COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
4657 }
set_compilation_state(CompilationState state)4658 void Script::set_compilation_state(CompilationState state) {
4659   set_flags(BooleanBit::set(flags(), kCompilationStateBit,
4660       state == COMPILATION_STATE_COMPILED));
4661 }
4662 
4663 
4664 #ifdef ENABLE_DEBUGGER_SUPPORT
ACCESSORS(DebugInfo,shared,SharedFunctionInfo,kSharedFunctionInfoIndex)4665 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
4666 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
4667 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
4668 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
4669 
4670 ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
4671 ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
4672 ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
4673 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
4674 #endif
4675 
4676 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
4677 ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
4678                  kOptimizedCodeMapOffset)
4679 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
4680 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
4681 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
4682           kInstanceClassNameOffset)
4683 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
4684 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
4685 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
4686 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
4687 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
4688 
4689 
4690 SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
4691 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
4692                kHiddenPrototypeBit)
4693 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
4694 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
4695                kNeedsAccessCheckBit)
4696 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
4697                kReadOnlyPrototypeBit)
4698 BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
4699                kRemovePrototypeBit)
4700 BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
4701                kDoNotCacheBit)
4702 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
4703                kIsExpressionBit)
4704 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
4705                kIsTopLevelBit)
4706 
4707 BOOL_ACCESSORS(SharedFunctionInfo,
4708                compiler_hints,
4709                allows_lazy_compilation,
4710                kAllowLazyCompilation)
4711 BOOL_ACCESSORS(SharedFunctionInfo,
4712                compiler_hints,
4713                allows_lazy_compilation_without_context,
4714                kAllowLazyCompilationWithoutContext)
4715 BOOL_ACCESSORS(SharedFunctionInfo,
4716                compiler_hints,
4717                uses_arguments,
4718                kUsesArguments)
4719 BOOL_ACCESSORS(SharedFunctionInfo,
4720                compiler_hints,
4721                has_duplicate_parameters,
4722                kHasDuplicateParameters)
4723 
4724 
4725 #if V8_HOST_ARCH_32_BIT
4726 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
4727 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
4728               kFormalParameterCountOffset)
4729 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
4730               kExpectedNofPropertiesOffset)
4731 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
4732 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
4733               kStartPositionAndTypeOffset)
4734 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
4735 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
4736               kFunctionTokenPositionOffset)
4737 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
4738               kCompilerHintsOffset)
4739 SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
4740               kOptCountAndBailoutReasonOffset)
4741 SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
4742 
4743 #else
4744 
4745 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
4746   STATIC_ASSERT(holder::offset % kPointerSize == 0);              \
4747   int holder::name() {                                            \
4748     int value = READ_INT_FIELD(this, offset);                     \
4749     ASSERT(kHeapObjectTag == 1);                                  \
4750     ASSERT((value & kHeapObjectTag) == 0);                        \
4751     return value >> 1;                                            \
4752   }                                                               \
4753   void holder::set_##name(int value) {                            \
4754     ASSERT(kHeapObjectTag == 1);                                  \
4755     ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
4756            (value & 0xC0000000) == 0x000000000);                  \
4757     WRITE_INT_FIELD(this,                                         \
4758                     offset,                                       \
4759                     (value << 1) & ~kHeapObjectTag);              \
4760   }
4761 
4762 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset)             \
4763   STATIC_ASSERT(holder::offset % kPointerSize == kIntSize);       \
4764   INT_ACCESSORS(holder, name, offset)
4765 
4766 
4767 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
4768 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
4769                         formal_parameter_count,
4770                         kFormalParameterCountOffset)
4771 
4772 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
4773                         expected_nof_properties,
4774                         kExpectedNofPropertiesOffset)
4775 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
4776 
4777 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
4778 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
4779                         start_position_and_type,
4780                         kStartPositionAndTypeOffset)
4781 
4782 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
4783                         function_token_position,
4784                         kFunctionTokenPositionOffset)
4785 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
4786                         compiler_hints,
4787                         kCompilerHintsOffset)
4788 
4789 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
4790                         opt_count_and_bailout_reason,
4791                         kOptCountAndBailoutReasonOffset)
4792 
4793 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
4794 
4795 #endif
4796 
4797 
4798 int SharedFunctionInfo::construction_count() {
4799   return READ_BYTE_FIELD(this, kConstructionCountOffset);
4800 }
4801 
4802 
set_construction_count(int value)4803 void SharedFunctionInfo::set_construction_count(int value) {
4804   ASSERT(0 <= value && value < 256);
4805   WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
4806 }
4807 
4808 
BOOL_ACCESSORS(SharedFunctionInfo,compiler_hints,live_objects_may_exist,kLiveObjectsMayExist)4809 BOOL_ACCESSORS(SharedFunctionInfo,
4810                compiler_hints,
4811                live_objects_may_exist,
4812                kLiveObjectsMayExist)
4813 
4814 
4815 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
4816   return initial_map() != GetHeap()->undefined_value();
4817 }
4818 
4819 
BOOL_GETTER(SharedFunctionInfo,compiler_hints,optimization_disabled,kOptimizationDisabled)4820 BOOL_GETTER(SharedFunctionInfo,
4821             compiler_hints,
4822             optimization_disabled,
4823             kOptimizationDisabled)
4824 
4825 
4826 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
4827   set_compiler_hints(BooleanBit::set(compiler_hints(),
4828                                      kOptimizationDisabled,
4829                                      disable));
4830   // If disabling optimizations we reflect that in the code object so
4831   // it will not be counted as optimizable code.
4832   if ((code()->kind() == Code::FUNCTION) && disable) {
4833     code()->set_optimizable(false);
4834   }
4835 }
4836 
4837 
profiler_ticks()4838 int SharedFunctionInfo::profiler_ticks() {
4839   if (code()->kind() != Code::FUNCTION) return 0;
4840   return code()->profiler_ticks();
4841 }
4842 
4843 
language_mode()4844 LanguageMode SharedFunctionInfo::language_mode() {
4845   int hints = compiler_hints();
4846   if (BooleanBit::get(hints, kExtendedModeFunction)) {
4847     ASSERT(BooleanBit::get(hints, kStrictModeFunction));
4848     return EXTENDED_MODE;
4849   }
4850   return BooleanBit::get(hints, kStrictModeFunction)
4851       ? STRICT_MODE : CLASSIC_MODE;
4852 }
4853 
4854 
set_language_mode(LanguageMode language_mode)4855 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
4856   // We only allow language mode transitions that go set the same language mode
4857   // again or go up in the chain:
4858   //   CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
4859   ASSERT(this->language_mode() == CLASSIC_MODE ||
4860          this->language_mode() == language_mode ||
4861          language_mode == EXTENDED_MODE);
4862   int hints = compiler_hints();
4863   hints = BooleanBit::set(
4864       hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
4865   hints = BooleanBit::set(
4866       hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
4867   set_compiler_hints(hints);
4868 }
4869 
4870 
is_classic_mode()4871 bool SharedFunctionInfo::is_classic_mode() {
4872   return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
4873 }
4874 
BOOL_GETTER(SharedFunctionInfo,compiler_hints,is_extended_mode,kExtendedModeFunction)4875 BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
4876             kExtendedModeFunction)
4877 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
4878 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
4879                kInlineBuiltin)
4880 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
4881                name_should_print_as_anonymous,
4882                kNameShouldPrintAsAnonymous)
4883 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
4884 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
4885 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
4886 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
4887                kDontOptimize)
4888 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
4889 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
4890 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
4891 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
4892 
4893 void SharedFunctionInfo::BeforeVisitingPointers() {
4894   if (IsInobjectSlackTrackingInProgress()) DetachInitialMap();
4895 }
4896 
4897 
ACCESSORS(CodeCache,default_cache,FixedArray,kDefaultCacheOffset)4898 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
4899 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
4900 
4901 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
4902 
4903 bool Script::HasValidSource() {
4904   Object* src = this->source();
4905   if (!src->IsString()) return true;
4906   String* src_str = String::cast(src);
4907   if (!StringShape(src_str).IsExternal()) return true;
4908   if (src_str->IsOneByteRepresentation()) {
4909     return ExternalAsciiString::cast(src)->resource() != NULL;
4910   } else if (src_str->IsTwoByteRepresentation()) {
4911     return ExternalTwoByteString::cast(src)->resource() != NULL;
4912   }
4913   return true;
4914 }
4915 
4916 
DontAdaptArguments()4917 void SharedFunctionInfo::DontAdaptArguments() {
4918   ASSERT(code()->kind() == Code::BUILTIN);
4919   set_formal_parameter_count(kDontAdaptArgumentsSentinel);
4920 }
4921 
4922 
start_position()4923 int SharedFunctionInfo::start_position() {
4924   return start_position_and_type() >> kStartPositionShift;
4925 }
4926 
4927 
set_start_position(int start_position)4928 void SharedFunctionInfo::set_start_position(int start_position) {
4929   set_start_position_and_type((start_position << kStartPositionShift)
4930     | (start_position_and_type() & ~kStartPositionMask));
4931 }
4932 
4933 
code()4934 Code* SharedFunctionInfo::code() {
4935   return Code::cast(READ_FIELD(this, kCodeOffset));
4936 }
4937 
4938 
set_code(Code * value,WriteBarrierMode mode)4939 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
4940   ASSERT(value->kind() != Code::OPTIMIZED_FUNCTION);
4941   WRITE_FIELD(this, kCodeOffset, value);
4942   CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
4943 }
4944 
4945 
ReplaceCode(Code * value)4946 void SharedFunctionInfo::ReplaceCode(Code* value) {
4947   // If the GC metadata field is already used then the function was
4948   // enqueued as a code flushing candidate and we remove it now.
4949   if (code()->gc_metadata() != NULL) {
4950     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
4951     flusher->EvictCandidate(this);
4952   }
4953 
4954   ASSERT(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
4955   set_code(value);
4956 }
4957 
4958 
scope_info()4959 ScopeInfo* SharedFunctionInfo::scope_info() {
4960   return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
4961 }
4962 
4963 
set_scope_info(ScopeInfo * value,WriteBarrierMode mode)4964 void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
4965                                         WriteBarrierMode mode) {
4966   WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
4967   CONDITIONAL_WRITE_BARRIER(GetHeap(),
4968                             this,
4969                             kScopeInfoOffset,
4970                             reinterpret_cast<Object*>(value),
4971                             mode);
4972 }
4973 
4974 
is_compiled()4975 bool SharedFunctionInfo::is_compiled() {
4976   return code() !=
4977       GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
4978 }
4979 
4980 
IsApiFunction()4981 bool SharedFunctionInfo::IsApiFunction() {
4982   return function_data()->IsFunctionTemplateInfo();
4983 }
4984 
4985 
get_api_func_data()4986 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
4987   ASSERT(IsApiFunction());
4988   return FunctionTemplateInfo::cast(function_data());
4989 }
4990 
4991 
HasBuiltinFunctionId()4992 bool SharedFunctionInfo::HasBuiltinFunctionId() {
4993   return function_data()->IsSmi();
4994 }
4995 
4996 
builtin_function_id()4997 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
4998   ASSERT(HasBuiltinFunctionId());
4999   return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
5000 }
5001 
5002 
ic_age()5003 int SharedFunctionInfo::ic_age() {
5004   return ICAgeBits::decode(counters());
5005 }
5006 
5007 
set_ic_age(int ic_age)5008 void SharedFunctionInfo::set_ic_age(int ic_age) {
5009   set_counters(ICAgeBits::update(counters(), ic_age));
5010 }
5011 
5012 
deopt_count()5013 int SharedFunctionInfo::deopt_count() {
5014   return DeoptCountBits::decode(counters());
5015 }
5016 
5017 
set_deopt_count(int deopt_count)5018 void SharedFunctionInfo::set_deopt_count(int deopt_count) {
5019   set_counters(DeoptCountBits::update(counters(), deopt_count));
5020 }
5021 
5022 
increment_deopt_count()5023 void SharedFunctionInfo::increment_deopt_count() {
5024   int value = counters();
5025   int deopt_count = DeoptCountBits::decode(value);
5026   deopt_count = (deopt_count + 1) & DeoptCountBits::kMax;
5027   set_counters(DeoptCountBits::update(value, deopt_count));
5028 }
5029 
5030 
opt_reenable_tries()5031 int SharedFunctionInfo::opt_reenable_tries() {
5032   return OptReenableTriesBits::decode(counters());
5033 }
5034 
5035 
set_opt_reenable_tries(int tries)5036 void SharedFunctionInfo::set_opt_reenable_tries(int tries) {
5037   set_counters(OptReenableTriesBits::update(counters(), tries));
5038 }
5039 
5040 
opt_count()5041 int SharedFunctionInfo::opt_count() {
5042   return OptCountBits::decode(opt_count_and_bailout_reason());
5043 }
5044 
5045 
set_opt_count(int opt_count)5046 void SharedFunctionInfo::set_opt_count(int opt_count) {
5047   set_opt_count_and_bailout_reason(
5048       OptCountBits::update(opt_count_and_bailout_reason(), opt_count));
5049 }
5050 
5051 
DisableOptimizationReason()5052 BailoutReason SharedFunctionInfo::DisableOptimizationReason() {
5053   BailoutReason reason = static_cast<BailoutReason>(
5054       DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason()));
5055   return reason;
5056 }
5057 
5058 
has_deoptimization_support()5059 bool SharedFunctionInfo::has_deoptimization_support() {
5060   Code* code = this->code();
5061   return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
5062 }
5063 
5064 
TryReenableOptimization()5065 void SharedFunctionInfo::TryReenableOptimization() {
5066   int tries = opt_reenable_tries();
5067   set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
5068   // We reenable optimization whenever the number of tries is a large
5069   // enough power of 2.
5070   if (tries >= 16 && (((tries - 1) & tries) == 0)) {
5071     set_optimization_disabled(false);
5072     set_opt_count(0);
5073     set_deopt_count(0);
5074     code()->set_optimizable(true);
5075   }
5076 }
5077 
5078 
IsBuiltin()5079 bool JSFunction::IsBuiltin() {
5080   return context()->global_object()->IsJSBuiltinsObject();
5081 }
5082 
5083 
NeedsArgumentsAdaption()5084 bool JSFunction::NeedsArgumentsAdaption() {
5085   return shared()->formal_parameter_count() !=
5086       SharedFunctionInfo::kDontAdaptArgumentsSentinel;
5087 }
5088 
5089 
IsOptimized()5090 bool JSFunction::IsOptimized() {
5091   return code()->kind() == Code::OPTIMIZED_FUNCTION;
5092 }
5093 
5094 
IsOptimizable()5095 bool JSFunction::IsOptimizable() {
5096   return code()->kind() == Code::FUNCTION && code()->optimizable();
5097 }
5098 
5099 
IsMarkedForLazyRecompilation()5100 bool JSFunction::IsMarkedForLazyRecompilation() {
5101   return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
5102 }
5103 
5104 
IsMarkedForConcurrentRecompilation()5105 bool JSFunction::IsMarkedForConcurrentRecompilation() {
5106   return code() == GetIsolate()->builtins()->builtin(
5107       Builtins::kConcurrentRecompile);
5108 }
5109 
5110 
IsInRecompileQueue()5111 bool JSFunction::IsInRecompileQueue() {
5112   return code() == GetIsolate()->builtins()->builtin(
5113       Builtins::kInRecompileQueue);
5114 }
5115 
5116 
code()5117 Code* JSFunction::code() {
5118   return Code::cast(
5119       Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
5120 }
5121 
5122 
set_code(Code * value)5123 void JSFunction::set_code(Code* value) {
5124   ASSERT(!GetHeap()->InNewSpace(value));
5125   Address entry = value->entry();
5126   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5127   GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
5128       this,
5129       HeapObject::RawField(this, kCodeEntryOffset),
5130       value);
5131 }
5132 
5133 
set_code_no_write_barrier(Code * value)5134 void JSFunction::set_code_no_write_barrier(Code* value) {
5135   ASSERT(!GetHeap()->InNewSpace(value));
5136   Address entry = value->entry();
5137   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5138 }
5139 
5140 
ReplaceCode(Code * code)5141 void JSFunction::ReplaceCode(Code* code) {
5142   bool was_optimized = IsOptimized();
5143   bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
5144 
5145   if (was_optimized && is_optimized) {
5146     shared()->EvictFromOptimizedCodeMap(
5147       this->code(), "Replacing with another optimized code");
5148   }
5149 
5150   set_code(code);
5151 
5152   // Add/remove the function from the list of optimized functions for this
5153   // context based on the state change.
5154   if (!was_optimized && is_optimized) {
5155     context()->native_context()->AddOptimizedFunction(this);
5156   }
5157   if (was_optimized && !is_optimized) {
5158     // TODO(titzer): linear in the number of optimized functions; fix!
5159     context()->native_context()->RemoveOptimizedFunction(this);
5160   }
5161 }
5162 
5163 
context()5164 Context* JSFunction::context() {
5165   return Context::cast(READ_FIELD(this, kContextOffset));
5166 }
5167 
5168 
set_context(Object * value)5169 void JSFunction::set_context(Object* value) {
5170   ASSERT(value->IsUndefined() || value->IsContext());
5171   WRITE_FIELD(this, kContextOffset, value);
5172   WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
5173 }
5174 
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)5175 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
5176           kPrototypeOrInitialMapOffset)
5177 
5178 
5179 Map* JSFunction::initial_map() {
5180   return Map::cast(prototype_or_initial_map());
5181 }
5182 
5183 
set_initial_map(Map * value)5184 void JSFunction::set_initial_map(Map* value) {
5185   set_prototype_or_initial_map(value);
5186 }
5187 
5188 
has_initial_map()5189 bool JSFunction::has_initial_map() {
5190   return prototype_or_initial_map()->IsMap();
5191 }
5192 
5193 
has_instance_prototype()5194 bool JSFunction::has_instance_prototype() {
5195   return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
5196 }
5197 
5198 
has_prototype()5199 bool JSFunction::has_prototype() {
5200   return map()->has_non_instance_prototype() || has_instance_prototype();
5201 }
5202 
5203 
instance_prototype()5204 Object* JSFunction::instance_prototype() {
5205   ASSERT(has_instance_prototype());
5206   if (has_initial_map()) return initial_map()->prototype();
5207   // When there is no initial map and the prototype is a JSObject, the
5208   // initial map field is used for the prototype field.
5209   return prototype_or_initial_map();
5210 }
5211 
5212 
prototype()5213 Object* JSFunction::prototype() {
5214   ASSERT(has_prototype());
5215   // If the function's prototype property has been set to a non-JSObject
5216   // value, that value is stored in the constructor field of the map.
5217   if (map()->has_non_instance_prototype()) return map()->constructor();
5218   return instance_prototype();
5219 }
5220 
5221 
should_have_prototype()5222 bool JSFunction::should_have_prototype() {
5223   return map()->function_with_prototype();
5224 }
5225 
5226 
is_compiled()5227 bool JSFunction::is_compiled() {
5228   return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
5229 }
5230 
5231 
literals()5232 FixedArray* JSFunction::literals() {
5233   ASSERT(!shared()->bound());
5234   return literals_or_bindings();
5235 }
5236 
5237 
set_literals(FixedArray * literals)5238 void JSFunction::set_literals(FixedArray* literals) {
5239   ASSERT(!shared()->bound());
5240   set_literals_or_bindings(literals);
5241 }
5242 
5243 
function_bindings()5244 FixedArray* JSFunction::function_bindings() {
5245   ASSERT(shared()->bound());
5246   return literals_or_bindings();
5247 }
5248 
5249 
set_function_bindings(FixedArray * bindings)5250 void JSFunction::set_function_bindings(FixedArray* bindings) {
5251   ASSERT(shared()->bound());
5252   // Bound function literal may be initialized to the empty fixed array
5253   // before the bindings are set.
5254   ASSERT(bindings == GetHeap()->empty_fixed_array() ||
5255          bindings->map() == GetHeap()->fixed_cow_array_map());
5256   set_literals_or_bindings(bindings);
5257 }
5258 
5259 
NumberOfLiterals()5260 int JSFunction::NumberOfLiterals() {
5261   ASSERT(!shared()->bound());
5262   return literals()->length();
5263 }
5264 
5265 
javascript_builtin(Builtins::JavaScript id)5266 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
5267   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5268   return READ_FIELD(this, OffsetOfFunctionWithId(id));
5269 }
5270 
5271 
set_javascript_builtin(Builtins::JavaScript id,Object * value)5272 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
5273                                               Object* value) {
5274   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5275   WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
5276   WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
5277 }
5278 
5279 
javascript_builtin_code(Builtins::JavaScript id)5280 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
5281   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5282   return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
5283 }
5284 
5285 
set_javascript_builtin_code(Builtins::JavaScript id,Code * value)5286 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
5287                                                    Code* value) {
5288   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5289   WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
5290   ASSERT(!GetHeap()->InNewSpace(value));
5291 }
5292 
5293 
ACCESSORS(JSProxy,handler,Object,kHandlerOffset)5294 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
5295 ACCESSORS(JSProxy, hash, Object, kHashOffset)
5296 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
5297 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
5298 
5299 
5300 void JSProxy::InitializeBody(int object_size, Object* value) {
5301   ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
5302   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
5303     WRITE_FIELD(this, offset, value);
5304   }
5305 }
5306 
5307 
ACCESSORS(JSSet,table,Object,kTableOffset)5308 ACCESSORS(JSSet, table, Object, kTableOffset)
5309 ACCESSORS(JSMap, table, Object, kTableOffset)
5310 ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
5311 ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
5312 
5313 
5314 Address Foreign::foreign_address() {
5315   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
5316 }
5317 
5318 
set_foreign_address(Address value)5319 void Foreign::set_foreign_address(Address value) {
5320   WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
5321 }
5322 
5323 
ACCESSORS(JSGeneratorObject,function,JSFunction,kFunctionOffset)5324 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
5325 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
5326 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
5327 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
5328 ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
5329 SMI_ACCESSORS(JSGeneratorObject, stack_handler_index, kStackHandlerIndexOffset)
5330 
5331 
5332 JSGeneratorObject* JSGeneratorObject::cast(Object* obj) {
5333   ASSERT(obj->IsJSGeneratorObject());
5334   ASSERT(HeapObject::cast(obj)->Size() == JSGeneratorObject::kSize);
5335   return reinterpret_cast<JSGeneratorObject*>(obj);
5336 }
5337 
5338 
ACCESSORS(JSModule,context,Object,kContextOffset)5339 ACCESSORS(JSModule, context, Object, kContextOffset)
5340 ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset)
5341 
5342 
5343 JSModule* JSModule::cast(Object* obj) {
5344   ASSERT(obj->IsJSModule());
5345   ASSERT(HeapObject::cast(obj)->Size() == JSModule::kSize);
5346   return reinterpret_cast<JSModule*>(obj);
5347 }
5348 
5349 
ACCESSORS(JSValue,value,Object,kValueOffset)5350 ACCESSORS(JSValue, value, Object, kValueOffset)
5351 
5352 
5353 JSValue* JSValue::cast(Object* obj) {
5354   ASSERT(obj->IsJSValue());
5355   ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
5356   return reinterpret_cast<JSValue*>(obj);
5357 }
5358 
5359 
ACCESSORS(JSDate,value,Object,kValueOffset)5360 ACCESSORS(JSDate, value, Object, kValueOffset)
5361 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
5362 ACCESSORS(JSDate, year, Object, kYearOffset)
5363 ACCESSORS(JSDate, month, Object, kMonthOffset)
5364 ACCESSORS(JSDate, day, Object, kDayOffset)
5365 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
5366 ACCESSORS(JSDate, hour, Object, kHourOffset)
5367 ACCESSORS(JSDate, min, Object, kMinOffset)
5368 ACCESSORS(JSDate, sec, Object, kSecOffset)
5369 
5370 
5371 JSDate* JSDate::cast(Object* obj) {
5372   ASSERT(obj->IsJSDate());
5373   ASSERT(HeapObject::cast(obj)->Size() == JSDate::kSize);
5374   return reinterpret_cast<JSDate*>(obj);
5375 }
5376 
5377 
ACCESSORS(JSMessageObject,type,String,kTypeOffset)5378 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
5379 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
5380 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
5381 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
5382 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
5383 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
5384 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
5385 
5386 
5387 JSMessageObject* JSMessageObject::cast(Object* obj) {
5388   ASSERT(obj->IsJSMessageObject());
5389   ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
5390   return reinterpret_cast<JSMessageObject*>(obj);
5391 }
5392 
5393 
INT_ACCESSORS(Code,instruction_size,kInstructionSizeOffset)5394 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
5395 INT_ACCESSORS(Code, prologue_offset, kPrologueOffset)
5396 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
5397 ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
5398 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
5399 ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
5400 
5401 
5402 void Code::WipeOutHeader() {
5403   WRITE_FIELD(this, kRelocationInfoOffset, NULL);
5404   WRITE_FIELD(this, kHandlerTableOffset, NULL);
5405   WRITE_FIELD(this, kDeoptimizationDataOffset, NULL);
5406   // Do not wipe out e.g. a minor key.
5407   if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) {
5408     WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL);
5409   }
5410 }
5411 
5412 
type_feedback_info()5413 Object* Code::type_feedback_info() {
5414   ASSERT(kind() == FUNCTION);
5415   return raw_type_feedback_info();
5416 }
5417 
5418 
set_type_feedback_info(Object * value,WriteBarrierMode mode)5419 void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
5420   ASSERT(kind() == FUNCTION);
5421   set_raw_type_feedback_info(value, mode);
5422   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
5423                             value, mode);
5424 }
5425 
5426 
next_code_link()5427 Object* Code::next_code_link() {
5428   CHECK(kind() == OPTIMIZED_FUNCTION);
5429   return raw_type_feedback_info();
5430 }
5431 
5432 
set_next_code_link(Object * value,WriteBarrierMode mode)5433 void Code::set_next_code_link(Object* value, WriteBarrierMode mode) {
5434   CHECK(kind() == OPTIMIZED_FUNCTION);
5435   set_raw_type_feedback_info(value);
5436   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
5437                             value, mode);
5438 }
5439 
5440 
stub_info()5441 int Code::stub_info() {
5442   ASSERT(kind() == COMPARE_IC || kind() == COMPARE_NIL_IC ||
5443          kind() == BINARY_OP_IC || kind() == LOAD_IC);
5444   return Smi::cast(raw_type_feedback_info())->value();
5445 }
5446 
5447 
set_stub_info(int value)5448 void Code::set_stub_info(int value) {
5449   ASSERT(kind() == COMPARE_IC ||
5450          kind() == COMPARE_NIL_IC ||
5451          kind() == BINARY_OP_IC ||
5452          kind() == STUB ||
5453          kind() == LOAD_IC ||
5454          kind() == KEYED_LOAD_IC ||
5455          kind() == STORE_IC ||
5456          kind() == KEYED_STORE_IC);
5457   set_raw_type_feedback_info(Smi::FromInt(value));
5458 }
5459 
5460 
ACCESSORS(Code,gc_metadata,Object,kGCMetadataOffset)5461 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
5462 INT_ACCESSORS(Code, ic_age, kICAgeOffset)
5463 
5464 
5465 byte* Code::instruction_start()  {
5466   return FIELD_ADDR(this, kHeaderSize);
5467 }
5468 
5469 
instruction_end()5470 byte* Code::instruction_end()  {
5471   return instruction_start() + instruction_size();
5472 }
5473 
5474 
body_size()5475 int Code::body_size() {
5476   return RoundUp(instruction_size(), kObjectAlignment);
5477 }
5478 
5479 
unchecked_relocation_info()5480 ByteArray* Code::unchecked_relocation_info() {
5481   return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
5482 }
5483 
5484 
relocation_start()5485 byte* Code::relocation_start() {
5486   return unchecked_relocation_info()->GetDataStartAddress();
5487 }
5488 
5489 
relocation_size()5490 int Code::relocation_size() {
5491   return unchecked_relocation_info()->length();
5492 }
5493 
5494 
entry()5495 byte* Code::entry() {
5496   return instruction_start();
5497 }
5498 
5499 
contains(byte * inner_pointer)5500 bool Code::contains(byte* inner_pointer) {
5501   return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
5502 }
5503 
5504 
ACCESSORS(JSArray,length,Object,kLengthOffset)5505 ACCESSORS(JSArray, length, Object, kLengthOffset)
5506 
5507 
5508 void* JSArrayBuffer::backing_store() {
5509   intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
5510   return reinterpret_cast<void*>(ptr);
5511 }
5512 
5513 
set_backing_store(void * value,WriteBarrierMode mode)5514 void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
5515   intptr_t ptr = reinterpret_cast<intptr_t>(value);
5516   WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
5517 }
5518 
5519 
ACCESSORS(JSArrayBuffer,byte_length,Object,kByteLengthOffset)5520 ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
5521 ACCESSORS_TO_SMI(JSArrayBuffer, flag, kFlagOffset)
5522 
5523 
5524 bool JSArrayBuffer::is_external() {
5525   return BooleanBit::get(flag(), kIsExternalBit);
5526 }
5527 
5528 
set_is_external(bool value)5529 void JSArrayBuffer::set_is_external(bool value) {
5530   set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
5531 }
5532 
5533 
should_be_freed()5534 bool JSArrayBuffer::should_be_freed() {
5535   return BooleanBit::get(flag(), kShouldBeFreed);
5536 }
5537 
5538 
set_should_be_freed(bool value)5539 void JSArrayBuffer::set_should_be_freed(bool value) {
5540   set_flag(BooleanBit::set(flag(), kShouldBeFreed, value));
5541 }
5542 
5543 
ACCESSORS(JSArrayBuffer,weak_next,Object,kWeakNextOffset)5544 ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
5545 ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset)
5546 
5547 
5548 ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
5549 ACCESSORS(JSArrayBufferView, byte_offset, Object, kByteOffsetOffset)
5550 ACCESSORS(JSArrayBufferView, byte_length, Object, kByteLengthOffset)
5551 ACCESSORS(JSArrayBufferView, weak_next, Object, kWeakNextOffset)
5552 ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
5553 
5554 ACCESSORS(JSRegExp, data, Object, kDataOffset)
5555 
5556 
5557 JSRegExp::Type JSRegExp::TypeTag() {
5558   Object* data = this->data();
5559   if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
5560   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
5561   return static_cast<JSRegExp::Type>(smi->value());
5562 }
5563 
5564 
CaptureCount()5565 int JSRegExp::CaptureCount() {
5566   switch (TypeTag()) {
5567     case ATOM:
5568       return 0;
5569     case IRREGEXP:
5570       return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
5571     default:
5572       UNREACHABLE();
5573       return -1;
5574   }
5575 }
5576 
5577 
GetFlags()5578 JSRegExp::Flags JSRegExp::GetFlags() {
5579   ASSERT(this->data()->IsFixedArray());
5580   Object* data = this->data();
5581   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
5582   return Flags(smi->value());
5583 }
5584 
5585 
Pattern()5586 String* JSRegExp::Pattern() {
5587   ASSERT(this->data()->IsFixedArray());
5588   Object* data = this->data();
5589   String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
5590   return pattern;
5591 }
5592 
5593 
DataAt(int index)5594 Object* JSRegExp::DataAt(int index) {
5595   ASSERT(TypeTag() != NOT_COMPILED);
5596   return FixedArray::cast(data())->get(index);
5597 }
5598 
5599 
SetDataAt(int index,Object * value)5600 void JSRegExp::SetDataAt(int index, Object* value) {
5601   ASSERT(TypeTag() != NOT_COMPILED);
5602   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
5603   FixedArray::cast(data())->set(index, value);
5604 }
5605 
5606 
GetElementsKind()5607 ElementsKind JSObject::GetElementsKind() {
5608   ElementsKind kind = map()->elements_kind();
5609 #if DEBUG
5610   FixedArrayBase* fixed_array =
5611       reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
5612 
5613   // If a GC was caused while constructing this object, the elements
5614   // pointer may point to a one pointer filler map.
5615   if (ElementsAreSafeToExamine()) {
5616     Map* map = fixed_array->map();
5617     ASSERT((IsFastSmiOrObjectElementsKind(kind) &&
5618             (map == GetHeap()->fixed_array_map() ||
5619              map == GetHeap()->fixed_cow_array_map())) ||
5620            (IsFastDoubleElementsKind(kind) &&
5621             (fixed_array->IsFixedDoubleArray() ||
5622              fixed_array == GetHeap()->empty_fixed_array())) ||
5623            (kind == DICTIONARY_ELEMENTS &&
5624             fixed_array->IsFixedArray() &&
5625             fixed_array->IsDictionary()) ||
5626            (kind > DICTIONARY_ELEMENTS));
5627     ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
5628            (elements()->IsFixedArray() && elements()->length() >= 2));
5629   }
5630 #endif
5631   return kind;
5632 }
5633 
5634 
GetElementsAccessor()5635 ElementsAccessor* JSObject::GetElementsAccessor() {
5636   return ElementsAccessor::ForKind(GetElementsKind());
5637 }
5638 
5639 
HasFastObjectElements()5640 bool JSObject::HasFastObjectElements() {
5641   return IsFastObjectElementsKind(GetElementsKind());
5642 }
5643 
5644 
HasFastSmiElements()5645 bool JSObject::HasFastSmiElements() {
5646   return IsFastSmiElementsKind(GetElementsKind());
5647 }
5648 
5649 
HasFastSmiOrObjectElements()5650 bool JSObject::HasFastSmiOrObjectElements() {
5651   return IsFastSmiOrObjectElementsKind(GetElementsKind());
5652 }
5653 
5654 
HasFastDoubleElements()5655 bool JSObject::HasFastDoubleElements() {
5656   return IsFastDoubleElementsKind(GetElementsKind());
5657 }
5658 
5659 
HasFastHoleyElements()5660 bool JSObject::HasFastHoleyElements() {
5661   return IsFastHoleyElementsKind(GetElementsKind());
5662 }
5663 
5664 
HasFastElements()5665 bool JSObject::HasFastElements() {
5666   return IsFastElementsKind(GetElementsKind());
5667 }
5668 
5669 
HasDictionaryElements()5670 bool JSObject::HasDictionaryElements() {
5671   return GetElementsKind() == DICTIONARY_ELEMENTS;
5672 }
5673 
5674 
HasNonStrictArgumentsElements()5675 bool JSObject::HasNonStrictArgumentsElements() {
5676   return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
5677 }
5678 
5679 
HasExternalArrayElements()5680 bool JSObject::HasExternalArrayElements() {
5681   HeapObject* array = elements();
5682   ASSERT(array != NULL);
5683   return array->IsExternalArray();
5684 }
5685 
5686 
5687 #define EXTERNAL_ELEMENTS_CHECK(name, type)          \
5688 bool JSObject::HasExternal##name##Elements() {       \
5689   HeapObject* array = elements();                    \
5690   ASSERT(array != NULL);                             \
5691   if (!array->IsHeapObject())                        \
5692     return false;                                    \
5693   return array->map()->instance_type() == type;      \
5694 }
5695 
5696 
EXTERNAL_ELEMENTS_CHECK(Byte,EXTERNAL_BYTE_ARRAY_TYPE)5697 EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
5698 EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
5699 EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
5700 EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
5701                         EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
5702 EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
5703 EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
5704                         EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
5705 EXTERNAL_ELEMENTS_CHECK(Float,
5706                         EXTERNAL_FLOAT_ARRAY_TYPE)
5707 EXTERNAL_ELEMENTS_CHECK(Double,
5708                         EXTERNAL_DOUBLE_ARRAY_TYPE)
5709 EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
5710 
5711 
5712 bool JSObject::HasNamedInterceptor() {
5713   return map()->has_named_interceptor();
5714 }
5715 
5716 
HasIndexedInterceptor()5717 bool JSObject::HasIndexedInterceptor() {
5718   return map()->has_indexed_interceptor();
5719 }
5720 
5721 
EnsureWritableFastElements()5722 MaybeObject* JSObject::EnsureWritableFastElements() {
5723   ASSERT(HasFastSmiOrObjectElements());
5724   FixedArray* elems = FixedArray::cast(elements());
5725   Isolate* isolate = GetIsolate();
5726   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
5727   Object* writable_elems;
5728   { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
5729       elems, isolate->heap()->fixed_array_map());
5730     if (!maybe_writable_elems->ToObject(&writable_elems)) {
5731       return maybe_writable_elems;
5732     }
5733   }
5734   set_elements(FixedArray::cast(writable_elems));
5735   isolate->counters()->cow_arrays_converted()->Increment();
5736   return writable_elems;
5737 }
5738 
5739 
property_dictionary()5740 NameDictionary* JSObject::property_dictionary() {
5741   ASSERT(!HasFastProperties());
5742   return NameDictionary::cast(properties());
5743 }
5744 
5745 
element_dictionary()5746 SeededNumberDictionary* JSObject::element_dictionary() {
5747   ASSERT(HasDictionaryElements());
5748   return SeededNumberDictionary::cast(elements());
5749 }
5750 
5751 
IsHashFieldComputed(uint32_t field)5752 bool Name::IsHashFieldComputed(uint32_t field) {
5753   return (field & kHashNotComputedMask) == 0;
5754 }
5755 
5756 
HasHashCode()5757 bool Name::HasHashCode() {
5758   return IsHashFieldComputed(hash_field());
5759 }
5760 
5761 
Hash()5762 uint32_t Name::Hash() {
5763   // Fast case: has hash code already been computed?
5764   uint32_t field = hash_field();
5765   if (IsHashFieldComputed(field)) return field >> kHashShift;
5766   // Slow case: compute hash code and set it. Has to be a string.
5767   return String::cast(this)->ComputeAndSetHash();
5768 }
5769 
5770 
StringHasher(int length,uint32_t seed)5771 StringHasher::StringHasher(int length, uint32_t seed)
5772   : length_(length),
5773     raw_running_hash_(seed),
5774     array_index_(0),
5775     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
5776     is_first_char_(true) {
5777   ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
5778 }
5779 
5780 
has_trivial_hash()5781 bool StringHasher::has_trivial_hash() {
5782   return length_ > String::kMaxHashCalcLength;
5783 }
5784 
5785 
AddCharacterCore(uint32_t running_hash,uint16_t c)5786 uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
5787   running_hash += c;
5788   running_hash += (running_hash << 10);
5789   running_hash ^= (running_hash >> 6);
5790   return running_hash;
5791 }
5792 
5793 
GetHashCore(uint32_t running_hash)5794 uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
5795   running_hash += (running_hash << 3);
5796   running_hash ^= (running_hash >> 11);
5797   running_hash += (running_hash << 15);
5798   if ((running_hash & String::kHashBitMask) == 0) {
5799     return kZeroHash;
5800   }
5801   return running_hash;
5802 }
5803 
5804 
AddCharacter(uint16_t c)5805 void StringHasher::AddCharacter(uint16_t c) {
5806   // Use the Jenkins one-at-a-time hash function to update the hash
5807   // for the given character.
5808   raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
5809 }
5810 
5811 
UpdateIndex(uint16_t c)5812 bool StringHasher::UpdateIndex(uint16_t c) {
5813   ASSERT(is_array_index_);
5814   if (c < '0' || c > '9') {
5815     is_array_index_ = false;
5816     return false;
5817   }
5818   int d = c - '0';
5819   if (is_first_char_) {
5820     is_first_char_ = false;
5821     if (c == '0' && length_ > 1) {
5822       is_array_index_ = false;
5823       return false;
5824     }
5825   }
5826   if (array_index_ > 429496729U - ((d + 2) >> 3)) {
5827     is_array_index_ = false;
5828     return false;
5829   }
5830   array_index_ = array_index_ * 10 + d;
5831   return true;
5832 }
5833 
5834 
5835 template<typename Char>
AddCharacters(const Char * chars,int length)5836 inline void StringHasher::AddCharacters(const Char* chars, int length) {
5837   ASSERT(sizeof(Char) == 1 || sizeof(Char) == 2);
5838   int i = 0;
5839   if (is_array_index_) {
5840     for (; i < length; i++) {
5841       AddCharacter(chars[i]);
5842       if (!UpdateIndex(chars[i])) {
5843         i++;
5844         break;
5845       }
5846     }
5847   }
5848   for (; i < length; i++) {
5849     ASSERT(!is_array_index_);
5850     AddCharacter(chars[i]);
5851   }
5852 }
5853 
5854 
5855 template <typename schar>
HashSequentialString(const schar * chars,int length,uint32_t seed)5856 uint32_t StringHasher::HashSequentialString(const schar* chars,
5857                                             int length,
5858                                             uint32_t seed) {
5859   StringHasher hasher(length, seed);
5860   if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
5861   return hasher.GetHashField();
5862 }
5863 
5864 
AsArrayIndex(uint32_t * index)5865 bool Name::AsArrayIndex(uint32_t* index) {
5866   return IsString() && String::cast(this)->AsArrayIndex(index);
5867 }
5868 
5869 
AsArrayIndex(uint32_t * index)5870 bool String::AsArrayIndex(uint32_t* index) {
5871   uint32_t field = hash_field();
5872   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
5873     return false;
5874   }
5875   return SlowAsArrayIndex(index);
5876 }
5877 
5878 
GetPrototype()5879 Object* JSReceiver::GetPrototype() {
5880   return map()->prototype();
5881 }
5882 
5883 
GetConstructor()5884 Object* JSReceiver::GetConstructor() {
5885   return map()->constructor();
5886 }
5887 
5888 
HasProperty(Handle<JSReceiver> object,Handle<Name> name)5889 bool JSReceiver::HasProperty(Handle<JSReceiver> object,
5890                              Handle<Name> name) {
5891   if (object->IsJSProxy()) {
5892     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
5893     return JSProxy::HasPropertyWithHandler(proxy, name);
5894   }
5895   return object->GetPropertyAttribute(*name) != ABSENT;
5896 }
5897 
5898 
HasLocalProperty(Handle<JSReceiver> object,Handle<Name> name)5899 bool JSReceiver::HasLocalProperty(Handle<JSReceiver> object,
5900                                   Handle<Name> name) {
5901   if (object->IsJSProxy()) {
5902     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
5903     return JSProxy::HasPropertyWithHandler(proxy, name);
5904   }
5905   return object->GetLocalPropertyAttribute(*name) != ABSENT;
5906 }
5907 
5908 
GetPropertyAttribute(Name * key)5909 PropertyAttributes JSReceiver::GetPropertyAttribute(Name* key) {
5910   uint32_t index;
5911   if (IsJSObject() && key->AsArrayIndex(&index)) {
5912     return GetElementAttribute(index);
5913   }
5914   return GetPropertyAttributeWithReceiver(this, key);
5915 }
5916 
5917 
GetElementAttribute(uint32_t index)5918 PropertyAttributes JSReceiver::GetElementAttribute(uint32_t index) {
5919   if (IsJSProxy()) {
5920     return JSProxy::cast(this)->GetElementAttributeWithHandler(this, index);
5921   }
5922   return JSObject::cast(this)->GetElementAttributeWithReceiver(
5923       this, index, true);
5924 }
5925 
5926 
IsDetached()5927 bool JSGlobalObject::IsDetached() {
5928   return JSGlobalProxy::cast(global_receiver())->IsDetachedFrom(this);
5929 }
5930 
5931 
IsDetachedFrom(GlobalObject * global)5932 bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) {
5933   return GetPrototype() != global;
5934 }
5935 
5936 
GetOrCreateIdentityHash(Handle<JSReceiver> object)5937 Handle<Object> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) {
5938   return object->IsJSProxy()
5939       ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object))
5940       : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object));
5941 }
5942 
5943 
GetIdentityHash()5944 Object* JSReceiver::GetIdentityHash() {
5945   return IsJSProxy()
5946       ? JSProxy::cast(this)->GetIdentityHash()
5947       : JSObject::cast(this)->GetIdentityHash();
5948 }
5949 
5950 
HasElement(Handle<JSReceiver> object,uint32_t index)5951 bool JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
5952   if (object->IsJSProxy()) {
5953     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
5954     return JSProxy::HasElementWithHandler(proxy, index);
5955   }
5956   return Handle<JSObject>::cast(object)->GetElementAttributeWithReceiver(
5957       *object, index, true) != ABSENT;
5958 }
5959 
5960 
HasLocalElement(Handle<JSReceiver> object,uint32_t index)5961 bool JSReceiver::HasLocalElement(Handle<JSReceiver> object, uint32_t index) {
5962   if (object->IsJSProxy()) {
5963     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
5964     return JSProxy::HasElementWithHandler(proxy, index);
5965   }
5966   return Handle<JSObject>::cast(object)->GetElementAttributeWithReceiver(
5967       *object, index, false) != ABSENT;
5968 }
5969 
5970 
GetLocalElementAttribute(uint32_t index)5971 PropertyAttributes JSReceiver::GetLocalElementAttribute(uint32_t index) {
5972   if (IsJSProxy()) {
5973     return JSProxy::cast(this)->GetElementAttributeWithHandler(this, index);
5974   }
5975   return JSObject::cast(this)->GetElementAttributeWithReceiver(
5976       this, index, false);
5977 }
5978 
5979 
all_can_read()5980 bool AccessorInfo::all_can_read() {
5981   return BooleanBit::get(flag(), kAllCanReadBit);
5982 }
5983 
5984 
set_all_can_read(bool value)5985 void AccessorInfo::set_all_can_read(bool value) {
5986   set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
5987 }
5988 
5989 
all_can_write()5990 bool AccessorInfo::all_can_write() {
5991   return BooleanBit::get(flag(), kAllCanWriteBit);
5992 }
5993 
5994 
set_all_can_write(bool value)5995 void AccessorInfo::set_all_can_write(bool value) {
5996   set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
5997 }
5998 
5999 
prohibits_overwriting()6000 bool AccessorInfo::prohibits_overwriting() {
6001   return BooleanBit::get(flag(), kProhibitsOverwritingBit);
6002 }
6003 
6004 
set_prohibits_overwriting(bool value)6005 void AccessorInfo::set_prohibits_overwriting(bool value) {
6006   set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
6007 }
6008 
6009 
property_attributes()6010 PropertyAttributes AccessorInfo::property_attributes() {
6011   return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
6012 }
6013 
6014 
set_property_attributes(PropertyAttributes attributes)6015 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
6016   set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
6017 }
6018 
6019 
IsCompatibleReceiver(Object * receiver)6020 bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
6021   Object* function_template = expected_receiver_type();
6022   if (!function_template->IsFunctionTemplateInfo()) return true;
6023   return FunctionTemplateInfo::cast(function_template)->IsTemplateFor(receiver);
6024 }
6025 
6026 
set_access_flags(v8::AccessControl access_control)6027 void AccessorPair::set_access_flags(v8::AccessControl access_control) {
6028   int current = access_flags()->value();
6029   current = BooleanBit::set(current,
6030                             kProhibitsOverwritingBit,
6031                             access_control & PROHIBITS_OVERWRITING);
6032   current = BooleanBit::set(current,
6033                             kAllCanReadBit,
6034                             access_control & ALL_CAN_READ);
6035   current = BooleanBit::set(current,
6036                             kAllCanWriteBit,
6037                             access_control & ALL_CAN_WRITE);
6038   set_access_flags(Smi::FromInt(current));
6039 }
6040 
6041 
all_can_read()6042 bool AccessorPair::all_can_read() {
6043   return BooleanBit::get(access_flags(), kAllCanReadBit);
6044 }
6045 
6046 
all_can_write()6047 bool AccessorPair::all_can_write() {
6048   return BooleanBit::get(access_flags(), kAllCanWriteBit);
6049 }
6050 
6051 
prohibits_overwriting()6052 bool AccessorPair::prohibits_overwriting() {
6053   return BooleanBit::get(access_flags(), kProhibitsOverwritingBit);
6054 }
6055 
6056 
6057 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value)6058 void Dictionary<Shape, Key>::SetEntry(int entry,
6059                                       Object* key,
6060                                       Object* value) {
6061   SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
6062 }
6063 
6064 
6065 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)6066 void Dictionary<Shape, Key>::SetEntry(int entry,
6067                                       Object* key,
6068                                       Object* value,
6069                                       PropertyDetails details) {
6070   ASSERT(!key->IsName() ||
6071          details.IsDeleted() ||
6072          details.dictionary_index() > 0);
6073   int index = HashTable<Shape, Key>::EntryToIndex(entry);
6074   DisallowHeapAllocation no_gc;
6075   WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
6076   FixedArray::set(index, key, mode);
6077   FixedArray::set(index+1, value, mode);
6078   FixedArray::set(index+2, details.AsSmi());
6079 }
6080 
6081 
IsMatch(uint32_t key,Object * other)6082 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
6083   ASSERT(other->IsNumber());
6084   return key == static_cast<uint32_t>(other->Number());
6085 }
6086 
6087 
Hash(uint32_t key)6088 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
6089   return ComputeIntegerHash(key, 0);
6090 }
6091 
6092 
HashForObject(uint32_t key,Object * other)6093 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
6094                                                       Object* other) {
6095   ASSERT(other->IsNumber());
6096   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
6097 }
6098 
SeededHash(uint32_t key,uint32_t seed)6099 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
6100   return ComputeIntegerHash(key, seed);
6101 }
6102 
SeededHashForObject(uint32_t key,uint32_t seed,Object * other)6103 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
6104                                                           uint32_t seed,
6105                                                           Object* other) {
6106   ASSERT(other->IsNumber());
6107   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
6108 }
6109 
AsObject(Heap * heap,uint32_t key)6110 MaybeObject* NumberDictionaryShape::AsObject(Heap* heap, uint32_t key) {
6111   return heap->NumberFromUint32(key);
6112 }
6113 
6114 
IsMatch(Name * key,Object * other)6115 bool NameDictionaryShape::IsMatch(Name* key, Object* other) {
6116   // We know that all entries in a hash table had their hash keys created.
6117   // Use that knowledge to have fast failure.
6118   if (key->Hash() != Name::cast(other)->Hash()) return false;
6119   return key->Equals(Name::cast(other));
6120 }
6121 
6122 
Hash(Name * key)6123 uint32_t NameDictionaryShape::Hash(Name* key) {
6124   return key->Hash();
6125 }
6126 
6127 
HashForObject(Name * key,Object * other)6128 uint32_t NameDictionaryShape::HashForObject(Name* key, Object* other) {
6129   return Name::cast(other)->Hash();
6130 }
6131 
6132 
AsObject(Heap * heap,Name * key)6133 MaybeObject* NameDictionaryShape::AsObject(Heap* heap, Name* key) {
6134   ASSERT(key->IsUniqueName());
6135   return key;
6136 }
6137 
6138 
6139 template <int entrysize>
IsMatch(Object * key,Object * other)6140 bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
6141   return key->SameValue(other);
6142 }
6143 
6144 
6145 template <int entrysize>
Hash(Object * key)6146 uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
6147   return Smi::cast(key->GetHash())->value();
6148 }
6149 
6150 
6151 template <int entrysize>
HashForObject(Object * key,Object * other)6152 uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
6153                                                         Object* other) {
6154   return Smi::cast(other->GetHash())->value();
6155 }
6156 
6157 
6158 template <int entrysize>
AsObject(Heap * heap,Object * key)6159 MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Heap* heap,
6160                                                        Object* key) {
6161   return key;
6162 }
6163 
6164 
6165 template <int entrysize>
IsMatch(Object * key,Object * other)6166 bool WeakHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
6167   return key->SameValue(other);
6168 }
6169 
6170 
6171 template <int entrysize>
Hash(Object * key)6172 uint32_t WeakHashTableShape<entrysize>::Hash(Object* key) {
6173   intptr_t hash = reinterpret_cast<intptr_t>(key);
6174   return (uint32_t)(hash & 0xFFFFFFFF);
6175 }
6176 
6177 
6178 template <int entrysize>
HashForObject(Object * key,Object * other)6179 uint32_t WeakHashTableShape<entrysize>::HashForObject(Object* key,
6180                                                       Object* other) {
6181   intptr_t hash = reinterpret_cast<intptr_t>(other);
6182   return (uint32_t)(hash & 0xFFFFFFFF);
6183 }
6184 
6185 
6186 template <int entrysize>
AsObject(Heap * heap,Object * key)6187 MaybeObject* WeakHashTableShape<entrysize>::AsObject(Heap* heap,
6188                                                     Object* key) {
6189   return key;
6190 }
6191 
6192 
ClearCodeCache(Heap * heap)6193 void Map::ClearCodeCache(Heap* heap) {
6194   // No write barrier is needed since empty_fixed_array is not in new space.
6195   // Please note this function is used during marking:
6196   //  - MarkCompactCollector::MarkUnmarkedObject
6197   //  - IncrementalMarking::Step
6198   ASSERT(!heap->InNewSpace(heap->empty_fixed_array()));
6199   WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
6200 }
6201 
6202 
EnsureSize(int required_size)6203 void JSArray::EnsureSize(int required_size) {
6204   ASSERT(HasFastSmiOrObjectElements());
6205   FixedArray* elts = FixedArray::cast(elements());
6206   const int kArraySizeThatFitsComfortablyInNewSpace = 128;
6207   if (elts->length() < required_size) {
6208     // Doubling in size would be overkill, but leave some slack to avoid
6209     // constantly growing.
6210     Expand(required_size + (required_size >> 3));
6211     // It's a performance benefit to keep a frequently used array in new-space.
6212   } else if (!GetHeap()->new_space()->Contains(elts) &&
6213              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
6214     // Expand will allocate a new backing store in new space even if the size
6215     // we asked for isn't larger than what we had before.
6216     Expand(required_size);
6217   }
6218 }
6219 
6220 
set_length(Smi * length)6221 void JSArray::set_length(Smi* length) {
6222   // Don't need a write barrier for a Smi.
6223   set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
6224 }
6225 
6226 
AllowsSetElementsLength()6227 bool JSArray::AllowsSetElementsLength() {
6228   bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
6229   ASSERT(result == !HasExternalArrayElements());
6230   return result;
6231 }
6232 
6233 
SetContent(FixedArrayBase * storage)6234 MaybeObject* JSArray::SetContent(FixedArrayBase* storage) {
6235   MaybeObject* maybe_result = EnsureCanContainElements(
6236       storage, storage->length(), ALLOW_COPIED_DOUBLE_ELEMENTS);
6237   if (maybe_result->IsFailure()) return maybe_result;
6238   ASSERT((storage->map() == GetHeap()->fixed_double_array_map() &&
6239           IsFastDoubleElementsKind(GetElementsKind())) ||
6240          ((storage->map() != GetHeap()->fixed_double_array_map()) &&
6241           (IsFastObjectElementsKind(GetElementsKind()) ||
6242            (IsFastSmiElementsKind(GetElementsKind()) &&
6243             FixedArray::cast(storage)->ContainsOnlySmisOrHoles()))));
6244   set_elements(storage);
6245   set_length(Smi::FromInt(storage->length()));
6246   return this;
6247 }
6248 
6249 
Copy()6250 MaybeObject* FixedArray::Copy() {
6251   if (length() == 0) return this;
6252   return GetHeap()->CopyFixedArray(this);
6253 }
6254 
6255 
Copy()6256 MaybeObject* FixedDoubleArray::Copy() {
6257   if (length() == 0) return this;
6258   return GetHeap()->CopyFixedDoubleArray(this);
6259 }
6260 
6261 
Copy()6262 MaybeObject* ConstantPoolArray::Copy() {
6263   if (length() == 0) return this;
6264   return GetHeap()->CopyConstantPoolArray(this);
6265 }
6266 
6267 
SetAstId(int index,TypeFeedbackId id)6268 void TypeFeedbackCells::SetAstId(int index, TypeFeedbackId id) {
6269   set(1 + index * 2, Smi::FromInt(id.ToInt()));
6270 }
6271 
6272 
AstId(int index)6273 TypeFeedbackId TypeFeedbackCells::AstId(int index) {
6274   return TypeFeedbackId(Smi::cast(get(1 + index * 2))->value());
6275 }
6276 
6277 
SetCell(int index,Cell * cell)6278 void TypeFeedbackCells::SetCell(int index, Cell* cell) {
6279   set(index * 2, cell);
6280 }
6281 
6282 
GetCell(int index)6283 Cell* TypeFeedbackCells::GetCell(int index) {
6284   return Cell::cast(get(index * 2));
6285 }
6286 
6287 
UninitializedSentinel(Isolate * isolate)6288 Handle<Object> TypeFeedbackCells::UninitializedSentinel(Isolate* isolate) {
6289   return isolate->factory()->the_hole_value();
6290 }
6291 
6292 
MegamorphicSentinel(Isolate * isolate)6293 Handle<Object> TypeFeedbackCells::MegamorphicSentinel(Isolate* isolate) {
6294   return isolate->factory()->undefined_value();
6295 }
6296 
6297 
MonomorphicArraySentinel(Isolate * isolate,ElementsKind elements_kind)6298 Handle<Object> TypeFeedbackCells::MonomorphicArraySentinel(Isolate* isolate,
6299     ElementsKind elements_kind) {
6300   return Handle<Object>(Smi::FromInt(static_cast<int>(elements_kind)), isolate);
6301 }
6302 
6303 
RawUninitializedSentinel(Heap * heap)6304 Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
6305   return heap->the_hole_value();
6306 }
6307 
6308 
ic_total_count()6309 int TypeFeedbackInfo::ic_total_count() {
6310   int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6311   return ICTotalCountField::decode(current);
6312 }
6313 
6314 
set_ic_total_count(int count)6315 void TypeFeedbackInfo::set_ic_total_count(int count) {
6316   int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6317   value = ICTotalCountField::update(value,
6318                                     ICTotalCountField::decode(count));
6319   WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
6320 }
6321 
6322 
ic_with_type_info_count()6323 int TypeFeedbackInfo::ic_with_type_info_count() {
6324   int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6325   return ICsWithTypeInfoCountField::decode(current);
6326 }
6327 
6328 
change_ic_with_type_info_count(int delta)6329 void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) {
6330   int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6331   int new_count = ICsWithTypeInfoCountField::decode(value) + delta;
6332   // We can get negative count here when the type-feedback info is
6333   // shared between two code objects. The can only happen when
6334   // the debugger made a shallow copy of code object (see Heap::CopyCode).
6335   // Since we do not optimize when the debugger is active, we can skip
6336   // this counter update.
6337   if (new_count >= 0) {
6338     new_count &= ICsWithTypeInfoCountField::kMask;
6339     value = ICsWithTypeInfoCountField::update(value, new_count);
6340     WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
6341   }
6342 }
6343 
6344 
initialize_storage()6345 void TypeFeedbackInfo::initialize_storage() {
6346   WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0));
6347   WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0));
6348 }
6349 
6350 
change_own_type_change_checksum()6351 void TypeFeedbackInfo::change_own_type_change_checksum() {
6352   int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6353   int checksum = OwnTypeChangeChecksum::decode(value);
6354   checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits);
6355   value = OwnTypeChangeChecksum::update(value, checksum);
6356   // Ensure packed bit field is in Smi range.
6357   if (value > Smi::kMaxValue) value |= Smi::kMinValue;
6358   if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
6359   WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
6360 }
6361 
6362 
set_inlined_type_change_checksum(int checksum)6363 void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) {
6364   int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6365   int mask = (1 << kTypeChangeChecksumBits) - 1;
6366   value = InlinedTypeChangeChecksum::update(value, checksum & mask);
6367   // Ensure packed bit field is in Smi range.
6368   if (value > Smi::kMaxValue) value |= Smi::kMinValue;
6369   if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
6370   WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
6371 }
6372 
6373 
own_type_change_checksum()6374 int TypeFeedbackInfo::own_type_change_checksum() {
6375   int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6376   return OwnTypeChangeChecksum::decode(value);
6377 }
6378 
6379 
matches_inlined_type_change_checksum(int checksum)6380 bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
6381   int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6382   int mask = (1 << kTypeChangeChecksumBits) - 1;
6383   return InlinedTypeChangeChecksum::decode(value) == (checksum & mask);
6384 }
6385 
6386 
ACCESSORS(TypeFeedbackInfo,type_feedback_cells,TypeFeedbackCells,kTypeFeedbackCellsOffset)6387 ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
6388           kTypeFeedbackCellsOffset)
6389 
6390 
6391 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
6392 
6393 
6394 Relocatable::Relocatable(Isolate* isolate) {
6395   isolate_ = isolate;
6396   prev_ = isolate->relocatable_top();
6397   isolate->set_relocatable_top(this);
6398 }
6399 
6400 
~Relocatable()6401 Relocatable::~Relocatable() {
6402   ASSERT_EQ(isolate_->relocatable_top(), this);
6403   isolate_->set_relocatable_top(prev_);
6404 }
6405 
6406 
SizeOf(Map * map,HeapObject * object)6407 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
6408   return map->instance_size();
6409 }
6410 
6411 
ForeignIterateBody(ObjectVisitor * v)6412 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
6413   v->VisitExternalReference(
6414       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
6415 }
6416 
6417 
6418 template<typename StaticVisitor>
ForeignIterateBody()6419 void Foreign::ForeignIterateBody() {
6420   StaticVisitor::VisitExternalReference(
6421       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
6422 }
6423 
6424 
ExternalAsciiStringIterateBody(ObjectVisitor * v)6425 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
6426   typedef v8::String::ExternalAsciiStringResource Resource;
6427   v->VisitExternalAsciiString(
6428       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6429 }
6430 
6431 
6432 template<typename StaticVisitor>
ExternalAsciiStringIterateBody()6433 void ExternalAsciiString::ExternalAsciiStringIterateBody() {
6434   typedef v8::String::ExternalAsciiStringResource Resource;
6435   StaticVisitor::VisitExternalAsciiString(
6436       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6437 }
6438 
6439 
ExternalTwoByteStringIterateBody(ObjectVisitor * v)6440 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
6441   typedef v8::String::ExternalStringResource Resource;
6442   v->VisitExternalTwoByteString(
6443       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6444 }
6445 
6446 
6447 template<typename StaticVisitor>
ExternalTwoByteStringIterateBody()6448 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
6449   typedef v8::String::ExternalStringResource Resource;
6450   StaticVisitor::VisitExternalTwoByteString(
6451       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6452 }
6453 
6454 
6455 template<int start_offset, int end_offset, int size>
IterateBody(HeapObject * obj,ObjectVisitor * v)6456 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
6457     HeapObject* obj,
6458     ObjectVisitor* v) {
6459     v->VisitPointers(HeapObject::RawField(obj, start_offset),
6460                      HeapObject::RawField(obj, end_offset));
6461 }
6462 
6463 
6464 template<int start_offset>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)6465 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
6466                                                        int object_size,
6467                                                        ObjectVisitor* v) {
6468   v->VisitPointers(HeapObject::RawField(obj, start_offset),
6469                    HeapObject::RawField(obj, object_size));
6470 }
6471 
6472 
6473 #undef TYPE_CHECKER
6474 #undef CAST_ACCESSOR
6475 #undef INT_ACCESSORS
6476 #undef ACCESSORS
6477 #undef ACCESSORS_TO_SMI
6478 #undef SMI_ACCESSORS
6479 #undef BOOL_GETTER
6480 #undef BOOL_ACCESSORS
6481 #undef FIELD_ADDR
6482 #undef READ_FIELD
6483 #undef WRITE_FIELD
6484 #undef WRITE_BARRIER
6485 #undef CONDITIONAL_WRITE_BARRIER
6486 #undef READ_DOUBLE_FIELD
6487 #undef WRITE_DOUBLE_FIELD
6488 #undef READ_INT_FIELD
6489 #undef WRITE_INT_FIELD
6490 #undef READ_INTPTR_FIELD
6491 #undef WRITE_INTPTR_FIELD
6492 #undef READ_UINT32_FIELD
6493 #undef WRITE_UINT32_FIELD
6494 #undef READ_SHORT_FIELD
6495 #undef WRITE_SHORT_FIELD
6496 #undef READ_BYTE_FIELD
6497 #undef WRITE_BYTE_FIELD
6498 
6499 
6500 } }  // namespace v8::internal
6501 
6502 #endif  // V8_OBJECTS_INL_H_
6503