• 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 
51 namespace v8 {
52 namespace internal {
53 
PropertyDetails(Smi * smi)54 PropertyDetails::PropertyDetails(Smi* smi) {
55   value_ = smi->value();
56 }
57 
58 
AsSmi()59 Smi* PropertyDetails::AsSmi() {
60   return Smi::FromInt(value_);
61 }
62 
63 
AsDeleted()64 PropertyDetails PropertyDetails::AsDeleted() {
65   Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
66   return PropertyDetails(smi);
67 }
68 
69 
70 #define TYPE_CHECKER(type, instancetype)                                \
71   bool Object::Is##type() {                                             \
72   return Object::IsHeapObject() &&                                      \
73       HeapObject::cast(this)->map()->instance_type() == instancetype;   \
74   }
75 
76 
77 #define CAST_ACCESSOR(type)                     \
78   type* type::cast(Object* object) {            \
79     ASSERT(object->Is##type());                 \
80     return reinterpret_cast<type*>(object);     \
81   }
82 
83 
84 #define INT_ACCESSORS(holder, name, offset)                             \
85   int holder::name() { return READ_INT_FIELD(this, offset); }           \
86   void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
87 
88 
89 #define ACCESSORS(holder, name, type, offset)                           \
90   type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
91   void holder::set_##name(type* value, WriteBarrierMode mode) {         \
92     WRITE_FIELD(this, offset, value);                                   \
93     CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);    \
94   }
95 
96 
97 // Getter that returns a tagged Smi and setter that writes a tagged Smi.
98 #define ACCESSORS_TO_SMI(holder, name, offset)                          \
99   Smi* holder::name() { return Smi::cast(READ_FIELD(this, offset)); }   \
100   void holder::set_##name(Smi* value, WriteBarrierMode mode) {          \
101     WRITE_FIELD(this, offset, value);                                   \
102   }
103 
104 
105 // Getter that returns a Smi as an int and writes an int as a Smi.
106 #define SMI_ACCESSORS(holder, name, offset)             \
107   int holder::name() {                                  \
108     Object* value = READ_FIELD(this, offset);           \
109     return Smi::cast(value)->value();                   \
110   }                                                     \
111   void holder::set_##name(int value) {                  \
112     WRITE_FIELD(this, offset, Smi::FromInt(value));     \
113   }
114 
115 
116 #define BOOL_GETTER(holder, field, name, offset)           \
117   bool holder::name() {                                    \
118     return BooleanBit::get(field(), offset);               \
119   }                                                        \
120 
121 
122 #define BOOL_ACCESSORS(holder, field, name, offset)        \
123   bool holder::name() {                                    \
124     return BooleanBit::get(field(), offset);               \
125   }                                                        \
126   void holder::set_##name(bool value) {                    \
127     set_##field(BooleanBit::set(field(), offset, value));  \
128   }
129 
130 
IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)131 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
132                                          ElementsKind to_kind) {
133   if (to_kind == FAST_ELEMENTS) {
134     return from_kind == FAST_SMI_ONLY_ELEMENTS ||
135         from_kind == FAST_DOUBLE_ELEMENTS;
136   } else {
137     return to_kind == FAST_DOUBLE_ELEMENTS &&
138         from_kind == FAST_SMI_ONLY_ELEMENTS;
139   }
140 }
141 
142 
IsFixedArrayBase()143 bool Object::IsFixedArrayBase() {
144   return IsFixedArray() || IsFixedDoubleArray();
145 }
146 
147 
IsInstanceOf(FunctionTemplateInfo * expected)148 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
149   // There is a constraint on the object; check.
150   if (!this->IsJSObject()) return false;
151   // Fetch the constructor function of the object.
152   Object* cons_obj = JSObject::cast(this)->map()->constructor();
153   if (!cons_obj->IsJSFunction()) return false;
154   JSFunction* fun = JSFunction::cast(cons_obj);
155   // Iterate through the chain of inheriting function templates to
156   // see if the required one occurs.
157   for (Object* type = fun->shared()->function_data();
158        type->IsFunctionTemplateInfo();
159        type = FunctionTemplateInfo::cast(type)->parent_template()) {
160     if (type == expected) return true;
161   }
162   // Didn't find the required type in the inheritance chain.
163   return false;
164 }
165 
166 
IsSmi()167 bool Object::IsSmi() {
168   return HAS_SMI_TAG(this);
169 }
170 
171 
IsHeapObject()172 bool Object::IsHeapObject() {
173   return Internals::HasHeapObjectTag(this);
174 }
175 
176 
NonFailureIsHeapObject()177 bool Object::NonFailureIsHeapObject() {
178   ASSERT(!this->IsFailure());
179   return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
180 }
181 
182 
TYPE_CHECKER(HeapNumber,HEAP_NUMBER_TYPE)183 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
184 
185 
186 bool Object::IsString() {
187   return Object::IsHeapObject()
188     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
189 }
190 
191 
IsSpecObject()192 bool Object::IsSpecObject() {
193   return Object::IsHeapObject()
194     && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
195 }
196 
197 
IsSpecFunction()198 bool Object::IsSpecFunction() {
199   if (!Object::IsHeapObject()) return false;
200   InstanceType type = HeapObject::cast(this)->map()->instance_type();
201   return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
202 }
203 
204 
IsSymbol()205 bool Object::IsSymbol() {
206   if (!this->IsHeapObject()) return false;
207   uint32_t type = HeapObject::cast(this)->map()->instance_type();
208   // Because the symbol tag is non-zero and no non-string types have the
209   // symbol bit set we can test for symbols with a very simple test
210   // operation.
211   STATIC_ASSERT(kSymbolTag != 0);
212   ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
213   return (type & kIsSymbolMask) != 0;
214 }
215 
216 
IsConsString()217 bool Object::IsConsString() {
218   if (!IsString()) return false;
219   return StringShape(String::cast(this)).IsCons();
220 }
221 
222 
IsSlicedString()223 bool Object::IsSlicedString() {
224   if (!IsString()) return false;
225   return StringShape(String::cast(this)).IsSliced();
226 }
227 
228 
IsSeqString()229 bool Object::IsSeqString() {
230   if (!IsString()) return false;
231   return StringShape(String::cast(this)).IsSequential();
232 }
233 
234 
IsSeqAsciiString()235 bool Object::IsSeqAsciiString() {
236   if (!IsString()) return false;
237   return StringShape(String::cast(this)).IsSequential() &&
238          String::cast(this)->IsAsciiRepresentation();
239 }
240 
241 
IsSeqTwoByteString()242 bool Object::IsSeqTwoByteString() {
243   if (!IsString()) return false;
244   return StringShape(String::cast(this)).IsSequential() &&
245          String::cast(this)->IsTwoByteRepresentation();
246 }
247 
248 
IsExternalString()249 bool Object::IsExternalString() {
250   if (!IsString()) return false;
251   return StringShape(String::cast(this)).IsExternal();
252 }
253 
254 
IsExternalAsciiString()255 bool Object::IsExternalAsciiString() {
256   if (!IsString()) return false;
257   return StringShape(String::cast(this)).IsExternal() &&
258          String::cast(this)->IsAsciiRepresentation();
259 }
260 
261 
IsExternalTwoByteString()262 bool Object::IsExternalTwoByteString() {
263   if (!IsString()) return false;
264   return StringShape(String::cast(this)).IsExternal() &&
265          String::cast(this)->IsTwoByteRepresentation();
266 }
267 
HasValidElements()268 bool Object::HasValidElements() {
269   // Dictionary is covered under FixedArray.
270   return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
271 }
272 
StringShape(String * str)273 StringShape::StringShape(String* str)
274   : type_(str->map()->instance_type()) {
275   set_valid();
276   ASSERT((type_ & kIsNotStringMask) == kStringTag);
277 }
278 
279 
StringShape(Map * map)280 StringShape::StringShape(Map* map)
281   : type_(map->instance_type()) {
282   set_valid();
283   ASSERT((type_ & kIsNotStringMask) == kStringTag);
284 }
285 
286 
StringShape(InstanceType t)287 StringShape::StringShape(InstanceType t)
288   : type_(static_cast<uint32_t>(t)) {
289   set_valid();
290   ASSERT((type_ & kIsNotStringMask) == kStringTag);
291 }
292 
293 
IsSymbol()294 bool StringShape::IsSymbol() {
295   ASSERT(valid());
296   STATIC_ASSERT(kSymbolTag != 0);
297   return (type_ & kIsSymbolMask) != 0;
298 }
299 
300 
IsAsciiRepresentation()301 bool String::IsAsciiRepresentation() {
302   uint32_t type = map()->instance_type();
303   return (type & kStringEncodingMask) == kAsciiStringTag;
304 }
305 
306 
IsTwoByteRepresentation()307 bool String::IsTwoByteRepresentation() {
308   uint32_t type = map()->instance_type();
309   return (type & kStringEncodingMask) == kTwoByteStringTag;
310 }
311 
312 
IsAsciiRepresentationUnderneath()313 bool String::IsAsciiRepresentationUnderneath() {
314   uint32_t type = map()->instance_type();
315   STATIC_ASSERT(kIsIndirectStringTag != 0);
316   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
317   ASSERT(IsFlat());
318   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
319     case kAsciiStringTag:
320       return true;
321     case kTwoByteStringTag:
322       return false;
323     default:  // Cons or sliced string.  Need to go deeper.
324       return GetUnderlying()->IsAsciiRepresentation();
325   }
326 }
327 
328 
IsTwoByteRepresentationUnderneath()329 bool String::IsTwoByteRepresentationUnderneath() {
330   uint32_t type = map()->instance_type();
331   STATIC_ASSERT(kIsIndirectStringTag != 0);
332   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
333   ASSERT(IsFlat());
334   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
335     case kAsciiStringTag:
336       return false;
337     case kTwoByteStringTag:
338       return true;
339     default:  // Cons or sliced string.  Need to go deeper.
340       return GetUnderlying()->IsTwoByteRepresentation();
341   }
342 }
343 
344 
HasOnlyAsciiChars()345 bool String::HasOnlyAsciiChars() {
346   uint32_t type = map()->instance_type();
347   return (type & kStringEncodingMask) == kAsciiStringTag ||
348          (type & kAsciiDataHintMask) == kAsciiDataHintTag;
349 }
350 
351 
IsCons()352 bool StringShape::IsCons() {
353   return (type_ & kStringRepresentationMask) == kConsStringTag;
354 }
355 
356 
IsSliced()357 bool StringShape::IsSliced() {
358   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
359 }
360 
361 
IsIndirect()362 bool StringShape::IsIndirect() {
363   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
364 }
365 
366 
IsExternal()367 bool StringShape::IsExternal() {
368   return (type_ & kStringRepresentationMask) == kExternalStringTag;
369 }
370 
371 
IsSequential()372 bool StringShape::IsSequential() {
373   return (type_ & kStringRepresentationMask) == kSeqStringTag;
374 }
375 
376 
representation_tag()377 StringRepresentationTag StringShape::representation_tag() {
378   uint32_t tag = (type_ & kStringRepresentationMask);
379   return static_cast<StringRepresentationTag>(tag);
380 }
381 
382 
encoding_tag()383 uint32_t StringShape::encoding_tag() {
384   return type_ & kStringEncodingMask;
385 }
386 
387 
full_representation_tag()388 uint32_t StringShape::full_representation_tag() {
389   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
390 }
391 
392 
393 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
394              Internals::kFullStringRepresentationMask);
395 
396 
IsSequentialAscii()397 bool StringShape::IsSequentialAscii() {
398   return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
399 }
400 
401 
IsSequentialTwoByte()402 bool StringShape::IsSequentialTwoByte() {
403   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
404 }
405 
406 
IsExternalAscii()407 bool StringShape::IsExternalAscii() {
408   return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
409 }
410 
411 
IsExternalTwoByte()412 bool StringShape::IsExternalTwoByte() {
413   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
414 }
415 
416 
417 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
418              Internals::kExternalTwoByteRepresentationTag);
419 
420 
Get(int index)421 uc32 FlatStringReader::Get(int index) {
422   ASSERT(0 <= index && index <= length_);
423   if (is_ascii_) {
424     return static_cast<const byte*>(start_)[index];
425   } else {
426     return static_cast<const uc16*>(start_)[index];
427   }
428 }
429 
430 
IsNumber()431 bool Object::IsNumber() {
432   return IsSmi() || IsHeapNumber();
433 }
434 
435 
TYPE_CHECKER(ByteArray,BYTE_ARRAY_TYPE)436 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
437 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
438 
439 
440 bool Object::IsFiller() {
441   if (!Object::IsHeapObject()) return false;
442   InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
443   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
444 }
445 
446 
TYPE_CHECKER(ExternalPixelArray,EXTERNAL_PIXEL_ARRAY_TYPE)447 TYPE_CHECKER(ExternalPixelArray, EXTERNAL_PIXEL_ARRAY_TYPE)
448 
449 
450 bool Object::IsExternalArray() {
451   if (!Object::IsHeapObject())
452     return false;
453   InstanceType instance_type =
454       HeapObject::cast(this)->map()->instance_type();
455   return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
456           instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
457 }
458 
459 
TYPE_CHECKER(ExternalByteArray,EXTERNAL_BYTE_ARRAY_TYPE)460 TYPE_CHECKER(ExternalByteArray, EXTERNAL_BYTE_ARRAY_TYPE)
461 TYPE_CHECKER(ExternalUnsignedByteArray, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
462 TYPE_CHECKER(ExternalShortArray, EXTERNAL_SHORT_ARRAY_TYPE)
463 TYPE_CHECKER(ExternalUnsignedShortArray, EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
464 TYPE_CHECKER(ExternalIntArray, EXTERNAL_INT_ARRAY_TYPE)
465 TYPE_CHECKER(ExternalUnsignedIntArray, EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
466 TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
467 TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
468 
469 
470 bool MaybeObject::IsFailure() {
471   return HAS_FAILURE_TAG(this);
472 }
473 
474 
IsRetryAfterGC()475 bool MaybeObject::IsRetryAfterGC() {
476   return HAS_FAILURE_TAG(this)
477     && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
478 }
479 
480 
IsOutOfMemory()481 bool MaybeObject::IsOutOfMemory() {
482   return HAS_FAILURE_TAG(this)
483       && Failure::cast(this)->IsOutOfMemoryException();
484 }
485 
486 
IsException()487 bool MaybeObject::IsException() {
488   return this == Failure::Exception();
489 }
490 
491 
IsTheHole()492 bool MaybeObject::IsTheHole() {
493   return !IsFailure() && ToObjectUnchecked()->IsTheHole();
494 }
495 
496 
cast(MaybeObject * obj)497 Failure* Failure::cast(MaybeObject* obj) {
498   ASSERT(HAS_FAILURE_TAG(obj));
499   return reinterpret_cast<Failure*>(obj);
500 }
501 
502 
IsJSReceiver()503 bool Object::IsJSReceiver() {
504   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
505   return IsHeapObject() &&
506       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
507 }
508 
509 
IsJSObject()510 bool Object::IsJSObject() {
511   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
512   return IsHeapObject() &&
513       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
514 }
515 
516 
IsJSProxy()517 bool Object::IsJSProxy() {
518   if (!Object::IsHeapObject()) return false;
519   InstanceType type = HeapObject::cast(this)->map()->instance_type();
520   return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
521 }
522 
523 
TYPE_CHECKER(JSFunctionProxy,JS_FUNCTION_PROXY_TYPE)524 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
525 TYPE_CHECKER(JSSet, JS_SET_TYPE)
526 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
527 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
528 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
529 TYPE_CHECKER(Map, MAP_TYPE)
530 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
531 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
532 
533 
534 bool Object::IsDescriptorArray() {
535   return IsFixedArray();
536 }
537 
538 
IsDeoptimizationInputData()539 bool Object::IsDeoptimizationInputData() {
540   // Must be a fixed array.
541   if (!IsFixedArray()) return false;
542 
543   // There's no sure way to detect the difference between a fixed array and
544   // a deoptimization data array.  Since this is used for asserts we can
545   // check that the length is zero or else the fixed size plus a multiple of
546   // the entry size.
547   int length = FixedArray::cast(this)->length();
548   if (length == 0) return true;
549 
550   length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
551   return length >= 0 &&
552       length % DeoptimizationInputData::kDeoptEntrySize == 0;
553 }
554 
555 
IsDeoptimizationOutputData()556 bool Object::IsDeoptimizationOutputData() {
557   if (!IsFixedArray()) return false;
558   // There's actually no way to see the difference between a fixed array and
559   // a deoptimization data array.  Since this is used for asserts we can check
560   // that the length is plausible though.
561   if (FixedArray::cast(this)->length() % 2 != 0) return false;
562   return true;
563 }
564 
565 
IsTypeFeedbackCells()566 bool Object::IsTypeFeedbackCells() {
567   if (!IsFixedArray()) return false;
568   // There's actually no way to see the difference between a fixed array and
569   // a cache cells array.  Since this is used for asserts we can check that
570   // the length is plausible though.
571   if (FixedArray::cast(this)->length() % 2 != 0) return false;
572   return true;
573 }
574 
575 
IsContext()576 bool Object::IsContext() {
577   if (Object::IsHeapObject()) {
578     Map* map = HeapObject::cast(this)->map();
579     Heap* heap = map->GetHeap();
580     return (map == heap->function_context_map() ||
581             map == heap->catch_context_map() ||
582             map == heap->with_context_map() ||
583             map == heap->global_context_map() ||
584             map == heap->block_context_map());
585   }
586   return false;
587 }
588 
589 
IsGlobalContext()590 bool Object::IsGlobalContext() {
591   return Object::IsHeapObject() &&
592       HeapObject::cast(this)->map() ==
593       HeapObject::cast(this)->GetHeap()->global_context_map();
594 }
595 
596 
IsScopeInfo()597 bool Object::IsScopeInfo() {
598   return Object::IsHeapObject() &&
599       HeapObject::cast(this)->map() ==
600       HeapObject::cast(this)->GetHeap()->scope_info_map();
601 }
602 
603 
TYPE_CHECKER(JSFunction,JS_FUNCTION_TYPE)604 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
605 
606 
607 template <> inline bool Is<JSFunction>(Object* obj) {
608   return obj->IsJSFunction();
609 }
610 
611 
TYPE_CHECKER(Code,CODE_TYPE)612 TYPE_CHECKER(Code, CODE_TYPE)
613 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
614 TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
615 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
616 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
617 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
618 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
619 
620 
621 bool Object::IsStringWrapper() {
622   return IsJSValue() && JSValue::cast(this)->value()->IsString();
623 }
624 
625 
TYPE_CHECKER(Foreign,FOREIGN_TYPE)626 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
627 
628 
629 bool Object::IsBoolean() {
630   return IsOddball() &&
631       ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
632 }
633 
634 
TYPE_CHECKER(JSArray,JS_ARRAY_TYPE)635 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
636 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
637 
638 
639 template <> inline bool Is<JSArray>(Object* obj) {
640   return obj->IsJSArray();
641 }
642 
643 
IsHashTable()644 bool Object::IsHashTable() {
645   return Object::IsHeapObject() &&
646       HeapObject::cast(this)->map() ==
647       HeapObject::cast(this)->GetHeap()->hash_table_map();
648 }
649 
650 
IsDictionary()651 bool Object::IsDictionary() {
652   return IsHashTable() &&
653       this != HeapObject::cast(this)->GetHeap()->symbol_table();
654 }
655 
656 
IsSymbolTable()657 bool Object::IsSymbolTable() {
658   return IsHashTable() && this ==
659          HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
660 }
661 
662 
IsJSFunctionResultCache()663 bool Object::IsJSFunctionResultCache() {
664   if (!IsFixedArray()) return false;
665   FixedArray* self = FixedArray::cast(this);
666   int length = self->length();
667   if (length < JSFunctionResultCache::kEntriesIndex) return false;
668   if ((length - JSFunctionResultCache::kEntriesIndex)
669       % JSFunctionResultCache::kEntrySize != 0) {
670     return false;
671   }
672 #ifdef DEBUG
673   if (FLAG_verify_heap) {
674     reinterpret_cast<JSFunctionResultCache*>(this)->
675         JSFunctionResultCacheVerify();
676   }
677 #endif
678   return true;
679 }
680 
681 
IsNormalizedMapCache()682 bool Object::IsNormalizedMapCache() {
683   if (!IsFixedArray()) return false;
684   if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
685     return false;
686   }
687 #ifdef DEBUG
688   if (FLAG_verify_heap) {
689     reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
690   }
691 #endif
692   return true;
693 }
694 
695 
IsCompilationCacheTable()696 bool Object::IsCompilationCacheTable() {
697   return IsHashTable();
698 }
699 
700 
IsCodeCacheHashTable()701 bool Object::IsCodeCacheHashTable() {
702   return IsHashTable();
703 }
704 
705 
IsPolymorphicCodeCacheHashTable()706 bool Object::IsPolymorphicCodeCacheHashTable() {
707   return IsHashTable();
708 }
709 
710 
IsMapCache()711 bool Object::IsMapCache() {
712   return IsHashTable();
713 }
714 
715 
IsPrimitive()716 bool Object::IsPrimitive() {
717   return IsOddball() || IsNumber() || IsString();
718 }
719 
720 
IsJSGlobalProxy()721 bool Object::IsJSGlobalProxy() {
722   bool result = IsHeapObject() &&
723                 (HeapObject::cast(this)->map()->instance_type() ==
724                  JS_GLOBAL_PROXY_TYPE);
725   ASSERT(!result || IsAccessCheckNeeded());
726   return result;
727 }
728 
729 
IsGlobalObject()730 bool Object::IsGlobalObject() {
731   if (!IsHeapObject()) return false;
732 
733   InstanceType type = HeapObject::cast(this)->map()->instance_type();
734   return type == JS_GLOBAL_OBJECT_TYPE ||
735          type == JS_BUILTINS_OBJECT_TYPE;
736 }
737 
738 
TYPE_CHECKER(JSGlobalObject,JS_GLOBAL_OBJECT_TYPE)739 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
740 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
741 
742 
743 bool Object::IsUndetectableObject() {
744   return IsHeapObject()
745     && HeapObject::cast(this)->map()->is_undetectable();
746 }
747 
748 
IsAccessCheckNeeded()749 bool Object::IsAccessCheckNeeded() {
750   return IsHeapObject()
751     && HeapObject::cast(this)->map()->is_access_check_needed();
752 }
753 
754 
IsStruct()755 bool Object::IsStruct() {
756   if (!IsHeapObject()) return false;
757   switch (HeapObject::cast(this)->map()->instance_type()) {
758 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
759   STRUCT_LIST(MAKE_STRUCT_CASE)
760 #undef MAKE_STRUCT_CASE
761     default: return false;
762   }
763 }
764 
765 
766 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
767   bool Object::Is##Name() {                                      \
768     return Object::IsHeapObject()                                \
769       && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
770   }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)771   STRUCT_LIST(MAKE_STRUCT_PREDICATE)
772 #undef MAKE_STRUCT_PREDICATE
773 
774 
775 bool Object::IsUndefined() {
776   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
777 }
778 
779 
IsNull()780 bool Object::IsNull() {
781   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
782 }
783 
784 
IsTheHole()785 bool Object::IsTheHole() {
786   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
787 }
788 
789 
IsTrue()790 bool Object::IsTrue() {
791   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
792 }
793 
794 
IsFalse()795 bool Object::IsFalse() {
796   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
797 }
798 
799 
IsArgumentsMarker()800 bool Object::IsArgumentsMarker() {
801   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
802 }
803 
804 
Number()805 double Object::Number() {
806   ASSERT(IsNumber());
807   return IsSmi()
808     ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
809     : reinterpret_cast<HeapNumber*>(this)->value();
810 }
811 
812 
IsNaN()813 bool Object::IsNaN() {
814   return this->IsHeapNumber() && isnan(HeapNumber::cast(this)->value());
815 }
816 
817 
ToSmi()818 MaybeObject* Object::ToSmi() {
819   if (IsSmi()) return this;
820   if (IsHeapNumber()) {
821     double value = HeapNumber::cast(this)->value();
822     int int_value = FastD2I(value);
823     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
824       return Smi::FromInt(int_value);
825     }
826   }
827   return Failure::Exception();
828 }
829 
830 
HasSpecificClassOf(String * name)831 bool Object::HasSpecificClassOf(String* name) {
832   return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
833 }
834 
835 
GetElement(uint32_t index)836 MaybeObject* Object::GetElement(uint32_t index) {
837   // GetElement can trigger a getter which can cause allocation.
838   // This was not always the case. This ASSERT is here to catch
839   // leftover incorrect uses.
840   ASSERT(HEAP->IsAllocationAllowed());
841   return GetElementWithReceiver(this, index);
842 }
843 
844 
GetElementNoExceptionThrown(uint32_t index)845 Object* Object::GetElementNoExceptionThrown(uint32_t index) {
846   MaybeObject* maybe = GetElementWithReceiver(this, index);
847   ASSERT(!maybe->IsFailure());
848   Object* result = NULL;  // Initialization to please compiler.
849   maybe->ToObject(&result);
850   return result;
851 }
852 
853 
GetProperty(String * key)854 MaybeObject* Object::GetProperty(String* key) {
855   PropertyAttributes attributes;
856   return GetPropertyWithReceiver(this, key, &attributes);
857 }
858 
859 
GetProperty(String * key,PropertyAttributes * attributes)860 MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
861   return GetPropertyWithReceiver(this, key, attributes);
862 }
863 
864 
865 #define FIELD_ADDR(p, offset) \
866   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
867 
868 #define READ_FIELD(p, offset) \
869   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
870 
871 #define WRITE_FIELD(p, offset, value) \
872   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
873 
874 #define WRITE_BARRIER(heap, object, offset, value)                      \
875   heap->incremental_marking()->RecordWrite(                             \
876       object, HeapObject::RawField(object, offset), value);             \
877   if (heap->InNewSpace(value)) {                                        \
878     heap->RecordWrite(object->address(), offset);                       \
879   }
880 
881 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode)    \
882   if (mode == UPDATE_WRITE_BARRIER) {                                   \
883     heap->incremental_marking()->RecordWrite(                           \
884       object, HeapObject::RawField(object, offset), value);             \
885     if (heap->InNewSpace(value)) {                                      \
886       heap->RecordWrite(object->address(), offset);                     \
887     }                                                                   \
888   }
889 
890 #ifndef V8_TARGET_ARCH_MIPS
891   #define READ_DOUBLE_FIELD(p, offset) \
892     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
893 #else  // V8_TARGET_ARCH_MIPS
894   // Prevent gcc from using load-double (mips ldc1) on (possibly)
895   // non-64-bit aligned HeapNumber::value.
read_double_field(void * p,int offset)896   static inline double read_double_field(void* p, int offset) {
897     union conversion {
898       double d;
899       uint32_t u[2];
900     } c;
901     c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
902     c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
903     return c.d;
904   }
905   #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
906 #endif  // V8_TARGET_ARCH_MIPS
907 
908 #ifndef V8_TARGET_ARCH_MIPS
909   #define WRITE_DOUBLE_FIELD(p, offset, value) \
910     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
911 #else  // V8_TARGET_ARCH_MIPS
912   // Prevent gcc from using store-double (mips sdc1) on (possibly)
913   // non-64-bit aligned HeapNumber::value.
write_double_field(void * p,int offset,double value)914   static inline void write_double_field(void* p, int offset,
915                                         double value) {
916     union conversion {
917       double d;
918       uint32_t u[2];
919     } c;
920     c.d = value;
921     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
922     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
923   }
924   #define WRITE_DOUBLE_FIELD(p, offset, value) \
925     write_double_field(p, offset, value)
926 #endif  // V8_TARGET_ARCH_MIPS
927 
928 
929 #define READ_INT_FIELD(p, offset) \
930   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
931 
932 #define WRITE_INT_FIELD(p, offset, value) \
933   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
934 
935 #define READ_INTPTR_FIELD(p, offset) \
936   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
937 
938 #define WRITE_INTPTR_FIELD(p, offset, value) \
939   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
940 
941 #define READ_UINT32_FIELD(p, offset) \
942   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
943 
944 #define WRITE_UINT32_FIELD(p, offset, value) \
945   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
946 
947 #define READ_INT64_FIELD(p, offset) \
948   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)))
949 
950 #define WRITE_INT64_FIELD(p, offset, value) \
951   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
952 
953 #define READ_SHORT_FIELD(p, offset) \
954   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
955 
956 #define WRITE_SHORT_FIELD(p, offset, value) \
957   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
958 
959 #define READ_BYTE_FIELD(p, offset) \
960   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
961 
962 #define WRITE_BYTE_FIELD(p, offset, value) \
963   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
964 
965 
RawField(HeapObject * obj,int byte_offset)966 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
967   return &READ_FIELD(obj, byte_offset);
968 }
969 
970 
value()971 int Smi::value() {
972   return Internals::SmiValue(this);
973 }
974 
975 
FromInt(int value)976 Smi* Smi::FromInt(int value) {
977   ASSERT(Smi::IsValid(value));
978   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
979   intptr_t tagged_value =
980       (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
981   return reinterpret_cast<Smi*>(tagged_value);
982 }
983 
984 
FromIntptr(intptr_t value)985 Smi* Smi::FromIntptr(intptr_t value) {
986   ASSERT(Smi::IsValid(value));
987   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
988   return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
989 }
990 
991 
type()992 Failure::Type Failure::type() const {
993   return static_cast<Type>(value() & kFailureTypeTagMask);
994 }
995 
996 
IsInternalError()997 bool Failure::IsInternalError() const {
998   return type() == INTERNAL_ERROR;
999 }
1000 
1001 
IsOutOfMemoryException()1002 bool Failure::IsOutOfMemoryException() const {
1003   return type() == OUT_OF_MEMORY_EXCEPTION;
1004 }
1005 
1006 
allocation_space()1007 AllocationSpace Failure::allocation_space() const {
1008   ASSERT_EQ(RETRY_AFTER_GC, type());
1009   return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1010                                       & kSpaceTagMask);
1011 }
1012 
1013 
InternalError()1014 Failure* Failure::InternalError() {
1015   return Construct(INTERNAL_ERROR);
1016 }
1017 
1018 
Exception()1019 Failure* Failure::Exception() {
1020   return Construct(EXCEPTION);
1021 }
1022 
1023 
OutOfMemoryException()1024 Failure* Failure::OutOfMemoryException() {
1025   return Construct(OUT_OF_MEMORY_EXCEPTION);
1026 }
1027 
1028 
value()1029 intptr_t Failure::value() const {
1030   return static_cast<intptr_t>(
1031       reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
1032 }
1033 
1034 
RetryAfterGC()1035 Failure* Failure::RetryAfterGC() {
1036   return RetryAfterGC(NEW_SPACE);
1037 }
1038 
1039 
RetryAfterGC(AllocationSpace space)1040 Failure* Failure::RetryAfterGC(AllocationSpace space) {
1041   ASSERT((space & ~kSpaceTagMask) == 0);
1042   return Construct(RETRY_AFTER_GC, space);
1043 }
1044 
1045 
Construct(Type type,intptr_t value)1046 Failure* Failure::Construct(Type type, intptr_t value) {
1047   uintptr_t info =
1048       (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
1049   ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
1050   return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
1051 }
1052 
1053 
IsValid(intptr_t value)1054 bool Smi::IsValid(intptr_t value) {
1055 #ifdef DEBUG
1056   bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1057 #endif
1058 
1059 #ifdef V8_TARGET_ARCH_X64
1060   // To be representable as a long smi, the value must be a 32-bit integer.
1061   bool result = (value == static_cast<int32_t>(value));
1062 #else
1063   // To be representable as an tagged small integer, the two
1064   // most-significant bits of 'value' must be either 00 or 11 due to
1065   // sign-extension. To check this we add 01 to the two
1066   // most-significant bits, and check if the most-significant bit is 0
1067   //
1068   // CAUTION: The original code below:
1069   // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1070   // may lead to incorrect results according to the C language spec, and
1071   // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1072   // compiler may produce undefined results in case of signed integer
1073   // overflow. The computation must be done w/ unsigned ints.
1074   bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
1075 #endif
1076   ASSERT(result == in_range);
1077   return result;
1078 }
1079 
1080 
FromMap(Map * map)1081 MapWord MapWord::FromMap(Map* map) {
1082   return MapWord(reinterpret_cast<uintptr_t>(map));
1083 }
1084 
1085 
ToMap()1086 Map* MapWord::ToMap() {
1087   return reinterpret_cast<Map*>(value_);
1088 }
1089 
1090 
IsForwardingAddress()1091 bool MapWord::IsForwardingAddress() {
1092   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1093 }
1094 
1095 
FromForwardingAddress(HeapObject * object)1096 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1097   Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1098   return MapWord(reinterpret_cast<uintptr_t>(raw));
1099 }
1100 
1101 
ToForwardingAddress()1102 HeapObject* MapWord::ToForwardingAddress() {
1103   ASSERT(IsForwardingAddress());
1104   return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1105 }
1106 
1107 
1108 #ifdef DEBUG
VerifyObjectField(int offset)1109 void HeapObject::VerifyObjectField(int offset) {
1110   VerifyPointer(READ_FIELD(this, offset));
1111 }
1112 
VerifySmiField(int offset)1113 void HeapObject::VerifySmiField(int offset) {
1114   ASSERT(READ_FIELD(this, offset)->IsSmi());
1115 }
1116 #endif
1117 
1118 
GetHeap()1119 Heap* HeapObject::GetHeap() {
1120   Heap* heap =
1121       MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1122   ASSERT(heap != NULL);
1123   ASSERT(heap->isolate() == Isolate::Current());
1124   return heap;
1125 }
1126 
1127 
GetIsolate()1128 Isolate* HeapObject::GetIsolate() {
1129   return GetHeap()->isolate();
1130 }
1131 
1132 
map()1133 Map* HeapObject::map() {
1134   return map_word().ToMap();
1135 }
1136 
1137 
set_map(Map * value)1138 void HeapObject::set_map(Map* value) {
1139   set_map_word(MapWord::FromMap(value));
1140   if (value != NULL) {
1141     // TODO(1600) We are passing NULL as a slot because maps can never be on
1142     // evacuation candidate.
1143     value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1144   }
1145 }
1146 
1147 
1148 // Unsafe accessor omitting write barrier.
set_map_no_write_barrier(Map * value)1149 void HeapObject::set_map_no_write_barrier(Map* value) {
1150   set_map_word(MapWord::FromMap(value));
1151 }
1152 
1153 
map_word()1154 MapWord HeapObject::map_word() {
1155   return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1156 }
1157 
1158 
set_map_word(MapWord map_word)1159 void HeapObject::set_map_word(MapWord map_word) {
1160   // WRITE_FIELD does not invoke write barrier, but there is no need
1161   // here.
1162   WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1163 }
1164 
1165 
FromAddress(Address address)1166 HeapObject* HeapObject::FromAddress(Address address) {
1167   ASSERT_TAG_ALIGNED(address);
1168   return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1169 }
1170 
1171 
address()1172 Address HeapObject::address() {
1173   return reinterpret_cast<Address>(this) - kHeapObjectTag;
1174 }
1175 
1176 
Size()1177 int HeapObject::Size() {
1178   return SizeFromMap(map());
1179 }
1180 
1181 
IteratePointers(ObjectVisitor * v,int start,int end)1182 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1183   v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1184                    reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1185 }
1186 
1187 
IteratePointer(ObjectVisitor * v,int offset)1188 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1189   v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1190 }
1191 
1192 
value()1193 double HeapNumber::value() {
1194   return READ_DOUBLE_FIELD(this, kValueOffset);
1195 }
1196 
1197 
set_value(double value)1198 void HeapNumber::set_value(double value) {
1199   WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1200 }
1201 
1202 
get_exponent()1203 int HeapNumber::get_exponent() {
1204   return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1205           kExponentShift) - kExponentBias;
1206 }
1207 
1208 
get_sign()1209 int HeapNumber::get_sign() {
1210   return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1211 }
1212 
1213 
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1214 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1215 
1216 
1217 Object** FixedArray::GetFirstElementAddress() {
1218   return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1219 }
1220 
1221 
ContainsOnlySmisOrHoles()1222 bool FixedArray::ContainsOnlySmisOrHoles() {
1223   Object* the_hole = GetHeap()->the_hole_value();
1224   Object** current = GetFirstElementAddress();
1225   for (int i = 0; i < length(); ++i) {
1226     Object* candidate = *current++;
1227     if (!candidate->IsSmi() && candidate != the_hole) return false;
1228   }
1229   return true;
1230 }
1231 
1232 
elements()1233 FixedArrayBase* JSObject::elements() {
1234   Object* array = READ_FIELD(this, kElementsOffset);
1235   return static_cast<FixedArrayBase*>(array);
1236 }
1237 
ValidateSmiOnlyElements()1238 void JSObject::ValidateSmiOnlyElements() {
1239 #if DEBUG
1240   if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1241     Heap* heap = GetHeap();
1242     // Don't use elements, since integrity checks will fail if there
1243     // are filler pointers in the array.
1244     FixedArray* fixed_array =
1245         reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset));
1246     Map* map = fixed_array->map();
1247     // Arrays that have been shifted in place can't be verified.
1248     if (map != heap->raw_unchecked_one_pointer_filler_map() &&
1249         map != heap->raw_unchecked_two_pointer_filler_map() &&
1250         map != heap->free_space_map()) {
1251       for (int i = 0; i < fixed_array->length(); i++) {
1252         Object* current = fixed_array->get(i);
1253         ASSERT(current->IsSmi() || current->IsTheHole());
1254       }
1255     }
1256   }
1257 #endif
1258 }
1259 
1260 
EnsureCanContainHeapObjectElements()1261 MaybeObject* JSObject::EnsureCanContainHeapObjectElements() {
1262 #if DEBUG
1263   ValidateSmiOnlyElements();
1264 #endif
1265   if ((map()->elements_kind() != FAST_ELEMENTS)) {
1266     return TransitionElementsKind(FAST_ELEMENTS);
1267   }
1268   return this;
1269 }
1270 
1271 
EnsureCanContainElements(Object ** objects,uint32_t count,EnsureElementsMode mode)1272 MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1273                                                 uint32_t count,
1274                                                 EnsureElementsMode mode) {
1275   ElementsKind current_kind = map()->elements_kind();
1276   ElementsKind target_kind = current_kind;
1277   ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1278   if (current_kind == FAST_ELEMENTS) return this;
1279 
1280   Heap* heap = GetHeap();
1281   Object* the_hole = heap->the_hole_value();
1282   Object* heap_number_map = heap->heap_number_map();
1283   for (uint32_t i = 0; i < count; ++i) {
1284     Object* current = *objects++;
1285     if (!current->IsSmi() && current != the_hole) {
1286       if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS &&
1287           HeapObject::cast(current)->map() == heap_number_map) {
1288         target_kind = FAST_DOUBLE_ELEMENTS;
1289       } else {
1290         target_kind = FAST_ELEMENTS;
1291         break;
1292       }
1293     }
1294   }
1295 
1296   if (target_kind != current_kind) {
1297     return TransitionElementsKind(target_kind);
1298   }
1299   return this;
1300 }
1301 
1302 
EnsureCanContainElements(FixedArrayBase * elements,EnsureElementsMode mode)1303 MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements,
1304                                                 EnsureElementsMode mode) {
1305   if (elements->map() != GetHeap()->fixed_double_array_map()) {
1306     ASSERT(elements->map() == GetHeap()->fixed_array_map() ||
1307            elements->map() == GetHeap()->fixed_cow_array_map());
1308     if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1309       mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1310     }
1311     Object** objects = FixedArray::cast(elements)->GetFirstElementAddress();
1312     return EnsureCanContainElements(objects, elements->length(), mode);
1313   }
1314 
1315   ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1316   if (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) {
1317     return TransitionElementsKind(FAST_DOUBLE_ELEMENTS);
1318   }
1319 
1320   return this;
1321 }
1322 
1323 
GetElementsTransitionMap(Isolate * isolate,ElementsKind to_kind)1324 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate,
1325                                                 ElementsKind to_kind) {
1326   Map* current_map = map();
1327   ElementsKind from_kind = current_map->elements_kind();
1328 
1329   if (from_kind == to_kind) return current_map;
1330 
1331   Context* global_context = isolate->context()->global_context();
1332   if (current_map == global_context->smi_js_array_map()) {
1333     if (to_kind == FAST_ELEMENTS) {
1334       return global_context->object_js_array_map();
1335     } else {
1336       if (to_kind == FAST_DOUBLE_ELEMENTS) {
1337         return global_context->double_js_array_map();
1338       } else {
1339         ASSERT(to_kind == DICTIONARY_ELEMENTS);
1340       }
1341     }
1342   }
1343   return GetElementsTransitionMapSlow(to_kind);
1344 }
1345 
1346 
set_map_and_elements(Map * new_map,FixedArrayBase * value,WriteBarrierMode mode)1347 void JSObject::set_map_and_elements(Map* new_map,
1348                                     FixedArrayBase* value,
1349                                     WriteBarrierMode mode) {
1350   ASSERT(value->HasValidElements());
1351 #ifdef DEBUG
1352   ValidateSmiOnlyElements();
1353 #endif
1354   if (new_map != NULL) {
1355     if (mode == UPDATE_WRITE_BARRIER) {
1356       set_map(new_map);
1357     } else {
1358       ASSERT(mode == SKIP_WRITE_BARRIER);
1359       set_map_no_write_barrier(new_map);
1360     }
1361   }
1362   ASSERT((map()->has_fast_elements() ||
1363           map()->has_fast_smi_only_elements() ||
1364           (value == GetHeap()->empty_fixed_array())) ==
1365          (value->map() == GetHeap()->fixed_array_map() ||
1366           value->map() == GetHeap()->fixed_cow_array_map()));
1367   ASSERT((value == GetHeap()->empty_fixed_array()) ||
1368          (map()->has_fast_double_elements() == value->IsFixedDoubleArray()));
1369   WRITE_FIELD(this, kElementsOffset, value);
1370   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1371 }
1372 
1373 
set_elements(FixedArrayBase * value,WriteBarrierMode mode)1374 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1375   set_map_and_elements(NULL, value, mode);
1376 }
1377 
1378 
initialize_properties()1379 void JSObject::initialize_properties() {
1380   ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1381   WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1382 }
1383 
1384 
initialize_elements()1385 void JSObject::initialize_elements() {
1386   ASSERT(map()->has_fast_elements() ||
1387          map()->has_fast_smi_only_elements() ||
1388          map()->has_fast_double_elements());
1389   ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1390   WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
1391 }
1392 
1393 
ResetElements()1394 MaybeObject* JSObject::ResetElements() {
1395   Object* obj;
1396   ElementsKind elements_kind = FLAG_smi_only_arrays
1397       ? FAST_SMI_ONLY_ELEMENTS
1398       : FAST_ELEMENTS;
1399   MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
1400                                                     elements_kind);
1401   if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1402   set_map(Map::cast(obj));
1403   initialize_elements();
1404   return this;
1405 }
1406 
1407 
ACCESSORS(Oddball,to_string,String,kToStringOffset)1408 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1409 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1410 
1411 
1412 byte Oddball::kind() {
1413   return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1414 }
1415 
1416 
set_kind(byte value)1417 void Oddball::set_kind(byte value) {
1418   WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1419 }
1420 
1421 
value()1422 Object* JSGlobalPropertyCell::value() {
1423   return READ_FIELD(this, kValueOffset);
1424 }
1425 
1426 
set_value(Object * val,WriteBarrierMode ignored)1427 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1428   // The write barrier is not used for global property cells.
1429   ASSERT(!val->IsJSGlobalPropertyCell());
1430   WRITE_FIELD(this, kValueOffset, val);
1431 }
1432 
1433 
GetHeaderSize()1434 int JSObject::GetHeaderSize() {
1435   InstanceType type = map()->instance_type();
1436   // Check for the most common kind of JavaScript object before
1437   // falling into the generic switch. This speeds up the internal
1438   // field operations considerably on average.
1439   if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1440   switch (type) {
1441     case JS_GLOBAL_PROXY_TYPE:
1442       return JSGlobalProxy::kSize;
1443     case JS_GLOBAL_OBJECT_TYPE:
1444       return JSGlobalObject::kSize;
1445     case JS_BUILTINS_OBJECT_TYPE:
1446       return JSBuiltinsObject::kSize;
1447     case JS_FUNCTION_TYPE:
1448       return JSFunction::kSize;
1449     case JS_VALUE_TYPE:
1450       return JSValue::kSize;
1451     case JS_DATE_TYPE:
1452       return JSDate::kSize;
1453     case JS_ARRAY_TYPE:
1454       return JSArray::kSize;
1455     case JS_WEAK_MAP_TYPE:
1456       return JSWeakMap::kSize;
1457     case JS_REGEXP_TYPE:
1458       return JSRegExp::kSize;
1459     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1460       return JSObject::kHeaderSize;
1461     case JS_MESSAGE_OBJECT_TYPE:
1462       return JSMessageObject::kSize;
1463     default:
1464       UNREACHABLE();
1465       return 0;
1466   }
1467 }
1468 
1469 
GetInternalFieldCount()1470 int JSObject::GetInternalFieldCount() {
1471   ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1472   // Make sure to adjust for the number of in-object properties. These
1473   // properties do contribute to the size, but are not internal fields.
1474   return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1475          map()->inobject_properties();
1476 }
1477 
1478 
GetInternalFieldOffset(int index)1479 int JSObject::GetInternalFieldOffset(int index) {
1480   ASSERT(index < GetInternalFieldCount() && index >= 0);
1481   return GetHeaderSize() + (kPointerSize * index);
1482 }
1483 
1484 
GetInternalField(int index)1485 Object* JSObject::GetInternalField(int index) {
1486   ASSERT(index < GetInternalFieldCount() && index >= 0);
1487   // Internal objects do follow immediately after the header, whereas in-object
1488   // properties are at the end of the object. Therefore there is no need
1489   // to adjust the index here.
1490   return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1491 }
1492 
1493 
SetInternalField(int index,Object * value)1494 void JSObject::SetInternalField(int index, Object* value) {
1495   ASSERT(index < GetInternalFieldCount() && index >= 0);
1496   // Internal objects do follow immediately after the header, whereas in-object
1497   // properties are at the end of the object. Therefore there is no need
1498   // to adjust the index here.
1499   int offset = GetHeaderSize() + (kPointerSize * index);
1500   WRITE_FIELD(this, offset, value);
1501   WRITE_BARRIER(GetHeap(), this, offset, value);
1502 }
1503 
1504 
SetInternalField(int index,Smi * value)1505 void JSObject::SetInternalField(int index, Smi* value) {
1506   ASSERT(index < GetInternalFieldCount() && index >= 0);
1507   // Internal objects do follow immediately after the header, whereas in-object
1508   // properties are at the end of the object. Therefore there is no need
1509   // to adjust the index here.
1510   int offset = GetHeaderSize() + (kPointerSize * index);
1511   WRITE_FIELD(this, offset, value);
1512 }
1513 
1514 
1515 // Access fast-case object properties at index. The use of these routines
1516 // is needed to correctly distinguish between properties stored in-object and
1517 // properties stored in the properties array.
FastPropertyAt(int index)1518 Object* JSObject::FastPropertyAt(int index) {
1519   // Adjust for the number of properties stored in the object.
1520   index -= map()->inobject_properties();
1521   if (index < 0) {
1522     int offset = map()->instance_size() + (index * kPointerSize);
1523     return READ_FIELD(this, offset);
1524   } else {
1525     ASSERT(index < properties()->length());
1526     return properties()->get(index);
1527   }
1528 }
1529 
1530 
FastPropertyAtPut(int index,Object * value)1531 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1532   // Adjust for the number of properties stored in the object.
1533   index -= map()->inobject_properties();
1534   if (index < 0) {
1535     int offset = map()->instance_size() + (index * kPointerSize);
1536     WRITE_FIELD(this, offset, value);
1537     WRITE_BARRIER(GetHeap(), this, offset, value);
1538   } else {
1539     ASSERT(index < properties()->length());
1540     properties()->set(index, value);
1541   }
1542   return value;
1543 }
1544 
1545 
GetInObjectPropertyOffset(int index)1546 int JSObject::GetInObjectPropertyOffset(int index) {
1547   // Adjust for the number of properties stored in the object.
1548   index -= map()->inobject_properties();
1549   ASSERT(index < 0);
1550   return map()->instance_size() + (index * kPointerSize);
1551 }
1552 
1553 
InObjectPropertyAt(int index)1554 Object* JSObject::InObjectPropertyAt(int index) {
1555   // Adjust for the number of properties stored in the object.
1556   index -= map()->inobject_properties();
1557   ASSERT(index < 0);
1558   int offset = map()->instance_size() + (index * kPointerSize);
1559   return READ_FIELD(this, offset);
1560 }
1561 
1562 
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1563 Object* JSObject::InObjectPropertyAtPut(int index,
1564                                         Object* value,
1565                                         WriteBarrierMode mode) {
1566   // Adjust for the number of properties stored in the object.
1567   index -= map()->inobject_properties();
1568   ASSERT(index < 0);
1569   int offset = map()->instance_size() + (index * kPointerSize);
1570   WRITE_FIELD(this, offset, value);
1571   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1572   return value;
1573 }
1574 
1575 
1576 
InitializeBody(Map * map,Object * pre_allocated_value,Object * filler_value)1577 void JSObject::InitializeBody(Map* map,
1578                               Object* pre_allocated_value,
1579                               Object* filler_value) {
1580   ASSERT(!filler_value->IsHeapObject() ||
1581          !GetHeap()->InNewSpace(filler_value));
1582   ASSERT(!pre_allocated_value->IsHeapObject() ||
1583          !GetHeap()->InNewSpace(pre_allocated_value));
1584   int size = map->instance_size();
1585   int offset = kHeaderSize;
1586   if (filler_value != pre_allocated_value) {
1587     int pre_allocated = map->pre_allocated_property_fields();
1588     ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1589     for (int i = 0; i < pre_allocated; i++) {
1590       WRITE_FIELD(this, offset, pre_allocated_value);
1591       offset += kPointerSize;
1592     }
1593   }
1594   while (offset < size) {
1595     WRITE_FIELD(this, offset, filler_value);
1596     offset += kPointerSize;
1597   }
1598 }
1599 
1600 
HasFastProperties()1601 bool JSObject::HasFastProperties() {
1602   return !properties()->IsDictionary();
1603 }
1604 
1605 
MaxFastProperties()1606 int JSObject::MaxFastProperties() {
1607   // Allow extra fast properties if the object has more than
1608   // kMaxFastProperties in-object properties. When this is the case,
1609   // it is very unlikely that the object is being used as a dictionary
1610   // and there is a good chance that allowing more map transitions
1611   // will be worth it.
1612   return Max(map()->inobject_properties(), kMaxFastProperties);
1613 }
1614 
1615 
InitializeBody(int object_size)1616 void Struct::InitializeBody(int object_size) {
1617   Object* value = GetHeap()->undefined_value();
1618   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1619     WRITE_FIELD(this, offset, value);
1620   }
1621 }
1622 
1623 
ToArrayIndex(uint32_t * index)1624 bool Object::ToArrayIndex(uint32_t* index) {
1625   if (IsSmi()) {
1626     int value = Smi::cast(this)->value();
1627     if (value < 0) return false;
1628     *index = value;
1629     return true;
1630   }
1631   if (IsHeapNumber()) {
1632     double value = HeapNumber::cast(this)->value();
1633     uint32_t uint_value = static_cast<uint32_t>(value);
1634     if (value == static_cast<double>(uint_value)) {
1635       *index = uint_value;
1636       return true;
1637     }
1638   }
1639   return false;
1640 }
1641 
1642 
IsStringObjectWithCharacterAt(uint32_t index)1643 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1644   if (!this->IsJSValue()) return false;
1645 
1646   JSValue* js_value = JSValue::cast(this);
1647   if (!js_value->value()->IsString()) return false;
1648 
1649   String* str = String::cast(js_value->value());
1650   if (index >= (uint32_t)str->length()) return false;
1651 
1652   return true;
1653 }
1654 
1655 
cast(Object * object)1656 FixedArrayBase* FixedArrayBase::cast(Object* object) {
1657   ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1658   return reinterpret_cast<FixedArrayBase*>(object);
1659 }
1660 
1661 
get(int index)1662 Object* FixedArray::get(int index) {
1663   ASSERT(index >= 0 && index < this->length());
1664   return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1665 }
1666 
1667 
set(int index,Smi * value)1668 void FixedArray::set(int index, Smi* value) {
1669   ASSERT(map() != HEAP->fixed_cow_array_map());
1670   ASSERT(index >= 0 && index < this->length());
1671   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1672   int offset = kHeaderSize + index * kPointerSize;
1673   WRITE_FIELD(this, offset, value);
1674 }
1675 
1676 
set(int index,Object * value)1677 void FixedArray::set(int index, Object* value) {
1678   ASSERT(map() != HEAP->fixed_cow_array_map());
1679   ASSERT(index >= 0 && index < this->length());
1680   int offset = kHeaderSize + index * kPointerSize;
1681   WRITE_FIELD(this, offset, value);
1682   WRITE_BARRIER(GetHeap(), this, offset, value);
1683 }
1684 
1685 
is_the_hole_nan(double value)1686 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1687   return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1688 }
1689 
1690 
hole_nan_as_double()1691 inline double FixedDoubleArray::hole_nan_as_double() {
1692   return BitCast<double, uint64_t>(kHoleNanInt64);
1693 }
1694 
1695 
canonical_not_the_hole_nan_as_double()1696 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1697   ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1698   ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1699   return OS::nan_value();
1700 }
1701 
1702 
get_scalar(int index)1703 double FixedDoubleArray::get_scalar(int index) {
1704   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1705          map() != HEAP->fixed_array_map());
1706   ASSERT(index >= 0 && index < this->length());
1707   double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1708   ASSERT(!is_the_hole_nan(result));
1709   return result;
1710 }
1711 
get_representation(int index)1712 int64_t FixedDoubleArray::get_representation(int index) {
1713   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1714          map() != HEAP->fixed_array_map());
1715   ASSERT(index >= 0 && index < this->length());
1716   return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
1717 }
1718 
get(int index)1719 MaybeObject* FixedDoubleArray::get(int index) {
1720   if (is_the_hole(index)) {
1721     return GetHeap()->the_hole_value();
1722   } else {
1723     return GetHeap()->NumberFromDouble(get_scalar(index));
1724   }
1725 }
1726 
1727 
set(int index,double value)1728 void FixedDoubleArray::set(int index, double value) {
1729   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1730          map() != HEAP->fixed_array_map());
1731   int offset = kHeaderSize + index * kDoubleSize;
1732   if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1733   WRITE_DOUBLE_FIELD(this, offset, value);
1734 }
1735 
1736 
set_the_hole(int index)1737 void FixedDoubleArray::set_the_hole(int index) {
1738   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1739          map() != HEAP->fixed_array_map());
1740   int offset = kHeaderSize + index * kDoubleSize;
1741   WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1742 }
1743 
1744 
is_the_hole(int index)1745 bool FixedDoubleArray::is_the_hole(int index) {
1746   int offset = kHeaderSize + index * kDoubleSize;
1747   return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1748 }
1749 
1750 
GetWriteBarrierMode(const AssertNoAllocation &)1751 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1752   Heap* heap = GetHeap();
1753   if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1754   if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
1755   return UPDATE_WRITE_BARRIER;
1756 }
1757 
1758 
set(int index,Object * value,WriteBarrierMode mode)1759 void FixedArray::set(int index,
1760                      Object* value,
1761                      WriteBarrierMode mode) {
1762   ASSERT(map() != HEAP->fixed_cow_array_map());
1763   ASSERT(index >= 0 && index < this->length());
1764   int offset = kHeaderSize + index * kPointerSize;
1765   WRITE_FIELD(this, offset, value);
1766   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1767 }
1768 
1769 
NoIncrementalWriteBarrierSet(FixedArray * array,int index,Object * value)1770 void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
1771                                               int index,
1772                                               Object* value) {
1773   ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1774   ASSERT(index >= 0 && index < array->length());
1775   int offset = kHeaderSize + index * kPointerSize;
1776   WRITE_FIELD(array, offset, value);
1777   Heap* heap = array->GetHeap();
1778   if (heap->InNewSpace(value)) {
1779     heap->RecordWrite(array->address(), offset);
1780   }
1781 }
1782 
1783 
NoWriteBarrierSet(FixedArray * array,int index,Object * value)1784 void FixedArray::NoWriteBarrierSet(FixedArray* array,
1785                                    int index,
1786                                    Object* value) {
1787   ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1788   ASSERT(index >= 0 && index < array->length());
1789   ASSERT(!HEAP->InNewSpace(value));
1790   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1791 }
1792 
1793 
set_undefined(int index)1794 void FixedArray::set_undefined(int index) {
1795   ASSERT(map() != HEAP->fixed_cow_array_map());
1796   set_undefined(GetHeap(), index);
1797 }
1798 
1799 
set_undefined(Heap * heap,int index)1800 void FixedArray::set_undefined(Heap* heap, int index) {
1801   ASSERT(index >= 0 && index < this->length());
1802   ASSERT(!heap->InNewSpace(heap->undefined_value()));
1803   WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1804               heap->undefined_value());
1805 }
1806 
1807 
set_null(int index)1808 void FixedArray::set_null(int index) {
1809   set_null(GetHeap(), index);
1810 }
1811 
1812 
set_null(Heap * heap,int index)1813 void FixedArray::set_null(Heap* heap, int index) {
1814   ASSERT(index >= 0 && index < this->length());
1815   ASSERT(!heap->InNewSpace(heap->null_value()));
1816   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1817 }
1818 
1819 
set_the_hole(int index)1820 void FixedArray::set_the_hole(int index) {
1821   ASSERT(map() != HEAP->fixed_cow_array_map());
1822   ASSERT(index >= 0 && index < this->length());
1823   ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1824   WRITE_FIELD(this,
1825               kHeaderSize + index * kPointerSize,
1826               GetHeap()->the_hole_value());
1827 }
1828 
1829 
set_unchecked(int index,Smi * value)1830 void FixedArray::set_unchecked(int index, Smi* value) {
1831   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1832   int offset = kHeaderSize + index * kPointerSize;
1833   WRITE_FIELD(this, offset, value);
1834 }
1835 
1836 
set_unchecked(Heap * heap,int index,Object * value,WriteBarrierMode mode)1837 void FixedArray::set_unchecked(Heap* heap,
1838                                int index,
1839                                Object* value,
1840                                WriteBarrierMode mode) {
1841   int offset = kHeaderSize + index * kPointerSize;
1842   WRITE_FIELD(this, offset, value);
1843   CONDITIONAL_WRITE_BARRIER(heap, this, offset, value, mode);
1844 }
1845 
1846 
set_null_unchecked(Heap * heap,int index)1847 void FixedArray::set_null_unchecked(Heap* heap, int index) {
1848   ASSERT(index >= 0 && index < this->length());
1849   ASSERT(!HEAP->InNewSpace(heap->null_value()));
1850   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1851 }
1852 
1853 
data_start()1854 Object** FixedArray::data_start() {
1855   return HeapObject::RawField(this, kHeaderSize);
1856 }
1857 
1858 
IsEmpty()1859 bool DescriptorArray::IsEmpty() {
1860   ASSERT(this->IsSmi() ||
1861          this->length() > kFirstIndex ||
1862          this == HEAP->empty_descriptor_array());
1863   return this->IsSmi() || length() <= kFirstIndex;
1864 }
1865 
1866 
bit_field3_storage()1867 int DescriptorArray::bit_field3_storage() {
1868   Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1869   return Smi::cast(storage)->value();
1870 }
1871 
set_bit_field3_storage(int value)1872 void DescriptorArray::set_bit_field3_storage(int value) {
1873   ASSERT(!IsEmpty());
1874   WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
1875 }
1876 
1877 
NoIncrementalWriteBarrierSwap(FixedArray * array,int first,int second)1878 void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
1879                                                     int first,
1880                                                     int second) {
1881   Object* tmp = array->get(first);
1882   NoIncrementalWriteBarrierSet(array, first, array->get(second));
1883   NoIncrementalWriteBarrierSet(array, second, tmp);
1884 }
1885 
1886 
Search(String * name)1887 int DescriptorArray::Search(String* name) {
1888   SLOW_ASSERT(IsSortedNoDuplicates());
1889 
1890   // Check for empty descriptor array.
1891   int nof = number_of_descriptors();
1892   if (nof == 0) return kNotFound;
1893 
1894   // Fast case: do linear search for small arrays.
1895   const int kMaxElementsForLinearSearch = 8;
1896   if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1897     return LinearSearch(name, nof);
1898   }
1899 
1900   // Slow case: perform binary search.
1901   return BinarySearch(name, 0, nof - 1);
1902 }
1903 
1904 
SearchWithCache(String * name)1905 int DescriptorArray::SearchWithCache(String* name) {
1906   int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
1907   if (number == DescriptorLookupCache::kAbsent) {
1908     number = Search(name);
1909     GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
1910   }
1911   return number;
1912 }
1913 
1914 
GetKey(int descriptor_number)1915 String* DescriptorArray::GetKey(int descriptor_number) {
1916   ASSERT(descriptor_number < number_of_descriptors());
1917   return String::cast(get(ToKeyIndex(descriptor_number)));
1918 }
1919 
1920 
GetValue(int descriptor_number)1921 Object* DescriptorArray::GetValue(int descriptor_number) {
1922   ASSERT(descriptor_number < number_of_descriptors());
1923   return GetContentArray()->get(ToValueIndex(descriptor_number));
1924 }
1925 
1926 
GetDetails(int descriptor_number)1927 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1928   ASSERT(descriptor_number < number_of_descriptors());
1929   return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1930 }
1931 
1932 
GetType(int descriptor_number)1933 PropertyType DescriptorArray::GetType(int descriptor_number) {
1934   ASSERT(descriptor_number < number_of_descriptors());
1935   return PropertyDetails(GetDetails(descriptor_number)).type();
1936 }
1937 
1938 
GetFieldIndex(int descriptor_number)1939 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1940   return Descriptor::IndexFromValue(GetValue(descriptor_number));
1941 }
1942 
1943 
GetConstantFunction(int descriptor_number)1944 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1945   return JSFunction::cast(GetValue(descriptor_number));
1946 }
1947 
1948 
GetCallbacksObject(int descriptor_number)1949 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1950   ASSERT(GetType(descriptor_number) == CALLBACKS);
1951   return GetValue(descriptor_number);
1952 }
1953 
1954 
GetCallbacks(int descriptor_number)1955 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1956   ASSERT(GetType(descriptor_number) == CALLBACKS);
1957   Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
1958   return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
1959 }
1960 
1961 
IsProperty(int descriptor_number)1962 bool DescriptorArray::IsProperty(int descriptor_number) {
1963   Entry entry(this, descriptor_number);
1964   return IsPropertyDescriptor(&entry);
1965 }
1966 
1967 
IsTransitionOnly(int descriptor_number)1968 bool DescriptorArray::IsTransitionOnly(int descriptor_number) {
1969   switch (GetType(descriptor_number)) {
1970     case MAP_TRANSITION:
1971     case CONSTANT_TRANSITION:
1972     case ELEMENTS_TRANSITION:
1973       return true;
1974     case CALLBACKS: {
1975       Object* value = GetValue(descriptor_number);
1976       if (!value->IsAccessorPair()) return false;
1977       AccessorPair* accessors = AccessorPair::cast(value);
1978       return accessors->getter()->IsMap() && accessors->setter()->IsMap();
1979     }
1980     case NORMAL:
1981     case FIELD:
1982     case CONSTANT_FUNCTION:
1983     case HANDLER:
1984     case INTERCEPTOR:
1985     case NULL_DESCRIPTOR:
1986       return false;
1987   }
1988   UNREACHABLE();  // Keep the compiler happy.
1989   return false;
1990 }
1991 
1992 
IsNullDescriptor(int descriptor_number)1993 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1994   return GetType(descriptor_number) == NULL_DESCRIPTOR;
1995 }
1996 
1997 
IsDontEnum(int descriptor_number)1998 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1999   return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
2000 }
2001 
2002 
Get(int descriptor_number,Descriptor * desc)2003 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2004   desc->Init(GetKey(descriptor_number),
2005              GetValue(descriptor_number),
2006              PropertyDetails(GetDetails(descriptor_number)));
2007 }
2008 
2009 
Set(int descriptor_number,Descriptor * desc,const WhitenessWitness &)2010 void DescriptorArray::Set(int descriptor_number,
2011                           Descriptor* desc,
2012                           const WhitenessWitness&) {
2013   // Range check.
2014   ASSERT(descriptor_number < number_of_descriptors());
2015 
2016   NoIncrementalWriteBarrierSet(this,
2017                                ToKeyIndex(descriptor_number),
2018                                desc->GetKey());
2019   FixedArray* content_array = GetContentArray();
2020   NoIncrementalWriteBarrierSet(content_array,
2021                                ToValueIndex(descriptor_number),
2022                                desc->GetValue());
2023   NoIncrementalWriteBarrierSet(content_array,
2024                                ToDetailsIndex(descriptor_number),
2025                                desc->GetDetails().AsSmi());
2026 }
2027 
2028 
NoIncrementalWriteBarrierSwapDescriptors(int first,int second)2029 void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
2030     int first, int second) {
2031   NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
2032   FixedArray* content_array = GetContentArray();
2033   NoIncrementalWriteBarrierSwap(content_array,
2034                                 ToValueIndex(first),
2035                                 ToValueIndex(second));
2036   NoIncrementalWriteBarrierSwap(content_array,
2037                                 ToDetailsIndex(first),
2038                                 ToDetailsIndex(second));
2039 }
2040 
2041 
WhitenessWitness(DescriptorArray * array)2042 DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
2043     : marking_(array->GetHeap()->incremental_marking()) {
2044   marking_->EnterNoMarkingScope();
2045   if (array->number_of_descriptors() > 0) {
2046     ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
2047     ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
2048   }
2049 }
2050 
2051 
~WhitenessWitness()2052 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
2053   marking_->LeaveNoMarkingScope();
2054 }
2055 
2056 
2057 template<typename Shape, typename Key>
ComputeCapacity(int at_least_space_for)2058 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2059   const int kMinCapacity = 32;
2060   int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2061   if (capacity < kMinCapacity) {
2062     capacity = kMinCapacity;  // Guarantee min capacity.
2063   }
2064   return capacity;
2065 }
2066 
2067 
2068 template<typename Shape, typename Key>
FindEntry(Key key)2069 int HashTable<Shape, Key>::FindEntry(Key key) {
2070   return FindEntry(GetIsolate(), key);
2071 }
2072 
2073 
2074 // Find entry for key otherwise return kNotFound.
2075 template<typename Shape, typename Key>
FindEntry(Isolate * isolate,Key key)2076 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2077   uint32_t capacity = Capacity();
2078   uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
2079   uint32_t count = 1;
2080   // EnsureCapacity will guarantee the hash table is never full.
2081   while (true) {
2082     Object* element = KeyAt(entry);
2083     // Empty entry.
2084     if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
2085     if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
2086         Shape::IsMatch(key, element)) return entry;
2087     entry = NextProbe(entry, count++, capacity);
2088   }
2089   return kNotFound;
2090 }
2091 
2092 
requires_slow_elements()2093 bool SeededNumberDictionary::requires_slow_elements() {
2094   Object* max_index_object = get(kMaxNumberKeyIndex);
2095   if (!max_index_object->IsSmi()) return false;
2096   return 0 !=
2097       (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2098 }
2099 
max_number_key()2100 uint32_t SeededNumberDictionary::max_number_key() {
2101   ASSERT(!requires_slow_elements());
2102   Object* max_index_object = get(kMaxNumberKeyIndex);
2103   if (!max_index_object->IsSmi()) return 0;
2104   uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2105   return value >> kRequiresSlowElementsTagSize;
2106 }
2107 
set_requires_slow_elements()2108 void SeededNumberDictionary::set_requires_slow_elements() {
2109   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2110 }
2111 
2112 
2113 // ------------------------------------
2114 // Cast operations
2115 
2116 
2117 CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedDoubleArray)2118 CAST_ACCESSOR(FixedDoubleArray)
2119 CAST_ACCESSOR(DescriptorArray)
2120 CAST_ACCESSOR(DeoptimizationInputData)
2121 CAST_ACCESSOR(DeoptimizationOutputData)
2122 CAST_ACCESSOR(TypeFeedbackCells)
2123 CAST_ACCESSOR(SymbolTable)
2124 CAST_ACCESSOR(JSFunctionResultCache)
2125 CAST_ACCESSOR(NormalizedMapCache)
2126 CAST_ACCESSOR(ScopeInfo)
2127 CAST_ACCESSOR(CompilationCacheTable)
2128 CAST_ACCESSOR(CodeCacheHashTable)
2129 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
2130 CAST_ACCESSOR(MapCache)
2131 CAST_ACCESSOR(String)
2132 CAST_ACCESSOR(SeqString)
2133 CAST_ACCESSOR(SeqAsciiString)
2134 CAST_ACCESSOR(SeqTwoByteString)
2135 CAST_ACCESSOR(SlicedString)
2136 CAST_ACCESSOR(ConsString)
2137 CAST_ACCESSOR(ExternalString)
2138 CAST_ACCESSOR(ExternalAsciiString)
2139 CAST_ACCESSOR(ExternalTwoByteString)
2140 CAST_ACCESSOR(JSReceiver)
2141 CAST_ACCESSOR(JSObject)
2142 CAST_ACCESSOR(Smi)
2143 CAST_ACCESSOR(HeapObject)
2144 CAST_ACCESSOR(HeapNumber)
2145 CAST_ACCESSOR(Oddball)
2146 CAST_ACCESSOR(JSGlobalPropertyCell)
2147 CAST_ACCESSOR(SharedFunctionInfo)
2148 CAST_ACCESSOR(Map)
2149 CAST_ACCESSOR(JSFunction)
2150 CAST_ACCESSOR(GlobalObject)
2151 CAST_ACCESSOR(JSGlobalProxy)
2152 CAST_ACCESSOR(JSGlobalObject)
2153 CAST_ACCESSOR(JSBuiltinsObject)
2154 CAST_ACCESSOR(Code)
2155 CAST_ACCESSOR(JSArray)
2156 CAST_ACCESSOR(JSRegExp)
2157 CAST_ACCESSOR(JSProxy)
2158 CAST_ACCESSOR(JSFunctionProxy)
2159 CAST_ACCESSOR(JSSet)
2160 CAST_ACCESSOR(JSMap)
2161 CAST_ACCESSOR(JSWeakMap)
2162 CAST_ACCESSOR(Foreign)
2163 CAST_ACCESSOR(ByteArray)
2164 CAST_ACCESSOR(FreeSpace)
2165 CAST_ACCESSOR(ExternalArray)
2166 CAST_ACCESSOR(ExternalByteArray)
2167 CAST_ACCESSOR(ExternalUnsignedByteArray)
2168 CAST_ACCESSOR(ExternalShortArray)
2169 CAST_ACCESSOR(ExternalUnsignedShortArray)
2170 CAST_ACCESSOR(ExternalIntArray)
2171 CAST_ACCESSOR(ExternalUnsignedIntArray)
2172 CAST_ACCESSOR(ExternalFloatArray)
2173 CAST_ACCESSOR(ExternalDoubleArray)
2174 CAST_ACCESSOR(ExternalPixelArray)
2175 CAST_ACCESSOR(Struct)
2176 
2177 
2178 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2179   STRUCT_LIST(MAKE_STRUCT_CAST)
2180 #undef MAKE_STRUCT_CAST
2181 
2182 
2183 template <typename Shape, typename Key>
2184 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2185   ASSERT(obj->IsHashTable());
2186   return reinterpret_cast<HashTable*>(obj);
2187 }
2188 
2189 
SMI_ACCESSORS(FixedArrayBase,length,kLengthOffset)2190 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
2191 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2192 
2193 SMI_ACCESSORS(String, length, kLengthOffset)
2194 
2195 
2196 uint32_t String::hash_field() {
2197   return READ_UINT32_FIELD(this, kHashFieldOffset);
2198 }
2199 
2200 
set_hash_field(uint32_t value)2201 void String::set_hash_field(uint32_t value) {
2202   WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
2203 #if V8_HOST_ARCH_64_BIT
2204   WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2205 #endif
2206 }
2207 
2208 
Equals(String * other)2209 bool String::Equals(String* other) {
2210   if (other == this) return true;
2211   if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2212     return false;
2213   }
2214   return SlowEquals(other);
2215 }
2216 
2217 
TryFlatten(PretenureFlag pretenure)2218 MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
2219   if (!StringShape(this).IsCons()) return this;
2220   ConsString* cons = ConsString::cast(this);
2221   if (cons->IsFlat()) return cons->first();
2222   return SlowTryFlatten(pretenure);
2223 }
2224 
2225 
TryFlattenGetString(PretenureFlag pretenure)2226 String* String::TryFlattenGetString(PretenureFlag pretenure) {
2227   MaybeObject* flat = TryFlatten(pretenure);
2228   Object* successfully_flattened;
2229   if (!flat->ToObject(&successfully_flattened)) return this;
2230   return String::cast(successfully_flattened);
2231 }
2232 
2233 
Get(int index)2234 uint16_t String::Get(int index) {
2235   ASSERT(index >= 0 && index < length());
2236   switch (StringShape(this).full_representation_tag()) {
2237     case kSeqStringTag | kAsciiStringTag:
2238       return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2239     case kSeqStringTag | kTwoByteStringTag:
2240       return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2241     case kConsStringTag | kAsciiStringTag:
2242     case kConsStringTag | kTwoByteStringTag:
2243       return ConsString::cast(this)->ConsStringGet(index);
2244     case kExternalStringTag | kAsciiStringTag:
2245       return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2246     case kExternalStringTag | kTwoByteStringTag:
2247       return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
2248     case kSlicedStringTag | kAsciiStringTag:
2249     case kSlicedStringTag | kTwoByteStringTag:
2250       return SlicedString::cast(this)->SlicedStringGet(index);
2251     default:
2252       break;
2253   }
2254 
2255   UNREACHABLE();
2256   return 0;
2257 }
2258 
2259 
Set(int index,uint16_t value)2260 void String::Set(int index, uint16_t value) {
2261   ASSERT(index >= 0 && index < length());
2262   ASSERT(StringShape(this).IsSequential());
2263 
2264   return this->IsAsciiRepresentation()
2265       ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2266       : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2267 }
2268 
2269 
IsFlat()2270 bool String::IsFlat() {
2271   if (!StringShape(this).IsCons()) return true;
2272   return ConsString::cast(this)->second()->length() == 0;
2273 }
2274 
2275 
GetUnderlying()2276 String* String::GetUnderlying() {
2277   // Giving direct access to underlying string only makes sense if the
2278   // wrapping string is already flattened.
2279   ASSERT(this->IsFlat());
2280   ASSERT(StringShape(this).IsIndirect());
2281   STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2282   const int kUnderlyingOffset = SlicedString::kParentOffset;
2283   return String::cast(READ_FIELD(this, kUnderlyingOffset));
2284 }
2285 
2286 
SeqAsciiStringGet(int index)2287 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2288   ASSERT(index >= 0 && index < length());
2289   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2290 }
2291 
2292 
SeqAsciiStringSet(int index,uint16_t value)2293 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2294   ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2295   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2296                    static_cast<byte>(value));
2297 }
2298 
2299 
GetCharsAddress()2300 Address SeqAsciiString::GetCharsAddress() {
2301   return FIELD_ADDR(this, kHeaderSize);
2302 }
2303 
2304 
GetChars()2305 char* SeqAsciiString::GetChars() {
2306   return reinterpret_cast<char*>(GetCharsAddress());
2307 }
2308 
2309 
GetCharsAddress()2310 Address SeqTwoByteString::GetCharsAddress() {
2311   return FIELD_ADDR(this, kHeaderSize);
2312 }
2313 
2314 
GetChars()2315 uc16* SeqTwoByteString::GetChars() {
2316   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2317 }
2318 
2319 
SeqTwoByteStringGet(int index)2320 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2321   ASSERT(index >= 0 && index < length());
2322   return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2323 }
2324 
2325 
SeqTwoByteStringSet(int index,uint16_t value)2326 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2327   ASSERT(index >= 0 && index < length());
2328   WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2329 }
2330 
2331 
SeqTwoByteStringSize(InstanceType instance_type)2332 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
2333   return SizeFor(length());
2334 }
2335 
2336 
SeqAsciiStringSize(InstanceType instance_type)2337 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
2338   return SizeFor(length());
2339 }
2340 
2341 
parent()2342 String* SlicedString::parent() {
2343   return String::cast(READ_FIELD(this, kParentOffset));
2344 }
2345 
2346 
set_parent(String * parent)2347 void SlicedString::set_parent(String* parent) {
2348   ASSERT(parent->IsSeqString() || parent->IsExternalString());
2349   WRITE_FIELD(this, kParentOffset, parent);
2350 }
2351 
2352 
SMI_ACCESSORS(SlicedString,offset,kOffsetOffset)2353 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2354 
2355 
2356 String* ConsString::first() {
2357   return String::cast(READ_FIELD(this, kFirstOffset));
2358 }
2359 
2360 
unchecked_first()2361 Object* ConsString::unchecked_first() {
2362   return READ_FIELD(this, kFirstOffset);
2363 }
2364 
2365 
set_first(String * value,WriteBarrierMode mode)2366 void ConsString::set_first(String* value, WriteBarrierMode mode) {
2367   WRITE_FIELD(this, kFirstOffset, value);
2368   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
2369 }
2370 
2371 
second()2372 String* ConsString::second() {
2373   return String::cast(READ_FIELD(this, kSecondOffset));
2374 }
2375 
2376 
unchecked_second()2377 Object* ConsString::unchecked_second() {
2378   return READ_FIELD(this, kSecondOffset);
2379 }
2380 
2381 
set_second(String * value,WriteBarrierMode mode)2382 void ConsString::set_second(String* value, WriteBarrierMode mode) {
2383   WRITE_FIELD(this, kSecondOffset, value);
2384   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
2385 }
2386 
2387 
is_short()2388 bool ExternalString::is_short() {
2389   InstanceType type = map()->instance_type();
2390   return (type & kShortExternalStringMask) == kShortExternalStringTag;
2391 }
2392 
2393 
resource()2394 const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2395   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2396 }
2397 
2398 
update_data_cache()2399 void ExternalAsciiString::update_data_cache() {
2400   if (is_short()) return;
2401   const char** data_field =
2402       reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
2403   *data_field = resource()->data();
2404 }
2405 
2406 
set_resource(const ExternalAsciiString::Resource * resource)2407 void ExternalAsciiString::set_resource(
2408     const ExternalAsciiString::Resource* resource) {
2409   *reinterpret_cast<const Resource**>(
2410       FIELD_ADDR(this, kResourceOffset)) = resource;
2411   if (resource != NULL) update_data_cache();
2412 }
2413 
2414 
GetChars()2415 const char* ExternalAsciiString::GetChars() {
2416   return resource()->data();
2417 }
2418 
2419 
ExternalAsciiStringGet(int index)2420 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
2421   ASSERT(index >= 0 && index < length());
2422   return GetChars()[index];
2423 }
2424 
2425 
resource()2426 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2427   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2428 }
2429 
2430 
update_data_cache()2431 void ExternalTwoByteString::update_data_cache() {
2432   if (is_short()) return;
2433   const uint16_t** data_field =
2434       reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
2435   *data_field = resource()->data();
2436 }
2437 
2438 
set_resource(const ExternalTwoByteString::Resource * resource)2439 void ExternalTwoByteString::set_resource(
2440     const ExternalTwoByteString::Resource* resource) {
2441   *reinterpret_cast<const Resource**>(
2442       FIELD_ADDR(this, kResourceOffset)) = resource;
2443   if (resource != NULL) update_data_cache();
2444 }
2445 
2446 
GetChars()2447 const uint16_t* ExternalTwoByteString::GetChars() {
2448   return resource()->data();
2449 }
2450 
2451 
ExternalTwoByteStringGet(int index)2452 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
2453   ASSERT(index >= 0 && index < length());
2454   return GetChars()[index];
2455 }
2456 
2457 
ExternalTwoByteStringGetData(unsigned start)2458 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
2459       unsigned start) {
2460   return GetChars() + start;
2461 }
2462 
2463 
MakeZeroSize()2464 void JSFunctionResultCache::MakeZeroSize() {
2465   set_finger_index(kEntriesIndex);
2466   set_size(kEntriesIndex);
2467 }
2468 
2469 
Clear()2470 void JSFunctionResultCache::Clear() {
2471   int cache_size = size();
2472   Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
2473   MemsetPointer(entries_start,
2474                 GetHeap()->the_hole_value(),
2475                 cache_size - kEntriesIndex);
2476   MakeZeroSize();
2477 }
2478 
2479 
size()2480 int JSFunctionResultCache::size() {
2481   return Smi::cast(get(kCacheSizeIndex))->value();
2482 }
2483 
2484 
set_size(int size)2485 void JSFunctionResultCache::set_size(int size) {
2486   set(kCacheSizeIndex, Smi::FromInt(size));
2487 }
2488 
2489 
finger_index()2490 int JSFunctionResultCache::finger_index() {
2491   return Smi::cast(get(kFingerIndex))->value();
2492 }
2493 
2494 
set_finger_index(int finger_index)2495 void JSFunctionResultCache::set_finger_index(int finger_index) {
2496   set(kFingerIndex, Smi::FromInt(finger_index));
2497 }
2498 
2499 
get(int index)2500 byte ByteArray::get(int index) {
2501   ASSERT(index >= 0 && index < this->length());
2502   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2503 }
2504 
2505 
set(int index,byte value)2506 void ByteArray::set(int index, byte value) {
2507   ASSERT(index >= 0 && index < this->length());
2508   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2509 }
2510 
2511 
get_int(int index)2512 int ByteArray::get_int(int index) {
2513   ASSERT(index >= 0 && (index * kIntSize) < this->length());
2514   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2515 }
2516 
2517 
FromDataStartAddress(Address address)2518 ByteArray* ByteArray::FromDataStartAddress(Address address) {
2519   ASSERT_TAG_ALIGNED(address);
2520   return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2521 }
2522 
2523 
GetDataStartAddress()2524 Address ByteArray::GetDataStartAddress() {
2525   return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2526 }
2527 
2528 
external_pixel_pointer()2529 uint8_t* ExternalPixelArray::external_pixel_pointer() {
2530   return reinterpret_cast<uint8_t*>(external_pointer());
2531 }
2532 
2533 
get_scalar(int index)2534 uint8_t ExternalPixelArray::get_scalar(int index) {
2535   ASSERT((index >= 0) && (index < this->length()));
2536   uint8_t* ptr = external_pixel_pointer();
2537   return ptr[index];
2538 }
2539 
2540 
get(int index)2541 MaybeObject* ExternalPixelArray::get(int index) {
2542   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2543 }
2544 
2545 
set(int index,uint8_t value)2546 void ExternalPixelArray::set(int index, uint8_t value) {
2547   ASSERT((index >= 0) && (index < this->length()));
2548   uint8_t* ptr = external_pixel_pointer();
2549   ptr[index] = value;
2550 }
2551 
2552 
external_pointer()2553 void* ExternalArray::external_pointer() {
2554   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2555   return reinterpret_cast<void*>(ptr);
2556 }
2557 
2558 
set_external_pointer(void * value,WriteBarrierMode mode)2559 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2560   intptr_t ptr = reinterpret_cast<intptr_t>(value);
2561   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2562 }
2563 
2564 
get_scalar(int index)2565 int8_t ExternalByteArray::get_scalar(int index) {
2566   ASSERT((index >= 0) && (index < this->length()));
2567   int8_t* ptr = static_cast<int8_t*>(external_pointer());
2568   return ptr[index];
2569 }
2570 
2571 
get(int index)2572 MaybeObject* ExternalByteArray::get(int index) {
2573   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2574 }
2575 
2576 
set(int index,int8_t value)2577 void ExternalByteArray::set(int index, int8_t value) {
2578   ASSERT((index >= 0) && (index < this->length()));
2579   int8_t* ptr = static_cast<int8_t*>(external_pointer());
2580   ptr[index] = value;
2581 }
2582 
2583 
get_scalar(int index)2584 uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
2585   ASSERT((index >= 0) && (index < this->length()));
2586   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2587   return ptr[index];
2588 }
2589 
2590 
get(int index)2591 MaybeObject* ExternalUnsignedByteArray::get(int index) {
2592   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2593 }
2594 
2595 
set(int index,uint8_t value)2596 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2597   ASSERT((index >= 0) && (index < this->length()));
2598   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2599   ptr[index] = value;
2600 }
2601 
2602 
get_scalar(int index)2603 int16_t ExternalShortArray::get_scalar(int index) {
2604   ASSERT((index >= 0) && (index < this->length()));
2605   int16_t* ptr = static_cast<int16_t*>(external_pointer());
2606   return ptr[index];
2607 }
2608 
2609 
get(int index)2610 MaybeObject* ExternalShortArray::get(int index) {
2611   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2612 }
2613 
2614 
set(int index,int16_t value)2615 void ExternalShortArray::set(int index, int16_t value) {
2616   ASSERT((index >= 0) && (index < this->length()));
2617   int16_t* ptr = static_cast<int16_t*>(external_pointer());
2618   ptr[index] = value;
2619 }
2620 
2621 
get_scalar(int index)2622 uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
2623   ASSERT((index >= 0) && (index < this->length()));
2624   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2625   return ptr[index];
2626 }
2627 
2628 
get(int index)2629 MaybeObject* ExternalUnsignedShortArray::get(int index) {
2630   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2631 }
2632 
2633 
set(int index,uint16_t value)2634 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2635   ASSERT((index >= 0) && (index < this->length()));
2636   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2637   ptr[index] = value;
2638 }
2639 
2640 
get_scalar(int index)2641 int32_t ExternalIntArray::get_scalar(int index) {
2642   ASSERT((index >= 0) && (index < this->length()));
2643   int32_t* ptr = static_cast<int32_t*>(external_pointer());
2644   return ptr[index];
2645 }
2646 
2647 
get(int index)2648 MaybeObject* ExternalIntArray::get(int index) {
2649     return GetHeap()->NumberFromInt32(get_scalar(index));
2650 }
2651 
2652 
set(int index,int32_t value)2653 void ExternalIntArray::set(int index, int32_t value) {
2654   ASSERT((index >= 0) && (index < this->length()));
2655   int32_t* ptr = static_cast<int32_t*>(external_pointer());
2656   ptr[index] = value;
2657 }
2658 
2659 
get_scalar(int index)2660 uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
2661   ASSERT((index >= 0) && (index < this->length()));
2662   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2663   return ptr[index];
2664 }
2665 
2666 
get(int index)2667 MaybeObject* ExternalUnsignedIntArray::get(int index) {
2668     return GetHeap()->NumberFromUint32(get_scalar(index));
2669 }
2670 
2671 
set(int index,uint32_t value)2672 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2673   ASSERT((index >= 0) && (index < this->length()));
2674   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2675   ptr[index] = value;
2676 }
2677 
2678 
get_scalar(int index)2679 float ExternalFloatArray::get_scalar(int index) {
2680   ASSERT((index >= 0) && (index < this->length()));
2681   float* ptr = static_cast<float*>(external_pointer());
2682   return ptr[index];
2683 }
2684 
2685 
get(int index)2686 MaybeObject* ExternalFloatArray::get(int index) {
2687     return GetHeap()->NumberFromDouble(get_scalar(index));
2688 }
2689 
2690 
set(int index,float value)2691 void ExternalFloatArray::set(int index, float value) {
2692   ASSERT((index >= 0) && (index < this->length()));
2693   float* ptr = static_cast<float*>(external_pointer());
2694   ptr[index] = value;
2695 }
2696 
2697 
get_scalar(int index)2698 double ExternalDoubleArray::get_scalar(int index) {
2699   ASSERT((index >= 0) && (index < this->length()));
2700   double* ptr = static_cast<double*>(external_pointer());
2701   return ptr[index];
2702 }
2703 
2704 
get(int index)2705 MaybeObject* ExternalDoubleArray::get(int index) {
2706     return GetHeap()->NumberFromDouble(get_scalar(index));
2707 }
2708 
2709 
set(int index,double value)2710 void ExternalDoubleArray::set(int index, double value) {
2711   ASSERT((index >= 0) && (index < this->length()));
2712   double* ptr = static_cast<double*>(external_pointer());
2713   ptr[index] = value;
2714 }
2715 
2716 
visitor_id()2717 int Map::visitor_id() {
2718   return READ_BYTE_FIELD(this, kVisitorIdOffset);
2719 }
2720 
2721 
set_visitor_id(int id)2722 void Map::set_visitor_id(int id) {
2723   ASSERT(0 <= id && id < 256);
2724   WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2725 }
2726 
2727 
instance_size()2728 int Map::instance_size() {
2729   return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2730 }
2731 
2732 
inobject_properties()2733 int Map::inobject_properties() {
2734   return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2735 }
2736 
2737 
pre_allocated_property_fields()2738 int Map::pre_allocated_property_fields() {
2739   return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2740 }
2741 
2742 
SizeFromMap(Map * map)2743 int HeapObject::SizeFromMap(Map* map) {
2744   int instance_size = map->instance_size();
2745   if (instance_size != kVariableSizeSentinel) return instance_size;
2746   // We can ignore the "symbol" bit becase it is only set for symbols
2747   // and implies a string type.
2748   int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
2749   // Only inline the most frequent cases.
2750   if (instance_type == FIXED_ARRAY_TYPE) {
2751     return FixedArray::BodyDescriptor::SizeOf(map, this);
2752   }
2753   if (instance_type == ASCII_STRING_TYPE) {
2754     return SeqAsciiString::SizeFor(
2755         reinterpret_cast<SeqAsciiString*>(this)->length());
2756   }
2757   if (instance_type == BYTE_ARRAY_TYPE) {
2758     return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2759   }
2760   if (instance_type == FREE_SPACE_TYPE) {
2761     return reinterpret_cast<FreeSpace*>(this)->size();
2762   }
2763   if (instance_type == STRING_TYPE) {
2764     return SeqTwoByteString::SizeFor(
2765         reinterpret_cast<SeqTwoByteString*>(this)->length());
2766   }
2767   if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2768     return FixedDoubleArray::SizeFor(
2769         reinterpret_cast<FixedDoubleArray*>(this)->length());
2770   }
2771   ASSERT(instance_type == CODE_TYPE);
2772   return reinterpret_cast<Code*>(this)->CodeSize();
2773 }
2774 
2775 
set_instance_size(int value)2776 void Map::set_instance_size(int value) {
2777   ASSERT_EQ(0, value & (kPointerSize - 1));
2778   value >>= kPointerSizeLog2;
2779   ASSERT(0 <= value && value < 256);
2780   WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2781 }
2782 
2783 
set_inobject_properties(int value)2784 void Map::set_inobject_properties(int value) {
2785   ASSERT(0 <= value && value < 256);
2786   WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2787 }
2788 
2789 
set_pre_allocated_property_fields(int value)2790 void Map::set_pre_allocated_property_fields(int value) {
2791   ASSERT(0 <= value && value < 256);
2792   WRITE_BYTE_FIELD(this,
2793                    kPreAllocatedPropertyFieldsOffset,
2794                    static_cast<byte>(value));
2795 }
2796 
2797 
instance_type()2798 InstanceType Map::instance_type() {
2799   return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2800 }
2801 
2802 
set_instance_type(InstanceType value)2803 void Map::set_instance_type(InstanceType value) {
2804   WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2805 }
2806 
2807 
unused_property_fields()2808 int Map::unused_property_fields() {
2809   return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2810 }
2811 
2812 
set_unused_property_fields(int value)2813 void Map::set_unused_property_fields(int value) {
2814   WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2815 }
2816 
2817 
bit_field()2818 byte Map::bit_field() {
2819   return READ_BYTE_FIELD(this, kBitFieldOffset);
2820 }
2821 
2822 
set_bit_field(byte value)2823 void Map::set_bit_field(byte value) {
2824   WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2825 }
2826 
2827 
bit_field2()2828 byte Map::bit_field2() {
2829   return READ_BYTE_FIELD(this, kBitField2Offset);
2830 }
2831 
2832 
set_bit_field2(byte value)2833 void Map::set_bit_field2(byte value) {
2834   WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2835 }
2836 
2837 
set_non_instance_prototype(bool value)2838 void Map::set_non_instance_prototype(bool value) {
2839   if (value) {
2840     set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2841   } else {
2842     set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2843   }
2844 }
2845 
2846 
has_non_instance_prototype()2847 bool Map::has_non_instance_prototype() {
2848   return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2849 }
2850 
2851 
set_function_with_prototype(bool value)2852 void Map::set_function_with_prototype(bool value) {
2853   if (value) {
2854     set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2855   } else {
2856     set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2857   }
2858 }
2859 
2860 
function_with_prototype()2861 bool Map::function_with_prototype() {
2862   return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2863 }
2864 
2865 
set_is_access_check_needed(bool access_check_needed)2866 void Map::set_is_access_check_needed(bool access_check_needed) {
2867   if (access_check_needed) {
2868     set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2869   } else {
2870     set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2871   }
2872 }
2873 
2874 
is_access_check_needed()2875 bool Map::is_access_check_needed() {
2876   return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2877 }
2878 
2879 
set_is_extensible(bool value)2880 void Map::set_is_extensible(bool value) {
2881   if (value) {
2882     set_bit_field2(bit_field2() | (1 << kIsExtensible));
2883   } else {
2884     set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2885   }
2886 }
2887 
is_extensible()2888 bool Map::is_extensible() {
2889   return ((1 << kIsExtensible) & bit_field2()) != 0;
2890 }
2891 
2892 
set_attached_to_shared_function_info(bool value)2893 void Map::set_attached_to_shared_function_info(bool value) {
2894   if (value) {
2895     set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2896   } else {
2897     set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2898   }
2899 }
2900 
attached_to_shared_function_info()2901 bool Map::attached_to_shared_function_info() {
2902   return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2903 }
2904 
2905 
set_is_shared(bool value)2906 void Map::set_is_shared(bool value) {
2907   if (value) {
2908     set_bit_field3(bit_field3() | (1 << kIsShared));
2909   } else {
2910     set_bit_field3(bit_field3() & ~(1 << kIsShared));
2911   }
2912 }
2913 
is_shared()2914 bool Map::is_shared() {
2915   return ((1 << kIsShared) & bit_field3()) != 0;
2916 }
2917 
2918 
unchecked_constructor()2919 JSFunction* Map::unchecked_constructor() {
2920   return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2921 }
2922 
2923 
flags()2924 Code::Flags Code::flags() {
2925   return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2926 }
2927 
2928 
set_flags(Code::Flags flags)2929 void Code::set_flags(Code::Flags flags) {
2930   STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
2931   // Make sure that all call stubs have an arguments count.
2932   ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2933           ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
2934          ExtractArgumentsCountFromFlags(flags) >= 0);
2935   WRITE_INT_FIELD(this, kFlagsOffset, flags);
2936 }
2937 
2938 
kind()2939 Code::Kind Code::kind() {
2940   return ExtractKindFromFlags(flags());
2941 }
2942 
2943 
ic_state()2944 InlineCacheState Code::ic_state() {
2945   InlineCacheState result = ExtractICStateFromFlags(flags());
2946   // Only allow uninitialized or debugger states for non-IC code
2947   // objects. This is used in the debugger to determine whether or not
2948   // a call to code object has been replaced with a debug break call.
2949   ASSERT(is_inline_cache_stub() ||
2950          result == UNINITIALIZED ||
2951          result == DEBUG_BREAK ||
2952          result == DEBUG_PREPARE_STEP_IN);
2953   return result;
2954 }
2955 
2956 
extra_ic_state()2957 Code::ExtraICState Code::extra_ic_state() {
2958   ASSERT(is_inline_cache_stub());
2959   return ExtractExtraICStateFromFlags(flags());
2960 }
2961 
2962 
type()2963 PropertyType Code::type() {
2964   return ExtractTypeFromFlags(flags());
2965 }
2966 
2967 
arguments_count()2968 int Code::arguments_count() {
2969   ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
2970   return ExtractArgumentsCountFromFlags(flags());
2971 }
2972 
2973 
major_key()2974 int Code::major_key() {
2975   ASSERT(kind() == STUB ||
2976          kind() == UNARY_OP_IC ||
2977          kind() == BINARY_OP_IC ||
2978          kind() == COMPARE_IC ||
2979          kind() == TO_BOOLEAN_IC);
2980   return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
2981 }
2982 
2983 
set_major_key(int major)2984 void Code::set_major_key(int major) {
2985   ASSERT(kind() == STUB ||
2986          kind() == UNARY_OP_IC ||
2987          kind() == BINARY_OP_IC ||
2988          kind() == COMPARE_IC ||
2989          kind() == TO_BOOLEAN_IC);
2990   ASSERT(0 <= major && major < 256);
2991   WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2992 }
2993 
2994 
is_pregenerated()2995 bool Code::is_pregenerated() {
2996   return kind() == STUB && IsPregeneratedField::decode(flags());
2997 }
2998 
2999 
set_is_pregenerated(bool value)3000 void Code::set_is_pregenerated(bool value) {
3001   ASSERT(kind() == STUB);
3002   Flags f = flags();
3003   f = static_cast<Flags>(IsPregeneratedField::update(f, value));
3004   set_flags(f);
3005 }
3006 
3007 
optimizable()3008 bool Code::optimizable() {
3009   ASSERT(kind() == FUNCTION);
3010   return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
3011 }
3012 
3013 
set_optimizable(bool value)3014 void Code::set_optimizable(bool value) {
3015   ASSERT(kind() == FUNCTION);
3016   WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
3017 }
3018 
3019 
has_deoptimization_support()3020 bool Code::has_deoptimization_support() {
3021   ASSERT(kind() == FUNCTION);
3022   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3023   return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
3024 }
3025 
3026 
set_has_deoptimization_support(bool value)3027 void Code::set_has_deoptimization_support(bool value) {
3028   ASSERT(kind() == FUNCTION);
3029   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3030   flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
3031   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3032 }
3033 
3034 
has_debug_break_slots()3035 bool Code::has_debug_break_slots() {
3036   ASSERT(kind() == FUNCTION);
3037   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3038   return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
3039 }
3040 
3041 
set_has_debug_break_slots(bool value)3042 void Code::set_has_debug_break_slots(bool value) {
3043   ASSERT(kind() == FUNCTION);
3044   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3045   flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
3046   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3047 }
3048 
3049 
is_compiled_optimizable()3050 bool Code::is_compiled_optimizable() {
3051   ASSERT(kind() == FUNCTION);
3052   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3053   return FullCodeFlagsIsCompiledOptimizable::decode(flags);
3054 }
3055 
3056 
set_compiled_optimizable(bool value)3057 void Code::set_compiled_optimizable(bool value) {
3058   ASSERT(kind() == FUNCTION);
3059   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3060   flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
3061   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3062 }
3063 
3064 
has_self_optimization_header()3065 bool Code::has_self_optimization_header() {
3066   ASSERT(kind() == FUNCTION);
3067   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3068   return FullCodeFlagsHasSelfOptimizationHeader::decode(flags);
3069 }
3070 
3071 
set_self_optimization_header(bool value)3072 void Code::set_self_optimization_header(bool value) {
3073   ASSERT(kind() == FUNCTION);
3074   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3075   flags = FullCodeFlagsHasSelfOptimizationHeader::update(flags, value);
3076   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3077 }
3078 
3079 
allow_osr_at_loop_nesting_level()3080 int Code::allow_osr_at_loop_nesting_level() {
3081   ASSERT(kind() == FUNCTION);
3082   return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
3083 }
3084 
3085 
set_allow_osr_at_loop_nesting_level(int level)3086 void Code::set_allow_osr_at_loop_nesting_level(int level) {
3087   ASSERT(kind() == FUNCTION);
3088   ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
3089   WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
3090 }
3091 
3092 
profiler_ticks()3093 int Code::profiler_ticks() {
3094   ASSERT(kind() == FUNCTION);
3095   return READ_BYTE_FIELD(this, kProfilerTicksOffset);
3096 }
3097 
3098 
set_profiler_ticks(int ticks)3099 void Code::set_profiler_ticks(int ticks) {
3100   ASSERT(kind() == FUNCTION);
3101   ASSERT(ticks < 256);
3102   WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
3103 }
3104 
3105 
stack_slots()3106 unsigned Code::stack_slots() {
3107   ASSERT(kind() == OPTIMIZED_FUNCTION);
3108   return READ_UINT32_FIELD(this, kStackSlotsOffset);
3109 }
3110 
3111 
set_stack_slots(unsigned slots)3112 void Code::set_stack_slots(unsigned slots) {
3113   ASSERT(kind() == OPTIMIZED_FUNCTION);
3114   WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
3115 }
3116 
3117 
safepoint_table_offset()3118 unsigned Code::safepoint_table_offset() {
3119   ASSERT(kind() == OPTIMIZED_FUNCTION);
3120   return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
3121 }
3122 
3123 
set_safepoint_table_offset(unsigned offset)3124 void Code::set_safepoint_table_offset(unsigned offset) {
3125   ASSERT(kind() == OPTIMIZED_FUNCTION);
3126   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
3127   WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
3128 }
3129 
3130 
stack_check_table_offset()3131 unsigned Code::stack_check_table_offset() {
3132   ASSERT(kind() == FUNCTION);
3133   return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
3134 }
3135 
3136 
set_stack_check_table_offset(unsigned offset)3137 void Code::set_stack_check_table_offset(unsigned offset) {
3138   ASSERT(kind() == FUNCTION);
3139   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
3140   WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
3141 }
3142 
3143 
check_type()3144 CheckType Code::check_type() {
3145   ASSERT(is_call_stub() || is_keyed_call_stub());
3146   byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
3147   return static_cast<CheckType>(type);
3148 }
3149 
3150 
set_check_type(CheckType value)3151 void Code::set_check_type(CheckType value) {
3152   ASSERT(is_call_stub() || is_keyed_call_stub());
3153   WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
3154 }
3155 
3156 
unary_op_type()3157 byte Code::unary_op_type() {
3158   ASSERT(is_unary_op_stub());
3159   return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
3160 }
3161 
3162 
set_unary_op_type(byte value)3163 void Code::set_unary_op_type(byte value) {
3164   ASSERT(is_unary_op_stub());
3165   WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
3166 }
3167 
3168 
binary_op_type()3169 byte Code::binary_op_type() {
3170   ASSERT(is_binary_op_stub());
3171   return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3172 }
3173 
3174 
set_binary_op_type(byte value)3175 void Code::set_binary_op_type(byte value) {
3176   ASSERT(is_binary_op_stub());
3177   WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3178 }
3179 
3180 
binary_op_result_type()3181 byte Code::binary_op_result_type() {
3182   ASSERT(is_binary_op_stub());
3183   return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3184 }
3185 
3186 
set_binary_op_result_type(byte value)3187 void Code::set_binary_op_result_type(byte value) {
3188   ASSERT(is_binary_op_stub());
3189   WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3190 }
3191 
3192 
compare_state()3193 byte Code::compare_state() {
3194   ASSERT(is_compare_ic_stub());
3195   return READ_BYTE_FIELD(this, kCompareStateOffset);
3196 }
3197 
3198 
set_compare_state(byte value)3199 void Code::set_compare_state(byte value) {
3200   ASSERT(is_compare_ic_stub());
3201   WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3202 }
3203 
3204 
to_boolean_state()3205 byte Code::to_boolean_state() {
3206   ASSERT(is_to_boolean_ic_stub());
3207   return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3208 }
3209 
3210 
set_to_boolean_state(byte value)3211 void Code::set_to_boolean_state(byte value) {
3212   ASSERT(is_to_boolean_ic_stub());
3213   WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3214 }
3215 
3216 
has_function_cache()3217 bool Code::has_function_cache() {
3218   ASSERT(kind() == STUB);
3219   return READ_BYTE_FIELD(this, kHasFunctionCacheOffset) != 0;
3220 }
3221 
3222 
set_has_function_cache(bool flag)3223 void Code::set_has_function_cache(bool flag) {
3224   ASSERT(kind() == STUB);
3225   WRITE_BYTE_FIELD(this, kHasFunctionCacheOffset, flag);
3226 }
3227 
3228 
is_inline_cache_stub()3229 bool Code::is_inline_cache_stub() {
3230   Kind kind = this->kind();
3231   return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3232 }
3233 
3234 
ComputeFlags(Kind kind,InlineCacheState ic_state,ExtraICState extra_ic_state,PropertyType type,int argc,InlineCacheHolderFlag holder)3235 Code::Flags Code::ComputeFlags(Kind kind,
3236                                InlineCacheState ic_state,
3237                                ExtraICState extra_ic_state,
3238                                PropertyType type,
3239                                int argc,
3240                                InlineCacheHolderFlag holder) {
3241   // Extra IC state is only allowed for call IC stubs or for store IC
3242   // stubs.
3243   ASSERT(extra_ic_state == kNoExtraICState ||
3244          kind == CALL_IC ||
3245          kind == STORE_IC ||
3246          kind == KEYED_STORE_IC);
3247   // Compute the bit mask.
3248   int bits = KindField::encode(kind)
3249       | ICStateField::encode(ic_state)
3250       | TypeField::encode(type)
3251       | ExtraICStateField::encode(extra_ic_state)
3252       | (argc << kArgumentsCountShift)
3253       | CacheHolderField::encode(holder);
3254   return static_cast<Flags>(bits);
3255 }
3256 
3257 
ComputeMonomorphicFlags(Kind kind,PropertyType type,ExtraICState extra_ic_state,InlineCacheHolderFlag holder,int argc)3258 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3259                                           PropertyType type,
3260                                           ExtraICState extra_ic_state,
3261                                           InlineCacheHolderFlag holder,
3262                                           int argc) {
3263   return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
3264 }
3265 
3266 
ExtractKindFromFlags(Flags flags)3267 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
3268   return KindField::decode(flags);
3269 }
3270 
3271 
ExtractICStateFromFlags(Flags flags)3272 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
3273   return ICStateField::decode(flags);
3274 }
3275 
3276 
ExtractExtraICStateFromFlags(Flags flags)3277 Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
3278   return ExtraICStateField::decode(flags);
3279 }
3280 
3281 
ExtractTypeFromFlags(Flags flags)3282 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
3283   return TypeField::decode(flags);
3284 }
3285 
3286 
ExtractArgumentsCountFromFlags(Flags flags)3287 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
3288   return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
3289 }
3290 
3291 
ExtractCacheHolderFromFlags(Flags flags)3292 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
3293   return CacheHolderField::decode(flags);
3294 }
3295 
3296 
RemoveTypeFromFlags(Flags flags)3297 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
3298   int bits = flags & ~TypeField::kMask;
3299   return static_cast<Flags>(bits);
3300 }
3301 
3302 
GetCodeFromTargetAddress(Address address)3303 Code* Code::GetCodeFromTargetAddress(Address address) {
3304   HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3305   // GetCodeFromTargetAddress might be called when marking objects during mark
3306   // sweep. reinterpret_cast is therefore used instead of the more appropriate
3307   // Code::cast. Code::cast does not work when the object's map is
3308   // marked.
3309   Code* result = reinterpret_cast<Code*>(code);
3310   return result;
3311 }
3312 
3313 
GetObjectFromEntryAddress(Address location_of_address)3314 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3315   return HeapObject::
3316       FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3317 }
3318 
3319 
prototype()3320 Object* Map::prototype() {
3321   return READ_FIELD(this, kPrototypeOffset);
3322 }
3323 
3324 
set_prototype(Object * value,WriteBarrierMode mode)3325 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
3326   ASSERT(value->IsNull() || value->IsJSReceiver());
3327   WRITE_FIELD(this, kPrototypeOffset, value);
3328   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
3329 }
3330 
3331 
instance_descriptors()3332 DescriptorArray* Map::instance_descriptors() {
3333   Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3334   if (object->IsSmi()) {
3335     return GetHeap()->empty_descriptor_array();
3336   } else {
3337     return DescriptorArray::cast(object);
3338   }
3339 }
3340 
3341 
init_instance_descriptors()3342 void Map::init_instance_descriptors() {
3343   WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3344 }
3345 
3346 
clear_instance_descriptors()3347 void Map::clear_instance_descriptors() {
3348   Object* object = READ_FIELD(this,
3349                               kInstanceDescriptorsOrBitField3Offset);
3350   if (!object->IsSmi()) {
3351     WRITE_FIELD(
3352         this,
3353         kInstanceDescriptorsOrBitField3Offset,
3354         Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3355   }
3356 }
3357 
3358 
set_instance_descriptors(DescriptorArray * value,WriteBarrierMode mode)3359 void Map::set_instance_descriptors(DescriptorArray* value,
3360                                    WriteBarrierMode mode) {
3361   Object* object = READ_FIELD(this,
3362                               kInstanceDescriptorsOrBitField3Offset);
3363   Heap* heap = GetHeap();
3364   if (value == heap->empty_descriptor_array()) {
3365     clear_instance_descriptors();
3366     return;
3367   } else {
3368     if (object->IsSmi()) {
3369       value->set_bit_field3_storage(Smi::cast(object)->value());
3370     } else {
3371       value->set_bit_field3_storage(
3372           DescriptorArray::cast(object)->bit_field3_storage());
3373     }
3374   }
3375   ASSERT(!is_shared());
3376   WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
3377   CONDITIONAL_WRITE_BARRIER(
3378       heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
3379 }
3380 
3381 
bit_field3()3382 int Map::bit_field3() {
3383   Object* object = READ_FIELD(this,
3384                               kInstanceDescriptorsOrBitField3Offset);
3385   if (object->IsSmi()) {
3386     return Smi::cast(object)->value();
3387   } else {
3388     return DescriptorArray::cast(object)->bit_field3_storage();
3389   }
3390 }
3391 
3392 
set_bit_field3(int value)3393 void Map::set_bit_field3(int value) {
3394   ASSERT(Smi::IsValid(value));
3395   Object* object = READ_FIELD(this,
3396                               kInstanceDescriptorsOrBitField3Offset);
3397   if (object->IsSmi()) {
3398     WRITE_FIELD(this,
3399                 kInstanceDescriptorsOrBitField3Offset,
3400                 Smi::FromInt(value));
3401   } else {
3402     DescriptorArray::cast(object)->set_bit_field3_storage(value);
3403   }
3404 }
3405 
3406 
unchecked_prototype_transitions()3407 FixedArray* Map::unchecked_prototype_transitions() {
3408   return reinterpret_cast<FixedArray*>(
3409       READ_FIELD(this, kPrototypeTransitionsOffset));
3410 }
3411 
3412 
ACCESSORS(Map,code_cache,Object,kCodeCacheOffset)3413 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
3414 ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
3415 ACCESSORS(Map, constructor, Object, kConstructorOffset)
3416 
3417 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
3418 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
3419 ACCESSORS(JSFunction,
3420           next_function_link,
3421           Object,
3422           kNextFunctionLinkOffset)
3423 
3424 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3425 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3426 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3427 
3428 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3429 
3430 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3431 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3432 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3433 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
3434 ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
3435 
3436 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
3437 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
3438 
3439 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3440 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3441 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3442 
3443 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3444 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3445 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3446 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3447 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3448 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3449 
3450 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3451 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3452 
3453 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3454 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3455 
3456 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3457 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3458 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3459           kPropertyAccessorsOffset)
3460 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3461           kPrototypeTemplateOffset)
3462 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3463 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3464           kNamedPropertyHandlerOffset)
3465 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3466           kIndexedPropertyHandlerOffset)
3467 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3468           kInstanceTemplateOffset)
3469 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3470 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3471 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3472           kInstanceCallHandlerOffset)
3473 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3474           kAccessCheckInfoOffset)
3475 ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
3476 
3477 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3478 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3479           kInternalFieldCountOffset)
3480 
3481 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3482 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3483 
3484 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3485 
3486 ACCESSORS(Script, source, Object, kSourceOffset)
3487 ACCESSORS(Script, name, Object, kNameOffset)
3488 ACCESSORS(Script, id, Object, kIdOffset)
3489 ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
3490 ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
3491 ACCESSORS(Script, data, Object, kDataOffset)
3492 ACCESSORS(Script, context_data, Object, kContextOffset)
3493 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
3494 ACCESSORS_TO_SMI(Script, type, kTypeOffset)
3495 ACCESSORS_TO_SMI(Script, compilation_type, kCompilationTypeOffset)
3496 ACCESSORS_TO_SMI(Script, compilation_state, kCompilationStateOffset)
3497 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
3498 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
3499 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
3500                  kEvalFrominstructionsOffsetOffset)
3501 
3502 #ifdef ENABLE_DEBUGGER_SUPPORT
3503 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3504 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3505 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3506 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3507 
3508 ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
3509 ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
3510 ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
3511 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3512 #endif
3513 
3514 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
3515 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3516 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
3517 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3518           kInstanceClassNameOffset)
3519 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
3520 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3521 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3522 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3523 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3524           kThisPropertyAssignmentsOffset)
3525 SMI_ACCESSORS(SharedFunctionInfo, ic_age, kICAgeOffset)
3526 
3527 
3528 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3529                kHiddenPrototypeBit)
3530 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3531 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3532                kNeedsAccessCheckBit)
3533 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3534                kReadOnlyPrototypeBit)
3535 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3536                kIsExpressionBit)
3537 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3538                kIsTopLevelBit)
3539 BOOL_GETTER(SharedFunctionInfo,
3540             compiler_hints,
3541             has_only_simple_this_property_assignments,
3542             kHasOnlySimpleThisPropertyAssignments)
3543 BOOL_ACCESSORS(SharedFunctionInfo,
3544                compiler_hints,
3545                allows_lazy_compilation,
3546                kAllowLazyCompilation)
3547 BOOL_ACCESSORS(SharedFunctionInfo,
3548                compiler_hints,
3549                uses_arguments,
3550                kUsesArguments)
3551 BOOL_ACCESSORS(SharedFunctionInfo,
3552                compiler_hints,
3553                has_duplicate_parameters,
3554                kHasDuplicateParameters)
3555 
3556 
3557 #if V8_HOST_ARCH_32_BIT
3558 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3559 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
3560               kFormalParameterCountOffset)
3561 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
3562               kExpectedNofPropertiesOffset)
3563 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3564 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
3565               kStartPositionAndTypeOffset)
3566 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3567 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
3568               kFunctionTokenPositionOffset)
3569 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
3570               kCompilerHintsOffset)
3571 SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
3572               kThisPropertyAssignmentsCountOffset)
3573 SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
3574 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3575 SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
3576 #else
3577 
3578 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
3579   STATIC_ASSERT(holder::offset % kPointerSize == 0);              \
3580   int holder::name() {                                            \
3581     int value = READ_INT_FIELD(this, offset);                     \
3582     ASSERT(kHeapObjectTag == 1);                                  \
3583     ASSERT((value & kHeapObjectTag) == 0);                        \
3584     return value >> 1;                                            \
3585   }                                                               \
3586   void holder::set_##name(int value) {                            \
3587     ASSERT(kHeapObjectTag == 1);                                  \
3588     ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
3589            (value & 0xC0000000) == 0x000000000);                  \
3590     WRITE_INT_FIELD(this,                                         \
3591                     offset,                                       \
3592                     (value << 1) & ~kHeapObjectTag);              \
3593   }
3594 
3595 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset)             \
3596   STATIC_ASSERT(holder::offset % kPointerSize == kIntSize);       \
3597   INT_ACCESSORS(holder, name, offset)
3598 
3599 
3600 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
3601 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3602                         formal_parameter_count,
3603                         kFormalParameterCountOffset)
3604 
3605 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3606                         expected_nof_properties,
3607                         kExpectedNofPropertiesOffset)
3608 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3609 
3610 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3611 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3612                         start_position_and_type,
3613                         kStartPositionAndTypeOffset)
3614 
3615 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3616                         function_token_position,
3617                         kFunctionTokenPositionOffset)
3618 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3619                         compiler_hints,
3620                         kCompilerHintsOffset)
3621 
3622 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3623                         this_property_assignments_count,
3624                         kThisPropertyAssignmentsCountOffset)
3625 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
3626 
3627 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3628 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
3629 #endif
3630 
3631 
3632 int SharedFunctionInfo::construction_count() {
3633   return READ_BYTE_FIELD(this, kConstructionCountOffset);
3634 }
3635 
3636 
set_construction_count(int value)3637 void SharedFunctionInfo::set_construction_count(int value) {
3638   ASSERT(0 <= value && value < 256);
3639   WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3640 }
3641 
3642 
BOOL_ACCESSORS(SharedFunctionInfo,compiler_hints,live_objects_may_exist,kLiveObjectsMayExist)3643 BOOL_ACCESSORS(SharedFunctionInfo,
3644                compiler_hints,
3645                live_objects_may_exist,
3646                kLiveObjectsMayExist)
3647 
3648 
3649 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
3650   return initial_map() != GetHeap()->undefined_value();
3651 }
3652 
3653 
BOOL_GETTER(SharedFunctionInfo,compiler_hints,optimization_disabled,kOptimizationDisabled)3654 BOOL_GETTER(SharedFunctionInfo,
3655             compiler_hints,
3656             optimization_disabled,
3657             kOptimizationDisabled)
3658 
3659 
3660 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3661   set_compiler_hints(BooleanBit::set(compiler_hints(),
3662                                      kOptimizationDisabled,
3663                                      disable));
3664   // If disabling optimizations we reflect that in the code object so
3665   // it will not be counted as optimizable code.
3666   if ((code()->kind() == Code::FUNCTION) && disable) {
3667     code()->set_optimizable(false);
3668   }
3669 }
3670 
3671 
language_mode()3672 LanguageMode SharedFunctionInfo::language_mode() {
3673   int hints = compiler_hints();
3674   if (BooleanBit::get(hints, kExtendedModeFunction)) {
3675     ASSERT(BooleanBit::get(hints, kStrictModeFunction));
3676     return EXTENDED_MODE;
3677   }
3678   return BooleanBit::get(hints, kStrictModeFunction)
3679       ? STRICT_MODE : CLASSIC_MODE;
3680 }
3681 
3682 
set_language_mode(LanguageMode language_mode)3683 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
3684   // We only allow language mode transitions that go set the same language mode
3685   // again or go up in the chain:
3686   //   CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
3687   ASSERT(this->language_mode() == CLASSIC_MODE ||
3688          this->language_mode() == language_mode ||
3689          language_mode == EXTENDED_MODE);
3690   int hints = compiler_hints();
3691   hints = BooleanBit::set(
3692       hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
3693   hints = BooleanBit::set(
3694       hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
3695   set_compiler_hints(hints);
3696 }
3697 
3698 
is_classic_mode()3699 bool SharedFunctionInfo::is_classic_mode() {
3700   return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
3701 }
3702 
BOOL_GETTER(SharedFunctionInfo,compiler_hints,is_extended_mode,kExtendedModeFunction)3703 BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
3704             kExtendedModeFunction)
3705 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3706 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3707                name_should_print_as_anonymous,
3708                kNameShouldPrintAsAnonymous)
3709 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3710 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
3711 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
3712 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
3713                kDontOptimize)
3714 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
3715 
3716 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3717 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3718 
3719 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3720 
3721 bool Script::HasValidSource() {
3722   Object* src = this->source();
3723   if (!src->IsString()) return true;
3724   String* src_str = String::cast(src);
3725   if (!StringShape(src_str).IsExternal()) return true;
3726   if (src_str->IsAsciiRepresentation()) {
3727     return ExternalAsciiString::cast(src)->resource() != NULL;
3728   } else if (src_str->IsTwoByteRepresentation()) {
3729     return ExternalTwoByteString::cast(src)->resource() != NULL;
3730   }
3731   return true;
3732 }
3733 
3734 
DontAdaptArguments()3735 void SharedFunctionInfo::DontAdaptArguments() {
3736   ASSERT(code()->kind() == Code::BUILTIN);
3737   set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3738 }
3739 
3740 
start_position()3741 int SharedFunctionInfo::start_position() {
3742   return start_position_and_type() >> kStartPositionShift;
3743 }
3744 
3745 
set_start_position(int start_position)3746 void SharedFunctionInfo::set_start_position(int start_position) {
3747   set_start_position_and_type((start_position << kStartPositionShift)
3748     | (start_position_and_type() & ~kStartPositionMask));
3749 }
3750 
3751 
code()3752 Code* SharedFunctionInfo::code() {
3753   return Code::cast(READ_FIELD(this, kCodeOffset));
3754 }
3755 
3756 
unchecked_code()3757 Code* SharedFunctionInfo::unchecked_code() {
3758   return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3759 }
3760 
3761 
set_code(Code * value,WriteBarrierMode mode)3762 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3763   WRITE_FIELD(this, kCodeOffset, value);
3764   CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
3765 }
3766 
3767 
scope_info()3768 ScopeInfo* SharedFunctionInfo::scope_info() {
3769   return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
3770 }
3771 
3772 
set_scope_info(ScopeInfo * value,WriteBarrierMode mode)3773 void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
3774                                         WriteBarrierMode mode) {
3775   WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3776   CONDITIONAL_WRITE_BARRIER(GetHeap(),
3777                             this,
3778                             kScopeInfoOffset,
3779                             reinterpret_cast<Object*>(value),
3780                             mode);
3781 }
3782 
3783 
is_compiled()3784 bool SharedFunctionInfo::is_compiled() {
3785   return code() !=
3786       Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
3787 }
3788 
3789 
IsApiFunction()3790 bool SharedFunctionInfo::IsApiFunction() {
3791   return function_data()->IsFunctionTemplateInfo();
3792 }
3793 
3794 
get_api_func_data()3795 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3796   ASSERT(IsApiFunction());
3797   return FunctionTemplateInfo::cast(function_data());
3798 }
3799 
3800 
HasBuiltinFunctionId()3801 bool SharedFunctionInfo::HasBuiltinFunctionId() {
3802   return function_data()->IsSmi();
3803 }
3804 
3805 
builtin_function_id()3806 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3807   ASSERT(HasBuiltinFunctionId());
3808   return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
3809 }
3810 
3811 
code_age()3812 int SharedFunctionInfo::code_age() {
3813   return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3814 }
3815 
3816 
set_code_age(int code_age)3817 void SharedFunctionInfo::set_code_age(int code_age) {
3818   int hints = compiler_hints() & ~(kCodeAgeMask << kCodeAgeShift);
3819   set_compiler_hints(hints | ((code_age & kCodeAgeMask) << kCodeAgeShift));
3820 }
3821 
3822 
has_deoptimization_support()3823 bool SharedFunctionInfo::has_deoptimization_support() {
3824   Code* code = this->code();
3825   return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3826 }
3827 
3828 
IsBuiltin()3829 bool JSFunction::IsBuiltin() {
3830   return context()->global()->IsJSBuiltinsObject();
3831 }
3832 
3833 
NeedsArgumentsAdaption()3834 bool JSFunction::NeedsArgumentsAdaption() {
3835   return shared()->formal_parameter_count() !=
3836       SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3837 }
3838 
3839 
IsOptimized()3840 bool JSFunction::IsOptimized() {
3841   return code()->kind() == Code::OPTIMIZED_FUNCTION;
3842 }
3843 
3844 
IsOptimizable()3845 bool JSFunction::IsOptimizable() {
3846   return code()->kind() == Code::FUNCTION && code()->optimizable();
3847 }
3848 
3849 
IsMarkedForLazyRecompilation()3850 bool JSFunction::IsMarkedForLazyRecompilation() {
3851   return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
3852 }
3853 
3854 
code()3855 Code* JSFunction::code() {
3856   return Code::cast(unchecked_code());
3857 }
3858 
3859 
unchecked_code()3860 Code* JSFunction::unchecked_code() {
3861   return reinterpret_cast<Code*>(
3862       Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
3863 }
3864 
3865 
set_code(Code * value)3866 void JSFunction::set_code(Code* value) {
3867   ASSERT(!HEAP->InNewSpace(value));
3868   Address entry = value->entry();
3869   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
3870   GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
3871       this,
3872       HeapObject::RawField(this, kCodeEntryOffset),
3873       value);
3874 }
3875 
3876 
ReplaceCode(Code * code)3877 void JSFunction::ReplaceCode(Code* code) {
3878   bool was_optimized = IsOptimized();
3879   bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3880 
3881   set_code(code);
3882 
3883   // Add/remove the function from the list of optimized functions for this
3884   // context based on the state change.
3885   if (!was_optimized && is_optimized) {
3886     context()->global_context()->AddOptimizedFunction(this);
3887   }
3888   if (was_optimized && !is_optimized) {
3889     context()->global_context()->RemoveOptimizedFunction(this);
3890   }
3891 }
3892 
3893 
context()3894 Context* JSFunction::context() {
3895   return Context::cast(READ_FIELD(this, kContextOffset));
3896 }
3897 
3898 
unchecked_context()3899 Object* JSFunction::unchecked_context() {
3900   return READ_FIELD(this, kContextOffset);
3901 }
3902 
3903 
unchecked_shared()3904 SharedFunctionInfo* JSFunction::unchecked_shared() {
3905   return reinterpret_cast<SharedFunctionInfo*>(
3906       READ_FIELD(this, kSharedFunctionInfoOffset));
3907 }
3908 
3909 
set_context(Object * value)3910 void JSFunction::set_context(Object* value) {
3911   ASSERT(value->IsUndefined() || value->IsContext());
3912   WRITE_FIELD(this, kContextOffset, value);
3913   WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
3914 }
3915 
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)3916 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3917           kPrototypeOrInitialMapOffset)
3918 
3919 
3920 Map* JSFunction::initial_map() {
3921   return Map::cast(prototype_or_initial_map());
3922 }
3923 
3924 
set_initial_map(Map * value)3925 void JSFunction::set_initial_map(Map* value) {
3926   set_prototype_or_initial_map(value);
3927 }
3928 
3929 
set_initial_map_and_cache_transitions(Map * initial_map)3930 MaybeObject* JSFunction::set_initial_map_and_cache_transitions(
3931     Map* initial_map) {
3932   Context* global_context = context()->global_context();
3933   Object* array_function =
3934       global_context->get(Context::ARRAY_FUNCTION_INDEX);
3935   if (array_function->IsJSFunction() &&
3936       this == JSFunction::cast(array_function)) {
3937     ASSERT(initial_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
3938 
3939     MaybeObject* maybe_map = initial_map->CopyDropTransitions();
3940     Map* new_double_map = NULL;
3941     if (!maybe_map->To<Map>(&new_double_map)) return maybe_map;
3942     new_double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
3943     maybe_map = initial_map->AddElementsTransition(FAST_DOUBLE_ELEMENTS,
3944                                                    new_double_map);
3945     if (maybe_map->IsFailure()) return maybe_map;
3946 
3947     maybe_map = new_double_map->CopyDropTransitions();
3948     Map* new_object_map = NULL;
3949     if (!maybe_map->To<Map>(&new_object_map)) return maybe_map;
3950     new_object_map->set_elements_kind(FAST_ELEMENTS);
3951     maybe_map = new_double_map->AddElementsTransition(FAST_ELEMENTS,
3952                                                       new_object_map);
3953     if (maybe_map->IsFailure()) return maybe_map;
3954 
3955     global_context->set_smi_js_array_map(initial_map);
3956     global_context->set_double_js_array_map(new_double_map);
3957     global_context->set_object_js_array_map(new_object_map);
3958   }
3959   set_initial_map(initial_map);
3960   return this;
3961 }
3962 
3963 
has_initial_map()3964 bool JSFunction::has_initial_map() {
3965   return prototype_or_initial_map()->IsMap();
3966 }
3967 
3968 
has_instance_prototype()3969 bool JSFunction::has_instance_prototype() {
3970   return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3971 }
3972 
3973 
has_prototype()3974 bool JSFunction::has_prototype() {
3975   return map()->has_non_instance_prototype() || has_instance_prototype();
3976 }
3977 
3978 
instance_prototype()3979 Object* JSFunction::instance_prototype() {
3980   ASSERT(has_instance_prototype());
3981   if (has_initial_map()) return initial_map()->prototype();
3982   // When there is no initial map and the prototype is a JSObject, the
3983   // initial map field is used for the prototype field.
3984   return prototype_or_initial_map();
3985 }
3986 
3987 
prototype()3988 Object* JSFunction::prototype() {
3989   ASSERT(has_prototype());
3990   // If the function's prototype property has been set to a non-JSObject
3991   // value, that value is stored in the constructor field of the map.
3992   if (map()->has_non_instance_prototype()) return map()->constructor();
3993   return instance_prototype();
3994 }
3995 
should_have_prototype()3996 bool JSFunction::should_have_prototype() {
3997   return map()->function_with_prototype();
3998 }
3999 
4000 
is_compiled()4001 bool JSFunction::is_compiled() {
4002   return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
4003 }
4004 
4005 
literals()4006 FixedArray* JSFunction::literals() {
4007   ASSERT(!shared()->bound());
4008   return literals_or_bindings();
4009 }
4010 
4011 
set_literals(FixedArray * literals)4012 void JSFunction::set_literals(FixedArray* literals) {
4013   ASSERT(!shared()->bound());
4014   set_literals_or_bindings(literals);
4015 }
4016 
4017 
function_bindings()4018 FixedArray* JSFunction::function_bindings() {
4019   ASSERT(shared()->bound());
4020   return literals_or_bindings();
4021 }
4022 
4023 
set_function_bindings(FixedArray * bindings)4024 void JSFunction::set_function_bindings(FixedArray* bindings) {
4025   ASSERT(shared()->bound());
4026   // Bound function literal may be initialized to the empty fixed array
4027   // before the bindings are set.
4028   ASSERT(bindings == GetHeap()->empty_fixed_array() ||
4029          bindings->map() == GetHeap()->fixed_cow_array_map());
4030   set_literals_or_bindings(bindings);
4031 }
4032 
4033 
NumberOfLiterals()4034 int JSFunction::NumberOfLiterals() {
4035   ASSERT(!shared()->bound());
4036   return literals()->length();
4037 }
4038 
4039 
javascript_builtin(Builtins::JavaScript id)4040 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
4041   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
4042   return READ_FIELD(this, OffsetOfFunctionWithId(id));
4043 }
4044 
4045 
set_javascript_builtin(Builtins::JavaScript id,Object * value)4046 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
4047                                               Object* value) {
4048   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
4049   WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
4050   WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
4051 }
4052 
4053 
javascript_builtin_code(Builtins::JavaScript id)4054 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
4055   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
4056   return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
4057 }
4058 
4059 
set_javascript_builtin_code(Builtins::JavaScript id,Code * value)4060 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
4061                                                    Code* value) {
4062   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
4063   WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
4064   ASSERT(!HEAP->InNewSpace(value));
4065 }
4066 
4067 
ACCESSORS(JSProxy,handler,Object,kHandlerOffset)4068 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
4069 ACCESSORS(JSProxy, hash, Object, kHashOffset)
4070 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
4071 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
4072 
4073 
4074 void JSProxy::InitializeBody(int object_size, Object* value) {
4075   ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
4076   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
4077     WRITE_FIELD(this, offset, value);
4078   }
4079 }
4080 
4081 
ACCESSORS(JSSet,table,Object,kTableOffset)4082 ACCESSORS(JSSet, table, Object, kTableOffset)
4083 ACCESSORS(JSMap, table, Object, kTableOffset)
4084 ACCESSORS(JSWeakMap, table, Object, kTableOffset)
4085 ACCESSORS(JSWeakMap, next, Object, kNextOffset)
4086 
4087 
4088 Address Foreign::foreign_address() {
4089   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
4090 }
4091 
4092 
set_foreign_address(Address value)4093 void Foreign::set_foreign_address(Address value) {
4094   WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
4095 }
4096 
4097 
ACCESSORS(JSValue,value,Object,kValueOffset)4098 ACCESSORS(JSValue, value, Object, kValueOffset)
4099 
4100 
4101 JSValue* JSValue::cast(Object* obj) {
4102   ASSERT(obj->IsJSValue());
4103   ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
4104   return reinterpret_cast<JSValue*>(obj);
4105 }
4106 
4107 
ACCESSORS(JSDate,value,Object,kValueOffset)4108 ACCESSORS(JSDate, value, Object, kValueOffset)
4109 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
4110 ACCESSORS(JSDate, year, Object, kYearOffset)
4111 ACCESSORS(JSDate, month, Object, kMonthOffset)
4112 ACCESSORS(JSDate, day, Object, kDayOffset)
4113 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
4114 ACCESSORS(JSDate, hour, Object, kHourOffset)
4115 ACCESSORS(JSDate, min, Object, kMinOffset)
4116 ACCESSORS(JSDate, sec, Object, kSecOffset)
4117 
4118 
4119 JSDate* JSDate::cast(Object* obj) {
4120   ASSERT(obj->IsJSDate());
4121   ASSERT(HeapObject::cast(obj)->Size() == JSDate::kSize);
4122   return reinterpret_cast<JSDate*>(obj);
4123 }
4124 
4125 
ACCESSORS(JSMessageObject,type,String,kTypeOffset)4126 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
4127 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
4128 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
4129 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
4130 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
4131 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
4132 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
4133 
4134 
4135 JSMessageObject* JSMessageObject::cast(Object* obj) {
4136   ASSERT(obj->IsJSMessageObject());
4137   ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
4138   return reinterpret_cast<JSMessageObject*>(obj);
4139 }
4140 
4141 
INT_ACCESSORS(Code,instruction_size,kInstructionSizeOffset)4142 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
4143 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
4144 ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
4145 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
4146 ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
4147 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
4148 INT_ACCESSORS(Code, ic_age, kICAgeOffset)
4149 
4150 byte* Code::instruction_start()  {
4151   return FIELD_ADDR(this, kHeaderSize);
4152 }
4153 
4154 
instruction_end()4155 byte* Code::instruction_end()  {
4156   return instruction_start() + instruction_size();
4157 }
4158 
4159 
body_size()4160 int Code::body_size() {
4161   return RoundUp(instruction_size(), kObjectAlignment);
4162 }
4163 
4164 
unchecked_deoptimization_data()4165 FixedArray* Code::unchecked_deoptimization_data() {
4166   return reinterpret_cast<FixedArray*>(
4167       READ_FIELD(this, kDeoptimizationDataOffset));
4168 }
4169 
4170 
unchecked_relocation_info()4171 ByteArray* Code::unchecked_relocation_info() {
4172   return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
4173 }
4174 
4175 
relocation_start()4176 byte* Code::relocation_start() {
4177   return unchecked_relocation_info()->GetDataStartAddress();
4178 }
4179 
4180 
relocation_size()4181 int Code::relocation_size() {
4182   return unchecked_relocation_info()->length();
4183 }
4184 
4185 
entry()4186 byte* Code::entry() {
4187   return instruction_start();
4188 }
4189 
4190 
contains(byte * inner_pointer)4191 bool Code::contains(byte* inner_pointer) {
4192   return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
4193 }
4194 
4195 
ACCESSORS(JSArray,length,Object,kLengthOffset)4196 ACCESSORS(JSArray, length, Object, kLengthOffset)
4197 
4198 
4199 ACCESSORS(JSRegExp, data, Object, kDataOffset)
4200 
4201 
4202 JSRegExp::Type JSRegExp::TypeTag() {
4203   Object* data = this->data();
4204   if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
4205   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
4206   return static_cast<JSRegExp::Type>(smi->value());
4207 }
4208 
4209 
TypeTagUnchecked()4210 JSRegExp::Type JSRegExp::TypeTagUnchecked() {
4211   Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
4212   return static_cast<JSRegExp::Type>(smi->value());
4213 }
4214 
4215 
CaptureCount()4216 int JSRegExp::CaptureCount() {
4217   switch (TypeTag()) {
4218     case ATOM:
4219       return 0;
4220     case IRREGEXP:
4221       return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
4222     default:
4223       UNREACHABLE();
4224       return -1;
4225   }
4226 }
4227 
4228 
GetFlags()4229 JSRegExp::Flags JSRegExp::GetFlags() {
4230   ASSERT(this->data()->IsFixedArray());
4231   Object* data = this->data();
4232   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
4233   return Flags(smi->value());
4234 }
4235 
4236 
Pattern()4237 String* JSRegExp::Pattern() {
4238   ASSERT(this->data()->IsFixedArray());
4239   Object* data = this->data();
4240   String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4241   return pattern;
4242 }
4243 
4244 
DataAt(int index)4245 Object* JSRegExp::DataAt(int index) {
4246   ASSERT(TypeTag() != NOT_COMPILED);
4247   return FixedArray::cast(data())->get(index);
4248 }
4249 
4250 
DataAtUnchecked(int index)4251 Object* JSRegExp::DataAtUnchecked(int index) {
4252   FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4253   int offset = FixedArray::kHeaderSize + index * kPointerSize;
4254   return READ_FIELD(fa, offset);
4255 }
4256 
4257 
SetDataAt(int index,Object * value)4258 void JSRegExp::SetDataAt(int index, Object* value) {
4259   ASSERT(TypeTag() != NOT_COMPILED);
4260   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
4261   FixedArray::cast(data())->set(index, value);
4262 }
4263 
4264 
SetDataAtUnchecked(int index,Object * value,Heap * heap)4265 void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4266   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
4267   FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4268   if (value->IsSmi()) {
4269     fa->set_unchecked(index, Smi::cast(value));
4270   } else {
4271     // We only do this during GC, so we don't need to notify the write barrier.
4272     fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4273   }
4274 }
4275 
4276 
GetElementsKind()4277 ElementsKind JSObject::GetElementsKind() {
4278   ElementsKind kind = map()->elements_kind();
4279 #if DEBUG
4280   FixedArrayBase* fixed_array =
4281       reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
4282   Map* map = fixed_array->map();
4283     ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) &&
4284             (map == GetHeap()->fixed_array_map() ||
4285              map == GetHeap()->fixed_cow_array_map())) ||
4286            (kind == FAST_DOUBLE_ELEMENTS &&
4287             (fixed_array->IsFixedDoubleArray() ||
4288             fixed_array == GetHeap()->empty_fixed_array())) ||
4289            (kind == DICTIONARY_ELEMENTS &&
4290             fixed_array->IsFixedArray() &&
4291             fixed_array->IsDictionary()) ||
4292            (kind > DICTIONARY_ELEMENTS));
4293     ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
4294            (elements()->IsFixedArray() && elements()->length() >= 2));
4295 #endif
4296   return kind;
4297 }
4298 
4299 
GetElementsAccessor()4300 ElementsAccessor* JSObject::GetElementsAccessor() {
4301   return ElementsAccessor::ForKind(GetElementsKind());
4302 }
4303 
4304 
HasFastElements()4305 bool JSObject::HasFastElements() {
4306   return GetElementsKind() == FAST_ELEMENTS;
4307 }
4308 
4309 
HasFastSmiOnlyElements()4310 bool JSObject::HasFastSmiOnlyElements() {
4311   return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS;
4312 }
4313 
4314 
HasFastTypeElements()4315 bool JSObject::HasFastTypeElements() {
4316   ElementsKind elements_kind = GetElementsKind();
4317   return elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4318       elements_kind == FAST_ELEMENTS;
4319 }
4320 
4321 
HasFastDoubleElements()4322 bool JSObject::HasFastDoubleElements() {
4323   return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4324 }
4325 
4326 
HasDictionaryElements()4327 bool JSObject::HasDictionaryElements() {
4328   return GetElementsKind() == DICTIONARY_ELEMENTS;
4329 }
4330 
4331 
HasNonStrictArgumentsElements()4332 bool JSObject::HasNonStrictArgumentsElements() {
4333   return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4334 }
4335 
4336 
HasExternalArrayElements()4337 bool JSObject::HasExternalArrayElements() {
4338   HeapObject* array = elements();
4339   ASSERT(array != NULL);
4340   return array->IsExternalArray();
4341 }
4342 
4343 
4344 #define EXTERNAL_ELEMENTS_CHECK(name, type)          \
4345 bool JSObject::HasExternal##name##Elements() {       \
4346   HeapObject* array = elements();                    \
4347   ASSERT(array != NULL);                             \
4348   if (!array->IsHeapObject())                        \
4349     return false;                                    \
4350   return array->map()->instance_type() == type;      \
4351 }
4352 
4353 
EXTERNAL_ELEMENTS_CHECK(Byte,EXTERNAL_BYTE_ARRAY_TYPE)4354 EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4355 EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4356 EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4357 EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4358                         EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4359 EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4360 EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4361                         EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4362 EXTERNAL_ELEMENTS_CHECK(Float,
4363                         EXTERNAL_FLOAT_ARRAY_TYPE)
4364 EXTERNAL_ELEMENTS_CHECK(Double,
4365                         EXTERNAL_DOUBLE_ARRAY_TYPE)
4366 EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
4367 
4368 
4369 bool JSObject::HasNamedInterceptor() {
4370   return map()->has_named_interceptor();
4371 }
4372 
4373 
HasIndexedInterceptor()4374 bool JSObject::HasIndexedInterceptor() {
4375   return map()->has_indexed_interceptor();
4376 }
4377 
4378 
EnsureWritableFastElements()4379 MaybeObject* JSObject::EnsureWritableFastElements() {
4380   ASSERT(HasFastTypeElements());
4381   FixedArray* elems = FixedArray::cast(elements());
4382   Isolate* isolate = GetIsolate();
4383   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
4384   Object* writable_elems;
4385   { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4386       elems, isolate->heap()->fixed_array_map());
4387     if (!maybe_writable_elems->ToObject(&writable_elems)) {
4388       return maybe_writable_elems;
4389     }
4390   }
4391   set_elements(FixedArray::cast(writable_elems));
4392   isolate->counters()->cow_arrays_converted()->Increment();
4393   return writable_elems;
4394 }
4395 
4396 
property_dictionary()4397 StringDictionary* JSObject::property_dictionary() {
4398   ASSERT(!HasFastProperties());
4399   return StringDictionary::cast(properties());
4400 }
4401 
4402 
element_dictionary()4403 SeededNumberDictionary* JSObject::element_dictionary() {
4404   ASSERT(HasDictionaryElements());
4405   return SeededNumberDictionary::cast(elements());
4406 }
4407 
4408 
IsHashFieldComputed(uint32_t field)4409 bool String::IsHashFieldComputed(uint32_t field) {
4410   return (field & kHashNotComputedMask) == 0;
4411 }
4412 
4413 
HasHashCode()4414 bool String::HasHashCode() {
4415   return IsHashFieldComputed(hash_field());
4416 }
4417 
4418 
Hash()4419 uint32_t String::Hash() {
4420   // Fast case: has hash code already been computed?
4421   uint32_t field = hash_field();
4422   if (IsHashFieldComputed(field)) return field >> kHashShift;
4423   // Slow case: compute hash code and set it.
4424   return ComputeAndSetHash();
4425 }
4426 
4427 
StringHasher(int length,uint32_t seed)4428 StringHasher::StringHasher(int length, uint32_t seed)
4429   : length_(length),
4430     raw_running_hash_(seed),
4431     array_index_(0),
4432     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4433     is_first_char_(true),
4434     is_valid_(true) {
4435   ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
4436 }
4437 
4438 
has_trivial_hash()4439 bool StringHasher::has_trivial_hash() {
4440   return length_ > String::kMaxHashCalcLength;
4441 }
4442 
4443 
AddCharacter(uint32_t c)4444 void StringHasher::AddCharacter(uint32_t c) {
4445   if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4446     AddSurrogatePair(c);  // Not inlined.
4447     return;
4448   }
4449   // Use the Jenkins one-at-a-time hash function to update the hash
4450   // for the given character.
4451   raw_running_hash_ += c;
4452   raw_running_hash_ += (raw_running_hash_ << 10);
4453   raw_running_hash_ ^= (raw_running_hash_ >> 6);
4454   // Incremental array index computation.
4455   if (is_array_index_) {
4456     if (c < '0' || c > '9') {
4457       is_array_index_ = false;
4458     } else {
4459       int d = c - '0';
4460       if (is_first_char_) {
4461         is_first_char_ = false;
4462         if (c == '0' && length_ > 1) {
4463           is_array_index_ = false;
4464           return;
4465         }
4466       }
4467       if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4468         is_array_index_ = false;
4469       } else {
4470         array_index_ = array_index_ * 10 + d;
4471       }
4472     }
4473   }
4474 }
4475 
4476 
AddCharacterNoIndex(uint32_t c)4477 void StringHasher::AddCharacterNoIndex(uint32_t c) {
4478   ASSERT(!is_array_index());
4479   if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4480     AddSurrogatePairNoIndex(c);  // Not inlined.
4481     return;
4482   }
4483   raw_running_hash_ += c;
4484   raw_running_hash_ += (raw_running_hash_ << 10);
4485   raw_running_hash_ ^= (raw_running_hash_ >> 6);
4486 }
4487 
4488 
GetHash()4489 uint32_t StringHasher::GetHash() {
4490   // Get the calculated raw hash value and do some more bit ops to distribute
4491   // the hash further. Ensure that we never return zero as the hash value.
4492   uint32_t result = raw_running_hash_;
4493   result += (result << 3);
4494   result ^= (result >> 11);
4495   result += (result << 15);
4496   if ((result & String::kHashBitMask) == 0) {
4497     result = 27;
4498   }
4499   return result;
4500 }
4501 
4502 
4503 template <typename schar>
HashSequentialString(const schar * chars,int length,uint32_t seed)4504 uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) {
4505   StringHasher hasher(length, seed);
4506   if (!hasher.has_trivial_hash()) {
4507     int i;
4508     for (i = 0; hasher.is_array_index() && (i < length); i++) {
4509       hasher.AddCharacter(chars[i]);
4510     }
4511     for (; i < length; i++) {
4512       hasher.AddCharacterNoIndex(chars[i]);
4513     }
4514   }
4515   return hasher.GetHashField();
4516 }
4517 
4518 
AsArrayIndex(uint32_t * index)4519 bool String::AsArrayIndex(uint32_t* index) {
4520   uint32_t field = hash_field();
4521   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4522     return false;
4523   }
4524   return SlowAsArrayIndex(index);
4525 }
4526 
4527 
GetPrototype()4528 Object* JSReceiver::GetPrototype() {
4529   return HeapObject::cast(this)->map()->prototype();
4530 }
4531 
4532 
HasProperty(String * name)4533 bool JSReceiver::HasProperty(String* name) {
4534   if (IsJSProxy()) {
4535     return JSProxy::cast(this)->HasPropertyWithHandler(name);
4536   }
4537   return GetPropertyAttribute(name) != ABSENT;
4538 }
4539 
4540 
HasLocalProperty(String * name)4541 bool JSReceiver::HasLocalProperty(String* name) {
4542   if (IsJSProxy()) {
4543     return JSProxy::cast(this)->HasPropertyWithHandler(name);
4544   }
4545   return GetLocalPropertyAttribute(name) != ABSENT;
4546 }
4547 
4548 
GetPropertyAttribute(String * key)4549 PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
4550   return GetPropertyAttributeWithReceiver(this, key);
4551 }
4552 
4553 // TODO(504): this may be useful in other places too where JSGlobalProxy
4554 // is used.
BypassGlobalProxy()4555 Object* JSObject::BypassGlobalProxy() {
4556   if (IsJSGlobalProxy()) {
4557     Object* proto = GetPrototype();
4558     if (proto->IsNull()) return GetHeap()->undefined_value();
4559     ASSERT(proto->IsJSGlobalObject());
4560     return proto;
4561   }
4562   return this;
4563 }
4564 
4565 
GetIdentityHash(CreationFlag flag)4566 MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
4567   return IsJSProxy()
4568       ? JSProxy::cast(this)->GetIdentityHash(flag)
4569       : JSObject::cast(this)->GetIdentityHash(flag);
4570 }
4571 
4572 
HasElement(uint32_t index)4573 bool JSReceiver::HasElement(uint32_t index) {
4574   if (IsJSProxy()) {
4575     return JSProxy::cast(this)->HasElementWithHandler(index);
4576   }
4577   return JSObject::cast(this)->HasElementWithReceiver(this, index);
4578 }
4579 
4580 
all_can_read()4581 bool AccessorInfo::all_can_read() {
4582   return BooleanBit::get(flag(), kAllCanReadBit);
4583 }
4584 
4585 
set_all_can_read(bool value)4586 void AccessorInfo::set_all_can_read(bool value) {
4587   set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4588 }
4589 
4590 
all_can_write()4591 bool AccessorInfo::all_can_write() {
4592   return BooleanBit::get(flag(), kAllCanWriteBit);
4593 }
4594 
4595 
set_all_can_write(bool value)4596 void AccessorInfo::set_all_can_write(bool value) {
4597   set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4598 }
4599 
4600 
prohibits_overwriting()4601 bool AccessorInfo::prohibits_overwriting() {
4602   return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4603 }
4604 
4605 
set_prohibits_overwriting(bool value)4606 void AccessorInfo::set_prohibits_overwriting(bool value) {
4607   set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4608 }
4609 
4610 
property_attributes()4611 PropertyAttributes AccessorInfo::property_attributes() {
4612   return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4613 }
4614 
4615 
set_property_attributes(PropertyAttributes attributes)4616 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
4617   set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
4618 }
4619 
4620 
4621 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value)4622 void Dictionary<Shape, Key>::SetEntry(int entry,
4623                                       Object* key,
4624                                       Object* value) {
4625   SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4626 }
4627 
4628 
4629 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)4630 void Dictionary<Shape, Key>::SetEntry(int entry,
4631                                       Object* key,
4632                                       Object* value,
4633                                       PropertyDetails details) {
4634   ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4635   int index = HashTable<Shape, Key>::EntryToIndex(entry);
4636   AssertNoAllocation no_gc;
4637   WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
4638   FixedArray::set(index, key, mode);
4639   FixedArray::set(index+1, value, mode);
4640   FixedArray::set(index+2, details.AsSmi());
4641 }
4642 
4643 
IsMatch(uint32_t key,Object * other)4644 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4645   ASSERT(other->IsNumber());
4646   return key == static_cast<uint32_t>(other->Number());
4647 }
4648 
4649 
Hash(uint32_t key)4650 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
4651   return ComputeIntegerHash(key, 0);
4652 }
4653 
4654 
HashForObject(uint32_t key,Object * other)4655 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
4656                                                       Object* other) {
4657   ASSERT(other->IsNumber());
4658   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
4659 }
4660 
SeededHash(uint32_t key,uint32_t seed)4661 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
4662   return ComputeIntegerHash(key, seed);
4663 }
4664 
SeededHashForObject(uint32_t key,uint32_t seed,Object * other)4665 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
4666                                                           uint32_t seed,
4667                                                           Object* other) {
4668   ASSERT(other->IsNumber());
4669   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
4670 }
4671 
AsObject(uint32_t key)4672 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4673   return Isolate::Current()->heap()->NumberFromUint32(key);
4674 }
4675 
4676 
IsMatch(String * key,Object * other)4677 bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4678   // We know that all entries in a hash table had their hash keys created.
4679   // Use that knowledge to have fast failure.
4680   if (key->Hash() != String::cast(other)->Hash()) return false;
4681   return key->Equals(String::cast(other));
4682 }
4683 
4684 
Hash(String * key)4685 uint32_t StringDictionaryShape::Hash(String* key) {
4686   return key->Hash();
4687 }
4688 
4689 
HashForObject(String * key,Object * other)4690 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4691   return String::cast(other)->Hash();
4692 }
4693 
4694 
AsObject(String * key)4695 MaybeObject* StringDictionaryShape::AsObject(String* key) {
4696   return key;
4697 }
4698 
4699 
4700 template <int entrysize>
IsMatch(Object * key,Object * other)4701 bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
4702   return key->SameValue(other);
4703 }
4704 
4705 
4706 template <int entrysize>
Hash(Object * key)4707 uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
4708   MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
4709   return Smi::cast(maybe_hash->ToObjectChecked())->value();
4710 }
4711 
4712 
4713 template <int entrysize>
HashForObject(Object * key,Object * other)4714 uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
4715                                                         Object* other) {
4716   MaybeObject* maybe_hash = other->GetHash(OMIT_CREATION);
4717   return Smi::cast(maybe_hash->ToObjectChecked())->value();
4718 }
4719 
4720 
4721 template <int entrysize>
AsObject(Object * key)4722 MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Object* key) {
4723   return key;
4724 }
4725 
4726 
ClearCodeCache(Heap * heap)4727 void Map::ClearCodeCache(Heap* heap) {
4728   // No write barrier is needed since empty_fixed_array is not in new space.
4729   // Please note this function is used during marking:
4730   //  - MarkCompactCollector::MarkUnmarkedObject
4731   //  - IncrementalMarking::Step
4732   ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4733   WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
4734 }
4735 
4736 
EnsureSize(int required_size)4737 void JSArray::EnsureSize(int required_size) {
4738   ASSERT(HasFastTypeElements());
4739   FixedArray* elts = FixedArray::cast(elements());
4740   const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4741   if (elts->length() < required_size) {
4742     // Doubling in size would be overkill, but leave some slack to avoid
4743     // constantly growing.
4744     Expand(required_size + (required_size >> 3));
4745     // It's a performance benefit to keep a frequently used array in new-space.
4746   } else if (!GetHeap()->new_space()->Contains(elts) &&
4747              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4748     // Expand will allocate a new backing store in new space even if the size
4749     // we asked for isn't larger than what we had before.
4750     Expand(required_size);
4751   }
4752 }
4753 
4754 
set_length(Smi * length)4755 void JSArray::set_length(Smi* length) {
4756   // Don't need a write barrier for a Smi.
4757   set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4758 }
4759 
4760 
AllowsSetElementsLength()4761 bool JSArray::AllowsSetElementsLength() {
4762   bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
4763   ASSERT(result == !HasExternalArrayElements());
4764   return result;
4765 }
4766 
4767 
SetContent(FixedArrayBase * storage)4768 MaybeObject* JSArray::SetContent(FixedArrayBase* storage) {
4769   MaybeObject* maybe_result = EnsureCanContainElements(
4770       storage, ALLOW_COPIED_DOUBLE_ELEMENTS);
4771   if (maybe_result->IsFailure()) return maybe_result;
4772   ASSERT((storage->map() == GetHeap()->fixed_double_array_map() &&
4773           GetElementsKind() == FAST_DOUBLE_ELEMENTS) ||
4774          ((storage->map() != GetHeap()->fixed_double_array_map()) &&
4775           ((GetElementsKind() == FAST_ELEMENTS) ||
4776            (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS &&
4777             FixedArray::cast(storage)->ContainsOnlySmisOrHoles()))));
4778   set_elements(storage);
4779   set_length(Smi::FromInt(storage->length()));
4780   return this;
4781 }
4782 
4783 
Copy()4784 MaybeObject* FixedArray::Copy() {
4785   if (length() == 0) return this;
4786   return GetHeap()->CopyFixedArray(this);
4787 }
4788 
4789 
Copy()4790 MaybeObject* FixedDoubleArray::Copy() {
4791   if (length() == 0) return this;
4792   return GetHeap()->CopyFixedDoubleArray(this);
4793 }
4794 
4795 
SetAstId(int index,Smi * id)4796 void TypeFeedbackCells::SetAstId(int index, Smi* id) {
4797   set(1 + index * 2, id);
4798 }
4799 
4800 
AstId(int index)4801 Smi* TypeFeedbackCells::AstId(int index) {
4802   return Smi::cast(get(1 + index * 2));
4803 }
4804 
4805 
SetCell(int index,JSGlobalPropertyCell * cell)4806 void TypeFeedbackCells::SetCell(int index, JSGlobalPropertyCell* cell) {
4807   set(index * 2, cell);
4808 }
4809 
4810 
Cell(int index)4811 JSGlobalPropertyCell* TypeFeedbackCells::Cell(int index) {
4812   return JSGlobalPropertyCell::cast(get(index * 2));
4813 }
4814 
4815 
UninitializedSentinel(Isolate * isolate)4816 Handle<Object> TypeFeedbackCells::UninitializedSentinel(Isolate* isolate) {
4817   return isolate->factory()->the_hole_value();
4818 }
4819 
4820 
MegamorphicSentinel(Isolate * isolate)4821 Handle<Object> TypeFeedbackCells::MegamorphicSentinel(Isolate* isolate) {
4822   return isolate->factory()->undefined_value();
4823 }
4824 
4825 
RawUninitializedSentinel(Heap * heap)4826 Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
4827   return heap->raw_unchecked_the_hole_value();
4828 }
4829 
4830 
SMI_ACCESSORS(TypeFeedbackInfo,ic_total_count,kIcTotalCountOffset)4831 SMI_ACCESSORS(TypeFeedbackInfo, ic_total_count, kIcTotalCountOffset)
4832 SMI_ACCESSORS(TypeFeedbackInfo, ic_with_type_info_count,
4833               kIcWithTypeinfoCountOffset)
4834 ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
4835           kTypeFeedbackCellsOffset)
4836 
4837 
4838 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
4839 
4840 
4841 Relocatable::Relocatable(Isolate* isolate) {
4842   ASSERT(isolate == Isolate::Current());
4843   isolate_ = isolate;
4844   prev_ = isolate->relocatable_top();
4845   isolate->set_relocatable_top(this);
4846 }
4847 
4848 
~Relocatable()4849 Relocatable::~Relocatable() {
4850   ASSERT(isolate_ == Isolate::Current());
4851   ASSERT_EQ(isolate_->relocatable_top(), this);
4852   isolate_->set_relocatable_top(prev_);
4853 }
4854 
4855 
SizeOf(Map * map,HeapObject * object)4856 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4857   return map->instance_size();
4858 }
4859 
4860 
ForeignIterateBody(ObjectVisitor * v)4861 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
4862   v->VisitExternalReference(
4863       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4864 }
4865 
4866 
4867 template<typename StaticVisitor>
ForeignIterateBody()4868 void Foreign::ForeignIterateBody() {
4869   StaticVisitor::VisitExternalReference(
4870       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4871 }
4872 
4873 
ExternalAsciiStringIterateBody(ObjectVisitor * v)4874 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4875   typedef v8::String::ExternalAsciiStringResource Resource;
4876   v->VisitExternalAsciiString(
4877       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4878 }
4879 
4880 
4881 template<typename StaticVisitor>
ExternalAsciiStringIterateBody()4882 void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4883   typedef v8::String::ExternalAsciiStringResource Resource;
4884   StaticVisitor::VisitExternalAsciiString(
4885       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4886 }
4887 
4888 
ExternalTwoByteStringIterateBody(ObjectVisitor * v)4889 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4890   typedef v8::String::ExternalStringResource Resource;
4891   v->VisitExternalTwoByteString(
4892       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4893 }
4894 
4895 
4896 template<typename StaticVisitor>
ExternalTwoByteStringIterateBody()4897 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4898   typedef v8::String::ExternalStringResource Resource;
4899   StaticVisitor::VisitExternalTwoByteString(
4900       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4901 }
4902 
4903 #define SLOT_ADDR(obj, offset) \
4904   reinterpret_cast<Object**>((obj)->address() + offset)
4905 
4906 template<int start_offset, int end_offset, int size>
IterateBody(HeapObject * obj,ObjectVisitor * v)4907 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4908     HeapObject* obj,
4909     ObjectVisitor* v) {
4910     v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4911 }
4912 
4913 
4914 template<int start_offset>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)4915 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4916                                                        int object_size,
4917                                                        ObjectVisitor* v) {
4918   v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4919 }
4920 
4921 #undef SLOT_ADDR
4922 
4923 #undef TYPE_CHECKER
4924 #undef CAST_ACCESSOR
4925 #undef INT_ACCESSORS
4926 #undef ACCESSORS
4927 #undef ACCESSORS_TO_SMI
4928 #undef SMI_ACCESSORS
4929 #undef BOOL_GETTER
4930 #undef BOOL_ACCESSORS
4931 #undef FIELD_ADDR
4932 #undef READ_FIELD
4933 #undef WRITE_FIELD
4934 #undef WRITE_BARRIER
4935 #undef CONDITIONAL_WRITE_BARRIER
4936 #undef READ_DOUBLE_FIELD
4937 #undef WRITE_DOUBLE_FIELD
4938 #undef READ_INT_FIELD
4939 #undef WRITE_INT_FIELD
4940 #undef READ_INTPTR_FIELD
4941 #undef WRITE_INTPTR_FIELD
4942 #undef READ_UINT32_FIELD
4943 #undef WRITE_UINT32_FIELD
4944 #undef READ_SHORT_FIELD
4945 #undef WRITE_SHORT_FIELD
4946 #undef READ_BYTE_FIELD
4947 #undef WRITE_BYTE_FIELD
4948 
4949 
4950 } }  // namespace v8::internal
4951 
4952 #endif  // V8_OBJECTS_INL_H_
4953