blob: e46dd8e7dd0e898142b730e96c1ac100080c907a [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004//
5// Review notes:
6//
7// - The use of macros in these inline functions may seem superfluous
8// but it is absolutely needed to make sure gcc generates optimal
9// code. gcc is not happy when attempting to inline too deep.
10//
11
12#ifndef V8_OBJECTS_INL_H_
13#define V8_OBJECTS_INL_H_
14
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/base/atomicops.h"
16#include "src/base/bits.h"
17#include "src/contexts.h"
18#include "src/conversions-inl.h"
19#include "src/elements.h"
20#include "src/factory.h"
21#include "src/field-index-inl.h"
22#include "src/heap/heap-inl.h"
23#include "src/heap/heap.h"
24#include "src/heap/incremental-marking.h"
25#include "src/heap/objects-visiting.h"
26#include "src/heap/spaces.h"
27#include "src/heap/store-buffer.h"
28#include "src/isolate.h"
29#include "src/lookup.h"
30#include "src/objects.h"
31#include "src/property.h"
32#include "src/prototype.h"
33#include "src/transitions-inl.h"
34#include "src/type-feedback-vector-inl.h"
35#include "src/v8memory.h"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000036
Steve Blocka7e24c12009-10-30 11:49:00 +000037namespace v8 {
38namespace internal {
39
40PropertyDetails::PropertyDetails(Smi* smi) {
41 value_ = smi->value();
42}
43
44
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045Smi* PropertyDetails::AsSmi() const {
46 // Ensure the upper 2 bits have the same value by sign extending it. This is
47 // necessary to be able to use the 31st bit of the property details.
48 int value = value_ << 1;
49 return Smi::FromInt(value >> 1);
Steve Blocka7e24c12009-10-30 11:49:00 +000050}
51
52
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053PropertyDetails PropertyDetails::AsDeleted() const {
Steve Block1e0659c2011-05-24 12:43:12 +010054 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000055 return PropertyDetails(smi);
56}
57
58
Ben Murdoch3ef787d2012-04-12 10:51:47 +010059#define TYPE_CHECKER(type, instancetype) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060 bool Object::Is##type() const { \
Ben Murdoch3ef787d2012-04-12 10:51:47 +010061 return Object::IsHeapObject() && \
62 HeapObject::cast(this)->map()->instance_type() == instancetype; \
63 }
64
65
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066#define CAST_ACCESSOR(type) \
67 type* type::cast(Object* object) { \
68 SLOW_DCHECK(object->Is##type()); \
69 return reinterpret_cast<type*>(object); \
70 } \
71 const type* type::cast(const Object* object) { \
72 SLOW_DCHECK(object->Is##type()); \
73 return reinterpret_cast<const type*>(object); \
Steve Blocka7e24c12009-10-30 11:49:00 +000074 }
75
76
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077#define INT_ACCESSORS(holder, name, offset) \
78 int holder::name() const { return READ_INT_FIELD(this, offset); } \
Steve Blocka7e24c12009-10-30 11:49:00 +000079 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
80
81
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082#define ACCESSORS(holder, name, type, offset) \
83 type* holder::name() const { return type::cast(READ_FIELD(this, offset)); } \
84 void holder::set_##name(type* value, WriteBarrierMode mode) { \
85 WRITE_FIELD(this, offset, value); \
86 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
Steve Blocka7e24c12009-10-30 11:49:00 +000087 }
88
89
Ben Murdoch3ef787d2012-04-12 10:51:47 +010090// Getter that returns a tagged Smi and setter that writes a tagged Smi.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091#define ACCESSORS_TO_SMI(holder, name, offset) \
92 Smi* holder::name() const { return Smi::cast(READ_FIELD(this, offset)); } \
93 void holder::set_##name(Smi* value, WriteBarrierMode mode) { \
94 WRITE_FIELD(this, offset, value); \
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +010095 }
96
97
Ben Murdoch3ef787d2012-04-12 10:51:47 +010098// Getter that returns a Smi as an int and writes an int as a Smi.
Steve Blocka7e24c12009-10-30 11:49:00 +000099#define SMI_ACCESSORS(holder, name, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 int holder::name() const { \
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 Object* value = READ_FIELD(this, offset); \
102 return Smi::cast(value)->value(); \
103 } \
104 void holder::set_##name(int value) { \
105 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
106 }
107
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108#define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \
109 int holder::synchronized_##name() const { \
110 Object* value = ACQUIRE_READ_FIELD(this, offset); \
111 return Smi::cast(value)->value(); \
112 } \
113 void holder::synchronized_set_##name(int value) { \
114 RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \
115 }
116
117#define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \
118 int holder::nobarrier_##name() const { \
119 Object* value = NOBARRIER_READ_FIELD(this, offset); \
120 return Smi::cast(value)->value(); \
121 } \
122 void holder::nobarrier_set_##name(int value) { \
123 NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \
124 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000125
126#define BOOL_GETTER(holder, field, name, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 bool holder::name() const { \
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 return BooleanBit::get(field(), offset); \
129 } \
130
131
132#define BOOL_ACCESSORS(holder, field, name, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 bool holder::name() const { \
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 return BooleanBit::get(field(), offset); \
135 } \
136 void holder::set_##name(bool value) { \
137 set_##field(BooleanBit::set(field(), offset, value)); \
138 }
139
140
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141bool Object::IsFixedArrayBase() const {
142 return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
143 IsFixedTypedArrayBase() || IsExternalArray();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100144}
145
146
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147// External objects are not extensible, so the map check is enough.
148bool Object::IsExternal() const {
149 return Object::IsHeapObject() &&
150 HeapObject::cast(this)->map() ==
151 HeapObject::cast(this)->GetHeap()->external_map();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100152}
153
154
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155bool Object::IsAccessorInfo() const {
156 return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
Steve Blocka7e24c12009-10-30 11:49:00 +0000157}
158
159
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160bool Object::IsSmi() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 return HAS_SMI_TAG(this);
162}
163
164
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165bool Object::IsHeapObject() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 return Internals::HasHeapObjectTag(this);
167}
168
169
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100170TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
172TYPE_CHECKER(Symbol, SYMBOL_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100173
174
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175bool Object::IsString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 return Object::IsHeapObject()
177 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
178}
179
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181bool Object::IsName() const {
182 return IsString() || IsSymbol();
183}
184
185
186bool Object::IsUniqueName() const {
187 return IsInternalizedString() || IsSymbol();
188}
189
190
191bool Object::IsSpecObject() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000192 return Object::IsHeapObject()
193 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
194}
195
196
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197bool Object::IsSpecFunction() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100198 if (!Object::IsHeapObject()) return false;
199 InstanceType type = HeapObject::cast(this)->map()->instance_type();
200 return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
201}
202
203
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204bool Object::IsTemplateInfo() const {
205 return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
Steve Blocka7e24c12009-10-30 11:49:00 +0000206}
207
208
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209bool Object::IsInternalizedString() const {
210 if (!this->IsHeapObject()) return false;
211 uint32_t type = HeapObject::cast(this)->map()->instance_type();
212 STATIC_ASSERT(kNotInternalizedTag != 0);
213 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
214 (kStringTag | kInternalizedTag);
215}
216
217
218bool Object::IsConsString() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000219 if (!IsString()) return false;
220 return StringShape(String::cast(this)).IsCons();
221}
222
223
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224bool Object::IsSlicedString() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000225 if (!IsString()) return false;
226 return StringShape(String::cast(this)).IsSliced();
Steve Blocka7e24c12009-10-30 11:49:00 +0000227}
228
229
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230bool Object::IsSeqString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 if (!IsString()) return false;
232 return StringShape(String::cast(this)).IsSequential();
233}
234
235
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236bool Object::IsSeqOneByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000237 if (!IsString()) return false;
238 return StringShape(String::cast(this)).IsSequential() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 String::cast(this)->IsOneByteRepresentation();
Steve Blocka7e24c12009-10-30 11:49:00 +0000240}
241
242
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243bool Object::IsSeqTwoByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000244 if (!IsString()) return false;
245 return StringShape(String::cast(this)).IsSequential() &&
246 String::cast(this)->IsTwoByteRepresentation();
247}
248
249
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250bool Object::IsExternalString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 if (!IsString()) return false;
252 return StringShape(String::cast(this)).IsExternal();
253}
254
255
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256bool Object::IsExternalOneByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 if (!IsString()) return false;
258 return StringShape(String::cast(this)).IsExternal() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 String::cast(this)->IsOneByteRepresentation();
Steve Blocka7e24c12009-10-30 11:49:00 +0000260}
261
262
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263bool Object::IsExternalTwoByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 if (!IsString()) return false;
265 return StringShape(String::cast(this)).IsExternal() &&
266 String::cast(this)->IsTwoByteRepresentation();
267}
268
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000270bool Object::HasValidElements() {
271 // Dictionary is covered under FixedArray.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
273 IsFixedTypedArrayBase();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000274}
Steve Blocka7e24c12009-10-30 11:49:00 +0000275
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276
277Handle<Object> Object::NewStorageFor(Isolate* isolate,
278 Handle<Object> object,
279 Representation representation) {
280 if (representation.IsSmi() && object->IsUninitialized()) {
281 return handle(Smi::FromInt(0), isolate);
282 }
283 if (!representation.IsDouble()) return object;
284 double value;
285 if (object->IsUninitialized()) {
286 value = 0;
287 } else if (object->IsMutableHeapNumber()) {
288 value = HeapNumber::cast(*object)->value();
289 } else {
290 value = object->Number();
291 }
292 return isolate->factory()->NewHeapNumber(value, MUTABLE);
293}
294
295
296Handle<Object> Object::WrapForRead(Isolate* isolate,
297 Handle<Object> object,
298 Representation representation) {
299 DCHECK(!object->IsUninitialized());
300 if (!representation.IsDouble()) {
301 DCHECK(object->FitsRepresentation(representation));
302 return object;
303 }
304 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
305}
306
307
308StringShape::StringShape(const String* str)
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 : type_(str->map()->instance_type()) {
310 set_valid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 DCHECK((type_ & kIsNotStringMask) == kStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000312}
313
314
315StringShape::StringShape(Map* map)
316 : type_(map->instance_type()) {
317 set_valid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 DCHECK((type_ & kIsNotStringMask) == kStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000319}
320
321
322StringShape::StringShape(InstanceType t)
323 : type_(static_cast<uint32_t>(t)) {
324 set_valid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 DCHECK((type_ & kIsNotStringMask) == kStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000326}
327
328
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329bool StringShape::IsInternalized() {
330 DCHECK(valid());
331 STATIC_ASSERT(kNotInternalizedTag != 0);
332 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
333 (kStringTag | kInternalizedTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000334}
335
336
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337bool String::IsOneByteRepresentation() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 uint32_t type = map()->instance_type();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 return (type & kStringEncodingMask) == kOneByteStringTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000340}
341
342
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000343bool String::IsTwoByteRepresentation() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 return (type & kStringEncodingMask) == kTwoByteStringTag;
346}
347
348
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349bool String::IsOneByteRepresentationUnderneath() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000350 uint32_t type = map()->instance_type();
351 STATIC_ASSERT(kIsIndirectStringTag != 0);
352 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 DCHECK(IsFlat());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000354 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 case kOneByteStringTag:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000356 return true;
357 case kTwoByteStringTag:
358 return false;
359 default: // Cons or sliced string. Need to go deeper.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 return GetUnderlying()->IsOneByteRepresentation();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000361 }
362}
363
364
365bool String::IsTwoByteRepresentationUnderneath() {
366 uint32_t type = map()->instance_type();
367 STATIC_ASSERT(kIsIndirectStringTag != 0);
368 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 DCHECK(IsFlat());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000370 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 case kOneByteStringTag:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000372 return false;
373 case kTwoByteStringTag:
374 return true;
375 default: // Cons or sliced string. Need to go deeper.
376 return GetUnderlying()->IsTwoByteRepresentation();
377 }
378}
379
380
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381bool String::HasOnlyOneByteChars() {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100382 uint32_t type = map()->instance_type();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383 return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
384 IsOneByteRepresentation();
Steve Block6ded16b2010-05-10 14:33:55 +0100385}
386
387
Steve Blocka7e24c12009-10-30 11:49:00 +0000388bool StringShape::IsCons() {
389 return (type_ & kStringRepresentationMask) == kConsStringTag;
390}
391
392
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000393bool StringShape::IsSliced() {
394 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
395}
396
397
398bool StringShape::IsIndirect() {
399 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
400}
401
402
Steve Blocka7e24c12009-10-30 11:49:00 +0000403bool StringShape::IsExternal() {
404 return (type_ & kStringRepresentationMask) == kExternalStringTag;
405}
406
407
408bool StringShape::IsSequential() {
409 return (type_ & kStringRepresentationMask) == kSeqStringTag;
410}
411
412
413StringRepresentationTag StringShape::representation_tag() {
414 uint32_t tag = (type_ & kStringRepresentationMask);
415 return static_cast<StringRepresentationTag>(tag);
416}
417
418
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000419uint32_t StringShape::encoding_tag() {
420 return type_ & kStringEncodingMask;
421}
422
423
Steve Blocka7e24c12009-10-30 11:49:00 +0000424uint32_t StringShape::full_representation_tag() {
425 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
426}
427
428
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 Internals::kFullStringRepresentationMask);
431
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
433 Internals::kStringEncodingMask);
Steve Blocka7e24c12009-10-30 11:49:00 +0000434
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435
436bool StringShape::IsSequentialOneByte() {
437 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000438}
439
440
441bool StringShape::IsSequentialTwoByte() {
442 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
443}
444
445
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446bool StringShape::IsExternalOneByte() {
447 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000448}
449
450
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
452 Internals::kExternalOneByteRepresentationTag);
453
454STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
455
456
Steve Blocka7e24c12009-10-30 11:49:00 +0000457bool StringShape::IsExternalTwoByte() {
458 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
459}
460
461
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
Steve Blocka7e24c12009-10-30 11:49:00 +0000463 Internals::kExternalTwoByteRepresentationTag);
464
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000466
467uc32 FlatStringReader::Get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468 DCHECK(0 <= index && index <= length_);
469 if (is_one_byte_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000470 return static_cast<const byte*>(start_)[index];
471 } else {
472 return static_cast<const uc16*>(start_)[index];
473 }
474}
475
476
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) {
478 return key->AsHandle(isolate);
479}
480
481
482Handle<Object> MapCacheShape::AsHandle(Isolate* isolate, HashTableKey* key) {
483 return key->AsHandle(isolate);
484}
485
486
487Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
488 HashTableKey* key) {
489 return key->AsHandle(isolate);
490}
491
492
493Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate,
494 HashTableKey* key) {
495 return key->AsHandle(isolate);
496}
497
498template <typename Char>
499class SequentialStringKey : public HashTableKey {
500 public:
501 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
502 : string_(string), hash_field_(0), seed_(seed) { }
503
504 virtual uint32_t Hash() OVERRIDE {
505 hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
506 string_.length(),
507 seed_);
508
509 uint32_t result = hash_field_ >> String::kHashShift;
510 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
511 return result;
512 }
513
514
515 virtual uint32_t HashForObject(Object* other) OVERRIDE {
516 return String::cast(other)->Hash();
517 }
518
519 Vector<const Char> string_;
520 uint32_t hash_field_;
521 uint32_t seed_;
522};
523
524
525class OneByteStringKey : public SequentialStringKey<uint8_t> {
526 public:
527 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
528 : SequentialStringKey<uint8_t>(str, seed) { }
529
530 virtual bool IsMatch(Object* string) OVERRIDE {
531 return String::cast(string)->IsOneByteEqualTo(string_);
532 }
533
534 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
535};
536
537
538class SeqOneByteSubStringKey : public HashTableKey {
539 public:
540 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length)
541 : string_(string), from_(from), length_(length) {
542 DCHECK(string_->IsSeqOneByteString());
543 }
544
545 virtual uint32_t Hash() OVERRIDE {
546 DCHECK(length_ >= 0);
547 DCHECK(from_ + length_ <= string_->length());
548 const uint8_t* chars = string_->GetChars() + from_;
549 hash_field_ = StringHasher::HashSequentialString(
550 chars, length_, string_->GetHeap()->HashSeed());
551 uint32_t result = hash_field_ >> String::kHashShift;
552 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
553 return result;
554 }
555
556 virtual uint32_t HashForObject(Object* other) OVERRIDE {
557 return String::cast(other)->Hash();
558 }
559
560 virtual bool IsMatch(Object* string) OVERRIDE;
561 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
562
563 private:
564 Handle<SeqOneByteString> string_;
565 int from_;
566 int length_;
567 uint32_t hash_field_;
568};
569
570
571class TwoByteStringKey : public SequentialStringKey<uc16> {
572 public:
573 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
574 : SequentialStringKey<uc16>(str, seed) { }
575
576 virtual bool IsMatch(Object* string) OVERRIDE {
577 return String::cast(string)->IsTwoByteEqualTo(string_);
578 }
579
580 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
581};
582
583
584// Utf8StringKey carries a vector of chars as key.
585class Utf8StringKey : public HashTableKey {
586 public:
587 explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
588 : string_(string), hash_field_(0), seed_(seed) { }
589
590 virtual bool IsMatch(Object* string) OVERRIDE {
591 return String::cast(string)->IsUtf8EqualTo(string_);
592 }
593
594 virtual uint32_t Hash() OVERRIDE {
595 if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
596 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
597 uint32_t result = hash_field_ >> String::kHashShift;
598 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
599 return result;
600 }
601
602 virtual uint32_t HashForObject(Object* other) OVERRIDE {
603 return String::cast(other)->Hash();
604 }
605
606 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
607 if (hash_field_ == 0) Hash();
608 return isolate->factory()->NewInternalizedStringFromUtf8(
609 string_, chars_, hash_field_);
610 }
611
612 Vector<const char> string_;
613 uint32_t hash_field_;
614 int chars_; // Caches the number of characters when computing the hash code.
615 uint32_t seed_;
616};
617
618
619bool Object::IsNumber() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000620 return IsSmi() || IsHeapNumber();
621}
622
623
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100624TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
625TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
626
627
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628bool Object::IsFiller() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100629 if (!Object::IsHeapObject()) return false;
630 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
631 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000632}
633
634
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000635bool Object::IsExternalArray() const {
Steve Block3ce2e202009-11-05 08:53:23 +0000636 if (!Object::IsHeapObject())
637 return false;
638 InstanceType instance_type =
639 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000640 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
641 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000642}
643
644
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
646 TYPE_CHECKER(External##Type##Array, EXTERNAL_##TYPE##_ARRAY_TYPE) \
647 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
648
649TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
650#undef TYPED_ARRAY_TYPE_CHECKER
Ben Murdoch257744e2011-11-30 15:57:28 +0000651
652
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653bool Object::IsFixedTypedArrayBase() const {
654 if (!Object::IsHeapObject()) return false;
655
656 InstanceType instance_type =
657 HeapObject::cast(this)->map()->instance_type();
658 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
659 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000660}
661
662
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663bool Object::IsJSReceiver() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100664 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000665 return IsHeapObject() &&
666 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
667}
668
669
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670bool Object::IsJSObject() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100671 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
672 return IsHeapObject() &&
673 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000674}
675
676
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677bool Object::IsJSProxy() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100678 if (!Object::IsHeapObject()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 return HeapObject::cast(this)->map()->IsJSProxyMap();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000680}
681
682
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100683TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
684TYPE_CHECKER(JSSet, JS_SET_TYPE)
685TYPE_CHECKER(JSMap, JS_MAP_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
687TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100688TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100690TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
691TYPE_CHECKER(Map, MAP_TYPE)
692TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
693TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000695
696
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697bool Object::IsJSWeakCollection() const {
698 return IsJSWeakMap() || IsJSWeakSet();
699}
700
701
702bool Object::IsDescriptorArray() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000703 return IsFixedArray();
704}
705
706
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707bool Object::IsTransitionArray() const {
708 return IsFixedArray();
709}
710
711
712bool Object::IsTypeFeedbackVector() const { return IsFixedArray(); }
713
714
715bool Object::IsDeoptimizationInputData() const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100716 // Must be a fixed array.
717 if (!IsFixedArray()) return false;
718
719 // There's no sure way to detect the difference between a fixed array and
720 // a deoptimization data array. Since this is used for asserts we can
721 // check that the length is zero or else the fixed size plus a multiple of
722 // the entry size.
723 int length = FixedArray::cast(this)->length();
724 if (length == 0) return true;
725
726 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100728}
729
730
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731bool Object::IsDeoptimizationOutputData() const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100732 if (!IsFixedArray()) return false;
733 // There's actually no way to see the difference between a fixed array and
734 // a deoptimization data array. Since this is used for asserts we can check
735 // that the length is plausible though.
736 if (FixedArray::cast(this)->length() % 2 != 0) return false;
737 return true;
738}
739
740
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741bool Object::IsDependentCode() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100742 if (!IsFixedArray()) return false;
743 // There's actually no way to see the difference between a fixed array and
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 // a dependent codes array.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100745 return true;
746}
747
748
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749bool Object::IsContext() const {
750 if (!Object::IsHeapObject()) return false;
751 Map* map = HeapObject::cast(this)->map();
752 Heap* heap = map->GetHeap();
753 return (map == heap->function_context_map() ||
754 map == heap->catch_context_map() ||
755 map == heap->with_context_map() ||
756 map == heap->native_context_map() ||
757 map == heap->block_context_map() ||
758 map == heap->module_context_map() ||
759 map == heap->global_context_map());
Steve Blocka7e24c12009-10-30 11:49:00 +0000760}
761
762
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763bool Object::IsNativeContext() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100764 return Object::IsHeapObject() &&
765 HeapObject::cast(this)->map() ==
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 HeapObject::cast(this)->GetHeap()->native_context_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000767}
768
769
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770bool Object::IsScopeInfo() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000771 return Object::IsHeapObject() &&
772 HeapObject::cast(this)->map() ==
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100773 HeapObject::cast(this)->GetHeap()->scope_info_map();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000774}
775
776
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100777TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000778
779
780template <> inline bool Is<JSFunction>(Object* obj) {
781 return obj->IsJSFunction();
782}
783
784
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100785TYPE_CHECKER(Code, CODE_TYPE)
786TYPE_CHECKER(Oddball, ODDBALL_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000787TYPE_CHECKER(Cell, CELL_TYPE)
788TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100789TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
791TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100792TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
793TYPE_CHECKER(JSDate, JS_DATE_TYPE)
794TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000795
796
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797bool Object::IsStringWrapper() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000798 return IsJSValue() && JSValue::cast(this)->value()->IsString();
799}
800
801
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100802TYPE_CHECKER(Foreign, FOREIGN_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000803
804
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805bool Object::IsBoolean() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100806 return IsOddball() &&
807 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000808}
809
810
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100811TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
813TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
814TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
815
816
817bool Object::IsJSArrayBufferView() const {
818 return IsJSDataView() || IsJSTypedArray();
819}
820
821
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000823
824
825template <> inline bool Is<JSArray>(Object* obj) {
826 return obj->IsJSArray();
827}
828
829
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830bool Object::IsHashTable() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100831 return Object::IsHeapObject() &&
832 HeapObject::cast(this)->map() ==
833 HeapObject::cast(this)->GetHeap()->hash_table_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000834}
835
836
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837bool Object::IsWeakHashTable() const {
838 return IsHashTable();
839}
840
841
842bool Object::IsDictionary() const {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000843 return IsHashTable() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844 this != HeapObject::cast(this)->GetHeap()->string_table();
Steve Blocka7e24c12009-10-30 11:49:00 +0000845}
846
847
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848bool Object::IsNameDictionary() const {
849 return IsDictionary();
Steve Blocka7e24c12009-10-30 11:49:00 +0000850}
851
852
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853bool Object::IsSeededNumberDictionary() const {
854 return IsDictionary();
855}
856
857
858bool Object::IsUnseededNumberDictionary() const {
859 return IsDictionary();
860}
861
862
863bool Object::IsStringTable() const {
864 return IsHashTable();
865}
866
867
868bool Object::IsJSFunctionResultCache() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100869 if (!IsFixedArray()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 const FixedArray* self = FixedArray::cast(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100871 int length = self->length();
872 if (length < JSFunctionResultCache::kEntriesIndex) return false;
873 if ((length - JSFunctionResultCache::kEntriesIndex)
874 % JSFunctionResultCache::kEntrySize != 0) {
875 return false;
876 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877#ifdef VERIFY_HEAP
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100878 if (FLAG_verify_heap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 // TODO(svenpanne) We use const_cast here and below to break our dependency
880 // cycle between the predicates and the verifiers. This can be removed when
881 // the verifiers are const-correct, too.
882 reinterpret_cast<JSFunctionResultCache*>(const_cast<Object*>(this))->
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100883 JSFunctionResultCacheVerify();
884 }
Steve Block6ded16b2010-05-10 14:33:55 +0100885#endif
886 return true;
887}
888
889
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890bool Object::IsNormalizedMapCache() const {
891 return NormalizedMapCache::IsNormalizedMapCache(this);
892}
893
894
895int NormalizedMapCache::GetIndex(Handle<Map> map) {
896 return map->Hash() % NormalizedMapCache::kEntries;
897}
898
899
900bool NormalizedMapCache::IsNormalizedMapCache(const Object* obj) {
901 if (!obj->IsFixedArray()) return false;
902 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100903 return false;
904 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905#ifdef VERIFY_HEAP
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100906 if (FLAG_verify_heap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 reinterpret_cast<NormalizedMapCache*>(const_cast<Object*>(obj))->
908 NormalizedMapCacheVerify();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100909 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100910#endif
911 return true;
912}
913
914
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915bool Object::IsCompilationCacheTable() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000916 return IsHashTable();
917}
918
919
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920bool Object::IsCodeCacheHashTable() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100921 return IsHashTable();
922}
923
924
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925bool Object::IsPolymorphicCodeCacheHashTable() const {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000926 return IsHashTable();
927}
928
929
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000930bool Object::IsMapCache() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 return IsHashTable();
932}
933
934
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935bool Object::IsObjectHashTable() const {
936 return IsHashTable();
937}
938
939
940bool Object::IsOrderedHashTable() const {
941 return IsHeapObject() &&
942 HeapObject::cast(this)->map() ==
943 HeapObject::cast(this)->GetHeap()->ordered_hash_table_map();
944}
945
946
947bool Object::IsOrderedHashSet() const {
948 return IsOrderedHashTable();
949}
950
951
952bool Object::IsOrderedHashMap() const {
953 return IsOrderedHashTable();
954}
955
956
957bool Object::IsPrimitive() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000958 return IsOddball() || IsNumber() || IsString();
959}
960
961
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962bool Object::IsJSGlobalProxy() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000963 bool result = IsHeapObject() &&
964 (HeapObject::cast(this)->map()->instance_type() ==
965 JS_GLOBAL_PROXY_TYPE);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 DCHECK(!result ||
967 HeapObject::cast(this)->map()->is_access_check_needed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 return result;
969}
970
971
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972bool Object::IsGlobalObject() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 if (!IsHeapObject()) return false;
974
975 InstanceType type = HeapObject::cast(this)->map()->instance_type();
976 return type == JS_GLOBAL_OBJECT_TYPE ||
977 type == JS_BUILTINS_OBJECT_TYPE;
978}
979
980
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100981TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
982TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000983
984
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000985bool Object::IsUndetectableObject() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000986 return IsHeapObject()
987 && HeapObject::cast(this)->map()->is_undetectable();
988}
989
990
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000991bool Object::IsAccessCheckNeeded() const {
992 if (!IsHeapObject()) return false;
993 if (IsJSGlobalProxy()) {
994 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
995 GlobalObject* global = proxy->GetIsolate()->context()->global_object();
996 return proxy->IsDetachedFrom(global);
997 }
998 return HeapObject::cast(this)->map()->is_access_check_needed();
Steve Blocka7e24c12009-10-30 11:49:00 +0000999}
1000
1001
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002bool Object::IsStruct() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001003 if (!IsHeapObject()) return false;
1004 switch (HeapObject::cast(this)->map()->instance_type()) {
1005#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
1006 STRUCT_LIST(MAKE_STRUCT_CASE)
1007#undef MAKE_STRUCT_CASE
1008 default: return false;
1009 }
1010}
1011
1012
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
1014 bool Object::Is##Name() const { \
1015 return Object::IsHeapObject() \
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
1017 }
1018 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
1019#undef MAKE_STRUCT_PREDICATE
1020
1021
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022bool Object::IsUndefined() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001023 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
Steve Blocka7e24c12009-10-30 11:49:00 +00001024}
1025
1026
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027bool Object::IsNull() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001028 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
1029}
1030
1031
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001032bool Object::IsTheHole() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001033 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
Steve Blocka7e24c12009-10-30 11:49:00 +00001034}
1035
1036
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037bool Object::IsException() const {
1038 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException;
1039}
1040
1041
1042bool Object::IsUninitialized() const {
1043 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
1044}
1045
1046
1047bool Object::IsTrue() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001048 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001049}
1050
1051
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052bool Object::IsFalse() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001053 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
Steve Blocka7e24c12009-10-30 11:49:00 +00001054}
1055
1056
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001057bool Object::IsArgumentsMarker() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001058 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
Ben Murdoch086aeea2011-05-13 15:57:08 +01001059}
1060
1061
Steve Blocka7e24c12009-10-30 11:49:00 +00001062double Object::Number() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063 DCHECK(IsNumber());
Steve Blocka7e24c12009-10-30 11:49:00 +00001064 return IsSmi()
1065 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
1066 : reinterpret_cast<HeapNumber*>(this)->value();
1067}
1068
1069
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001070bool Object::IsNaN() const {
1071 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001072}
1073
1074
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001075bool Object::IsMinusZero() const {
1076 return this->IsHeapNumber() &&
1077 i::IsMinusZero(HeapNumber::cast(this)->value());
1078}
1079
1080
1081MaybeHandle<Smi> Object::ToSmi(Isolate* isolate, Handle<Object> object) {
1082 if (object->IsSmi()) return Handle<Smi>::cast(object);
1083 if (object->IsHeapNumber()) {
1084 double value = Handle<HeapNumber>::cast(object)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001085 int int_value = FastD2I(value);
1086 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 return handle(Smi::FromInt(int_value), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 }
1089 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001090 return Handle<Smi>();
1091}
1092
1093
1094MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
1095 Handle<Object> object) {
1096 return ToObject(
1097 isolate, object, handle(isolate->context()->native_context(), isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +00001098}
1099
1100
1101bool Object::HasSpecificClassOf(String* name) {
1102 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
1103}
1104
1105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001106MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
1107 Handle<Name> name) {
1108 LookupIterator it(object, name);
1109 return GetProperty(&it);
1110}
1111
1112
1113MaybeHandle<Object> Object::GetElement(Isolate* isolate,
1114 Handle<Object> object,
1115 uint32_t index) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001116 // GetElement can trigger a getter which can cause allocation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001117 // This was not always the case. This DCHECK is here to catch
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001118 // leftover incorrect uses.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119 DCHECK(AllowHeapAllocation::IsAllowed());
1120 return Object::GetElementWithReceiver(isolate, object, object, index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001121}
1122
1123
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
1125 Handle<Name> name) {
1126 uint32_t index;
1127 Isolate* isolate = name->GetIsolate();
1128 if (name->AsArrayIndex(&index)) return GetElement(isolate, object, index);
1129 return GetProperty(object, name);
John Reck59135872010-11-02 12:39:01 -07001130}
1131
1132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
1134 Handle<Object> object,
1135 const char* name) {
1136 Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
1137 DCHECK(!str.is_null());
1138#ifdef DEBUG
1139 uint32_t index; // Assert that the name is not an array index.
1140 DCHECK(!str->AsArrayIndex(&index));
1141#endif // DEBUG
1142 return GetProperty(object, str);
Steve Blocka7e24c12009-10-30 11:49:00 +00001143}
1144
1145
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001146MaybeHandle<Object> JSProxy::GetElementWithHandler(Handle<JSProxy> proxy,
1147 Handle<Object> receiver,
1148 uint32_t index) {
1149 return GetPropertyWithHandler(
1150 proxy, receiver, proxy->GetIsolate()->factory()->Uint32ToString(index));
1151}
1152
1153
1154MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
1155 Handle<JSReceiver> receiver,
1156 uint32_t index,
1157 Handle<Object> value,
1158 StrictMode strict_mode) {
1159 Isolate* isolate = proxy->GetIsolate();
1160 Handle<String> name = isolate->factory()->Uint32ToString(index);
1161 return SetPropertyWithHandler(proxy, receiver, name, value, strict_mode);
1162}
1163
1164
1165Maybe<bool> JSProxy::HasElementWithHandler(Handle<JSProxy> proxy,
1166 uint32_t index) {
1167 Isolate* isolate = proxy->GetIsolate();
1168 Handle<String> name = isolate->factory()->Uint32ToString(index);
1169 return HasPropertyWithHandler(proxy, name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001170}
1171
1172
1173#define FIELD_ADDR(p, offset) \
1174 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
1175
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001176#define FIELD_ADDR_CONST(p, offset) \
1177 (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
1178
Steve Blocka7e24c12009-10-30 11:49:00 +00001179#define READ_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 (*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset)))
1181
1182#define ACQUIRE_READ_FIELD(p, offset) \
1183 reinterpret_cast<Object*>(base::Acquire_Load( \
1184 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
1185
1186#define NOBARRIER_READ_FIELD(p, offset) \
1187 reinterpret_cast<Object*>(base::NoBarrier_Load( \
1188 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
Steve Blocka7e24c12009-10-30 11:49:00 +00001189
1190#define WRITE_FIELD(p, offset, value) \
1191 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
1192
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001193#define RELEASE_WRITE_FIELD(p, offset, value) \
1194 base::Release_Store( \
1195 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
1196 reinterpret_cast<base::AtomicWord>(value));
1197
1198#define NOBARRIER_WRITE_FIELD(p, offset, value) \
1199 base::NoBarrier_Store( \
1200 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
1201 reinterpret_cast<base::AtomicWord>(value));
1202
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001203#define WRITE_BARRIER(heap, object, offset, value) \
1204 heap->incremental_marking()->RecordWrite( \
1205 object, HeapObject::RawField(object, offset), value); \
1206 if (heap->InNewSpace(value)) { \
1207 heap->RecordWrite(object->address(), offset); \
1208 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001209
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001210#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
1211 if (mode == UPDATE_WRITE_BARRIER) { \
1212 heap->incremental_marking()->RecordWrite( \
1213 object, HeapObject::RawField(object, offset), value); \
1214 if (heap->InNewSpace(value)) { \
1215 heap->RecordWrite(object->address(), offset); \
1216 } \
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 }
1218
Steve Block44f0eee2011-05-26 01:26:41 +01001219#ifndef V8_TARGET_ARCH_MIPS
1220 #define READ_DOUBLE_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001221 (*reinterpret_cast<const double*>(FIELD_ADDR_CONST(p, offset)))
Steve Block44f0eee2011-05-26 01:26:41 +01001222#else // V8_TARGET_ARCH_MIPS
1223 // Prevent gcc from using load-double (mips ldc1) on (possibly)
1224 // non-64-bit aligned HeapNumber::value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001225 static inline double read_double_field(const void* p, int offset) {
Steve Block44f0eee2011-05-26 01:26:41 +01001226 union conversion {
1227 double d;
1228 uint32_t u[2];
1229 } c;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230 c.u[0] = (*reinterpret_cast<const uint32_t*>(
1231 FIELD_ADDR_CONST(p, offset)));
1232 c.u[1] = (*reinterpret_cast<const uint32_t*>(
1233 FIELD_ADDR_CONST(p, offset + 4)));
Steve Block44f0eee2011-05-26 01:26:41 +01001234 return c.d;
1235 }
1236 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
1237#endif // V8_TARGET_ARCH_MIPS
Steve Blocka7e24c12009-10-30 11:49:00 +00001238
Steve Block44f0eee2011-05-26 01:26:41 +01001239#ifndef V8_TARGET_ARCH_MIPS
1240 #define WRITE_DOUBLE_FIELD(p, offset, value) \
1241 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
1242#else // V8_TARGET_ARCH_MIPS
1243 // Prevent gcc from using store-double (mips sdc1) on (possibly)
1244 // non-64-bit aligned HeapNumber::value.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001245 static inline void write_double_field(void* p, int offset,
Steve Block44f0eee2011-05-26 01:26:41 +01001246 double value) {
1247 union conversion {
1248 double d;
1249 uint32_t u[2];
1250 } c;
1251 c.d = value;
1252 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
1253 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
1254 }
1255 #define WRITE_DOUBLE_FIELD(p, offset, value) \
1256 write_double_field(p, offset, value)
1257#endif // V8_TARGET_ARCH_MIPS
1258
Steve Blocka7e24c12009-10-30 11:49:00 +00001259
1260#define READ_INT_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 (*reinterpret_cast<const int*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001262
1263#define WRITE_INT_FIELD(p, offset, value) \
1264 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
1265
1266#define READ_INTPTR_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 (*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001268
1269#define WRITE_INTPTR_FIELD(p, offset, value) \
1270 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
1271
1272#define READ_UINT32_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 (*reinterpret_cast<const uint32_t*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001274
1275#define WRITE_UINT32_FIELD(p, offset, value) \
1276 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
1277
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001278#define READ_INT32_FIELD(p, offset) \
1279 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
1280
1281#define WRITE_INT32_FIELD(p, offset, value) \
1282 (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
1283
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001284#define READ_INT64_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001286
1287#define WRITE_INT64_FIELD(p, offset, value) \
1288 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
1289
Steve Blocka7e24c12009-10-30 11:49:00 +00001290#define READ_SHORT_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001292
1293#define WRITE_SHORT_FIELD(p, offset, value) \
1294 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
1295
1296#define READ_BYTE_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
1298
1299#define NOBARRIER_READ_BYTE_FIELD(p, offset) \
1300 static_cast<byte>(base::NoBarrier_Load( \
1301 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset))))
Steve Blocka7e24c12009-10-30 11:49:00 +00001302
1303#define WRITE_BYTE_FIELD(p, offset, value) \
1304 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
1305
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306#define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \
1307 base::NoBarrier_Store( \
1308 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
1309 static_cast<base::Atomic8>(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001310
1311Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312 return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset));
Steve Blocka7e24c12009-10-30 11:49:00 +00001313}
1314
1315
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316int Smi::value() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001317 return Internals::SmiValue(this);
1318}
1319
1320
1321Smi* Smi::FromInt(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322 DCHECK(Smi::IsValid(value));
1323 return reinterpret_cast<Smi*>(Internals::IntToSmi(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001324}
1325
1326
1327Smi* Smi::FromIntptr(intptr_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 DCHECK(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +00001329 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
1330 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001331}
1332
1333
Steve Blocka7e24c12009-10-30 11:49:00 +00001334bool Smi::IsValid(intptr_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 bool result = Internals::IsValidSmi(value);
1336 DCHECK_EQ(result, value >= kMinValue && value <= kMaxValue);
Steve Blocka7e24c12009-10-30 11:49:00 +00001337 return result;
1338}
1339
1340
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341MapWord MapWord::FromMap(const Map* map) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 return MapWord(reinterpret_cast<uintptr_t>(map));
1343}
1344
1345
1346Map* MapWord::ToMap() {
1347 return reinterpret_cast<Map*>(value_);
1348}
1349
1350
1351bool MapWord::IsForwardingAddress() {
1352 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1353}
1354
1355
1356MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1357 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1358 return MapWord(reinterpret_cast<uintptr_t>(raw));
1359}
1360
1361
1362HeapObject* MapWord::ToForwardingAddress() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001363 DCHECK(IsForwardingAddress());
Steve Blocka7e24c12009-10-30 11:49:00 +00001364 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1365}
1366
1367
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368#ifdef VERIFY_HEAP
Steve Blocka7e24c12009-10-30 11:49:00 +00001369void HeapObject::VerifyObjectField(int offset) {
1370 VerifyPointer(READ_FIELD(this, offset));
1371}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001372
1373void HeapObject::VerifySmiField(int offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 CHECK(READ_FIELD(this, offset)->IsSmi());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001375}
Steve Blocka7e24c12009-10-30 11:49:00 +00001376#endif
1377
1378
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379Heap* HeapObject::GetHeap() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001380 Heap* heap =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 MemoryChunk::FromAddress(reinterpret_cast<const byte*>(this))->heap();
1382 SLOW_DCHECK(heap != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001383 return heap;
Steve Block44f0eee2011-05-26 01:26:41 +01001384}
1385
1386
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387Isolate* HeapObject::GetIsolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001388 return GetHeap()->isolate();
1389}
1390
1391
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392Map* HeapObject::map() const {
1393#ifdef DEBUG
1394 // Clear mark potentially added by PathTracer.
1395 uintptr_t raw_value =
1396 map_word().ToRawValue() & ~static_cast<uintptr_t>(PathTracer::kMarkTag);
1397 return MapWord::FromRawValue(raw_value).ToMap();
1398#else
Steve Blocka7e24c12009-10-30 11:49:00 +00001399 return map_word().ToMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001401}
1402
1403
1404void HeapObject::set_map(Map* value) {
1405 set_map_word(MapWord::FromMap(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001406 if (value != NULL) {
1407 // TODO(1600) We are passing NULL as a slot because maps can never be on
1408 // evacuation candidate.
1409 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1410 }
1411}
1412
1413
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001414Map* HeapObject::synchronized_map() {
1415 return synchronized_map_word().ToMap();
1416}
1417
1418
1419void HeapObject::synchronized_set_map(Map* value) {
1420 synchronized_set_map_word(MapWord::FromMap(value));
1421 if (value != NULL) {
1422 // TODO(1600) We are passing NULL as a slot because maps can never be on
1423 // evacuation candidate.
1424 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1425 }
1426}
1427
1428
1429void HeapObject::synchronized_set_map_no_write_barrier(Map* value) {
1430 synchronized_set_map_word(MapWord::FromMap(value));
1431}
1432
1433
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001434// Unsafe accessor omitting write barrier.
1435void HeapObject::set_map_no_write_barrier(Map* value) {
1436 set_map_word(MapWord::FromMap(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001437}
1438
1439
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001440MapWord HeapObject::map_word() const {
1441 return MapWord(
1442 reinterpret_cast<uintptr_t>(NOBARRIER_READ_FIELD(this, kMapOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001443}
1444
1445
1446void HeapObject::set_map_word(MapWord map_word) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001447 NOBARRIER_WRITE_FIELD(
1448 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1449}
1450
1451
1452MapWord HeapObject::synchronized_map_word() const {
1453 return MapWord(
1454 reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset)));
1455}
1456
1457
1458void HeapObject::synchronized_set_map_word(MapWord map_word) {
1459 RELEASE_WRITE_FIELD(
1460 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001461}
1462
1463
1464HeapObject* HeapObject::FromAddress(Address address) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 DCHECK_TAG_ALIGNED(address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1467}
1468
1469
1470Address HeapObject::address() {
1471 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1472}
1473
1474
1475int HeapObject::Size() {
1476 return SizeFromMap(map());
1477}
1478
1479
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480bool HeapObject::MayContainRawValues() {
1481 InstanceType type = map()->instance_type();
1482 if (type <= LAST_NAME_TYPE) {
1483 if (type == SYMBOL_TYPE) {
1484 return false;
1485 }
1486 DCHECK(type < FIRST_NONSTRING_TYPE);
1487 // There are four string representations: sequential strings, external
1488 // strings, cons strings, and sliced strings.
1489 // Only the former two contain raw values and no heap pointers (besides the
1490 // map-word).
1491 return ((type & kIsIndirectStringMask) != kIsIndirectStringTag);
1492 }
1493 // The ConstantPoolArray contains heap pointers, but also raw values.
1494 if (type == CONSTANT_POOL_ARRAY_TYPE) return true;
1495 return (type <= LAST_DATA_TYPE);
1496}
1497
1498
Steve Blocka7e24c12009-10-30 11:49:00 +00001499void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1500 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1501 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1502}
1503
1504
1505void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1506 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1507}
1508
1509
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510void HeapObject::IterateNextCodeLink(ObjectVisitor* v, int offset) {
1511 v->VisitNextCodeLink(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1512}
1513
1514
1515double HeapNumber::value() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001516 return READ_DOUBLE_FIELD(this, kValueOffset);
1517}
1518
1519
1520void HeapNumber::set_value(double value) {
1521 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1522}
1523
1524
Steve Block6ded16b2010-05-10 14:33:55 +01001525int HeapNumber::get_exponent() {
1526 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1527 kExponentShift) - kExponentBias;
1528}
1529
1530
1531int HeapNumber::get_sign() {
1532 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1533}
1534
1535
Steve Blocka7e24c12009-10-30 11:49:00 +00001536ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1537
1538
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001539Object** FixedArray::GetFirstElementAddress() {
1540 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1541}
1542
1543
1544bool FixedArray::ContainsOnlySmisOrHoles() {
1545 Object* the_hole = GetHeap()->the_hole_value();
1546 Object** current = GetFirstElementAddress();
1547 for (int i = 0; i < length(); ++i) {
1548 Object* candidate = *current++;
1549 if (!candidate->IsSmi() && candidate != the_hole) return false;
1550 }
1551 return true;
1552}
1553
1554
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555FixedArrayBase* JSObject::elements() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001556 Object* array = READ_FIELD(this, kElementsOffset);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001557 return static_cast<FixedArrayBase*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001558}
1559
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560
1561void JSObject::ValidateElements(Handle<JSObject> object) {
1562#ifdef ENABLE_SLOW_DCHECKS
1563 if (FLAG_enable_slow_asserts) {
1564 ElementsAccessor* accessor = object->GetElementsAccessor();
1565 accessor->Validate(object);
1566 }
1567#endif
1568}
1569
1570
1571void AllocationSite::Initialize() {
1572 set_transition_info(Smi::FromInt(0));
1573 SetElementsKind(GetInitialFastElementsKind());
1574 set_nested_site(Smi::FromInt(0));
1575 set_pretenure_data(Smi::FromInt(0));
1576 set_pretenure_create_count(Smi::FromInt(0));
1577 set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1578 SKIP_WRITE_BARRIER);
1579}
1580
1581
1582void AllocationSite::MarkZombie() {
1583 DCHECK(!IsZombie());
1584 Initialize();
1585 set_pretenure_decision(kZombie);
1586}
1587
1588
1589// Heuristic: We only need to create allocation site info if the boilerplate
1590// elements kind is the initial elements kind.
1591AllocationSiteMode AllocationSite::GetMode(
1592 ElementsKind boilerplate_elements_kind) {
1593 if (FLAG_pretenuring_call_new ||
1594 IsFastSmiElementsKind(boilerplate_elements_kind)) {
1595 return TRACK_ALLOCATION_SITE;
1596 }
1597
1598 return DONT_TRACK_ALLOCATION_SITE;
1599}
1600
1601
1602AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
1603 ElementsKind to) {
1604 if (FLAG_pretenuring_call_new ||
1605 (IsFastSmiElementsKind(from) &&
1606 IsMoreGeneralElementsKindTransition(from, to))) {
1607 return TRACK_ALLOCATION_SITE;
1608 }
1609
1610 return DONT_TRACK_ALLOCATION_SITE;
1611}
1612
1613
1614inline bool AllocationSite::CanTrack(InstanceType type) {
1615 if (FLAG_allocation_site_pretenuring) {
1616 return type == JS_ARRAY_TYPE ||
1617 type == JS_OBJECT_TYPE ||
1618 type < FIRST_NONSTRING_TYPE;
1619 }
1620 return type == JS_ARRAY_TYPE;
1621}
1622
1623
1624inline DependentCode::DependencyGroup AllocationSite::ToDependencyGroup(
1625 Reason reason) {
1626 switch (reason) {
1627 case TENURING:
1628 return DependentCode::kAllocationSiteTenuringChangedGroup;
1629 break;
1630 case TRANSITIONS:
1631 return DependentCode::kAllocationSiteTransitionChangedGroup;
1632 break;
1633 }
1634 UNREACHABLE();
1635 return DependentCode::kAllocationSiteTransitionChangedGroup;
1636}
1637
1638
1639inline void AllocationSite::set_memento_found_count(int count) {
1640 int value = pretenure_data()->value();
1641 // Verify that we can count more mementos than we can possibly find in one
1642 // new space collection.
1643 DCHECK((GetHeap()->MaxSemiSpaceSize() /
1644 (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
1645 AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
1646 DCHECK(count < MementoFoundCountBits::kMax);
1647 set_pretenure_data(
1648 Smi::FromInt(MementoFoundCountBits::update(value, count)),
1649 SKIP_WRITE_BARRIER);
1650}
1651
1652inline bool AllocationSite::IncrementMementoFoundCount() {
1653 if (IsZombie()) return false;
1654
1655 int value = memento_found_count();
1656 set_memento_found_count(value + 1);
1657 return memento_found_count() == kPretenureMinimumCreated;
1658}
1659
1660
1661inline void AllocationSite::IncrementMementoCreateCount() {
1662 DCHECK(FLAG_allocation_site_pretenuring);
1663 int value = memento_create_count();
1664 set_memento_create_count(value + 1);
1665}
1666
1667
1668inline bool AllocationSite::MakePretenureDecision(
1669 PretenureDecision current_decision,
1670 double ratio,
1671 bool maximum_size_scavenge) {
1672 // Here we just allow state transitions from undecided or maybe tenure
1673 // to don't tenure, maybe tenure, or tenure.
1674 if ((current_decision == kUndecided || current_decision == kMaybeTenure)) {
1675 if (ratio >= kPretenureRatio) {
1676 // We just transition into tenure state when the semi-space was at
1677 // maximum capacity.
1678 if (maximum_size_scavenge) {
1679 set_deopt_dependent_code(true);
1680 set_pretenure_decision(kTenure);
1681 // Currently we just need to deopt when we make a state transition to
1682 // tenure.
1683 return true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001684 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001685 set_pretenure_decision(kMaybeTenure);
1686 } else {
1687 set_pretenure_decision(kDontTenure);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001688 }
1689 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001690 return false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001691}
1692
1693
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001694inline bool AllocationSite::DigestPretenuringFeedback(
1695 bool maximum_size_scavenge) {
1696 bool deopt = false;
1697 int create_count = memento_create_count();
1698 int found_count = memento_found_count();
1699 bool minimum_mementos_created = create_count >= kPretenureMinimumCreated;
1700 double ratio =
1701 minimum_mementos_created || FLAG_trace_pretenuring_statistics ?
1702 static_cast<double>(found_count) / create_count : 0.0;
1703 PretenureDecision current_decision = pretenure_decision();
1704
1705 if (minimum_mementos_created) {
1706 deopt = MakePretenureDecision(
1707 current_decision, ratio, maximum_size_scavenge);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001708 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001709
1710 if (FLAG_trace_pretenuring_statistics) {
1711 PrintF(
1712 "AllocationSite(%p): (created, found, ratio) (%d, %d, %f) %s => %s\n",
1713 static_cast<void*>(this), create_count, found_count, ratio,
1714 PretenureDecisionName(current_decision),
1715 PretenureDecisionName(pretenure_decision()));
1716 }
1717
1718 // Clear feedback calculation fields until the next gc.
1719 set_memento_found_count(0);
1720 set_memento_create_count(0);
1721 return deopt;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001722}
1723
1724
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001725void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1726 JSObject::ValidateElements(object);
1727 ElementsKind elements_kind = object->map()->elements_kind();
1728 if (!IsFastObjectElementsKind(elements_kind)) {
1729 if (IsFastHoleyElementsKind(elements_kind)) {
1730 TransitionElementsKind(object, FAST_HOLEY_ELEMENTS);
1731 } else {
1732 TransitionElementsKind(object, FAST_ELEMENTS);
1733 }
1734 }
1735}
1736
1737
1738void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1739 Object** objects,
1740 uint32_t count,
1741 EnsureElementsMode mode) {
1742 ElementsKind current_kind = object->map()->elements_kind();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001743 ElementsKind target_kind = current_kind;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001744 {
1745 DisallowHeapAllocation no_allocation;
1746 DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1747 bool is_holey = IsFastHoleyElementsKind(current_kind);
1748 if (current_kind == FAST_HOLEY_ELEMENTS) return;
1749 Heap* heap = object->GetHeap();
1750 Object* the_hole = heap->the_hole_value();
1751 for (uint32_t i = 0; i < count; ++i) {
1752 Object* current = *objects++;
1753 if (current == the_hole) {
1754 is_holey = true;
1755 target_kind = GetHoleyElementsKind(target_kind);
1756 } else if (!current->IsSmi()) {
1757 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1758 if (IsFastSmiElementsKind(target_kind)) {
1759 if (is_holey) {
1760 target_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
1761 } else {
1762 target_kind = FAST_DOUBLE_ELEMENTS;
1763 }
1764 }
1765 } else if (is_holey) {
1766 target_kind = FAST_HOLEY_ELEMENTS;
1767 break;
1768 } else {
1769 target_kind = FAST_ELEMENTS;
1770 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001771 }
1772 }
1773 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001774 if (target_kind != current_kind) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 TransitionElementsKind(object, target_kind);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001776 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001777}
1778
1779
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001780void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1781 Handle<FixedArrayBase> elements,
1782 uint32_t length,
1783 EnsureElementsMode mode) {
1784 Heap* heap = object->GetHeap();
1785 if (elements->map() != heap->fixed_double_array_map()) {
1786 DCHECK(elements->map() == heap->fixed_array_map() ||
1787 elements->map() == heap->fixed_cow_array_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001788 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1789 mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1790 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001791 Object** objects =
1792 Handle<FixedArray>::cast(elements)->GetFirstElementAddress();
1793 EnsureCanContainElements(object, objects, length, mode);
1794 return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001795 }
1796
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001797 DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1798 if (object->GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) {
1799 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS);
1800 } else if (object->GetElementsKind() == FAST_SMI_ELEMENTS) {
1801 Handle<FixedDoubleArray> double_array =
1802 Handle<FixedDoubleArray>::cast(elements);
1803 for (uint32_t i = 0; i < length; ++i) {
1804 if (double_array->is_the_hole(i)) {
1805 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS);
1806 return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001807 }
1808 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001809 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001810 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001811}
1812
1813
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001814void JSObject::SetMapAndElements(Handle<JSObject> object,
1815 Handle<Map> new_map,
1816 Handle<FixedArrayBase> value) {
1817 JSObject::MigrateToMap(object, new_map);
1818 DCHECK((object->map()->has_fast_smi_or_object_elements() ||
1819 (*value == object->GetHeap()->empty_fixed_array())) ==
1820 (value->map() == object->GetHeap()->fixed_array_map() ||
1821 value->map() == object->GetHeap()->fixed_cow_array_map()));
1822 DCHECK((*value == object->GetHeap()->empty_fixed_array()) ||
1823 (object->map()->has_fast_double_elements() ==
1824 value->IsFixedDoubleArray()));
1825 object->set_elements(*value);
1826}
1827
1828
1829void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001830 WRITE_FIELD(this, kElementsOffset, value);
1831 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1832}
1833
Steve Blocka7e24c12009-10-30 11:49:00 +00001834
1835void JSObject::initialize_properties() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001836 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
Steve Block44f0eee2011-05-26 01:26:41 +01001837 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001838}
1839
1840
1841void JSObject::initialize_elements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001842 FixedArrayBase* elements = map()->GetInitialElements();
1843 WRITE_FIELD(this, kElementsOffset, elements);
Steve Blocka7e24c12009-10-30 11:49:00 +00001844}
1845
1846
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001847Handle<String> Map::ExpectedTransitionKey(Handle<Map> map) {
1848 DisallowHeapAllocation no_gc;
1849 if (!map->HasTransitionArray()) return Handle<String>::null();
1850 TransitionArray* transitions = map->transitions();
1851 if (!transitions->IsSimpleTransition()) return Handle<String>::null();
1852 int transition = TransitionArray::kSimpleTransitionIndex;
1853 PropertyDetails details = transitions->GetTargetDetails(transition);
1854 Name* name = transitions->GetKey(transition);
1855 if (details.type() != FIELD) return Handle<String>::null();
1856 if (details.attributes() != NONE) return Handle<String>::null();
1857 if (!name->IsString()) return Handle<String>::null();
1858 return Handle<String>(String::cast(name));
1859}
1860
1861
1862Handle<Map> Map::ExpectedTransitionTarget(Handle<Map> map) {
1863 DCHECK(!ExpectedTransitionKey(map).is_null());
1864 return Handle<Map>(map->transitions()->GetTarget(
1865 TransitionArray::kSimpleTransitionIndex));
1866}
1867
1868
1869Handle<Map> Map::FindTransitionToField(Handle<Map> map, Handle<Name> key) {
1870 DisallowHeapAllocation no_allocation;
1871 if (!map->HasTransitionArray()) return Handle<Map>::null();
1872 TransitionArray* transitions = map->transitions();
1873 int transition = transitions->Search(*key);
1874 if (transition == TransitionArray::kNotFound) return Handle<Map>::null();
1875 PropertyDetails target_details = transitions->GetTargetDetails(transition);
1876 if (target_details.type() != FIELD) return Handle<Map>::null();
1877 if (target_details.attributes() != NONE) return Handle<Map>::null();
1878 return Handle<Map>(transitions->GetTarget(transition));
Steve Block8defd9f2010-07-08 12:39:36 +01001879}
1880
1881
Steve Blocka7e24c12009-10-30 11:49:00 +00001882ACCESSORS(Oddball, to_string, String, kToStringOffset)
1883ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1884
1885
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001886byte Oddball::kind() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001887 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
Steve Block44f0eee2011-05-26 01:26:41 +01001888}
1889
1890
1891void Oddball::set_kind(byte value) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001892 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
Steve Block44f0eee2011-05-26 01:26:41 +01001893}
1894
1895
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001896Object* Cell::value() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001897 return READ_FIELD(this, kValueOffset);
1898}
1899
1900
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001901void Cell::set_value(Object* val, WriteBarrierMode ignored) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001902 // The write barrier is not used for global property cells.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001903 DCHECK(!val->IsPropertyCell() && !val->IsCell());
Steve Blocka7e24c12009-10-30 11:49:00 +00001904 WRITE_FIELD(this, kValueOffset, val);
1905}
1906
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001907ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1908
1909Object* PropertyCell::type_raw() const {
1910 return READ_FIELD(this, kTypeOffset);
1911}
1912
1913
1914void PropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
1915 WRITE_FIELD(this, kTypeOffset, val);
1916}
1917
Steve Blocka7e24c12009-10-30 11:49:00 +00001918
1919int JSObject::GetHeaderSize() {
1920 InstanceType type = map()->instance_type();
1921 // Check for the most common kind of JavaScript object before
1922 // falling into the generic switch. This speeds up the internal
1923 // field operations considerably on average.
1924 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1925 switch (type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001926 case JS_GENERATOR_OBJECT_TYPE:
1927 return JSGeneratorObject::kSize;
1928 case JS_MODULE_TYPE:
1929 return JSModule::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001930 case JS_GLOBAL_PROXY_TYPE:
1931 return JSGlobalProxy::kSize;
1932 case JS_GLOBAL_OBJECT_TYPE:
1933 return JSGlobalObject::kSize;
1934 case JS_BUILTINS_OBJECT_TYPE:
1935 return JSBuiltinsObject::kSize;
1936 case JS_FUNCTION_TYPE:
1937 return JSFunction::kSize;
1938 case JS_VALUE_TYPE:
1939 return JSValue::kSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001940 case JS_DATE_TYPE:
1941 return JSDate::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001942 case JS_ARRAY_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001943 return JSArray::kSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001944 case JS_ARRAY_BUFFER_TYPE:
1945 return JSArrayBuffer::kSize;
1946 case JS_TYPED_ARRAY_TYPE:
1947 return JSTypedArray::kSize;
1948 case JS_DATA_VIEW_TYPE:
1949 return JSDataView::kSize;
1950 case JS_SET_TYPE:
1951 return JSSet::kSize;
1952 case JS_MAP_TYPE:
1953 return JSMap::kSize;
1954 case JS_SET_ITERATOR_TYPE:
1955 return JSSetIterator::kSize;
1956 case JS_MAP_ITERATOR_TYPE:
1957 return JSMapIterator::kSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001958 case JS_WEAK_MAP_TYPE:
1959 return JSWeakMap::kSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001960 case JS_WEAK_SET_TYPE:
1961 return JSWeakSet::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001962 case JS_REGEXP_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001963 return JSRegExp::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001964 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1965 return JSObject::kHeaderSize;
Steve Block1e0659c2011-05-24 12:43:12 +01001966 case JS_MESSAGE_OBJECT_TYPE:
1967 return JSMessageObject::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001968 default:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001969 // TODO(jkummerow): Re-enable this. Blink currently hits this
1970 // from its CustomElementConstructorBuilder.
1971 // UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +00001972 return 0;
1973 }
1974}
1975
1976
1977int JSObject::GetInternalFieldCount() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001978 DCHECK(1 << kPointerSizeLog2 == kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00001979 // Make sure to adjust for the number of in-object properties. These
1980 // properties do contribute to the size, but are not internal fields.
1981 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1982 map()->inobject_properties();
1983}
1984
1985
Steve Block44f0eee2011-05-26 01:26:41 +01001986int JSObject::GetInternalFieldOffset(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001987 DCHECK(index < GetInternalFieldCount() && index >= 0);
Steve Block44f0eee2011-05-26 01:26:41 +01001988 return GetHeaderSize() + (kPointerSize * index);
1989}
1990
1991
Steve Blocka7e24c12009-10-30 11:49:00 +00001992Object* JSObject::GetInternalField(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001993 DCHECK(index < GetInternalFieldCount() && index >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001994 // Internal objects do follow immediately after the header, whereas in-object
1995 // properties are at the end of the object. Therefore there is no need
1996 // to adjust the index here.
1997 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1998}
1999
2000
2001void JSObject::SetInternalField(int index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002002 DCHECK(index < GetInternalFieldCount() && index >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002003 // Internal objects do follow immediately after the header, whereas in-object
2004 // properties are at the end of the object. Therefore there is no need
2005 // to adjust the index here.
2006 int offset = GetHeaderSize() + (kPointerSize * index);
2007 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002008 WRITE_BARRIER(GetHeap(), this, offset, value);
2009}
2010
2011
2012void JSObject::SetInternalField(int index, Smi* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002013 DCHECK(index < GetInternalFieldCount() && index >= 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002014 // Internal objects do follow immediately after the header, whereas in-object
2015 // properties are at the end of the object. Therefore there is no need
2016 // to adjust the index here.
2017 int offset = GetHeaderSize() + (kPointerSize * index);
2018 WRITE_FIELD(this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002019}
2020
2021
2022// Access fast-case object properties at index. The use of these routines
2023// is needed to correctly distinguish between properties stored in-object and
2024// properties stored in the properties array.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002025Object* JSObject::RawFastPropertyAt(FieldIndex index) {
2026 if (index.is_inobject()) {
2027 return READ_FIELD(this, index.offset());
Steve Blocka7e24c12009-10-30 11:49:00 +00002028 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002029 return properties()->get(index.outobject_array_index());
Steve Blocka7e24c12009-10-30 11:49:00 +00002030 }
2031}
2032
2033
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002034void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
2035 if (index.is_inobject()) {
2036 int offset = index.offset();
Steve Blocka7e24c12009-10-30 11:49:00 +00002037 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002038 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002039 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002040 properties()->set(index.outobject_array_index(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002041 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002042}
2043
2044
Steve Block44f0eee2011-05-26 01:26:41 +01002045int JSObject::GetInObjectPropertyOffset(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002046 return map()->GetInObjectPropertyOffset(index);
Steve Block44f0eee2011-05-26 01:26:41 +01002047}
2048
2049
Steve Blocka7e24c12009-10-30 11:49:00 +00002050Object* JSObject::InObjectPropertyAt(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002051 int offset = GetInObjectPropertyOffset(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002052 return READ_FIELD(this, offset);
2053}
2054
2055
2056Object* JSObject::InObjectPropertyAtPut(int index,
2057 Object* value,
2058 WriteBarrierMode mode) {
2059 // Adjust for the number of properties stored in the object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002060 int offset = GetInObjectPropertyOffset(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002061 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002062 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002063 return value;
2064}
2065
2066
2067
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002068void JSObject::InitializeBody(Map* map,
2069 Object* pre_allocated_value,
2070 Object* filler_value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071 DCHECK(!filler_value->IsHeapObject() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002072 !GetHeap()->InNewSpace(filler_value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002073 DCHECK(!pre_allocated_value->IsHeapObject() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002074 !GetHeap()->InNewSpace(pre_allocated_value));
2075 int size = map->instance_size();
2076 int offset = kHeaderSize;
2077 if (filler_value != pre_allocated_value) {
2078 int pre_allocated = map->pre_allocated_property_fields();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002079 DCHECK(pre_allocated * kPointerSize + kHeaderSize <= size);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002080 for (int i = 0; i < pre_allocated; i++) {
2081 WRITE_FIELD(this, offset, pre_allocated_value);
2082 offset += kPointerSize;
2083 }
2084 }
2085 while (offset < size) {
2086 WRITE_FIELD(this, offset, filler_value);
2087 offset += kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002088 }
2089}
2090
2091
Steve Block8defd9f2010-07-08 12:39:36 +01002092bool JSObject::HasFastProperties() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002093 DCHECK(properties()->IsDictionary() == map()->is_dictionary_map());
Steve Block8defd9f2010-07-08 12:39:36 +01002094 return !properties()->IsDictionary();
2095}
2096
2097
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002098bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
2099 if (unused_property_fields() != 0) return false;
2100 if (is_prototype_map()) return false;
2101 int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12;
2102 int limit = Max(minimum, inobject_properties());
2103 int external = NumberOfFields() - inobject_properties();
2104 return external > limit;
Steve Block8defd9f2010-07-08 12:39:36 +01002105}
2106
2107
Steve Blocka7e24c12009-10-30 11:49:00 +00002108void Struct::InitializeBody(int object_size) {
Steve Block44f0eee2011-05-26 01:26:41 +01002109 Object* value = GetHeap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002110 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
2111 WRITE_FIELD(this, offset, value);
2112 }
2113}
2114
2115
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002116bool Object::ToArrayIndex(uint32_t* index) {
2117 if (IsSmi()) {
2118 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002119 if (value < 0) return false;
2120 *index = value;
2121 return true;
2122 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002123 if (IsHeapNumber()) {
2124 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 uint32_t uint_value = static_cast<uint32_t>(value);
2126 if (value == static_cast<double>(uint_value)) {
2127 *index = uint_value;
2128 return true;
2129 }
2130 }
2131 return false;
2132}
2133
2134
2135bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
2136 if (!this->IsJSValue()) return false;
2137
2138 JSValue* js_value = JSValue::cast(this);
2139 if (!js_value->value()->IsString()) return false;
2140
2141 String* str = String::cast(js_value->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002142 if (index >= static_cast<uint32_t>(str->length())) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00002143
2144 return true;
2145}
2146
2147
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002148void Object::VerifyApiCallResultType() {
2149#if ENABLE_EXTRA_CHECKS
2150 if (!(IsSmi() ||
2151 IsString() ||
2152 IsSymbol() ||
2153 IsSpecObject() ||
2154 IsHeapNumber() ||
2155 IsUndefined() ||
2156 IsTrue() ||
2157 IsFalse() ||
2158 IsNull())) {
2159 FATAL("API call returned invalid object");
2160 }
2161#endif // ENABLE_EXTRA_CHECKS
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002162}
2163
2164
Steve Blocka7e24c12009-10-30 11:49:00 +00002165Object* FixedArray::get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002166 SLOW_DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002167 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
2168}
2169
2170
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002171Handle<Object> FixedArray::get(Handle<FixedArray> array, int index) {
2172 return handle(array->get(index), array->GetIsolate());
2173}
2174
2175
2176bool FixedArray::is_the_hole(int index) {
2177 return get(index) == GetHeap()->the_hole_value();
2178}
2179
2180
Steve Blocka7e24c12009-10-30 11:49:00 +00002181void FixedArray::set(int index, Smi* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002182 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2183 DCHECK(index >= 0 && index < this->length());
2184 DCHECK(reinterpret_cast<Object*>(value)->IsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002185 int offset = kHeaderSize + index * kPointerSize;
2186 WRITE_FIELD(this, offset, value);
2187}
2188
2189
2190void FixedArray::set(int index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002191 DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
2192 DCHECK_EQ(FIXED_ARRAY_TYPE, map()->instance_type());
2193 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002194 int offset = kHeaderSize + index * kPointerSize;
2195 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002196 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002197}
2198
2199
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002200inline bool FixedDoubleArray::is_the_hole_nan(double value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002201 return bit_cast<uint64_t, double>(value) == kHoleNanInt64;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002202}
2203
2204
2205inline double FixedDoubleArray::hole_nan_as_double() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002206 return bit_cast<double, uint64_t>(kHoleNanInt64);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002207}
2208
2209
2210inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002211 DCHECK(bit_cast<uint64_t>(base::OS::nan_value()) != kHoleNanInt64);
2212 DCHECK((bit_cast<uint64_t>(base::OS::nan_value()) >> 32) != kHoleNanUpper32);
2213 return base::OS::nan_value();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002214}
2215
2216
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002217double FixedDoubleArray::get_scalar(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002218 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2219 map() != GetHeap()->fixed_array_map());
2220 DCHECK(index >= 0 && index < this->length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002221 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002222 DCHECK(!is_the_hole_nan(result));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002223 return result;
2224}
2225
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002226int64_t FixedDoubleArray::get_representation(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002227 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2228 map() != GetHeap()->fixed_array_map());
2229 DCHECK(index >= 0 && index < this->length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002230 return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
2231}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002232
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002233
2234Handle<Object> FixedDoubleArray::get(Handle<FixedDoubleArray> array,
2235 int index) {
2236 if (array->is_the_hole(index)) {
2237 return array->GetIsolate()->factory()->the_hole_value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002238 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002239 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002240 }
2241}
2242
2243
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002244void FixedDoubleArray::set(int index, double value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002245 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2246 map() != GetHeap()->fixed_array_map());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002247 int offset = kHeaderSize + index * kDoubleSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248 if (std::isnan(value)) value = canonical_not_the_hole_nan_as_double();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002249 WRITE_DOUBLE_FIELD(this, offset, value);
2250}
2251
2252
2253void FixedDoubleArray::set_the_hole(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002254 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2255 map() != GetHeap()->fixed_array_map());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002256 int offset = kHeaderSize + index * kDoubleSize;
2257 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
2258}
2259
2260
2261bool FixedDoubleArray::is_the_hole(int index) {
2262 int offset = kHeaderSize + index * kDoubleSize;
2263 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
2264}
2265
2266
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002267double* FixedDoubleArray::data_start() {
2268 return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
2269}
2270
2271
2272void FixedDoubleArray::FillWithHoles(int from, int to) {
2273 for (int i = from; i < to; i++) {
2274 set_the_hole(i);
2275 }
2276}
2277
2278
2279void ConstantPoolArray::NumberOfEntries::increment(Type type) {
2280 DCHECK(type < NUMBER_OF_TYPES);
2281 element_counts_[type]++;
2282}
2283
2284
2285int ConstantPoolArray::NumberOfEntries::equals(
2286 const ConstantPoolArray::NumberOfEntries& other) const {
2287 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2288 if (element_counts_[i] != other.element_counts_[i]) return false;
2289 }
2290 return true;
2291}
2292
2293
2294bool ConstantPoolArray::NumberOfEntries::is_empty() const {
2295 return total_count() == 0;
2296}
2297
2298
2299int ConstantPoolArray::NumberOfEntries::count_of(Type type) const {
2300 DCHECK(type < NUMBER_OF_TYPES);
2301 return element_counts_[type];
2302}
2303
2304
2305int ConstantPoolArray::NumberOfEntries::base_of(Type type) const {
2306 int base = 0;
2307 DCHECK(type < NUMBER_OF_TYPES);
2308 for (int i = 0; i < type; i++) {
2309 base += element_counts_[i];
2310 }
2311 return base;
2312}
2313
2314
2315int ConstantPoolArray::NumberOfEntries::total_count() const {
2316 int count = 0;
2317 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2318 count += element_counts_[i];
2319 }
2320 return count;
2321}
2322
2323
2324int ConstantPoolArray::NumberOfEntries::are_in_range(int min, int max) const {
2325 for (int i = FIRST_TYPE; i < NUMBER_OF_TYPES; i++) {
2326 if (element_counts_[i] < min || element_counts_[i] > max) {
2327 return false;
2328 }
2329 }
2330 return true;
2331}
2332
2333
2334int ConstantPoolArray::Iterator::next_index() {
2335 DCHECK(!is_finished());
2336 int ret = next_index_++;
2337 update_section();
2338 return ret;
2339}
2340
2341
2342bool ConstantPoolArray::Iterator::is_finished() {
2343 return next_index_ > array_->last_index(type_, final_section_);
2344}
2345
2346
2347void ConstantPoolArray::Iterator::update_section() {
2348 if (next_index_ > array_->last_index(type_, current_section_) &&
2349 current_section_ != final_section_) {
2350 DCHECK(final_section_ == EXTENDED_SECTION);
2351 current_section_ = EXTENDED_SECTION;
2352 next_index_ = array_->first_index(type_, EXTENDED_SECTION);
2353 }
2354}
2355
2356
2357bool ConstantPoolArray::is_extended_layout() {
2358 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2359 return IsExtendedField::decode(small_layout_1);
2360}
2361
2362
2363ConstantPoolArray::LayoutSection ConstantPoolArray::final_section() {
2364 return is_extended_layout() ? EXTENDED_SECTION : SMALL_SECTION;
2365}
2366
2367
2368int ConstantPoolArray::first_extended_section_index() {
2369 DCHECK(is_extended_layout());
2370 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2371 return TotalCountField::decode(small_layout_2);
2372}
2373
2374
2375int ConstantPoolArray::get_extended_section_header_offset() {
2376 return RoundUp(SizeFor(NumberOfEntries(this, SMALL_SECTION)), kInt64Size);
2377}
2378
2379
2380ConstantPoolArray::WeakObjectState ConstantPoolArray::get_weak_object_state() {
2381 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2382 return WeakObjectStateField::decode(small_layout_2);
2383}
2384
2385
2386void ConstantPoolArray::set_weak_object_state(
2387 ConstantPoolArray::WeakObjectState state) {
2388 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2389 small_layout_2 = WeakObjectStateField::update(small_layout_2, state);
2390 WRITE_INT32_FIELD(this, kSmallLayout2Offset, small_layout_2);
2391}
2392
2393
2394int ConstantPoolArray::first_index(Type type, LayoutSection section) {
2395 int index = 0;
2396 if (section == EXTENDED_SECTION) {
2397 DCHECK(is_extended_layout());
2398 index += first_extended_section_index();
2399 }
2400
2401 for (Type type_iter = FIRST_TYPE; type_iter < type;
2402 type_iter = next_type(type_iter)) {
2403 index += number_of_entries(type_iter, section);
2404 }
2405
2406 return index;
2407}
2408
2409
2410int ConstantPoolArray::last_index(Type type, LayoutSection section) {
2411 return first_index(type, section) + number_of_entries(type, section) - 1;
2412}
2413
2414
2415int ConstantPoolArray::number_of_entries(Type type, LayoutSection section) {
2416 if (section == SMALL_SECTION) {
2417 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2418 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2419 switch (type) {
2420 case INT64:
2421 return Int64CountField::decode(small_layout_1);
2422 case CODE_PTR:
2423 return CodePtrCountField::decode(small_layout_1);
2424 case HEAP_PTR:
2425 return HeapPtrCountField::decode(small_layout_1);
2426 case INT32:
2427 return Int32CountField::decode(small_layout_2);
2428 default:
2429 UNREACHABLE();
2430 return 0;
2431 }
2432 } else {
2433 DCHECK(section == EXTENDED_SECTION && is_extended_layout());
2434 int offset = get_extended_section_header_offset();
2435 switch (type) {
2436 case INT64:
2437 offset += kExtendedInt64CountOffset;
2438 break;
2439 case CODE_PTR:
2440 offset += kExtendedCodePtrCountOffset;
2441 break;
2442 case HEAP_PTR:
2443 offset += kExtendedHeapPtrCountOffset;
2444 break;
2445 case INT32:
2446 offset += kExtendedInt32CountOffset;
2447 break;
2448 default:
2449 UNREACHABLE();
2450 }
2451 return READ_INT_FIELD(this, offset);
2452 }
2453}
2454
2455
2456bool ConstantPoolArray::offset_is_type(int offset, Type type) {
2457 return (offset >= OffsetOfElementAt(first_index(type, SMALL_SECTION)) &&
2458 offset <= OffsetOfElementAt(last_index(type, SMALL_SECTION))) ||
2459 (is_extended_layout() &&
2460 offset >= OffsetOfElementAt(first_index(type, EXTENDED_SECTION)) &&
2461 offset <= OffsetOfElementAt(last_index(type, EXTENDED_SECTION)));
2462}
2463
2464
2465ConstantPoolArray::Type ConstantPoolArray::get_type(int index) {
2466 LayoutSection section;
2467 if (is_extended_layout() && index >= first_extended_section_index()) {
2468 section = EXTENDED_SECTION;
2469 } else {
2470 section = SMALL_SECTION;
2471 }
2472
2473 Type type = FIRST_TYPE;
2474 while (index > last_index(type, section)) {
2475 type = next_type(type);
2476 }
2477 DCHECK(type <= LAST_TYPE);
2478 return type;
2479}
2480
2481
2482int64_t ConstantPoolArray::get_int64_entry(int index) {
2483 DCHECK(map() == GetHeap()->constant_pool_array_map());
2484 DCHECK(get_type(index) == INT64);
2485 return READ_INT64_FIELD(this, OffsetOfElementAt(index));
2486}
2487
2488
2489double ConstantPoolArray::get_int64_entry_as_double(int index) {
2490 STATIC_ASSERT(kDoubleSize == kInt64Size);
2491 DCHECK(map() == GetHeap()->constant_pool_array_map());
2492 DCHECK(get_type(index) == INT64);
2493 return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
2494}
2495
2496
2497Address ConstantPoolArray::get_code_ptr_entry(int index) {
2498 DCHECK(map() == GetHeap()->constant_pool_array_map());
2499 DCHECK(get_type(index) == CODE_PTR);
2500 return reinterpret_cast<Address>(READ_FIELD(this, OffsetOfElementAt(index)));
2501}
2502
2503
2504Object* ConstantPoolArray::get_heap_ptr_entry(int index) {
2505 DCHECK(map() == GetHeap()->constant_pool_array_map());
2506 DCHECK(get_type(index) == HEAP_PTR);
2507 return READ_FIELD(this, OffsetOfElementAt(index));
2508}
2509
2510
2511int32_t ConstantPoolArray::get_int32_entry(int index) {
2512 DCHECK(map() == GetHeap()->constant_pool_array_map());
2513 DCHECK(get_type(index) == INT32);
2514 return READ_INT32_FIELD(this, OffsetOfElementAt(index));
2515}
2516
2517
2518void ConstantPoolArray::set(int index, int64_t value) {
2519 DCHECK(map() == GetHeap()->constant_pool_array_map());
2520 DCHECK(get_type(index) == INT64);
2521 WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
2522}
2523
2524
2525void ConstantPoolArray::set(int index, double value) {
2526 STATIC_ASSERT(kDoubleSize == kInt64Size);
2527 DCHECK(map() == GetHeap()->constant_pool_array_map());
2528 DCHECK(get_type(index) == INT64);
2529 WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
2530}
2531
2532
2533void ConstantPoolArray::set(int index, Address value) {
2534 DCHECK(map() == GetHeap()->constant_pool_array_map());
2535 DCHECK(get_type(index) == CODE_PTR);
2536 WRITE_FIELD(this, OffsetOfElementAt(index), reinterpret_cast<Object*>(value));
2537}
2538
2539
2540void ConstantPoolArray::set(int index, Object* value) {
2541 DCHECK(map() == GetHeap()->constant_pool_array_map());
2542 DCHECK(!GetHeap()->InNewSpace(value));
2543 DCHECK(get_type(index) == HEAP_PTR);
2544 WRITE_FIELD(this, OffsetOfElementAt(index), value);
2545 WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
2546}
2547
2548
2549void ConstantPoolArray::set(int index, int32_t value) {
2550 DCHECK(map() == GetHeap()->constant_pool_array_map());
2551 DCHECK(get_type(index) == INT32);
2552 WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value);
2553}
2554
2555
2556void ConstantPoolArray::set_at_offset(int offset, int32_t value) {
2557 DCHECK(map() == GetHeap()->constant_pool_array_map());
2558 DCHECK(offset_is_type(offset, INT32));
2559 WRITE_INT32_FIELD(this, offset, value);
2560}
2561
2562
2563void ConstantPoolArray::set_at_offset(int offset, int64_t value) {
2564 DCHECK(map() == GetHeap()->constant_pool_array_map());
2565 DCHECK(offset_is_type(offset, INT64));
2566 WRITE_INT64_FIELD(this, offset, value);
2567}
2568
2569
2570void ConstantPoolArray::set_at_offset(int offset, double value) {
2571 DCHECK(map() == GetHeap()->constant_pool_array_map());
2572 DCHECK(offset_is_type(offset, INT64));
2573 WRITE_DOUBLE_FIELD(this, offset, value);
2574}
2575
2576
2577void ConstantPoolArray::set_at_offset(int offset, Address value) {
2578 DCHECK(map() == GetHeap()->constant_pool_array_map());
2579 DCHECK(offset_is_type(offset, CODE_PTR));
2580 WRITE_FIELD(this, offset, reinterpret_cast<Object*>(value));
2581 WRITE_BARRIER(GetHeap(), this, offset, reinterpret_cast<Object*>(value));
2582}
2583
2584
2585void ConstantPoolArray::set_at_offset(int offset, Object* value) {
2586 DCHECK(map() == GetHeap()->constant_pool_array_map());
2587 DCHECK(!GetHeap()->InNewSpace(value));
2588 DCHECK(offset_is_type(offset, HEAP_PTR));
2589 WRITE_FIELD(this, offset, value);
2590 WRITE_BARRIER(GetHeap(), this, offset, value);
2591}
2592
2593
2594void ConstantPoolArray::Init(const NumberOfEntries& small) {
2595 uint32_t small_layout_1 =
2596 Int64CountField::encode(small.count_of(INT64)) |
2597 CodePtrCountField::encode(small.count_of(CODE_PTR)) |
2598 HeapPtrCountField::encode(small.count_of(HEAP_PTR)) |
2599 IsExtendedField::encode(false);
2600 uint32_t small_layout_2 =
2601 Int32CountField::encode(small.count_of(INT32)) |
2602 TotalCountField::encode(small.total_count()) |
2603 WeakObjectStateField::encode(NO_WEAK_OBJECTS);
2604 WRITE_UINT32_FIELD(this, kSmallLayout1Offset, small_layout_1);
2605 WRITE_UINT32_FIELD(this, kSmallLayout2Offset, small_layout_2);
2606 if (kHeaderSize != kFirstEntryOffset) {
2607 DCHECK(kFirstEntryOffset - kHeaderSize == kInt32Size);
2608 WRITE_UINT32_FIELD(this, kHeaderSize, 0); // Zero out header padding.
2609 }
2610}
2611
2612
2613void ConstantPoolArray::InitExtended(const NumberOfEntries& small,
2614 const NumberOfEntries& extended) {
2615 // Initialize small layout fields first.
2616 Init(small);
2617
2618 // Set is_extended_layout field.
2619 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2620 small_layout_1 = IsExtendedField::update(small_layout_1, true);
2621 WRITE_INT32_FIELD(this, kSmallLayout1Offset, small_layout_1);
2622
2623 // Initialize the extended layout fields.
2624 int extended_header_offset = get_extended_section_header_offset();
2625 WRITE_INT_FIELD(this, extended_header_offset + kExtendedInt64CountOffset,
2626 extended.count_of(INT64));
2627 WRITE_INT_FIELD(this, extended_header_offset + kExtendedCodePtrCountOffset,
2628 extended.count_of(CODE_PTR));
2629 WRITE_INT_FIELD(this, extended_header_offset + kExtendedHeapPtrCountOffset,
2630 extended.count_of(HEAP_PTR));
2631 WRITE_INT_FIELD(this, extended_header_offset + kExtendedInt32CountOffset,
2632 extended.count_of(INT32));
2633}
2634
2635
2636int ConstantPoolArray::size() {
2637 NumberOfEntries small(this, SMALL_SECTION);
2638 if (!is_extended_layout()) {
2639 return SizeFor(small);
2640 } else {
2641 NumberOfEntries extended(this, EXTENDED_SECTION);
2642 return SizeForExtended(small, extended);
2643 }
2644}
2645
2646
2647int ConstantPoolArray::length() {
2648 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2649 int length = TotalCountField::decode(small_layout_2);
2650 if (is_extended_layout()) {
2651 length += number_of_entries(INT64, EXTENDED_SECTION) +
2652 number_of_entries(CODE_PTR, EXTENDED_SECTION) +
2653 number_of_entries(HEAP_PTR, EXTENDED_SECTION) +
2654 number_of_entries(INT32, EXTENDED_SECTION);
2655 }
2656 return length;
2657}
2658
2659
2660WriteBarrierMode HeapObject::GetWriteBarrierMode(
2661 const DisallowHeapAllocation& promise) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002662 Heap* heap = GetHeap();
2663 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
2664 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
Steve Blocka7e24c12009-10-30 11:49:00 +00002665 return UPDATE_WRITE_BARRIER;
2666}
2667
2668
2669void FixedArray::set(int index,
2670 Object* value,
2671 WriteBarrierMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002672 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2673 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002674 int offset = kHeaderSize + index * kPointerSize;
2675 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002676 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002677}
2678
2679
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002680void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
2681 int index,
2682 Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002683 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map());
2684 DCHECK(index >= 0 && index < array->length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002685 int offset = kHeaderSize + index * kPointerSize;
2686 WRITE_FIELD(array, offset, value);
2687 Heap* heap = array->GetHeap();
2688 if (heap->InNewSpace(value)) {
2689 heap->RecordWrite(array->address(), offset);
2690 }
2691}
2692
2693
2694void FixedArray::NoWriteBarrierSet(FixedArray* array,
2695 int index,
2696 Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002697 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map());
2698 DCHECK(index >= 0 && index < array->length());
2699 DCHECK(!array->GetHeap()->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002700 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
2701}
2702
2703
2704void FixedArray::set_undefined(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002705 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2706 DCHECK(index >= 0 && index < this->length());
2707 DCHECK(!GetHeap()->InNewSpace(GetHeap()->undefined_value()));
2708 WRITE_FIELD(this,
2709 kHeaderSize + index * kPointerSize,
2710 GetHeap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002711}
2712
2713
2714void FixedArray::set_null(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002715 DCHECK(index >= 0 && index < this->length());
2716 DCHECK(!GetHeap()->InNewSpace(GetHeap()->null_value()));
2717 WRITE_FIELD(this,
2718 kHeaderSize + index * kPointerSize,
2719 GetHeap()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002720}
2721
2722
2723void FixedArray::set_the_hole(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002724 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2725 DCHECK(index >= 0 && index < this->length());
2726 DCHECK(!GetHeap()->InNewSpace(GetHeap()->the_hole_value()));
Steve Block44f0eee2011-05-26 01:26:41 +01002727 WRITE_FIELD(this,
2728 kHeaderSize + index * kPointerSize,
2729 GetHeap()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002730}
2731
2732
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002733void FixedArray::FillWithHoles(int from, int to) {
2734 for (int i = from; i < to; i++) {
2735 set_the_hole(i);
2736 }
Iain Merrick75681382010-08-19 15:07:18 +01002737}
2738
2739
Steve Block6ded16b2010-05-10 14:33:55 +01002740Object** FixedArray::data_start() {
2741 return HeapObject::RawField(this, kHeaderSize);
2742}
2743
2744
Steve Blocka7e24c12009-10-30 11:49:00 +00002745bool DescriptorArray::IsEmpty() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002746 DCHECK(length() >= kFirstIndex ||
2747 this == GetHeap()->empty_descriptor_array());
2748 return length() < kFirstIndex;
Ben Murdoch257744e2011-11-30 15:57:28 +00002749}
2750
2751
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002752void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
2753 WRITE_FIELD(
2754 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
Steve Blocka7e24c12009-10-30 11:49:00 +00002755}
2756
2757
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002758// Perform a binary search in a fixed array. Low and high are entry indices. If
2759// there are three entries in this array it should be called with low=0 and
2760// high=2.
2761template<SearchMode search_mode, typename T>
2762int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
2763 uint32_t hash = name->Hash();
2764 int limit = high;
2765
2766 DCHECK(low <= high);
2767
2768 while (low != high) {
2769 int mid = (low + high) / 2;
2770 Name* mid_name = array->GetSortedKey(mid);
2771 uint32_t mid_hash = mid_name->Hash();
2772
2773 if (mid_hash >= hash) {
2774 high = mid;
2775 } else {
2776 low = mid + 1;
2777 }
2778 }
2779
2780 for (; low <= limit; ++low) {
2781 int sort_index = array->GetSortedKeyIndex(low);
2782 Name* entry = array->GetKey(sort_index);
2783 if (entry->Hash() != hash) break;
2784 if (entry->Equals(name)) {
2785 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
2786 return sort_index;
2787 }
2788 return T::kNotFound;
2789 }
2790 }
2791
2792 return T::kNotFound;
Steve Blocka7e24c12009-10-30 11:49:00 +00002793}
2794
2795
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002796// Perform a linear search in this fixed array. len is the number of entry
2797// indices that are valid.
2798template<SearchMode search_mode, typename T>
2799int LinearSearch(T* array, Name* name, int len, int valid_entries) {
2800 uint32_t hash = name->Hash();
2801 if (search_mode == ALL_ENTRIES) {
2802 for (int number = 0; number < len; number++) {
2803 int sorted_index = array->GetSortedKeyIndex(number);
2804 Name* entry = array->GetKey(sorted_index);
2805 uint32_t current_hash = entry->Hash();
2806 if (current_hash > hash) break;
2807 if (current_hash == hash && entry->Equals(name)) return sorted_index;
2808 }
2809 } else {
2810 DCHECK(len >= valid_entries);
2811 for (int number = 0; number < valid_entries; number++) {
2812 Name* entry = array->GetKey(number);
2813 uint32_t current_hash = entry->Hash();
2814 if (current_hash == hash && entry->Equals(name)) return number;
2815 }
2816 }
2817 return T::kNotFound;
2818}
Steve Blocka7e24c12009-10-30 11:49:00 +00002819
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002820
2821template<SearchMode search_mode, typename T>
2822int Search(T* array, Name* name, int valid_entries) {
2823 if (search_mode == VALID_ENTRIES) {
2824 SLOW_DCHECK(array->IsSortedNoDuplicates(valid_entries));
2825 } else {
2826 SLOW_DCHECK(array->IsSortedNoDuplicates());
2827 }
2828
2829 int nof = array->number_of_entries();
2830 if (nof == 0) return T::kNotFound;
Steve Blocka7e24c12009-10-30 11:49:00 +00002831
2832 // Fast case: do linear search for small arrays.
2833 const int kMaxElementsForLinearSearch = 8;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002834 if ((search_mode == ALL_ENTRIES &&
2835 nof <= kMaxElementsForLinearSearch) ||
2836 (search_mode == VALID_ENTRIES &&
2837 valid_entries <= (kMaxElementsForLinearSearch * 3))) {
2838 return LinearSearch<search_mode>(array, name, nof, valid_entries);
Steve Blocka7e24c12009-10-30 11:49:00 +00002839 }
2840
2841 // Slow case: perform binary search.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002842 return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries);
Steve Blocka7e24c12009-10-30 11:49:00 +00002843}
2844
2845
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002846int DescriptorArray::Search(Name* name, int valid_descriptors) {
2847 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
2848}
2849
2850
2851int DescriptorArray::SearchWithCache(Name* name, Map* map) {
2852 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2853 if (number_of_own_descriptors == 0) return kNotFound;
2854
2855 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2856 int number = cache->Lookup(map, name);
2857
Iain Merrick75681382010-08-19 15:07:18 +01002858 if (number == DescriptorLookupCache::kAbsent) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002859 number = Search(name, number_of_own_descriptors);
2860 cache->Update(map, name, number);
Iain Merrick75681382010-08-19 15:07:18 +01002861 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002862
Iain Merrick75681382010-08-19 15:07:18 +01002863 return number;
2864}
2865
2866
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002867PropertyDetails Map::GetLastDescriptorDetails() {
2868 return instance_descriptors()->GetDetails(LastAdded());
2869}
2870
2871
2872void Map::LookupDescriptor(JSObject* holder,
2873 Name* name,
2874 LookupResult* result) {
2875 DescriptorArray* descriptors = this->instance_descriptors();
2876 int number = descriptors->SearchWithCache(name, this);
2877 if (number == DescriptorArray::kNotFound) return result->NotFound();
2878 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2879}
2880
2881
2882void Map::LookupTransition(JSObject* holder,
2883 Name* name,
2884 LookupResult* result) {
2885 int transition_index = this->SearchTransition(name);
2886 if (transition_index == TransitionArray::kNotFound) return result->NotFound();
2887 result->TransitionResult(holder, this->GetTransition(transition_index));
2888}
2889
2890
2891FixedArrayBase* Map::GetInitialElements() {
2892 if (has_fast_smi_or_object_elements() ||
2893 has_fast_double_elements()) {
2894 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
2895 return GetHeap()->empty_fixed_array();
2896 } else if (has_external_array_elements()) {
2897 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this);
2898 DCHECK(!GetHeap()->InNewSpace(empty_array));
2899 return empty_array;
2900 } else if (has_fixed_typed_array_elements()) {
2901 FixedTypedArrayBase* empty_array =
2902 GetHeap()->EmptyFixedTypedArrayForMap(this);
2903 DCHECK(!GetHeap()->InNewSpace(empty_array));
2904 return empty_array;
2905 } else {
2906 UNREACHABLE();
2907 }
2908 return NULL;
2909}
2910
2911
2912Object** DescriptorArray::GetKeySlot(int descriptor_number) {
2913 DCHECK(descriptor_number < number_of_descriptors());
2914 return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
2915}
2916
2917
2918Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
2919 return GetKeySlot(descriptor_number);
2920}
2921
2922
2923Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
2924 return GetValueSlot(descriptor_number - 1) + 1;
2925}
2926
2927
2928Name* DescriptorArray::GetKey(int descriptor_number) {
2929 DCHECK(descriptor_number < number_of_descriptors());
2930 return Name::cast(get(ToKeyIndex(descriptor_number)));
2931}
2932
2933
2934int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
2935 return GetDetails(descriptor_number).pointer();
2936}
2937
2938
2939Name* DescriptorArray::GetSortedKey(int descriptor_number) {
2940 return GetKey(GetSortedKeyIndex(descriptor_number));
2941}
2942
2943
2944void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
2945 PropertyDetails details = GetDetails(descriptor_index);
2946 set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
2947}
2948
2949
2950void DescriptorArray::SetRepresentation(int descriptor_index,
2951 Representation representation) {
2952 DCHECK(!representation.IsNone());
2953 PropertyDetails details = GetDetails(descriptor_index);
2954 set(ToDetailsIndex(descriptor_index),
2955 details.CopyWithRepresentation(representation).AsSmi());
2956}
2957
2958
2959Object** DescriptorArray::GetValueSlot(int descriptor_number) {
2960 DCHECK(descriptor_number < number_of_descriptors());
2961 return RawFieldOfElementAt(ToValueIndex(descriptor_number));
2962}
2963
2964
2965int DescriptorArray::GetValueOffset(int descriptor_number) {
2966 return OffsetOfElementAt(ToValueIndex(descriptor_number));
Steve Blocka7e24c12009-10-30 11:49:00 +00002967}
2968
2969
2970Object* DescriptorArray::GetValue(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002971 DCHECK(descriptor_number < number_of_descriptors());
2972 return get(ToValueIndex(descriptor_number));
Steve Blocka7e24c12009-10-30 11:49:00 +00002973}
2974
2975
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002976void DescriptorArray::SetValue(int descriptor_index, Object* value) {
2977 set(ToValueIndex(descriptor_index), value);
2978}
2979
2980
2981PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
2982 DCHECK(descriptor_number < number_of_descriptors());
2983 Object* details = get(ToDetailsIndex(descriptor_number));
2984 return PropertyDetails(Smi::cast(details));
Steve Blocka7e24c12009-10-30 11:49:00 +00002985}
2986
2987
2988PropertyType DescriptorArray::GetType(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002989 return GetDetails(descriptor_number).type();
Steve Blocka7e24c12009-10-30 11:49:00 +00002990}
2991
2992
2993int DescriptorArray::GetFieldIndex(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002994 DCHECK(GetDetails(descriptor_number).type() == FIELD);
2995 return GetDetails(descriptor_number).field_index();
Steve Blocka7e24c12009-10-30 11:49:00 +00002996}
2997
2998
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002999HeapType* DescriptorArray::GetFieldType(int descriptor_number) {
3000 DCHECK(GetDetails(descriptor_number).type() == FIELD);
3001 return HeapType::cast(GetValue(descriptor_number));
3002}
3003
3004
3005Object* DescriptorArray::GetConstant(int descriptor_number) {
3006 return GetValue(descriptor_number);
Steve Blocka7e24c12009-10-30 11:49:00 +00003007}
3008
3009
3010Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003011 DCHECK(GetType(descriptor_number) == CALLBACKS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003012 return GetValue(descriptor_number);
3013}
3014
3015
3016AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003017 DCHECK(GetType(descriptor_number) == CALLBACKS);
Ben Murdoch257744e2011-11-30 15:57:28 +00003018 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003019 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00003020}
3021
3022
Steve Blocka7e24c12009-10-30 11:49:00 +00003023void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003024 desc->Init(handle(GetKey(descriptor_number), GetIsolate()),
3025 handle(GetValue(descriptor_number), GetIsolate()),
3026 GetDetails(descriptor_number));
Steve Blocka7e24c12009-10-30 11:49:00 +00003027}
3028
3029
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003030void DescriptorArray::Set(int descriptor_number,
3031 Descriptor* desc,
3032 const WhitenessWitness&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003033 // Range check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003034 DCHECK(descriptor_number < number_of_descriptors());
Steve Blocka7e24c12009-10-30 11:49:00 +00003035
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003036 NoIncrementalWriteBarrierSet(this,
3037 ToKeyIndex(descriptor_number),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003038 *desc->GetKey());
3039 NoIncrementalWriteBarrierSet(this,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003040 ToValueIndex(descriptor_number),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003041 *desc->GetValue());
3042 NoIncrementalWriteBarrierSet(this,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003043 ToDetailsIndex(descriptor_number),
3044 desc->GetDetails().AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00003045}
3046
3047
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003048void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
3049 // Range check.
3050 DCHECK(descriptor_number < number_of_descriptors());
3051
3052 set(ToKeyIndex(descriptor_number), *desc->GetKey());
3053 set(ToValueIndex(descriptor_number), *desc->GetValue());
3054 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
3055}
3056
3057
3058void DescriptorArray::Append(Descriptor* desc) {
3059 DisallowHeapAllocation no_gc;
3060 int descriptor_number = number_of_descriptors();
3061 SetNumberOfDescriptors(descriptor_number + 1);
3062 Set(descriptor_number, desc);
3063
3064 uint32_t hash = desc->GetKey()->Hash();
3065
3066 int insertion;
3067
3068 for (insertion = descriptor_number; insertion > 0; --insertion) {
3069 Name* key = GetSortedKey(insertion - 1);
3070 if (key->Hash() <= hash) break;
3071 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
3072 }
3073
3074 SetSortedKey(insertion, descriptor_number);
3075}
3076
3077
3078void DescriptorArray::SwapSortedKeys(int first, int second) {
3079 int first_key = GetSortedKeyIndex(first);
3080 SetSortedKey(first, GetSortedKeyIndex(second));
3081 SetSortedKey(second, first_key);
Ben Murdoch85b71792012-04-11 18:30:58 +01003082}
3083
3084
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003085DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
3086 : marking_(array->GetHeap()->incremental_marking()) {
3087 marking_->EnterNoMarkingScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003088 DCHECK(!marking_->IsMarking() ||
3089 Marking::Color(array) == Marking::WHITE_OBJECT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003090}
3091
3092
3093DescriptorArray::WhitenessWitness::~WhitenessWitness() {
3094 marking_->LeaveNoMarkingScope();
Steve Blocka7e24c12009-10-30 11:49:00 +00003095}
3096
3097
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003098template<typename Derived, typename Shape, typename Key>
3099int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003100 const int kMinCapacity = 32;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003101 int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003102 if (capacity < kMinCapacity) {
3103 capacity = kMinCapacity; // Guarantee min capacity.
3104 }
3105 return capacity;
3106}
3107
3108
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003109template<typename Derived, typename Shape, typename Key>
3110int HashTable<Derived, Shape, Key>::FindEntry(Key key) {
Steve Block44f0eee2011-05-26 01:26:41 +01003111 return FindEntry(GetIsolate(), key);
3112}
3113
3114
3115// Find entry for key otherwise return kNotFound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003116template<typename Derived, typename Shape, typename Key>
3117int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key) {
Steve Block44f0eee2011-05-26 01:26:41 +01003118 uint32_t capacity = Capacity();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003119 uint32_t entry = FirstProbe(HashTable::Hash(key), capacity);
Steve Block44f0eee2011-05-26 01:26:41 +01003120 uint32_t count = 1;
3121 // EnsureCapacity will guarantee the hash table is never full.
3122 while (true) {
3123 Object* element = KeyAt(entry);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003124 // Empty entry. Uses raw unchecked accessors because it is called by the
3125 // string table during bootstrapping.
Ben Murdochc7cc0282012-03-05 14:35:55 +00003126 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003127 if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
Steve Block44f0eee2011-05-26 01:26:41 +01003128 Shape::IsMatch(key, element)) return entry;
3129 entry = NextProbe(entry, count++, capacity);
3130 }
3131 return kNotFound;
3132}
3133
3134
Ben Murdochc7cc0282012-03-05 14:35:55 +00003135bool SeededNumberDictionary::requires_slow_elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003136 Object* max_index_object = get(kMaxNumberKeyIndex);
3137 if (!max_index_object->IsSmi()) return false;
3138 return 0 !=
3139 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
3140}
3141
Ben Murdochc7cc0282012-03-05 14:35:55 +00003142uint32_t SeededNumberDictionary::max_number_key() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003143 DCHECK(!requires_slow_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003144 Object* max_index_object = get(kMaxNumberKeyIndex);
3145 if (!max_index_object->IsSmi()) return 0;
3146 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
3147 return value >> kRequiresSlowElementsTagSize;
3148}
3149
Ben Murdochc7cc0282012-03-05 14:35:55 +00003150void SeededNumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00003151 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00003152}
3153
3154
3155// ------------------------------------
3156// Cast operations
3157
3158
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003159CAST_ACCESSOR(AccessorInfo)
3160CAST_ACCESSOR(ByteArray)
3161CAST_ACCESSOR(Cell)
3162CAST_ACCESSOR(Code)
3163CAST_ACCESSOR(CodeCacheHashTable)
3164CAST_ACCESSOR(CompilationCacheTable)
3165CAST_ACCESSOR(ConsString)
3166CAST_ACCESSOR(ConstantPoolArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003167CAST_ACCESSOR(DeoptimizationInputData)
3168CAST_ACCESSOR(DeoptimizationOutputData)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003169CAST_ACCESSOR(DependentCode)
3170CAST_ACCESSOR(DescriptorArray)
Steve Block3ce2e202009-11-05 08:53:23 +00003171CAST_ACCESSOR(ExternalArray)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003172CAST_ACCESSOR(ExternalOneByteString)
3173CAST_ACCESSOR(ExternalFloat32Array)
3174CAST_ACCESSOR(ExternalFloat64Array)
3175CAST_ACCESSOR(ExternalInt16Array)
3176CAST_ACCESSOR(ExternalInt32Array)
3177CAST_ACCESSOR(ExternalInt8Array)
3178CAST_ACCESSOR(ExternalString)
3179CAST_ACCESSOR(ExternalTwoByteString)
3180CAST_ACCESSOR(ExternalUint16Array)
3181CAST_ACCESSOR(ExternalUint32Array)
3182CAST_ACCESSOR(ExternalUint8Array)
3183CAST_ACCESSOR(ExternalUint8ClampedArray)
3184CAST_ACCESSOR(FixedArray)
3185CAST_ACCESSOR(FixedArrayBase)
3186CAST_ACCESSOR(FixedDoubleArray)
3187CAST_ACCESSOR(FixedTypedArrayBase)
3188CAST_ACCESSOR(Foreign)
3189CAST_ACCESSOR(FreeSpace)
3190CAST_ACCESSOR(GlobalObject)
3191CAST_ACCESSOR(HeapObject)
3192CAST_ACCESSOR(JSArray)
3193CAST_ACCESSOR(JSArrayBuffer)
3194CAST_ACCESSOR(JSArrayBufferView)
3195CAST_ACCESSOR(JSBuiltinsObject)
3196CAST_ACCESSOR(JSDataView)
3197CAST_ACCESSOR(JSDate)
3198CAST_ACCESSOR(JSFunction)
3199CAST_ACCESSOR(JSFunctionProxy)
3200CAST_ACCESSOR(JSFunctionResultCache)
3201CAST_ACCESSOR(JSGeneratorObject)
3202CAST_ACCESSOR(JSGlobalObject)
3203CAST_ACCESSOR(JSGlobalProxy)
3204CAST_ACCESSOR(JSMap)
3205CAST_ACCESSOR(JSMapIterator)
3206CAST_ACCESSOR(JSMessageObject)
3207CAST_ACCESSOR(JSModule)
3208CAST_ACCESSOR(JSObject)
3209CAST_ACCESSOR(JSProxy)
3210CAST_ACCESSOR(JSReceiver)
3211CAST_ACCESSOR(JSRegExp)
3212CAST_ACCESSOR(JSSet)
3213CAST_ACCESSOR(JSSetIterator)
3214CAST_ACCESSOR(JSTypedArray)
3215CAST_ACCESSOR(JSValue)
3216CAST_ACCESSOR(JSWeakMap)
3217CAST_ACCESSOR(JSWeakSet)
3218CAST_ACCESSOR(Map)
3219CAST_ACCESSOR(MapCache)
3220CAST_ACCESSOR(Name)
3221CAST_ACCESSOR(NameDictionary)
3222CAST_ACCESSOR(NormalizedMapCache)
3223CAST_ACCESSOR(Object)
3224CAST_ACCESSOR(ObjectHashTable)
3225CAST_ACCESSOR(Oddball)
3226CAST_ACCESSOR(OrderedHashMap)
3227CAST_ACCESSOR(OrderedHashSet)
3228CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
3229CAST_ACCESSOR(PropertyCell)
3230CAST_ACCESSOR(ScopeInfo)
3231CAST_ACCESSOR(SeededNumberDictionary)
3232CAST_ACCESSOR(SeqOneByteString)
3233CAST_ACCESSOR(SeqString)
3234CAST_ACCESSOR(SeqTwoByteString)
3235CAST_ACCESSOR(SharedFunctionInfo)
3236CAST_ACCESSOR(SlicedString)
3237CAST_ACCESSOR(Smi)
3238CAST_ACCESSOR(String)
3239CAST_ACCESSOR(StringTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00003240CAST_ACCESSOR(Struct)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003241CAST_ACCESSOR(Symbol)
3242CAST_ACCESSOR(UnseededNumberDictionary)
3243CAST_ACCESSOR(WeakHashTable)
3244
3245
3246template <class Traits>
3247FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
3248 SLOW_DCHECK(object->IsHeapObject() &&
3249 HeapObject::cast(object)->map()->instance_type() ==
3250 Traits::kInstanceType);
3251 return reinterpret_cast<FixedTypedArray<Traits>*>(object);
3252}
3253
3254
3255template <class Traits>
3256const FixedTypedArray<Traits>*
3257FixedTypedArray<Traits>::cast(const Object* object) {
3258 SLOW_DCHECK(object->IsHeapObject() &&
3259 HeapObject::cast(object)->map()->instance_type() ==
3260 Traits::kInstanceType);
3261 return reinterpret_cast<FixedTypedArray<Traits>*>(object);
3262}
Steve Blocka7e24c12009-10-30 11:49:00 +00003263
3264
3265#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
3266 STRUCT_LIST(MAKE_STRUCT_CAST)
3267#undef MAKE_STRUCT_CAST
3268
3269
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003270template <typename Derived, typename Shape, typename Key>
3271HashTable<Derived, Shape, Key>*
3272HashTable<Derived, Shape, Key>::cast(Object* obj) {
3273 SLOW_DCHECK(obj->IsHashTable());
Steve Blocka7e24c12009-10-30 11:49:00 +00003274 return reinterpret_cast<HashTable*>(obj);
3275}
3276
3277
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003278template <typename Derived, typename Shape, typename Key>
3279const HashTable<Derived, Shape, Key>*
3280HashTable<Derived, Shape, Key>::cast(const Object* obj) {
3281 SLOW_DCHECK(obj->IsHashTable());
3282 return reinterpret_cast<const HashTable*>(obj);
3283}
3284
3285
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003286SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003287SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
3288
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003289SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003290NOBARRIER_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003291
Steve Block6ded16b2010-05-10 14:33:55 +01003292SMI_ACCESSORS(String, length, kLengthOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003293SYNCHRONIZED_SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00003294
3295
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003296uint32_t Name::hash_field() {
Steve Blockd0582a62009-12-15 09:54:21 +00003297 return READ_UINT32_FIELD(this, kHashFieldOffset);
3298}
3299
3300
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003301void Name::set_hash_field(uint32_t value) {
Steve Blockd0582a62009-12-15 09:54:21 +00003302 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003303#if V8_HOST_ARCH_64_BIT
3304 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
3305#endif
Steve Blockd0582a62009-12-15 09:54:21 +00003306}
3307
3308
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003309bool Name::Equals(Name* other) {
3310 if (other == this) return true;
3311 if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
3312 this->IsSymbol() || other->IsSymbol()) {
3313 return false;
3314 }
3315 return String::cast(this)->SlowEquals(String::cast(other));
3316}
3317
3318
3319bool Name::Equals(Handle<Name> one, Handle<Name> two) {
3320 if (one.is_identical_to(two)) return true;
3321 if ((one->IsInternalizedString() && two->IsInternalizedString()) ||
3322 one->IsSymbol() || two->IsSymbol()) {
3323 return false;
3324 }
3325 return String::SlowEquals(Handle<String>::cast(one),
3326 Handle<String>::cast(two));
3327}
3328
3329
3330ACCESSORS(Symbol, name, Object, kNameOffset)
3331ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
3332BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
3333BOOL_ACCESSORS(Symbol, flags, is_own, kOwnBit)
3334
3335
Steve Blocka7e24c12009-10-30 11:49:00 +00003336bool String::Equals(String* other) {
3337 if (other == this) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003338 if (this->IsInternalizedString() && other->IsInternalizedString()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003339 return false;
3340 }
3341 return SlowEquals(other);
3342}
3343
3344
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003345bool String::Equals(Handle<String> one, Handle<String> two) {
3346 if (one.is_identical_to(two)) return true;
3347 if (one->IsInternalizedString() && two->IsInternalizedString()) {
3348 return false;
3349 }
3350 return SlowEquals(one, two);
Steve Blocka7e24c12009-10-30 11:49:00 +00003351}
3352
3353
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003354Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
3355 if (!string->IsConsString()) return string;
3356 Handle<ConsString> cons = Handle<ConsString>::cast(string);
3357 if (cons->IsFlat()) return handle(cons->first());
3358 return SlowFlatten(cons, pretenure);
Leon Clarkef7060e22010-06-03 12:02:55 +01003359}
3360
3361
Steve Blocka7e24c12009-10-30 11:49:00 +00003362uint16_t String::Get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003363 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003364 switch (StringShape(this).full_representation_tag()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003365 case kSeqStringTag | kOneByteStringTag:
3366 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003367 case kSeqStringTag | kTwoByteStringTag:
3368 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003369 case kConsStringTag | kOneByteStringTag:
Steve Blocka7e24c12009-10-30 11:49:00 +00003370 case kConsStringTag | kTwoByteStringTag:
3371 return ConsString::cast(this)->ConsStringGet(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003372 case kExternalStringTag | kOneByteStringTag:
3373 return ExternalOneByteString::cast(this)->ExternalOneByteStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003374 case kExternalStringTag | kTwoByteStringTag:
3375 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003376 case kSlicedStringTag | kOneByteStringTag:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003377 case kSlicedStringTag | kTwoByteStringTag:
3378 return SlicedString::cast(this)->SlicedStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003379 default:
3380 break;
3381 }
3382
3383 UNREACHABLE();
3384 return 0;
3385}
3386
3387
3388void String::Set(int index, uint16_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003389 DCHECK(index >= 0 && index < length());
3390 DCHECK(StringShape(this).IsSequential());
Steve Blocka7e24c12009-10-30 11:49:00 +00003391
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003392 return this->IsOneByteRepresentation()
3393 ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value)
Steve Blocka7e24c12009-10-30 11:49:00 +00003394 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
3395}
3396
3397
3398bool String::IsFlat() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003399 if (!StringShape(this).IsCons()) return true;
3400 return ConsString::cast(this)->second()->length() == 0;
3401}
3402
3403
3404String* String::GetUnderlying() {
3405 // Giving direct access to underlying string only makes sense if the
3406 // wrapping string is already flattened.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003407 DCHECK(this->IsFlat());
3408 DCHECK(StringShape(this).IsIndirect());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003409 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
3410 const int kUnderlyingOffset = SlicedString::kParentOffset;
3411 return String::cast(READ_FIELD(this, kUnderlyingOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00003412}
3413
3414
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003415template<class Visitor>
3416ConsString* String::VisitFlat(Visitor* visitor,
3417 String* string,
3418 const int offset) {
3419 int slice_offset = offset;
3420 const int length = string->length();
3421 DCHECK(offset <= length);
3422 while (true) {
3423 int32_t type = string->map()->instance_type();
3424 switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
3425 case kSeqStringTag | kOneByteStringTag:
3426 visitor->VisitOneByteString(
3427 SeqOneByteString::cast(string)->GetChars() + slice_offset,
3428 length - offset);
3429 return NULL;
3430
3431 case kSeqStringTag | kTwoByteStringTag:
3432 visitor->VisitTwoByteString(
3433 SeqTwoByteString::cast(string)->GetChars() + slice_offset,
3434 length - offset);
3435 return NULL;
3436
3437 case kExternalStringTag | kOneByteStringTag:
3438 visitor->VisitOneByteString(
3439 ExternalOneByteString::cast(string)->GetChars() + slice_offset,
3440 length - offset);
3441 return NULL;
3442
3443 case kExternalStringTag | kTwoByteStringTag:
3444 visitor->VisitTwoByteString(
3445 ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
3446 length - offset);
3447 return NULL;
3448
3449 case kSlicedStringTag | kOneByteStringTag:
3450 case kSlicedStringTag | kTwoByteStringTag: {
3451 SlicedString* slicedString = SlicedString::cast(string);
3452 slice_offset += slicedString->offset();
3453 string = slicedString->parent();
3454 continue;
3455 }
3456
3457 case kConsStringTag | kOneByteStringTag:
3458 case kConsStringTag | kTwoByteStringTag:
3459 return ConsString::cast(string);
3460
3461 default:
3462 UNREACHABLE();
3463 return NULL;
3464 }
3465 }
3466}
3467
3468
3469uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
3470 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003471 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3472}
3473
3474
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003475void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
3476 DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003477 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
3478 static_cast<byte>(value));
3479}
3480
3481
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003482Address SeqOneByteString::GetCharsAddress() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003483 return FIELD_ADDR(this, kHeaderSize);
3484}
3485
3486
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003487uint8_t* SeqOneByteString::GetChars() {
3488 return reinterpret_cast<uint8_t*>(GetCharsAddress());
Steve Blocka7e24c12009-10-30 11:49:00 +00003489}
3490
3491
3492Address SeqTwoByteString::GetCharsAddress() {
3493 return FIELD_ADDR(this, kHeaderSize);
3494}
3495
3496
3497uc16* SeqTwoByteString::GetChars() {
3498 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
3499}
3500
3501
3502uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003503 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003504 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
3505}
3506
3507
3508void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003509 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003510 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
3511}
3512
3513
3514int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01003515 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003516}
3517
3518
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003519int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01003520 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003521}
3522
3523
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003524String* SlicedString::parent() {
3525 return String::cast(READ_FIELD(this, kParentOffset));
3526}
3527
3528
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003529void SlicedString::set_parent(String* parent, WriteBarrierMode mode) {
3530 DCHECK(parent->IsSeqString() || parent->IsExternalString());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003531 WRITE_FIELD(this, kParentOffset, parent);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003532 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003533}
3534
3535
3536SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
3537
3538
Steve Blocka7e24c12009-10-30 11:49:00 +00003539String* ConsString::first() {
3540 return String::cast(READ_FIELD(this, kFirstOffset));
3541}
3542
3543
3544Object* ConsString::unchecked_first() {
3545 return READ_FIELD(this, kFirstOffset);
3546}
3547
3548
3549void ConsString::set_first(String* value, WriteBarrierMode mode) {
3550 WRITE_FIELD(this, kFirstOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003551 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003552}
3553
3554
3555String* ConsString::second() {
3556 return String::cast(READ_FIELD(this, kSecondOffset));
3557}
3558
3559
3560Object* ConsString::unchecked_second() {
3561 return READ_FIELD(this, kSecondOffset);
3562}
3563
3564
3565void ConsString::set_second(String* value, WriteBarrierMode mode) {
3566 WRITE_FIELD(this, kSecondOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003567 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003568}
3569
3570
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003571bool ExternalString::is_short() {
3572 InstanceType type = map()->instance_type();
3573 return (type & kShortExternalStringMask) == kShortExternalStringTag;
3574}
3575
3576
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003577const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003578 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3579}
3580
3581
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003582void ExternalOneByteString::update_data_cache() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003583 if (is_short()) return;
3584 const char** data_field =
3585 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
3586 *data_field = resource()->data();
3587}
3588
3589
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003590void ExternalOneByteString::set_resource(
3591 const ExternalOneByteString::Resource* resource) {
3592 DCHECK(IsAligned(reinterpret_cast<intptr_t>(resource), kPointerSize));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003593 *reinterpret_cast<const Resource**>(
3594 FIELD_ADDR(this, kResourceOffset)) = resource;
3595 if (resource != NULL) update_data_cache();
Steve Blocka7e24c12009-10-30 11:49:00 +00003596}
3597
3598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003599const uint8_t* ExternalOneByteString::GetChars() {
3600 return reinterpret_cast<const uint8_t*>(resource()->data());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003601}
3602
3603
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003604uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
3605 DCHECK(index >= 0 && index < length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003606 return GetChars()[index];
3607}
3608
3609
3610const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003611 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3612}
3613
3614
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003615void ExternalTwoByteString::update_data_cache() {
3616 if (is_short()) return;
3617 const uint16_t** data_field =
3618 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
3619 *data_field = resource()->data();
3620}
3621
3622
Steve Blocka7e24c12009-10-30 11:49:00 +00003623void ExternalTwoByteString::set_resource(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003624 const ExternalTwoByteString::Resource* resource) {
3625 *reinterpret_cast<const Resource**>(
3626 FIELD_ADDR(this, kResourceOffset)) = resource;
3627 if (resource != NULL) update_data_cache();
3628}
3629
3630
3631const uint16_t* ExternalTwoByteString::GetChars() {
3632 return resource()->data();
3633}
3634
3635
3636uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003637 DCHECK(index >= 0 && index < length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003638 return GetChars()[index];
3639}
3640
3641
3642const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
3643 unsigned start) {
3644 return GetChars() + start;
Steve Blocka7e24c12009-10-30 11:49:00 +00003645}
3646
3647
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003648int ConsStringIteratorOp::OffsetForDepth(int depth) {
3649 return depth & kDepthMask;
3650}
3651
3652
3653void ConsStringIteratorOp::PushLeft(ConsString* string) {
3654 frames_[depth_++ & kDepthMask] = string;
3655}
3656
3657
3658void ConsStringIteratorOp::PushRight(ConsString* string) {
3659 // Inplace update.
3660 frames_[(depth_-1) & kDepthMask] = string;
3661}
3662
3663
3664void ConsStringIteratorOp::AdjustMaximumDepth() {
3665 if (depth_ > maximum_depth_) maximum_depth_ = depth_;
3666}
3667
3668
3669void ConsStringIteratorOp::Pop() {
3670 DCHECK(depth_ > 0);
3671 DCHECK(depth_ <= maximum_depth_);
3672 depth_--;
3673}
3674
3675
3676uint16_t StringCharacterStream::GetNext() {
3677 DCHECK(buffer8_ != NULL && end_ != NULL);
3678 // Advance cursor if needed.
3679 if (buffer8_ == end_) HasMore();
3680 DCHECK(buffer8_ < end_);
3681 return is_one_byte_ ? *buffer8_++ : *buffer16_++;
3682}
3683
3684
3685StringCharacterStream::StringCharacterStream(String* string,
3686 ConsStringIteratorOp* op,
3687 int offset)
3688 : is_one_byte_(false),
3689 op_(op) {
3690 Reset(string, offset);
3691}
3692
3693
3694void StringCharacterStream::Reset(String* string, int offset) {
3695 buffer8_ = NULL;
3696 end_ = NULL;
3697 ConsString* cons_string = String::VisitFlat(this, string, offset);
3698 op_->Reset(cons_string, offset);
3699 if (cons_string != NULL) {
3700 string = op_->Next(&offset);
3701 if (string != NULL) String::VisitFlat(this, string, offset);
3702 }
3703}
3704
3705
3706bool StringCharacterStream::HasMore() {
3707 if (buffer8_ != end_) return true;
3708 int offset;
3709 String* string = op_->Next(&offset);
3710 DCHECK_EQ(offset, 0);
3711 if (string == NULL) return false;
3712 String::VisitFlat(this, string);
3713 DCHECK(buffer8_ != end_);
3714 return true;
3715}
3716
3717
3718void StringCharacterStream::VisitOneByteString(
3719 const uint8_t* chars, int length) {
3720 is_one_byte_ = true;
3721 buffer8_ = chars;
3722 end_ = chars + length;
3723}
3724
3725
3726void StringCharacterStream::VisitTwoByteString(
3727 const uint16_t* chars, int length) {
3728 is_one_byte_ = false;
3729 buffer16_ = chars;
3730 end_ = reinterpret_cast<const uint8_t*>(chars + length);
3731}
3732
3733
Steve Block6ded16b2010-05-10 14:33:55 +01003734void JSFunctionResultCache::MakeZeroSize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003735 set_finger_index(kEntriesIndex);
3736 set_size(kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01003737}
3738
3739
3740void JSFunctionResultCache::Clear() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003741 int cache_size = size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003742 Object** entries_start = RawFieldOfElementAt(kEntriesIndex);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003743 MemsetPointer(entries_start,
Steve Block44f0eee2011-05-26 01:26:41 +01003744 GetHeap()->the_hole_value(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003745 cache_size - kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01003746 MakeZeroSize();
3747}
3748
3749
Ben Murdochb8e0da22011-05-16 14:20:40 +01003750int JSFunctionResultCache::size() {
3751 return Smi::cast(get(kCacheSizeIndex))->value();
3752}
3753
3754
3755void JSFunctionResultCache::set_size(int size) {
3756 set(kCacheSizeIndex, Smi::FromInt(size));
3757}
3758
3759
3760int JSFunctionResultCache::finger_index() {
3761 return Smi::cast(get(kFingerIndex))->value();
3762}
3763
3764
3765void JSFunctionResultCache::set_finger_index(int finger_index) {
3766 set(kFingerIndex, Smi::FromInt(finger_index));
3767}
3768
3769
Steve Blocka7e24c12009-10-30 11:49:00 +00003770byte ByteArray::get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003771 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003772 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3773}
3774
3775
3776void ByteArray::set(int index, byte value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003777 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003778 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
3779}
3780
3781
3782int ByteArray::get_int(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003783 DCHECK(index >= 0 && (index * kIntSize) < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003784 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
3785}
3786
3787
3788ByteArray* ByteArray::FromDataStartAddress(Address address) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003789 DCHECK_TAG_ALIGNED(address);
Steve Blocka7e24c12009-10-30 11:49:00 +00003790 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
3791}
3792
3793
3794Address ByteArray::GetDataStartAddress() {
3795 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
3796}
3797
3798
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003799uint8_t* ExternalUint8ClampedArray::external_uint8_clamped_pointer() {
Steve Block44f0eee2011-05-26 01:26:41 +01003800 return reinterpret_cast<uint8_t*>(external_pointer());
Steve Blocka7e24c12009-10-30 11:49:00 +00003801}
3802
3803
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003804uint8_t ExternalUint8ClampedArray::get_scalar(int index) {
3805 DCHECK((index >= 0) && (index < this->length()));
3806 uint8_t* ptr = external_uint8_clamped_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00003807 return ptr[index];
3808}
3809
3810
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003811Handle<Object> ExternalUint8ClampedArray::get(
3812 Handle<ExternalUint8ClampedArray> array,
3813 int index) {
3814 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3815 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003816}
3817
3818
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003819void ExternalUint8ClampedArray::set(int index, uint8_t value) {
3820 DCHECK((index >= 0) && (index < this->length()));
3821 uint8_t* ptr = external_uint8_clamped_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00003822 ptr[index] = value;
3823}
3824
3825
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003826void* ExternalArray::external_pointer() const {
Steve Block3ce2e202009-11-05 08:53:23 +00003827 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
3828 return reinterpret_cast<void*>(ptr);
3829}
3830
3831
3832void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
3833 intptr_t ptr = reinterpret_cast<intptr_t>(value);
3834 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
3835}
3836
3837
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003838int8_t ExternalInt8Array::get_scalar(int index) {
3839 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003840 int8_t* ptr = static_cast<int8_t*>(external_pointer());
3841 return ptr[index];
3842}
3843
3844
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003845Handle<Object> ExternalInt8Array::get(Handle<ExternalInt8Array> array,
3846 int index) {
3847 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3848 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003849}
3850
3851
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003852void ExternalInt8Array::set(int index, int8_t value) {
3853 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003854 int8_t* ptr = static_cast<int8_t*>(external_pointer());
3855 ptr[index] = value;
3856}
3857
3858
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003859uint8_t ExternalUint8Array::get_scalar(int index) {
3860 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003861 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3862 return ptr[index];
3863}
3864
3865
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003866Handle<Object> ExternalUint8Array::get(Handle<ExternalUint8Array> array,
3867 int index) {
3868 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3869 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003870}
3871
3872
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003873void ExternalUint8Array::set(int index, uint8_t value) {
3874 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003875 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3876 ptr[index] = value;
3877}
3878
3879
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003880int16_t ExternalInt16Array::get_scalar(int index) {
3881 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003882 int16_t* ptr = static_cast<int16_t*>(external_pointer());
3883 return ptr[index];
3884}
3885
3886
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003887Handle<Object> ExternalInt16Array::get(Handle<ExternalInt16Array> array,
3888 int index) {
3889 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3890 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003891}
3892
3893
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003894void ExternalInt16Array::set(int index, int16_t value) {
3895 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003896 int16_t* ptr = static_cast<int16_t*>(external_pointer());
3897 ptr[index] = value;
3898}
3899
3900
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003901uint16_t ExternalUint16Array::get_scalar(int index) {
3902 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003903 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3904 return ptr[index];
3905}
3906
3907
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003908Handle<Object> ExternalUint16Array::get(Handle<ExternalUint16Array> array,
3909 int index) {
3910 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3911 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003912}
3913
3914
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003915void ExternalUint16Array::set(int index, uint16_t value) {
3916 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003917 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3918 ptr[index] = value;
3919}
3920
3921
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003922int32_t ExternalInt32Array::get_scalar(int index) {
3923 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003924 int32_t* ptr = static_cast<int32_t*>(external_pointer());
3925 return ptr[index];
3926}
3927
3928
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003929Handle<Object> ExternalInt32Array::get(Handle<ExternalInt32Array> array,
3930 int index) {
3931 return array->GetIsolate()->factory()->
3932 NewNumberFromInt(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003933}
3934
3935
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003936void ExternalInt32Array::set(int index, int32_t value) {
3937 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003938 int32_t* ptr = static_cast<int32_t*>(external_pointer());
3939 ptr[index] = value;
3940}
3941
3942
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003943uint32_t ExternalUint32Array::get_scalar(int index) {
3944 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003945 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3946 return ptr[index];
3947}
3948
3949
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003950Handle<Object> ExternalUint32Array::get(Handle<ExternalUint32Array> array,
3951 int index) {
3952 return array->GetIsolate()->factory()->
3953 NewNumberFromUint(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003954}
3955
3956
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003957void ExternalUint32Array::set(int index, uint32_t value) {
3958 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003959 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3960 ptr[index] = value;
3961}
3962
3963
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003964float ExternalFloat32Array::get_scalar(int index) {
3965 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003966 float* ptr = static_cast<float*>(external_pointer());
3967 return ptr[index];
3968}
3969
3970
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003971Handle<Object> ExternalFloat32Array::get(Handle<ExternalFloat32Array> array,
3972 int index) {
3973 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003974}
3975
3976
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003977void ExternalFloat32Array::set(int index, float value) {
3978 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00003979 float* ptr = static_cast<float*>(external_pointer());
3980 ptr[index] = value;
3981}
3982
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003983
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003984double ExternalFloat64Array::get_scalar(int index) {
3985 DCHECK((index >= 0) && (index < this->length()));
Ben Murdoch257744e2011-11-30 15:57:28 +00003986 double* ptr = static_cast<double*>(external_pointer());
3987 return ptr[index];
3988}
3989
3990
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003991Handle<Object> ExternalFloat64Array::get(Handle<ExternalFloat64Array> array,
3992 int index) {
3993 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003994}
3995
3996
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003997void ExternalFloat64Array::set(int index, double value) {
3998 DCHECK((index >= 0) && (index < this->length()));
Ben Murdoch257744e2011-11-30 15:57:28 +00003999 double* ptr = static_cast<double*>(external_pointer());
4000 ptr[index] = value;
4001}
4002
4003
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004004void* FixedTypedArrayBase::DataPtr() {
4005 return FIELD_ADDR(this, kDataOffset);
4006}
4007
4008
4009int FixedTypedArrayBase::DataSize(InstanceType type) {
4010 int element_size;
4011 switch (type) {
4012#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
4013 case FIXED_##TYPE##_ARRAY_TYPE: \
4014 element_size = size; \
4015 break;
4016
4017 TYPED_ARRAYS(TYPED_ARRAY_CASE)
4018#undef TYPED_ARRAY_CASE
4019 default:
4020 UNREACHABLE();
4021 return 0;
4022 }
4023 return length() * element_size;
4024}
4025
4026
4027int FixedTypedArrayBase::DataSize() {
4028 return DataSize(map()->instance_type());
4029}
4030
4031
4032int FixedTypedArrayBase::size() {
4033 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
4034}
4035
4036
4037int FixedTypedArrayBase::TypedArraySize(InstanceType type) {
4038 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
4039}
4040
4041
4042uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
4043
4044
4045uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
4046
4047
4048int8_t Int8ArrayTraits::defaultValue() { return 0; }
4049
4050
4051uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
4052
4053
4054int16_t Int16ArrayTraits::defaultValue() { return 0; }
4055
4056
4057uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
4058
4059
4060int32_t Int32ArrayTraits::defaultValue() { return 0; }
4061
4062
4063float Float32ArrayTraits::defaultValue() {
4064 return static_cast<float>(base::OS::nan_value());
4065}
4066
4067
4068double Float64ArrayTraits::defaultValue() { return base::OS::nan_value(); }
4069
4070
4071template <class Traits>
4072typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
4073 DCHECK((index >= 0) && (index < this->length()));
4074 ElementType* ptr = reinterpret_cast<ElementType*>(
4075 FIELD_ADDR(this, kDataOffset));
4076 return ptr[index];
4077}
4078
4079
4080template<> inline
4081FixedTypedArray<Float64ArrayTraits>::ElementType
4082 FixedTypedArray<Float64ArrayTraits>::get_scalar(int index) {
4083 DCHECK((index >= 0) && (index < this->length()));
4084 return READ_DOUBLE_FIELD(this, ElementOffset(index));
4085}
4086
4087
4088template <class Traits>
4089void FixedTypedArray<Traits>::set(int index, ElementType value) {
4090 DCHECK((index >= 0) && (index < this->length()));
4091 ElementType* ptr = reinterpret_cast<ElementType*>(
4092 FIELD_ADDR(this, kDataOffset));
4093 ptr[index] = value;
4094}
4095
4096
4097template<> inline
4098void FixedTypedArray<Float64ArrayTraits>::set(
4099 int index, Float64ArrayTraits::ElementType value) {
4100 DCHECK((index >= 0) && (index < this->length()));
4101 WRITE_DOUBLE_FIELD(this, ElementOffset(index), value);
4102}
4103
4104
4105template <class Traits>
4106typename Traits::ElementType FixedTypedArray<Traits>::from_int(int value) {
4107 return static_cast<ElementType>(value);
4108}
4109
4110
4111template <> inline
4112uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_int(int value) {
4113 if (value < 0) return 0;
4114 if (value > 0xFF) return 0xFF;
4115 return static_cast<uint8_t>(value);
4116}
4117
4118
4119template <class Traits>
4120typename Traits::ElementType FixedTypedArray<Traits>::from_double(
4121 double value) {
4122 return static_cast<ElementType>(DoubleToInt32(value));
4123}
4124
4125
4126template<> inline
4127uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_double(double value) {
4128 if (value < 0) return 0;
4129 if (value > 0xFF) return 0xFF;
4130 return static_cast<uint8_t>(lrint(value));
4131}
4132
4133
4134template<> inline
4135float FixedTypedArray<Float32ArrayTraits>::from_double(double value) {
4136 return static_cast<float>(value);
4137}
4138
4139
4140template<> inline
4141double FixedTypedArray<Float64ArrayTraits>::from_double(double value) {
4142 return value;
4143}
4144
4145
4146template <class Traits>
4147Handle<Object> FixedTypedArray<Traits>::get(
4148 Handle<FixedTypedArray<Traits> > array,
4149 int index) {
4150 return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index));
4151}
4152
4153
4154template <class Traits>
4155Handle<Object> FixedTypedArray<Traits>::SetValue(
4156 Handle<FixedTypedArray<Traits> > array,
4157 uint32_t index,
4158 Handle<Object> value) {
4159 ElementType cast_value = Traits::defaultValue();
4160 if (index < static_cast<uint32_t>(array->length())) {
4161 if (value->IsSmi()) {
4162 int int_value = Handle<Smi>::cast(value)->value();
4163 cast_value = from_int(int_value);
4164 } else if (value->IsHeapNumber()) {
4165 double double_value = Handle<HeapNumber>::cast(value)->value();
4166 cast_value = from_double(double_value);
4167 } else {
4168 // Clamp undefined to the default value. All other types have been
4169 // converted to a number type further up in the call chain.
4170 DCHECK(value->IsUndefined());
4171 }
4172 array->set(index, cast_value);
4173 }
4174 return Traits::ToHandle(array->GetIsolate(), cast_value);
4175}
4176
4177
4178Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
4179 return handle(Smi::FromInt(scalar), isolate);
4180}
4181
4182
4183Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
4184 uint8_t scalar) {
4185 return handle(Smi::FromInt(scalar), isolate);
4186}
4187
4188
4189Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
4190 return handle(Smi::FromInt(scalar), isolate);
4191}
4192
4193
4194Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
4195 return handle(Smi::FromInt(scalar), isolate);
4196}
4197
4198
4199Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
4200 return handle(Smi::FromInt(scalar), isolate);
4201}
4202
4203
4204Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
4205 return isolate->factory()->NewNumberFromUint(scalar);
4206}
4207
4208
4209Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
4210 return isolate->factory()->NewNumberFromInt(scalar);
4211}
4212
4213
4214Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
4215 return isolate->factory()->NewNumber(scalar);
4216}
4217
4218
4219Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
4220 return isolate->factory()->NewNumber(scalar);
4221}
4222
4223
Iain Merrick9ac36c92010-09-13 15:29:50 +01004224int Map::visitor_id() {
4225 return READ_BYTE_FIELD(this, kVisitorIdOffset);
4226}
4227
4228
4229void Map::set_visitor_id(int id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004230 DCHECK(0 <= id && id < 256);
Iain Merrick9ac36c92010-09-13 15:29:50 +01004231 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
4232}
4233
Steve Block3ce2e202009-11-05 08:53:23 +00004234
Steve Blocka7e24c12009-10-30 11:49:00 +00004235int Map::instance_size() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004236 return NOBARRIER_READ_BYTE_FIELD(
4237 this, kInstanceSizeOffset) << kPointerSizeLog2;
Steve Blocka7e24c12009-10-30 11:49:00 +00004238}
4239
4240
4241int Map::inobject_properties() {
4242 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
4243}
4244
4245
4246int Map::pre_allocated_property_fields() {
4247 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
4248}
4249
4250
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004251int Map::GetInObjectPropertyOffset(int index) {
4252 // Adjust for the number of properties stored in the object.
4253 index -= inobject_properties();
4254 DCHECK(index <= 0);
4255 return instance_size() + (index * kPointerSize);
4256}
4257
4258
Steve Blocka7e24c12009-10-30 11:49:00 +00004259int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01004260 int instance_size = map->instance_size();
4261 if (instance_size != kVariableSizeSentinel) return instance_size;
Steve Blocka7e24c12009-10-30 11:49:00 +00004262 // Only inline the most frequent cases.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004263 InstanceType instance_type = map->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +00004264 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01004265 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00004266 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004267 if (instance_type == ONE_BYTE_STRING_TYPE ||
4268 instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
4269 return SeqOneByteString::SizeFor(
4270 reinterpret_cast<SeqOneByteString*>(this)->length());
Steve Block791712a2010-08-27 10:21:07 +01004271 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004272 if (instance_type == BYTE_ARRAY_TYPE) {
4273 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
4274 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004275 if (instance_type == FREE_SPACE_TYPE) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004276 return reinterpret_cast<FreeSpace*>(this)->nobarrier_size();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004277 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004278 if (instance_type == STRING_TYPE ||
4279 instance_type == INTERNALIZED_STRING_TYPE) {
Steve Block791712a2010-08-27 10:21:07 +01004280 return SeqTwoByteString::SizeFor(
4281 reinterpret_cast<SeqTwoByteString*>(this)->length());
4282 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004283 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
4284 return FixedDoubleArray::SizeFor(
4285 reinterpret_cast<FixedDoubleArray*>(this)->length());
4286 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004287 if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
4288 return reinterpret_cast<ConstantPoolArray*>(this)->size();
4289 }
4290 if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
4291 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
4292 return reinterpret_cast<FixedTypedArrayBase*>(
4293 this)->TypedArraySize(instance_type);
4294 }
4295 DCHECK(instance_type == CODE_TYPE);
Steve Block791712a2010-08-27 10:21:07 +01004296 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00004297}
4298
4299
4300void Map::set_instance_size(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004301 DCHECK_EQ(0, value & (kPointerSize - 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00004302 value >>= kPointerSizeLog2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004303 DCHECK(0 <= value && value < 256);
4304 NOBARRIER_WRITE_BYTE_FIELD(
4305 this, kInstanceSizeOffset, static_cast<byte>(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00004306}
4307
4308
4309void Map::set_inobject_properties(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004310 DCHECK(0 <= value && value < 256);
Steve Blocka7e24c12009-10-30 11:49:00 +00004311 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
4312}
4313
4314
4315void Map::set_pre_allocated_property_fields(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004316 DCHECK(0 <= value && value < 256);
Steve Blocka7e24c12009-10-30 11:49:00 +00004317 WRITE_BYTE_FIELD(this,
4318 kPreAllocatedPropertyFieldsOffset,
4319 static_cast<byte>(value));
4320}
4321
4322
4323InstanceType Map::instance_type() {
4324 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
4325}
4326
4327
4328void Map::set_instance_type(InstanceType value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004329 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
4330}
4331
4332
4333int Map::unused_property_fields() {
4334 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
4335}
4336
4337
4338void Map::set_unused_property_fields(int value) {
4339 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
4340}
4341
4342
4343byte Map::bit_field() {
4344 return READ_BYTE_FIELD(this, kBitFieldOffset);
4345}
4346
4347
4348void Map::set_bit_field(byte value) {
4349 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
4350}
4351
4352
4353byte Map::bit_field2() {
4354 return READ_BYTE_FIELD(this, kBitField2Offset);
4355}
4356
4357
4358void Map::set_bit_field2(byte value) {
4359 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
4360}
4361
4362
4363void Map::set_non_instance_prototype(bool value) {
4364 if (value) {
4365 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
4366 } else {
4367 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
4368 }
4369}
4370
4371
4372bool Map::has_non_instance_prototype() {
4373 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
4374}
4375
4376
Steve Block6ded16b2010-05-10 14:33:55 +01004377void Map::set_function_with_prototype(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004378 set_bit_field(FunctionWithPrototype::update(bit_field(), value));
Steve Block6ded16b2010-05-10 14:33:55 +01004379}
4380
4381
4382bool Map::function_with_prototype() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004383 return FunctionWithPrototype::decode(bit_field());
Steve Block6ded16b2010-05-10 14:33:55 +01004384}
4385
4386
Steve Blocka7e24c12009-10-30 11:49:00 +00004387void Map::set_is_access_check_needed(bool access_check_needed) {
4388 if (access_check_needed) {
4389 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
4390 } else {
4391 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
4392 }
4393}
4394
4395
4396bool Map::is_access_check_needed() {
4397 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
4398}
4399
4400
Steve Block8defd9f2010-07-08 12:39:36 +01004401void Map::set_is_extensible(bool value) {
4402 if (value) {
4403 set_bit_field2(bit_field2() | (1 << kIsExtensible));
4404 } else {
4405 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
4406 }
4407}
4408
4409bool Map::is_extensible() {
4410 return ((1 << kIsExtensible) & bit_field2()) != 0;
4411}
4412
4413
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004414void Map::set_is_prototype_map(bool value) {
4415 set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004416}
4417
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004418bool Map::is_prototype_map() {
4419 return IsPrototypeMapBits::decode(bit_field2());
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004420}
4421
4422
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004423void Map::set_dictionary_map(bool value) {
4424 uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value);
4425 new_bit_field3 = IsUnstable::update(new_bit_field3, value);
4426 set_bit_field3(new_bit_field3);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004427}
4428
4429
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004430bool Map::is_dictionary_map() {
4431 return DictionaryMap::decode(bit_field3());
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004432}
4433
Steve Block8defd9f2010-07-08 12:39:36 +01004434
Steve Blocka7e24c12009-10-30 11:49:00 +00004435Code::Flags Code::flags() {
4436 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
4437}
4438
4439
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004440void Map::set_owns_descriptors(bool owns_descriptors) {
4441 set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors));
4442}
4443
4444
4445bool Map::owns_descriptors() {
4446 return OwnsDescriptors::decode(bit_field3());
4447}
4448
4449
4450void Map::set_has_instance_call_handler() {
4451 set_bit_field3(HasInstanceCallHandler::update(bit_field3(), true));
4452}
4453
4454
4455bool Map::has_instance_call_handler() {
4456 return HasInstanceCallHandler::decode(bit_field3());
4457}
4458
4459
4460void Map::deprecate() {
4461 set_bit_field3(Deprecated::update(bit_field3(), true));
4462}
4463
4464
4465bool Map::is_deprecated() {
4466 return Deprecated::decode(bit_field3());
4467}
4468
4469
4470void Map::set_migration_target(bool value) {
4471 set_bit_field3(IsMigrationTarget::update(bit_field3(), value));
4472}
4473
4474
4475bool Map::is_migration_target() {
4476 return IsMigrationTarget::decode(bit_field3());
4477}
4478
4479
4480void Map::set_done_inobject_slack_tracking(bool value) {
4481 set_bit_field3(DoneInobjectSlackTracking::update(bit_field3(), value));
4482}
4483
4484
4485bool Map::done_inobject_slack_tracking() {
4486 return DoneInobjectSlackTracking::decode(bit_field3());
4487}
4488
4489
4490void Map::set_construction_count(int value) {
4491 set_bit_field3(ConstructionCount::update(bit_field3(), value));
4492}
4493
4494
4495int Map::construction_count() {
4496 return ConstructionCount::decode(bit_field3());
4497}
4498
4499
4500void Map::freeze() {
4501 set_bit_field3(IsFrozen::update(bit_field3(), true));
4502}
4503
4504
4505bool Map::is_frozen() {
4506 return IsFrozen::decode(bit_field3());
4507}
4508
4509
4510void Map::mark_unstable() {
4511 set_bit_field3(IsUnstable::update(bit_field3(), true));
4512}
4513
4514
4515bool Map::is_stable() {
4516 return !IsUnstable::decode(bit_field3());
4517}
4518
4519
4520bool Map::has_code_cache() {
4521 return code_cache() != GetIsolate()->heap()->empty_fixed_array();
4522}
4523
4524
4525bool Map::CanBeDeprecated() {
4526 int descriptor = LastAdded();
4527 for (int i = 0; i <= descriptor; i++) {
4528 PropertyDetails details = instance_descriptors()->GetDetails(i);
4529 if (details.representation().IsNone()) return true;
4530 if (details.representation().IsSmi()) return true;
4531 if (details.representation().IsDouble()) return true;
4532 if (details.representation().IsHeapObject()) return true;
4533 if (details.type() == CONSTANT) return true;
4534 }
4535 return false;
4536}
4537
4538
4539void Map::NotifyLeafMapLayoutChange() {
4540 if (is_stable()) {
4541 mark_unstable();
4542 dependent_code()->DeoptimizeDependentCodeGroup(
4543 GetIsolate(),
4544 DependentCode::kPrototypeCheckGroup);
4545 }
4546}
4547
4548
4549bool Map::CanOmitMapChecks() {
4550 return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
4551}
4552
4553
4554int DependentCode::number_of_entries(DependencyGroup group) {
4555 if (length() == 0) return 0;
4556 return Smi::cast(get(group))->value();
4557}
4558
4559
4560void DependentCode::set_number_of_entries(DependencyGroup group, int value) {
4561 set(group, Smi::FromInt(value));
4562}
4563
4564
4565bool DependentCode::is_code_at(int i) {
4566 return get(kCodesStartIndex + i)->IsCode();
4567}
4568
4569Code* DependentCode::code_at(int i) {
4570 return Code::cast(get(kCodesStartIndex + i));
4571}
4572
4573
4574CompilationInfo* DependentCode::compilation_info_at(int i) {
4575 return reinterpret_cast<CompilationInfo*>(
4576 Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
4577}
4578
4579
4580void DependentCode::set_object_at(int i, Object* object) {
4581 set(kCodesStartIndex + i, object);
4582}
4583
4584
4585Object* DependentCode::object_at(int i) {
4586 return get(kCodesStartIndex + i);
4587}
4588
4589
4590Object** DependentCode::slot_at(int i) {
4591 return RawFieldOfElementAt(kCodesStartIndex + i);
4592}
4593
4594
4595void DependentCode::clear_at(int i) {
4596 set_undefined(kCodesStartIndex + i);
4597}
4598
4599
4600void DependentCode::copy(int from, int to) {
4601 set(kCodesStartIndex + to, get(kCodesStartIndex + from));
4602}
4603
4604
4605void DependentCode::ExtendGroup(DependencyGroup group) {
4606 GroupStartIndexes starts(this);
4607 for (int g = kGroupCount - 1; g > group; g--) {
4608 if (starts.at(g) < starts.at(g + 1)) {
4609 copy(starts.at(g), starts.at(g + 1));
4610 }
4611 }
4612}
4613
4614
Steve Blocka7e24c12009-10-30 11:49:00 +00004615void Code::set_flags(Code::Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004616 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00004617 WRITE_INT_FIELD(this, kFlagsOffset, flags);
4618}
4619
4620
4621Code::Kind Code::kind() {
4622 return ExtractKindFromFlags(flags());
4623}
4624
4625
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004626bool Code::IsCodeStubOrIC() {
4627 return kind() == STUB || kind() == HANDLER || kind() == LOAD_IC ||
4628 kind() == KEYED_LOAD_IC || kind() == CALL_IC || kind() == STORE_IC ||
4629 kind() == KEYED_STORE_IC || kind() == BINARY_OP_IC ||
4630 kind() == COMPARE_IC || kind() == COMPARE_NIL_IC ||
4631 kind() == TO_BOOLEAN_IC;
4632}
4633
4634
Steve Blocka7e24c12009-10-30 11:49:00 +00004635InlineCacheState Code::ic_state() {
4636 InlineCacheState result = ExtractICStateFromFlags(flags());
4637 // Only allow uninitialized or debugger states for non-IC code
4638 // objects. This is used in the debugger to determine whether or not
4639 // a call to code object has been replaced with a debug break call.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004640 DCHECK(is_inline_cache_stub() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00004641 result == UNINITIALIZED ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004642 result == DEBUG_STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00004643 return result;
4644}
4645
4646
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004647ExtraICState Code::extra_ic_state() {
4648 DCHECK(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
Ben Murdochb8e0da22011-05-16 14:20:40 +01004649 return ExtractExtraICStateFromFlags(flags());
4650}
4651
4652
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004653Code::StubType Code::type() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004654 return ExtractTypeFromFlags(flags());
4655}
4656
4657
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004658// For initialization.
4659void Code::set_raw_kind_specific_flags1(int value) {
4660 WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004661}
4662
4663
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004664void Code::set_raw_kind_specific_flags2(int value) {
4665 WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004666}
4667
4668
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004669inline bool Code::is_crankshafted() {
4670 return IsCrankshaftedField::decode(
4671 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
Steve Blocka7e24c12009-10-30 11:49:00 +00004672}
4673
4674
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004675inline bool Code::is_hydrogen_stub() {
4676 return is_crankshafted() && kind() != OPTIMIZED_FUNCTION;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004677}
4678
4679
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004680inline void Code::set_is_crankshafted(bool value) {
4681 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4682 int updated = IsCrankshaftedField::update(previous, value);
4683 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4684}
4685
4686
4687inline bool Code::is_turbofanned() {
4688 DCHECK(kind() == OPTIMIZED_FUNCTION || kind() == STUB);
4689 return IsTurbofannedField::decode(
4690 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4691}
4692
4693
4694inline void Code::set_is_turbofanned(bool value) {
4695 DCHECK(kind() == OPTIMIZED_FUNCTION || kind() == STUB);
4696 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4697 int updated = IsTurbofannedField::update(previous, value);
4698 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004699}
4700
4701
Ben Murdochb0fe1622011-05-05 13:52:32 +01004702bool Code::optimizable() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004703 DCHECK_EQ(FUNCTION, kind());
Ben Murdochb0fe1622011-05-05 13:52:32 +01004704 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
4705}
4706
4707
4708void Code::set_optimizable(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004709 DCHECK_EQ(FUNCTION, kind());
Ben Murdochb0fe1622011-05-05 13:52:32 +01004710 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
4711}
4712
4713
4714bool Code::has_deoptimization_support() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004715 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004716 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4717 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004718}
4719
4720
4721void Code::set_has_deoptimization_support(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004722 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004723 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4724 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
4725 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4726}
4727
4728
4729bool Code::has_debug_break_slots() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004730 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004731 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4732 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
4733}
4734
4735
4736void Code::set_has_debug_break_slots(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004737 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004738 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4739 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
4740 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004741}
4742
4743
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004744bool Code::is_compiled_optimizable() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004745 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004746 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4747 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
4748}
4749
4750
4751void Code::set_compiled_optimizable(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004752 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004753 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4754 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
4755 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4756}
4757
4758
Ben Murdochb0fe1622011-05-05 13:52:32 +01004759int Code::allow_osr_at_loop_nesting_level() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004760 DCHECK_EQ(FUNCTION, kind());
4761 int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4762 return AllowOSRAtLoopNestingLevelField::decode(fields);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004763}
4764
4765
4766void Code::set_allow_osr_at_loop_nesting_level(int level) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004767 DCHECK_EQ(FUNCTION, kind());
4768 DCHECK(level >= 0 && level <= kMaxLoopNestingMarker);
4769 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4770 int updated = AllowOSRAtLoopNestingLevelField::update(previous, level);
4771 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004772}
4773
4774
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004775int Code::profiler_ticks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004776 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004777 return READ_BYTE_FIELD(this, kProfilerTicksOffset);
4778}
4779
4780
4781void Code::set_profiler_ticks(int ticks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004782 DCHECK(ticks < 256);
4783 if (kind() == FUNCTION) {
4784 WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
4785 }
4786}
4787
4788
4789int Code::builtin_index() {
4790 DCHECK_EQ(BUILTIN, kind());
4791 return READ_INT32_FIELD(this, kKindSpecificFlags1Offset);
4792}
4793
4794
4795void Code::set_builtin_index(int index) {
4796 DCHECK_EQ(BUILTIN, kind());
4797 WRITE_INT32_FIELD(this, kKindSpecificFlags1Offset, index);
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004798}
4799
4800
Ben Murdochb0fe1622011-05-05 13:52:32 +01004801unsigned Code::stack_slots() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004802 DCHECK(is_crankshafted());
4803 return StackSlotsField::decode(
4804 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004805}
4806
4807
4808void Code::set_stack_slots(unsigned slots) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004809 CHECK(slots <= (1 << kStackSlotsBitCount));
4810 DCHECK(is_crankshafted());
4811 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4812 int updated = StackSlotsField::update(previous, slots);
4813 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004814}
4815
4816
Steve Block1e0659c2011-05-24 12:43:12 +01004817unsigned Code::safepoint_table_offset() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004818 DCHECK(is_crankshafted());
4819 return SafepointTableOffsetField::decode(
4820 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004821}
4822
4823
Steve Block1e0659c2011-05-24 12:43:12 +01004824void Code::set_safepoint_table_offset(unsigned offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004825 CHECK(offset <= (1 << kSafepointTableOffsetBitCount));
4826 DCHECK(is_crankshafted());
4827 DCHECK(IsAligned(offset, static_cast<unsigned>(kIntSize)));
4828 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4829 int updated = SafepointTableOffsetField::update(previous, offset);
4830 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004831}
4832
4833
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004834unsigned Code::back_edge_table_offset() {
4835 DCHECK_EQ(FUNCTION, kind());
4836 return BackEdgeTableOffsetField::decode(
4837 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004838}
4839
4840
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004841void Code::set_back_edge_table_offset(unsigned offset) {
4842 DCHECK_EQ(FUNCTION, kind());
4843 DCHECK(IsAligned(offset, static_cast<unsigned>(kPointerSize)));
4844 offset = offset >> kPointerSizeLog2;
4845 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4846 int updated = BackEdgeTableOffsetField::update(previous, offset);
4847 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004848}
4849
4850
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004851bool Code::back_edges_patched_for_osr() {
4852 DCHECK_EQ(FUNCTION, kind());
4853 return allow_osr_at_loop_nesting_level() > 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004854}
4855
4856
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004857byte Code::to_boolean_state() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004858 return extra_ic_state();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004859}
4860
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004861
4862bool Code::has_function_cache() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004863 DCHECK(kind() == STUB);
4864 return HasFunctionCacheField::decode(
4865 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004866}
4867
4868
4869void Code::set_has_function_cache(bool flag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004870 DCHECK(kind() == STUB);
4871 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4872 int updated = HasFunctionCacheField::update(previous, flag);
4873 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4874}
4875
4876
4877bool Code::marked_for_deoptimization() {
4878 DCHECK(kind() == OPTIMIZED_FUNCTION);
4879 return MarkedForDeoptimizationField::decode(
4880 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4881}
4882
4883
4884void Code::set_marked_for_deoptimization(bool flag) {
4885 DCHECK(kind() == OPTIMIZED_FUNCTION);
4886 DCHECK(!flag || AllowDeoptimization::IsAllowed(GetIsolate()));
4887 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4888 int updated = MarkedForDeoptimizationField::update(previous, flag);
4889 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4890}
4891
4892
4893bool Code::is_weak_stub() {
4894 return CanBeWeakStub() && WeakStubField::decode(
4895 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4896}
4897
4898
4899void Code::mark_as_weak_stub() {
4900 DCHECK(CanBeWeakStub());
4901 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4902 int updated = WeakStubField::update(previous, true);
4903 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4904}
4905
4906
4907bool Code::is_invalidated_weak_stub() {
4908 return is_weak_stub() && InvalidatedWeakStubField::decode(
4909 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4910}
4911
4912
4913void Code::mark_as_invalidated_weak_stub() {
4914 DCHECK(is_inline_cache_stub());
4915 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4916 int updated = InvalidatedWeakStubField::update(previous, true);
4917 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004918}
4919
4920
Steve Blocka7e24c12009-10-30 11:49:00 +00004921bool Code::is_inline_cache_stub() {
4922 Kind kind = this->kind();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004923 switch (kind) {
4924#define CASE(name) case name: return true;
4925 IC_KIND_LIST(CASE)
4926#undef CASE
4927 default: return false;
4928 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004929}
4930
4931
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004932bool Code::is_keyed_stub() {
4933 return is_keyed_load_stub() || is_keyed_store_stub();
4934}
4935
4936
4937bool Code::is_debug_stub() {
4938 return ic_state() == DEBUG_STUB;
4939}
4940
4941
4942ConstantPoolArray* Code::constant_pool() {
4943 return ConstantPoolArray::cast(READ_FIELD(this, kConstantPoolOffset));
4944}
4945
4946
4947void Code::set_constant_pool(Object* value) {
4948 DCHECK(value->IsConstantPoolArray());
4949 WRITE_FIELD(this, kConstantPoolOffset, value);
4950 WRITE_BARRIER(GetHeap(), this, kConstantPoolOffset, value);
4951}
4952
4953
4954Code::Flags Code::ComputeFlags(Kind kind, InlineCacheState ic_state,
4955 ExtraICState extra_ic_state, StubType type,
4956 CacheHolderFlag holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004957 // Compute the bit mask.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004958 unsigned int bits = KindField::encode(kind)
Ben Murdoch589d6972011-11-30 16:04:58 +00004959 | ICStateField::encode(ic_state)
4960 | TypeField::encode(type)
4961 | ExtraICStateField::encode(extra_ic_state)
Ben Murdoch589d6972011-11-30 16:04:58 +00004962 | CacheHolderField::encode(holder);
4963 return static_cast<Flags>(bits);
Steve Blocka7e24c12009-10-30 11:49:00 +00004964}
4965
4966
4967Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01004968 ExtraICState extra_ic_state,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004969 CacheHolderFlag holder,
4970 StubType type) {
4971 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, holder);
4972}
4973
4974
4975Code::Flags Code::ComputeHandlerFlags(Kind handler_kind, StubType type,
4976 CacheHolderFlag holder) {
4977 return ComputeFlags(Code::HANDLER, MONOMORPHIC, handler_kind, type, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00004978}
4979
4980
4981Code::Kind Code::ExtractKindFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004982 return KindField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00004983}
4984
4985
4986InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004987 return ICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00004988}
4989
4990
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004991ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004992 return ExtraICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00004993}
4994
4995
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004996Code::StubType Code::ExtractTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004997 return TypeField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00004998}
4999
5000
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005001CacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005002 return CacheHolderField::decode(flags);
Steve Block8defd9f2010-07-08 12:39:36 +01005003}
5004
5005
Steve Blocka7e24c12009-10-30 11:49:00 +00005006Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005007 int bits = flags & ~TypeField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00005008 return static_cast<Flags>(bits);
5009}
5010
5011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005012Code::Flags Code::RemoveTypeAndHolderFromFlags(Flags flags) {
5013 int bits = flags & ~TypeField::kMask & ~CacheHolderField::kMask;
5014 return static_cast<Flags>(bits);
5015}
5016
5017
Steve Blocka7e24c12009-10-30 11:49:00 +00005018Code* Code::GetCodeFromTargetAddress(Address address) {
5019 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
5020 // GetCodeFromTargetAddress might be called when marking objects during mark
5021 // sweep. reinterpret_cast is therefore used instead of the more appropriate
5022 // Code::cast. Code::cast does not work when the object's map is
5023 // marked.
5024 Code* result = reinterpret_cast<Code*>(code);
5025 return result;
5026}
5027
5028
Steve Block791712a2010-08-27 10:21:07 +01005029Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
5030 return HeapObject::
5031 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
5032}
5033
5034
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005035bool Code::IsWeakObjectInOptimizedCode(Object* object) {
5036 if (!FLAG_collect_maps) return false;
5037 if (object->IsMap()) {
5038 return Map::cast(object)->CanTransition() &&
5039 FLAG_weak_embedded_maps_in_optimized_code;
5040 }
5041 if (object->IsJSObject() ||
5042 (object->IsCell() && Cell::cast(object)->value()->IsJSObject())) {
5043 return FLAG_weak_embedded_objects_in_optimized_code;
5044 }
5045 return false;
5046}
5047
5048
5049class Code::FindAndReplacePattern {
5050 public:
5051 FindAndReplacePattern() : count_(0) { }
5052 void Add(Handle<Map> map_to_find, Handle<Object> obj_to_replace) {
5053 DCHECK(count_ < kMaxCount);
5054 find_[count_] = map_to_find;
5055 replace_[count_] = obj_to_replace;
5056 ++count_;
5057 }
5058 private:
5059 static const int kMaxCount = 4;
5060 int count_;
5061 Handle<Map> find_[kMaxCount];
5062 Handle<Object> replace_[kMaxCount];
5063 friend class Code;
5064};
5065
5066
5067bool Code::IsWeakObjectInIC(Object* object) {
5068 return object->IsMap() && Map::cast(object)->CanTransition() &&
5069 FLAG_collect_maps &&
5070 FLAG_weak_embedded_maps_in_ic;
5071}
5072
5073
5074Object* Map::prototype() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00005075 return READ_FIELD(this, kPrototypeOffset);
5076}
5077
5078
5079void Map::set_prototype(Object* value, WriteBarrierMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005080 DCHECK(value->IsNull() || value->IsJSReceiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00005081 WRITE_FIELD(this, kPrototypeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005082 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
Steve Block1e0659c2011-05-24 12:43:12 +01005083}
5084
5085
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005086// If the descriptor is using the empty transition array, install a new empty
5087// transition array that will have place for an element transition.
5088static void EnsureHasTransitionArray(Handle<Map> map) {
5089 Handle<TransitionArray> transitions;
5090 if (!map->HasTransitionArray()) {
5091 transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
5092 transitions->set_back_pointer_storage(map->GetBackPointer());
5093 } else if (!map->transitions()->IsFullTransitionArray()) {
5094 transitions = TransitionArray::ExtendToFullTransitionArray(map);
Ben Murdoch257744e2011-11-30 15:57:28 +00005095 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00005096 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005097 }
5098 map->set_transitions(*transitions);
5099}
5100
5101
5102void Map::InitializeDescriptors(DescriptorArray* descriptors) {
5103 int len = descriptors->number_of_descriptors();
5104 set_instance_descriptors(descriptors);
5105 SetNumberOfOwnDescriptors(len);
5106}
5107
5108
5109ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
5110
5111
5112void Map::set_bit_field3(uint32_t bits) {
5113 if (kInt32Size != kPointerSize) {
5114 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0);
5115 }
5116 WRITE_UINT32_FIELD(this, kBitField3Offset, bits);
5117}
5118
5119
5120uint32_t Map::bit_field3() {
5121 return READ_UINT32_FIELD(this, kBitField3Offset);
5122}
5123
5124
5125void Map::AppendDescriptor(Descriptor* desc) {
5126 DescriptorArray* descriptors = instance_descriptors();
5127 int number_of_own_descriptors = NumberOfOwnDescriptors();
5128 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
5129 descriptors->Append(desc);
5130 SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
5131}
5132
5133
5134Object* Map::GetBackPointer() {
5135 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5136 if (object->IsDescriptorArray()) {
5137 return TransitionArray::cast(object)->back_pointer_storage();
Ben Murdoch257744e2011-11-30 15:57:28 +00005138 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005139 DCHECK(object->IsMap() || object->IsUndefined());
5140 return object;
5141 }
5142}
5143
5144
5145bool Map::HasElementsTransition() {
5146 return HasTransitionArray() && transitions()->HasElementsTransition();
5147}
5148
5149
5150bool Map::HasTransitionArray() const {
5151 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5152 return object->IsTransitionArray();
5153}
5154
5155
5156Map* Map::elements_transition_map() {
5157 int index = transitions()->Search(GetHeap()->elements_transition_symbol());
5158 return transitions()->GetTarget(index);
5159}
5160
5161
5162bool Map::CanHaveMoreTransitions() {
5163 if (!HasTransitionArray()) return true;
5164 return FixedArray::SizeFor(transitions()->length() +
5165 TransitionArray::kTransitionSize)
5166 <= Page::kMaxRegularHeapObjectSize;
5167}
5168
5169
5170Map* Map::GetTransition(int transition_index) {
5171 return transitions()->GetTarget(transition_index);
5172}
5173
5174
5175int Map::SearchTransition(Name* name) {
5176 if (HasTransitionArray()) return transitions()->Search(name);
5177 return TransitionArray::kNotFound;
5178}
5179
5180
5181FixedArray* Map::GetPrototypeTransitions() {
5182 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
5183 if (!transitions()->HasPrototypeTransitions()) {
5184 return GetHeap()->empty_fixed_array();
5185 }
5186 return transitions()->GetPrototypeTransitions();
5187}
5188
5189
5190void Map::SetPrototypeTransitions(
5191 Handle<Map> map, Handle<FixedArray> proto_transitions) {
5192 EnsureHasTransitionArray(map);
5193 int old_number_of_transitions = map->NumberOfProtoTransitions();
5194#ifdef DEBUG
5195 if (map->HasPrototypeTransitions()) {
5196 DCHECK(map->GetPrototypeTransitions() != *proto_transitions);
5197 map->ZapPrototypeTransitions();
5198 }
5199#endif
5200 map->transitions()->SetPrototypeTransitions(*proto_transitions);
5201 map->SetNumberOfProtoTransitions(old_number_of_transitions);
5202}
5203
5204
5205bool Map::HasPrototypeTransitions() {
5206 return HasTransitionArray() && transitions()->HasPrototypeTransitions();
5207}
5208
5209
5210TransitionArray* Map::transitions() const {
5211 DCHECK(HasTransitionArray());
5212 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5213 return TransitionArray::cast(object);
5214}
5215
5216
5217void Map::set_transitions(TransitionArray* transition_array,
5218 WriteBarrierMode mode) {
5219 // Transition arrays are not shared. When one is replaced, it should not
5220 // keep referenced objects alive, so we zap it.
5221 // When there is another reference to the array somewhere (e.g. a handle),
5222 // not zapping turns from a waste of memory into a source of crashes.
5223 if (HasTransitionArray()) {
5224#ifdef DEBUG
5225 for (int i = 0; i < transitions()->number_of_transitions(); i++) {
5226 Map* target = transitions()->GetTarget(i);
5227 if (target->instance_descriptors() == instance_descriptors()) {
5228 Name* key = transitions()->GetKey(i);
5229 int new_target_index = transition_array->Search(key);
5230 DCHECK(new_target_index != TransitionArray::kNotFound);
5231 DCHECK(transition_array->GetTarget(new_target_index) == target);
5232 }
Ben Murdoch257744e2011-11-30 15:57:28 +00005233 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005234#endif
5235 DCHECK(transitions() != transition_array);
5236 ZapTransitions();
Ben Murdoch257744e2011-11-30 15:57:28 +00005237 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005238
5239 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005240 CONDITIONAL_WRITE_BARRIER(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005241 GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00005242}
5243
5244
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005245void Map::init_back_pointer(Object* undefined) {
5246 DCHECK(undefined->IsUndefined());
5247 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined);
5248}
5249
5250
5251void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
5252 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
5253 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) ||
5254 (value->IsMap() && GetBackPointer()->IsUndefined()));
5255 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5256 if (object->IsTransitionArray()) {
5257 TransitionArray::cast(object)->set_back_pointer_storage(value);
Ben Murdoch257744e2011-11-30 15:57:28 +00005258 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005259 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value);
5260 CONDITIONAL_WRITE_BARRIER(
5261 GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00005262 }
5263}
5264
5265
Steve Block6ded16b2010-05-10 14:33:55 +01005266ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005267ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005268ACCESSORS(Map, constructor, Object, kConstructorOffset)
5269
5270ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005271ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005272ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005273
5274ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005275ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005276ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005277ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005278
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005279ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
5280ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005281
Steve Blocka7e24c12009-10-30 11:49:00 +00005282ACCESSORS(AccessorInfo, name, Object, kNameOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005283ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005284ACCESSORS(AccessorInfo, expected_receiver_type, Object,
5285 kExpectedReceiverTypeOffset)
5286
5287ACCESSORS(DeclaredAccessorDescriptor, serialized_data, ByteArray,
5288 kSerializedDataOffset)
5289
5290ACCESSORS(DeclaredAccessorInfo, descriptor, DeclaredAccessorDescriptor,
5291 kDescriptorOffset)
5292
5293ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset)
5294ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
5295ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
5296
5297ACCESSORS(Box, value, Object, kValueOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005298
5299ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
5300ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
Ben Murdochc7cc0282012-03-05 14:35:55 +00005301
Steve Blocka7e24c12009-10-30 11:49:00 +00005302ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
5303ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
5304ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
5305
5306ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
5307ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
5308ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
5309ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
5310ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
5311ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
5312
5313ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
5314ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
5315
5316ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
5317ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005318ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005319
5320ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
5321ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005322ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
5323 kPrototypeTemplateOffset)
5324ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
5325ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
5326 kNamedPropertyHandlerOffset)
5327ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
5328 kIndexedPropertyHandlerOffset)
5329ACCESSORS(FunctionTemplateInfo, instance_template, Object,
5330 kInstanceTemplateOffset)
5331ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
5332ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
5333ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
5334 kInstanceCallHandlerOffset)
5335ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
5336 kAccessCheckInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005337ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005338
5339ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
5340ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
5341 kInternalFieldCountOffset)
5342
5343ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
5344ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
5345
5346ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
5347
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005348ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
5349ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
5350ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
5351ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
5352 kPretenureCreateCountOffset)
5353ACCESSORS(AllocationSite, dependent_code, DependentCode,
5354 kDependentCodeOffset)
5355ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
5356ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
5357
Steve Blocka7e24c12009-10-30 11:49:00 +00005358ACCESSORS(Script, source, Object, kSourceOffset)
5359ACCESSORS(Script, name, Object, kNameOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005360ACCESSORS(Script, id, Smi, kIdOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005361ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
5362ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005363ACCESSORS(Script, context_data, Object, kContextOffset)
Ben Murdoch257744e2011-11-30 15:57:28 +00005364ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005365ACCESSORS_TO_SMI(Script, type, kTypeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005366ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00005367ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005368ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
5369 kEvalFrominstructionsOffsetOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005370ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
5371BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
5372ACCESSORS(Script, source_url, Object, kSourceUrlOffset)
5373ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005374
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005375Script::CompilationType Script::compilation_type() {
5376 return BooleanBit::get(flags(), kCompilationTypeBit) ?
5377 COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST;
5378}
5379void Script::set_compilation_type(CompilationType type) {
5380 set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
5381 type == COMPILATION_TYPE_EVAL));
5382}
5383Script::CompilationState Script::compilation_state() {
5384 return BooleanBit::get(flags(), kCompilationStateBit) ?
5385 COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
5386}
5387void Script::set_compilation_state(CompilationState state) {
5388 set_flags(BooleanBit::set(flags(), kCompilationStateBit,
5389 state == COMPILATION_STATE_COMPILED));
5390}
5391
5392
Steve Blocka7e24c12009-10-30 11:49:00 +00005393ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
5394ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
5395ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
5396ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
5397
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005398ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
5399ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
5400ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00005401ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00005402
Steve Blocka7e24c12009-10-30 11:49:00 +00005403ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005404ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
5405 kOptimizedCodeMapOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005406ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005407ACCESSORS(SharedFunctionInfo, feedback_vector, TypeFeedbackVector,
5408 kFeedbackVectorOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005409ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
5410 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01005411ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005412ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
5413ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
5414ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005415
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005416
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005417SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005418BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
5419 kHiddenPrototypeBit)
5420BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
5421BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
5422 kNeedsAccessCheckBit)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005423BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
5424 kReadOnlyPrototypeBit)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005425BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
5426 kRemovePrototypeBit)
5427BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
5428 kDoNotCacheBit)
Steve Blocka7e24c12009-10-30 11:49:00 +00005429BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
5430 kIsExpressionBit)
5431BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
5432 kIsTopLevelBit)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005433
Steve Blockd0582a62009-12-15 09:54:21 +00005434BOOL_ACCESSORS(SharedFunctionInfo,
5435 compiler_hints,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005436 allows_lazy_compilation,
5437 kAllowLazyCompilation)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005438BOOL_ACCESSORS(SharedFunctionInfo,
5439 compiler_hints,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005440 allows_lazy_compilation_without_context,
5441 kAllowLazyCompilationWithoutContext)
5442BOOL_ACCESSORS(SharedFunctionInfo,
5443 compiler_hints,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005444 uses_arguments,
5445 kUsesArguments)
5446BOOL_ACCESSORS(SharedFunctionInfo,
5447 compiler_hints,
5448 has_duplicate_parameters,
5449 kHasDuplicateParameters)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005450BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, asm_function, kIsAsmFunction)
Steve Blocka7e24c12009-10-30 11:49:00 +00005451
Iain Merrick75681382010-08-19 15:07:18 +01005452
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005453#if V8_HOST_ARCH_32_BIT
5454SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
5455SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00005456 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005457SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00005458 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005459SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5460SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00005461 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005462SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
5463SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00005464 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005465SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00005466 kCompilerHintsOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005467SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
5468 kOptCountAndBailoutReasonOffset)
5469SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005470SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005471SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
5472
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005473#else
Steve Blocka7e24c12009-10-30 11:49:00 +00005474
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005475#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005476 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005477 int holder::name() const { \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005478 int value = READ_INT_FIELD(this, offset); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005479 DCHECK(kHeapObjectTag == 1); \
5480 DCHECK((value & kHeapObjectTag) == 0); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005481 return value >> 1; \
5482 } \
5483 void holder::set_##name(int value) { \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005484 DCHECK(kHeapObjectTag == 1); \
5485 DCHECK((value & 0xC0000000) == 0xC0000000 || \
5486 (value & 0xC0000000) == 0x0); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005487 WRITE_INT_FIELD(this, \
5488 offset, \
5489 (value << 1) & ~kHeapObjectTag); \
5490 }
5491
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005492#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
5493 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005494 INT_ACCESSORS(holder, name, offset)
5495
5496
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005497PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005498PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5499 formal_parameter_count,
5500 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005501
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005502PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5503 expected_nof_properties,
5504 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005505PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5506
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005507PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
5508PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5509 start_position_and_type,
5510 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005511
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005512PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5513 function_token_position,
5514 kFunctionTokenPositionOffset)
5515PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5516 compiler_hints,
5517 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005518
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005519PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005520 opt_count_and_bailout_reason,
5521 kOptCountAndBailoutReasonOffset)
5522PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005523
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005524PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5525 ast_node_count,
5526 kAstNodeCountOffset)
5527PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5528 profiler_ticks,
5529 kProfilerTicksOffset)
5530
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005531#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005532
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005533
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005534BOOL_GETTER(SharedFunctionInfo,
5535 compiler_hints,
5536 optimization_disabled,
5537 kOptimizationDisabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01005538
5539
5540void SharedFunctionInfo::set_optimization_disabled(bool disable) {
5541 set_compiler_hints(BooleanBit::set(compiler_hints(),
5542 kOptimizationDisabled,
5543 disable));
5544 // If disabling optimizations we reflect that in the code object so
5545 // it will not be counted as optimizable code.
5546 if ((code()->kind() == Code::FUNCTION) && disable) {
5547 code()->set_optimizable(false);
5548 }
5549}
5550
5551
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005552StrictMode SharedFunctionInfo::strict_mode() {
5553 return BooleanBit::get(compiler_hints(), kStrictModeFunction)
5554 ? STRICT : SLOPPY;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005555}
5556
5557
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005558void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
5559 // We only allow mode transitions from sloppy to strict.
5560 DCHECK(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005561 int hints = compiler_hints();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005562 hints = BooleanBit::set(hints, kStrictModeFunction, strict_mode == STRICT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005563 set_compiler_hints(hints);
5564}
5565
5566
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005567FunctionKind SharedFunctionInfo::kind() {
5568 return FunctionKindBits::decode(compiler_hints());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005569}
5570
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005571
5572void SharedFunctionInfo::set_kind(FunctionKind kind) {
5573 DCHECK(IsValidFunctionKind(kind));
5574 int hints = compiler_hints();
5575 hints = FunctionKindBits::update(hints, kind);
5576 set_compiler_hints(hints);
5577}
5578
5579
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005580BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005581BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
5582 kInlineBuiltin)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005583BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
5584 name_should_print_as_anonymous,
5585 kNameShouldPrintAsAnonymous)
5586BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
5587BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005588BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005589BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
5590BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
5591BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
5592BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
5593BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
5594 kIsConciseMethod)
Ben Murdoch257744e2011-11-30 15:57:28 +00005595
Steve Block6ded16b2010-05-10 14:33:55 +01005596ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
5597ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
5598
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005599ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
5600
Steve Block3ce2e202009-11-05 08:53:23 +00005601bool Script::HasValidSource() {
5602 Object* src = this->source();
5603 if (!src->IsString()) return true;
5604 String* src_str = String::cast(src);
5605 if (!StringShape(src_str).IsExternal()) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005606 if (src_str->IsOneByteRepresentation()) {
5607 return ExternalOneByteString::cast(src)->resource() != NULL;
Steve Block3ce2e202009-11-05 08:53:23 +00005608 } else if (src_str->IsTwoByteRepresentation()) {
5609 return ExternalTwoByteString::cast(src)->resource() != NULL;
5610 }
5611 return true;
5612}
5613
5614
Steve Blocka7e24c12009-10-30 11:49:00 +00005615void SharedFunctionInfo::DontAdaptArguments() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005616 DCHECK(code()->kind() == Code::BUILTIN);
Steve Blocka7e24c12009-10-30 11:49:00 +00005617 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
5618}
5619
5620
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005621int SharedFunctionInfo::start_position() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00005622 return start_position_and_type() >> kStartPositionShift;
5623}
5624
5625
5626void SharedFunctionInfo::set_start_position(int start_position) {
5627 set_start_position_and_type((start_position << kStartPositionShift)
5628 | (start_position_and_type() & ~kStartPositionMask));
5629}
5630
5631
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005632Code* SharedFunctionInfo::code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00005633 return Code::cast(READ_FIELD(this, kCodeOffset));
5634}
5635
5636
5637void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005638 DCHECK(value->kind() != Code::OPTIMIZED_FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00005639 WRITE_FIELD(this, kCodeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005640 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00005641}
5642
5643
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005644void SharedFunctionInfo::ReplaceCode(Code* value) {
5645 // If the GC metadata field is already used then the function was
5646 // enqueued as a code flushing candidate and we remove it now.
5647 if (code()->gc_metadata() != NULL) {
5648 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
5649 flusher->EvictCandidate(this);
5650 }
5651
5652 DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
5653
5654 set_code(value);
5655}
5656
5657
5658ScopeInfo* SharedFunctionInfo::scope_info() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005659 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005660}
5661
5662
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005663void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005664 WriteBarrierMode mode) {
5665 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005666 CONDITIONAL_WRITE_BARRIER(GetHeap(),
5667 this,
5668 kScopeInfoOffset,
5669 reinterpret_cast<Object*>(value),
5670 mode);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005671}
5672
5673
Steve Blocka7e24c12009-10-30 11:49:00 +00005674bool SharedFunctionInfo::is_compiled() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005675 return code() != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy);
Steve Blocka7e24c12009-10-30 11:49:00 +00005676}
5677
5678
Steve Block6ded16b2010-05-10 14:33:55 +01005679bool SharedFunctionInfo::IsApiFunction() {
5680 return function_data()->IsFunctionTemplateInfo();
5681}
5682
5683
5684FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005685 DCHECK(IsApiFunction());
Steve Block6ded16b2010-05-10 14:33:55 +01005686 return FunctionTemplateInfo::cast(function_data());
5687}
5688
5689
Ben Murdochb0fe1622011-05-05 13:52:32 +01005690bool SharedFunctionInfo::HasBuiltinFunctionId() {
Kristian Monsen25f61362010-05-21 11:50:48 +01005691 return function_data()->IsSmi();
5692}
5693
5694
Ben Murdochb0fe1622011-05-05 13:52:32 +01005695BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005696 DCHECK(HasBuiltinFunctionId());
Ben Murdochb0fe1622011-05-05 13:52:32 +01005697 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00005698}
5699
5700
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005701int SharedFunctionInfo::ic_age() {
5702 return ICAgeBits::decode(counters());
Iain Merrick75681382010-08-19 15:07:18 +01005703}
5704
5705
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005706void SharedFunctionInfo::set_ic_age(int ic_age) {
5707 set_counters(ICAgeBits::update(counters(), ic_age));
5708}
5709
5710
5711int SharedFunctionInfo::deopt_count() {
5712 return DeoptCountBits::decode(counters());
5713}
5714
5715
5716void SharedFunctionInfo::set_deopt_count(int deopt_count) {
5717 set_counters(DeoptCountBits::update(counters(), deopt_count));
5718}
5719
5720
5721void SharedFunctionInfo::increment_deopt_count() {
5722 int value = counters();
5723 int deopt_count = DeoptCountBits::decode(value);
5724 deopt_count = (deopt_count + 1) & DeoptCountBits::kMax;
5725 set_counters(DeoptCountBits::update(value, deopt_count));
5726}
5727
5728
5729int SharedFunctionInfo::opt_reenable_tries() {
5730 return OptReenableTriesBits::decode(counters());
5731}
5732
5733
5734void SharedFunctionInfo::set_opt_reenable_tries(int tries) {
5735 set_counters(OptReenableTriesBits::update(counters(), tries));
5736}
5737
5738
5739int SharedFunctionInfo::opt_count() {
5740 return OptCountBits::decode(opt_count_and_bailout_reason());
5741}
5742
5743
5744void SharedFunctionInfo::set_opt_count(int opt_count) {
5745 set_opt_count_and_bailout_reason(
5746 OptCountBits::update(opt_count_and_bailout_reason(), opt_count));
5747}
5748
5749
5750BailoutReason SharedFunctionInfo::DisableOptimizationReason() {
5751 BailoutReason reason = static_cast<BailoutReason>(
5752 DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason()));
5753 return reason;
Iain Merrick75681382010-08-19 15:07:18 +01005754}
5755
5756
Ben Murdochb0fe1622011-05-05 13:52:32 +01005757bool SharedFunctionInfo::has_deoptimization_support() {
5758 Code* code = this->code();
5759 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
5760}
5761
5762
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005763void SharedFunctionInfo::TryReenableOptimization() {
5764 int tries = opt_reenable_tries();
5765 set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
5766 // We reenable optimization whenever the number of tries is a large
5767 // enough power of 2.
5768 if (tries >= 16 && (((tries - 1) & tries) == 0)) {
5769 set_optimization_disabled(false);
5770 set_opt_count(0);
5771 set_deopt_count(0);
5772 code()->set_optimizable(true);
5773 }
5774}
5775
5776
Steve Blocka7e24c12009-10-30 11:49:00 +00005777bool JSFunction::IsBuiltin() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005778 return context()->global_object()->IsJSBuiltinsObject();
5779}
5780
5781
5782bool JSFunction::IsFromNativeScript() {
5783 Object* script = shared()->script();
5784 bool native = script->IsScript() &&
5785 Script::cast(script)->type()->value() == Script::TYPE_NATIVE;
5786 DCHECK(!IsBuiltin() || native); // All builtins are also native.
5787 return native;
5788}
5789
5790
5791bool JSFunction::IsFromExtensionScript() {
5792 Object* script = shared()->script();
5793 return script->IsScript() &&
5794 Script::cast(script)->type()->value() == Script::TYPE_EXTENSION;
Steve Blocka7e24c12009-10-30 11:49:00 +00005795}
5796
5797
Ben Murdochb0fe1622011-05-05 13:52:32 +01005798bool JSFunction::NeedsArgumentsAdaption() {
5799 return shared()->formal_parameter_count() !=
5800 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
5801}
5802
5803
5804bool JSFunction::IsOptimized() {
5805 return code()->kind() == Code::OPTIMIZED_FUNCTION;
5806}
5807
5808
Ben Murdoch8b112d22011-06-08 16:22:53 +01005809bool JSFunction::IsOptimizable() {
5810 return code()->kind() == Code::FUNCTION && code()->optimizable();
5811}
5812
5813
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005814bool JSFunction::IsMarkedForOptimization() {
5815 return code() == GetIsolate()->builtins()->builtin(
5816 Builtins::kCompileOptimized);
5817}
5818
5819
5820bool JSFunction::IsMarkedForConcurrentOptimization() {
5821 return code() == GetIsolate()->builtins()->builtin(
5822 Builtins::kCompileOptimizedConcurrent);
5823}
5824
5825
5826bool JSFunction::IsInOptimizationQueue() {
5827 return code() == GetIsolate()->builtins()->builtin(
5828 Builtins::kInOptimizationQueue);
5829}
5830
5831
5832bool JSFunction::IsInobjectSlackTrackingInProgress() {
5833 return has_initial_map() &&
5834 initial_map()->construction_count() != JSFunction::kNoSlackTracking;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005835}
5836
5837
Steve Blocka7e24c12009-10-30 11:49:00 +00005838Code* JSFunction::code() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005839 return Code::cast(
Steve Block791712a2010-08-27 10:21:07 +01005840 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00005841}
5842
5843
5844void JSFunction::set_code(Code* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005845 DCHECK(!GetHeap()->InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01005846 Address entry = value->entry();
5847 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005848 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
5849 this,
5850 HeapObject::RawField(this, kCodeEntryOffset),
5851 value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005852}
5853
5854
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005855void JSFunction::set_code_no_write_barrier(Code* value) {
5856 DCHECK(!GetHeap()->InNewSpace(value));
5857 Address entry = value->entry();
5858 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5859}
5860
5861
Ben Murdochb0fe1622011-05-05 13:52:32 +01005862void JSFunction::ReplaceCode(Code* code) {
5863 bool was_optimized = IsOptimized();
5864 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
5865
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005866 if (was_optimized && is_optimized) {
5867 shared()->EvictFromOptimizedCodeMap(this->code(),
5868 "Replacing with another optimized code");
5869 }
5870
Ben Murdochb0fe1622011-05-05 13:52:32 +01005871 set_code(code);
5872
5873 // Add/remove the function from the list of optimized functions for this
5874 // context based on the state change.
5875 if (!was_optimized && is_optimized) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005876 context()->native_context()->AddOptimizedFunction(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005877 }
5878 if (was_optimized && !is_optimized) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005879 // TODO(titzer): linear in the number of optimized functions; fix!
5880 context()->native_context()->RemoveOptimizedFunction(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005881 }
5882}
5883
5884
Steve Blocka7e24c12009-10-30 11:49:00 +00005885Context* JSFunction::context() {
5886 return Context::cast(READ_FIELD(this, kContextOffset));
5887}
5888
5889
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005890JSObject* JSFunction::global_proxy() {
5891 return context()->global_proxy();
Iain Merrick75681382010-08-19 15:07:18 +01005892}
5893
5894
Steve Blocka7e24c12009-10-30 11:49:00 +00005895void JSFunction::set_context(Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005896 DCHECK(value->IsUndefined() || value->IsContext());
Steve Blocka7e24c12009-10-30 11:49:00 +00005897 WRITE_FIELD(this, kContextOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005898 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005899}
5900
5901ACCESSORS(JSFunction, prototype_or_initial_map, Object,
5902 kPrototypeOrInitialMapOffset)
5903
5904
5905Map* JSFunction::initial_map() {
5906 return Map::cast(prototype_or_initial_map());
5907}
5908
5909
Steve Blocka7e24c12009-10-30 11:49:00 +00005910bool JSFunction::has_initial_map() {
5911 return prototype_or_initial_map()->IsMap();
5912}
5913
5914
5915bool JSFunction::has_instance_prototype() {
5916 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
5917}
5918
5919
5920bool JSFunction::has_prototype() {
5921 return map()->has_non_instance_prototype() || has_instance_prototype();
5922}
5923
5924
5925Object* JSFunction::instance_prototype() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005926 DCHECK(has_instance_prototype());
Steve Blocka7e24c12009-10-30 11:49:00 +00005927 if (has_initial_map()) return initial_map()->prototype();
5928 // When there is no initial map and the prototype is a JSObject, the
5929 // initial map field is used for the prototype field.
5930 return prototype_or_initial_map();
5931}
5932
5933
5934Object* JSFunction::prototype() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005935 DCHECK(has_prototype());
Steve Blocka7e24c12009-10-30 11:49:00 +00005936 // If the function's prototype property has been set to a non-JSObject
5937 // value, that value is stored in the constructor field of the map.
5938 if (map()->has_non_instance_prototype()) return map()->constructor();
5939 return instance_prototype();
5940}
5941
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005942
Steve Block6ded16b2010-05-10 14:33:55 +01005943bool JSFunction::should_have_prototype() {
5944 return map()->function_with_prototype();
5945}
5946
Steve Blocka7e24c12009-10-30 11:49:00 +00005947
5948bool JSFunction::is_compiled() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005949 return code() != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy);
Steve Blocka7e24c12009-10-30 11:49:00 +00005950}
5951
5952
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005953FixedArray* JSFunction::literals() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005954 DCHECK(!shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005955 return literals_or_bindings();
5956}
5957
5958
5959void JSFunction::set_literals(FixedArray* literals) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005960 DCHECK(!shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005961 set_literals_or_bindings(literals);
5962}
5963
5964
5965FixedArray* JSFunction::function_bindings() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005966 DCHECK(shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005967 return literals_or_bindings();
5968}
5969
5970
5971void JSFunction::set_function_bindings(FixedArray* bindings) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005972 DCHECK(shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005973 // Bound function literal may be initialized to the empty fixed array
5974 // before the bindings are set.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005975 DCHECK(bindings == GetHeap()->empty_fixed_array() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005976 bindings->map() == GetHeap()->fixed_cow_array_map());
5977 set_literals_or_bindings(bindings);
5978}
5979
5980
Steve Blocka7e24c12009-10-30 11:49:00 +00005981int JSFunction::NumberOfLiterals() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005982 DCHECK(!shared()->bound());
Steve Blocka7e24c12009-10-30 11:49:00 +00005983 return literals()->length();
5984}
5985
5986
5987Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005988 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005989 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00005990}
5991
5992
5993void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
5994 Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005995 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005996 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005997 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
Steve Block6ded16b2010-05-10 14:33:55 +01005998}
5999
6000
6001Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006002 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01006003 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
6004}
6005
6006
6007void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
6008 Code* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006009 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01006010 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006011 DCHECK(!GetHeap()->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006012}
6013
6014
Ben Murdoch257744e2011-11-30 15:57:28 +00006015ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006016ACCESSORS(JSProxy, hash, Object, kHashOffset)
Ben Murdoch589d6972011-11-30 16:04:58 +00006017ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
6018ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
6019
6020
6021void JSProxy::InitializeBody(int object_size, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006022 DCHECK(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
Ben Murdoch589d6972011-11-30 16:04:58 +00006023 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
6024 WRITE_FIELD(this, offset, value);
6025 }
6026}
Ben Murdoch257744e2011-11-30 15:57:28 +00006027
6028
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006029ACCESSORS(JSCollection, table, Object, kTableOffset)
6030
6031
6032#define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \
6033 template<class Derived, class TableType> \
6034 type* OrderedHashTableIterator<Derived, TableType>::name() const { \
6035 return type::cast(READ_FIELD(this, offset)); \
6036 } \
6037 template<class Derived, class TableType> \
6038 void OrderedHashTableIterator<Derived, TableType>::set_##name( \
6039 type* value, WriteBarrierMode mode) { \
6040 WRITE_FIELD(this, offset, value); \
6041 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
6042 }
6043
6044ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset)
6045ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Object, kIndexOffset)
6046ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Object, kKindOffset)
6047
6048#undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS
6049
6050
6051ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
6052ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006053
6054
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006055Address Foreign::foreign_address() {
6056 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006057}
6058
6059
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006060void Foreign::set_foreign_address(Address value) {
6061 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006062}
6063
6064
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006065ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
6066ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
6067ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
6068SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
6069ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
6070SMI_ACCESSORS(JSGeneratorObject, stack_handler_index, kStackHandlerIndexOffset)
6071
6072bool JSGeneratorObject::is_suspended() {
6073 DCHECK_LT(kGeneratorExecuting, kGeneratorClosed);
6074 DCHECK_EQ(kGeneratorClosed, 0);
6075 return continuation() > 0;
6076}
6077
6078bool JSGeneratorObject::is_closed() {
6079 return continuation() == kGeneratorClosed;
6080}
6081
6082bool JSGeneratorObject::is_executing() {
6083 return continuation() == kGeneratorExecuting;
6084}
6085
6086ACCESSORS(JSModule, context, Object, kContextOffset)
6087ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset)
6088
6089
Steve Blocka7e24c12009-10-30 11:49:00 +00006090ACCESSORS(JSValue, value, Object, kValueOffset)
6091
6092
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006093HeapNumber* HeapNumber::cast(Object* object) {
6094 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
6095 return reinterpret_cast<HeapNumber*>(object);
6096}
6097
6098
6099const HeapNumber* HeapNumber::cast(const Object* object) {
6100 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
6101 return reinterpret_cast<const HeapNumber*>(object);
Steve Blocka7e24c12009-10-30 11:49:00 +00006102}
6103
6104
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006105ACCESSORS(JSDate, value, Object, kValueOffset)
6106ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
6107ACCESSORS(JSDate, year, Object, kYearOffset)
6108ACCESSORS(JSDate, month, Object, kMonthOffset)
6109ACCESSORS(JSDate, day, Object, kDayOffset)
6110ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
6111ACCESSORS(JSDate, hour, Object, kHourOffset)
6112ACCESSORS(JSDate, min, Object, kMinOffset)
6113ACCESSORS(JSDate, sec, Object, kSecOffset)
6114
6115
Steve Block1e0659c2011-05-24 12:43:12 +01006116ACCESSORS(JSMessageObject, type, String, kTypeOffset)
6117ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
6118ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
Steve Block1e0659c2011-05-24 12:43:12 +01006119ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
6120SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
6121SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
6122
6123
Steve Blocka7e24c12009-10-30 11:49:00 +00006124INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006125INT_ACCESSORS(Code, prologue_offset, kPrologueOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01006126ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006127ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01006128ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006129ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
6130ACCESSORS(Code, next_code_link, Object, kNextCodeLinkOffset)
6131
6132
6133void Code::WipeOutHeader() {
6134 WRITE_FIELD(this, kRelocationInfoOffset, NULL);
6135 WRITE_FIELD(this, kHandlerTableOffset, NULL);
6136 WRITE_FIELD(this, kDeoptimizationDataOffset, NULL);
6137 WRITE_FIELD(this, kConstantPoolOffset, NULL);
6138 // Do not wipe out major/minor keys on a code stub or IC
6139 if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) {
6140 WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL);
6141 }
6142}
6143
6144
6145Object* Code::type_feedback_info() {
6146 DCHECK(kind() == FUNCTION);
6147 return raw_type_feedback_info();
6148}
6149
6150
6151void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
6152 DCHECK(kind() == FUNCTION);
6153 set_raw_type_feedback_info(value, mode);
6154 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
6155 value, mode);
6156}
6157
6158
6159uint32_t Code::stub_key() {
6160 DCHECK(IsCodeStubOrIC());
6161 Smi* smi_key = Smi::cast(raw_type_feedback_info());
6162 return static_cast<uint32_t>(smi_key->value());
6163}
6164
6165
6166void Code::set_stub_key(uint32_t key) {
6167 DCHECK(IsCodeStubOrIC());
6168 set_raw_type_feedback_info(Smi::FromInt(key));
6169}
6170
6171
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006172ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
6173INT_ACCESSORS(Code, ic_age, kICAgeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00006174
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006175
Steve Blocka7e24c12009-10-30 11:49:00 +00006176byte* Code::instruction_start() {
6177 return FIELD_ADDR(this, kHeaderSize);
6178}
6179
6180
Leon Clarkeac952652010-07-15 11:15:24 +01006181byte* Code::instruction_end() {
6182 return instruction_start() + instruction_size();
6183}
6184
6185
Steve Blocka7e24c12009-10-30 11:49:00 +00006186int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01006187 return RoundUp(instruction_size(), kObjectAlignment);
6188}
6189
6190
6191ByteArray* Code::unchecked_relocation_info() {
6192 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00006193}
6194
6195
6196byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01006197 return unchecked_relocation_info()->GetDataStartAddress();
6198}
6199
6200
6201int Code::relocation_size() {
6202 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00006203}
6204
6205
6206byte* Code::entry() {
6207 return instruction_start();
6208}
6209
6210
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006211bool Code::contains(byte* inner_pointer) {
6212 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
Steve Blocka7e24c12009-10-30 11:49:00 +00006213}
6214
6215
Steve Blocka7e24c12009-10-30 11:49:00 +00006216ACCESSORS(JSArray, length, Object, kLengthOffset)
6217
6218
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006219void* JSArrayBuffer::backing_store() const {
6220 intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
6221 return reinterpret_cast<void*>(ptr);
6222}
6223
6224
6225void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
6226 intptr_t ptr = reinterpret_cast<intptr_t>(value);
6227 WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
6228}
6229
6230
6231ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
6232ACCESSORS_TO_SMI(JSArrayBuffer, flag, kFlagOffset)
6233
6234
6235bool JSArrayBuffer::is_external() {
6236 return BooleanBit::get(flag(), kIsExternalBit);
6237}
6238
6239
6240void JSArrayBuffer::set_is_external(bool value) {
6241 set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
6242}
6243
6244
6245bool JSArrayBuffer::should_be_freed() {
6246 return BooleanBit::get(flag(), kShouldBeFreed);
6247}
6248
6249
6250void JSArrayBuffer::set_should_be_freed(bool value) {
6251 set_flag(BooleanBit::set(flag(), kShouldBeFreed, value));
6252}
6253
6254
6255ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
6256ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset)
6257
6258
6259ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
6260ACCESSORS(JSArrayBufferView, byte_offset, Object, kByteOffsetOffset)
6261ACCESSORS(JSArrayBufferView, byte_length, Object, kByteLengthOffset)
6262ACCESSORS(JSArrayBufferView, weak_next, Object, kWeakNextOffset)
6263ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
6264
Steve Blocka7e24c12009-10-30 11:49:00 +00006265ACCESSORS(JSRegExp, data, Object, kDataOffset)
6266
6267
6268JSRegExp::Type JSRegExp::TypeTag() {
6269 Object* data = this->data();
6270 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
6271 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
6272 return static_cast<JSRegExp::Type>(smi->value());
6273}
6274
6275
6276int JSRegExp::CaptureCount() {
6277 switch (TypeTag()) {
6278 case ATOM:
6279 return 0;
6280 case IRREGEXP:
6281 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
6282 default:
6283 UNREACHABLE();
6284 return -1;
6285 }
6286}
6287
6288
6289JSRegExp::Flags JSRegExp::GetFlags() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006290 DCHECK(this->data()->IsFixedArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00006291 Object* data = this->data();
6292 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
6293 return Flags(smi->value());
6294}
6295
6296
6297String* JSRegExp::Pattern() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006298 DCHECK(this->data()->IsFixedArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00006299 Object* data = this->data();
6300 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
6301 return pattern;
6302}
6303
6304
6305Object* JSRegExp::DataAt(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006306 DCHECK(TypeTag() != NOT_COMPILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00006307 return FixedArray::cast(data())->get(index);
6308}
6309
6310
6311void JSRegExp::SetDataAt(int index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006312 DCHECK(TypeTag() != NOT_COMPILED);
6313 DCHECK(index >= kDataIndex); // Only implementation data can be set this way.
Steve Blocka7e24c12009-10-30 11:49:00 +00006314 FixedArray::cast(data())->set(index, value);
6315}
6316
6317
Ben Murdoch589d6972011-11-30 16:04:58 +00006318ElementsKind JSObject::GetElementsKind() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006319 ElementsKind kind = map()->elements_kind();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006320#if DEBUG
6321 FixedArrayBase* fixed_array =
6322 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006323
6324 // If a GC was caused while constructing this object, the elements
6325 // pointer may point to a one pointer filler map.
6326 if (ElementsAreSafeToExamine()) {
6327 Map* map = fixed_array->map();
6328 DCHECK((IsFastSmiOrObjectElementsKind(kind) &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006329 (map == GetHeap()->fixed_array_map() ||
6330 map == GetHeap()->fixed_cow_array_map())) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006331 (IsFastDoubleElementsKind(kind) &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006332 (fixed_array->IsFixedDoubleArray() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006333 fixed_array == GetHeap()->empty_fixed_array())) ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006334 (kind == DICTIONARY_ELEMENTS &&
6335 fixed_array->IsFixedArray() &&
6336 fixed_array->IsDictionary()) ||
6337 (kind > DICTIONARY_ELEMENTS));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006338 DCHECK((kind != SLOPPY_ARGUMENTS_ELEMENTS) ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006339 (elements()->IsFixedArray() && elements()->length() >= 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006340 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006341#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006342 return kind;
Steve Blocka7e24c12009-10-30 11:49:00 +00006343}
6344
6345
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006346ElementsAccessor* JSObject::GetElementsAccessor() {
6347 return ElementsAccessor::ForKind(GetElementsKind());
6348}
6349
6350
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006351bool JSObject::HasFastObjectElements() {
6352 return IsFastObjectElementsKind(GetElementsKind());
Steve Blocka7e24c12009-10-30 11:49:00 +00006353}
6354
6355
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006356bool JSObject::HasFastSmiElements() {
6357 return IsFastSmiElementsKind(GetElementsKind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006358}
6359
6360
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006361bool JSObject::HasFastSmiOrObjectElements() {
6362 return IsFastSmiOrObjectElementsKind(GetElementsKind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006363}
6364
6365
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006366bool JSObject::HasFastDoubleElements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006367 return IsFastDoubleElementsKind(GetElementsKind());
6368}
6369
6370
6371bool JSObject::HasFastHoleyElements() {
6372 return IsFastHoleyElementsKind(GetElementsKind());
6373}
6374
6375
6376bool JSObject::HasFastElements() {
6377 return IsFastElementsKind(GetElementsKind());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006378}
6379
6380
Steve Blocka7e24c12009-10-30 11:49:00 +00006381bool JSObject::HasDictionaryElements() {
6382 return GetElementsKind() == DICTIONARY_ELEMENTS;
6383}
6384
6385
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006386bool JSObject::HasSloppyArgumentsElements() {
6387 return GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006388}
6389
6390
Steve Block3ce2e202009-11-05 08:53:23 +00006391bool JSObject::HasExternalArrayElements() {
Steve Block44f0eee2011-05-26 01:26:41 +01006392 HeapObject* array = elements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006393 DCHECK(array != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01006394 return array->IsExternalArray();
Steve Block3ce2e202009-11-05 08:53:23 +00006395}
6396
6397
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006398#define EXTERNAL_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \
6399bool JSObject::HasExternal##Type##Elements() { \
6400 HeapObject* array = elements(); \
6401 DCHECK(array != NULL); \
6402 if (!array->IsHeapObject()) \
6403 return false; \
6404 return array->map()->instance_type() == EXTERNAL_##TYPE##_ARRAY_TYPE; \
6405}
6406
6407TYPED_ARRAYS(EXTERNAL_ELEMENTS_CHECK)
6408
6409#undef EXTERNAL_ELEMENTS_CHECK
6410
6411
6412bool JSObject::HasFixedTypedArrayElements() {
6413 HeapObject* array = elements();
6414 DCHECK(array != NULL);
6415 return array->IsFixedTypedArrayBase();
Steve Block3ce2e202009-11-05 08:53:23 +00006416}
6417
6418
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006419#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \
6420bool JSObject::HasFixed##Type##Elements() { \
6421 HeapObject* array = elements(); \
6422 DCHECK(array != NULL); \
6423 if (!array->IsHeapObject()) \
6424 return false; \
6425 return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \
6426}
6427
6428TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)
6429
6430#undef FIXED_TYPED_ELEMENTS_CHECK
Steve Block3ce2e202009-11-05 08:53:23 +00006431
6432
Steve Blocka7e24c12009-10-30 11:49:00 +00006433bool JSObject::HasNamedInterceptor() {
6434 return map()->has_named_interceptor();
6435}
6436
6437
6438bool JSObject::HasIndexedInterceptor() {
6439 return map()->has_indexed_interceptor();
6440}
6441
6442
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006443NameDictionary* JSObject::property_dictionary() {
6444 DCHECK(!HasFastProperties());
6445 return NameDictionary::cast(properties());
Steve Blocka7e24c12009-10-30 11:49:00 +00006446}
6447
6448
Ben Murdochc7cc0282012-03-05 14:35:55 +00006449SeededNumberDictionary* JSObject::element_dictionary() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006450 DCHECK(HasDictionaryElements());
Ben Murdochc7cc0282012-03-05 14:35:55 +00006451 return SeededNumberDictionary::cast(elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00006452}
6453
6454
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006455bool Name::IsHashFieldComputed(uint32_t field) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006456 return (field & kHashNotComputedMask) == 0;
6457}
6458
6459
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006460bool Name::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006461 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00006462}
6463
6464
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006465uint32_t Name::Hash() {
Steve Blocka7e24c12009-10-30 11:49:00 +00006466 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00006467 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006468 if (IsHashFieldComputed(field)) return field >> kHashShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006469 // Slow case: compute hash code and set it. Has to be a string.
6470 return String::cast(this)->ComputeAndSetHash();
6471}
6472
6473bool Name::IsOwn() {
6474 return this->IsSymbol() && Symbol::cast(this)->is_own();
Steve Blocka7e24c12009-10-30 11:49:00 +00006475}
6476
6477
Ben Murdochc7cc0282012-03-05 14:35:55 +00006478StringHasher::StringHasher(int length, uint32_t seed)
Steve Blocka7e24c12009-10-30 11:49:00 +00006479 : length_(length),
Ben Murdochc7cc0282012-03-05 14:35:55 +00006480 raw_running_hash_(seed),
Steve Blocka7e24c12009-10-30 11:49:00 +00006481 array_index_(0),
6482 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006483 is_first_char_(true) {
6484 DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0);
Ben Murdochc7cc0282012-03-05 14:35:55 +00006485}
Steve Blocka7e24c12009-10-30 11:49:00 +00006486
6487
6488bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00006489 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00006490}
6491
6492
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006493uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
6494 running_hash += c;
6495 running_hash += (running_hash << 10);
6496 running_hash ^= (running_hash >> 6);
6497 return running_hash;
6498}
6499
6500
6501uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
6502 running_hash += (running_hash << 3);
6503 running_hash ^= (running_hash >> 11);
6504 running_hash += (running_hash << 15);
6505 if ((running_hash & String::kHashBitMask) == 0) {
6506 return kZeroHash;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006507 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006508 return running_hash;
6509}
6510
6511
6512void StringHasher::AddCharacter(uint16_t c) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006513 // Use the Jenkins one-at-a-time hash function to update the hash
6514 // for the given character.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006515 raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
6516}
6517
6518
6519bool StringHasher::UpdateIndex(uint16_t c) {
6520 DCHECK(is_array_index_);
6521 if (c < '0' || c > '9') {
6522 is_array_index_ = false;
6523 return false;
6524 }
6525 int d = c - '0';
6526 if (is_first_char_) {
6527 is_first_char_ = false;
6528 if (c == '0' && length_ > 1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006529 is_array_index_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006530 return false;
6531 }
6532 }
6533 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
6534 is_array_index_ = false;
6535 return false;
6536 }
6537 array_index_ = array_index_ * 10 + d;
6538 return true;
6539}
6540
6541
6542template<typename Char>
6543inline void StringHasher::AddCharacters(const Char* chars, int length) {
6544 DCHECK(sizeof(Char) == 1 || sizeof(Char) == 2);
6545 int i = 0;
6546 if (is_array_index_) {
6547 for (; i < length; i++) {
6548 AddCharacter(chars[i]);
6549 if (!UpdateIndex(chars[i])) {
6550 i++;
6551 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00006552 }
6553 }
6554 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006555 for (; i < length; i++) {
6556 DCHECK(!is_array_index_);
6557 AddCharacter(chars[i]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006558 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006559}
6560
6561
Steve Block44f0eee2011-05-26 01:26:41 +01006562template <typename schar>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006563uint32_t StringHasher::HashSequentialString(const schar* chars,
6564 int length,
6565 uint32_t seed) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00006566 StringHasher hasher(length, seed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006567 if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
6568 return hasher.GetHashField();
6569}
6570
6571
6572uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) {
6573 IteratingStringHasher hasher(string->length(), seed);
6574 // Nothing to do.
6575 if (hasher.has_trivial_hash()) return hasher.GetHashField();
6576 ConsString* cons_string = String::VisitFlat(&hasher, string);
6577 // The string was flat.
6578 if (cons_string == NULL) return hasher.GetHashField();
6579 // This is a ConsString, iterate across it.
6580 ConsStringIteratorOp op(cons_string);
6581 int offset;
6582 while (NULL != (string = op.Next(&offset))) {
6583 String::VisitFlat(&hasher, string, offset);
Steve Block44f0eee2011-05-26 01:26:41 +01006584 }
6585 return hasher.GetHashField();
6586}
6587
6588
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006589void IteratingStringHasher::VisitOneByteString(const uint8_t* chars,
6590 int length) {
6591 AddCharacters(chars, length);
6592}
6593
6594
6595void IteratingStringHasher::VisitTwoByteString(const uint16_t* chars,
6596 int length) {
6597 AddCharacters(chars, length);
6598}
6599
6600
6601bool Name::AsArrayIndex(uint32_t* index) {
6602 return IsString() && String::cast(this)->AsArrayIndex(index);
6603}
6604
6605
Steve Blocka7e24c12009-10-30 11:49:00 +00006606bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00006607 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006608 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
6609 return false;
6610 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006611 return SlowAsArrayIndex(index);
6612}
6613
6614
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006615void String::SetForwardedInternalizedString(String* canonical) {
6616 DCHECK(IsInternalizedString());
6617 DCHECK(HasHashCode());
6618 if (canonical == this) return; // No need to forward.
6619 DCHECK(SlowEquals(canonical));
6620 DCHECK(canonical->IsInternalizedString());
6621 DCHECK(canonical->HasHashCode());
6622 WRITE_FIELD(this, kHashFieldOffset, canonical);
6623 // Setting the hash field to a tagged value sets the LSB, causing the hash
6624 // code to be interpreted as uninitialized. We use this fact to recognize
6625 // that we have a forwarded string.
6626 DCHECK(!HasHashCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00006627}
6628
6629
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006630String* String::GetForwardedInternalizedString() {
6631 DCHECK(IsInternalizedString());
6632 if (HasHashCode()) return this;
6633 String* canonical = String::cast(READ_FIELD(this, kHashFieldOffset));
6634 DCHECK(canonical->IsInternalizedString());
6635 DCHECK(SlowEquals(canonical));
6636 DCHECK(canonical->HasHashCode());
6637 return canonical;
6638}
6639
6640
6641Object* JSReceiver::GetConstructor() {
6642 return map()->constructor();
6643}
6644
6645
6646Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
6647 Handle<Name> name) {
6648 if (object->IsJSProxy()) {
6649 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6650 return JSProxy::HasPropertyWithHandler(proxy, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006651 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006652 Maybe<PropertyAttributes> result = GetPropertyAttributes(object, name);
6653 if (!result.has_value) return Maybe<bool>();
6654 return maybe(result.value != ABSENT);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006655}
6656
6657
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006658Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
6659 Handle<Name> name) {
6660 if (object->IsJSProxy()) {
6661 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6662 return JSProxy::HasPropertyWithHandler(proxy, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006663 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006664 Maybe<PropertyAttributes> result = GetOwnPropertyAttributes(object, name);
6665 if (!result.has_value) return Maybe<bool>();
6666 return maybe(result.value != ABSENT);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006667}
6668
6669
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006670Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
6671 Handle<JSReceiver> object, Handle<Name> key) {
6672 uint32_t index;
6673 if (object->IsJSObject() && key->AsArrayIndex(&index)) {
6674 return GetElementAttribute(object, index);
Steve Blockd0582a62009-12-15 09:54:21 +00006675 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006676 LookupIterator it(object, key);
6677 return GetPropertyAttributes(&it);
Steve Blockd0582a62009-12-15 09:54:21 +00006678}
6679
6680
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006681Maybe<PropertyAttributes> JSReceiver::GetElementAttribute(
6682 Handle<JSReceiver> object, uint32_t index) {
6683 if (object->IsJSProxy()) {
6684 return JSProxy::GetElementAttributeWithHandler(
6685 Handle<JSProxy>::cast(object), object, index);
6686 }
6687 return JSObject::GetElementAttributeWithReceiver(
6688 Handle<JSObject>::cast(object), object, index, true);
6689}
6690
6691
6692bool JSGlobalObject::IsDetached() {
6693 return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this);
6694}
6695
6696
6697bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) const {
6698 const PrototypeIterator iter(this->GetIsolate(),
6699 const_cast<JSGlobalProxy*>(this));
6700 return iter.GetCurrent() != global;
6701}
6702
6703
6704Handle<Smi> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) {
6705 return object->IsJSProxy()
6706 ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object))
6707 : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object));
6708}
6709
6710
6711Object* JSReceiver::GetIdentityHash() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006712 return IsJSProxy()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006713 ? JSProxy::cast(this)->GetIdentityHash()
6714 : JSObject::cast(this)->GetIdentityHash();
Steve Blockd0582a62009-12-15 09:54:21 +00006715}
6716
6717
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006718Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
6719 if (object->IsJSProxy()) {
6720 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6721 return JSProxy::HasElementWithHandler(proxy, index);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006722 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006723 Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
6724 Handle<JSObject>::cast(object), object, index, true);
6725 if (!result.has_value) return Maybe<bool>();
6726 return maybe(result.value != ABSENT);
6727}
6728
6729
6730Maybe<bool> JSReceiver::HasOwnElement(Handle<JSReceiver> object,
6731 uint32_t index) {
6732 if (object->IsJSProxy()) {
6733 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6734 return JSProxy::HasElementWithHandler(proxy, index);
6735 }
6736 Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
6737 Handle<JSObject>::cast(object), object, index, false);
6738 if (!result.has_value) return Maybe<bool>();
6739 return maybe(result.value != ABSENT);
6740}
6741
6742
6743Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttribute(
6744 Handle<JSReceiver> object, uint32_t index) {
6745 if (object->IsJSProxy()) {
6746 return JSProxy::GetElementAttributeWithHandler(
6747 Handle<JSProxy>::cast(object), object, index);
6748 }
6749 return JSObject::GetElementAttributeWithReceiver(
6750 Handle<JSObject>::cast(object), object, index, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00006751}
6752
6753
6754bool AccessorInfo::all_can_read() {
6755 return BooleanBit::get(flag(), kAllCanReadBit);
6756}
6757
6758
6759void AccessorInfo::set_all_can_read(bool value) {
6760 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
6761}
6762
6763
6764bool AccessorInfo::all_can_write() {
6765 return BooleanBit::get(flag(), kAllCanWriteBit);
6766}
6767
6768
6769void AccessorInfo::set_all_can_write(bool value) {
6770 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
6771}
6772
6773
Steve Blocka7e24c12009-10-30 11:49:00 +00006774PropertyAttributes AccessorInfo::property_attributes() {
6775 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
6776}
6777
6778
6779void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
Ben Murdoch589d6972011-11-30 16:04:58 +00006780 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006781}
6782
Ben Murdoch8b112d22011-06-08 16:22:53 +01006783
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006784bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
6785 if (!HasExpectedReceiverType()) return true;
6786 if (!receiver->IsJSObject()) return false;
6787 return FunctionTemplateInfo::cast(expected_receiver_type())
6788 ->IsTemplateFor(JSObject::cast(receiver)->map());
6789}
6790
6791
6792void ExecutableAccessorInfo::clear_setter() {
6793 set_setter(GetIsolate()->heap()->undefined_value(), SKIP_WRITE_BARRIER);
6794}
6795
6796
6797template<typename Derived, typename Shape, typename Key>
6798void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
6799 Handle<Object> key,
6800 Handle<Object> value) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01006801 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
6802}
6803
6804
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006805template<typename Derived, typename Shape, typename Key>
6806void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
6807 Handle<Object> key,
6808 Handle<Object> value,
6809 PropertyDetails details) {
6810 DCHECK(!key->IsName() ||
6811 details.IsDeleted() ||
6812 details.dictionary_index() > 0);
6813 int index = DerivedHashTable::EntryToIndex(entry);
6814 DisallowHeapAllocation no_gc;
Leon Clarke4515c472010-02-03 11:58:03 +00006815 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006816 FixedArray::set(index, *key, mode);
6817 FixedArray::set(index+1, *value, mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006818 FixedArray::set(index+2, details.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00006819}
6820
6821
Steve Block44f0eee2011-05-26 01:26:41 +01006822bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006823 DCHECK(other->IsNumber());
Steve Block44f0eee2011-05-26 01:26:41 +01006824 return key == static_cast<uint32_t>(other->Number());
6825}
6826
6827
Ben Murdochc7cc0282012-03-05 14:35:55 +00006828uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
6829 return ComputeIntegerHash(key, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01006830}
6831
6832
Ben Murdochc7cc0282012-03-05 14:35:55 +00006833uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
6834 Object* other) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006835 DCHECK(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00006836 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
Steve Block44f0eee2011-05-26 01:26:41 +01006837}
6838
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006839
Ben Murdochc7cc0282012-03-05 14:35:55 +00006840uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
6841 return ComputeIntegerHash(key, seed);
6842}
6843
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006844
Ben Murdochc7cc0282012-03-05 14:35:55 +00006845uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
6846 uint32_t seed,
6847 Object* other) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006848 DCHECK(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00006849 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
6850}
Steve Block44f0eee2011-05-26 01:26:41 +01006851
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006852
6853Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) {
6854 return isolate->factory()->NewNumberFromUint(key);
Steve Block44f0eee2011-05-26 01:26:41 +01006855}
6856
6857
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006858bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
Steve Block44f0eee2011-05-26 01:26:41 +01006859 // We know that all entries in a hash table had their hash keys created.
6860 // Use that knowledge to have fast failure.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006861 if (key->Hash() != Name::cast(other)->Hash()) return false;
6862 return key->Equals(Name::cast(other));
Steve Block44f0eee2011-05-26 01:26:41 +01006863}
6864
6865
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006866uint32_t NameDictionaryShape::Hash(Handle<Name> key) {
Steve Block44f0eee2011-05-26 01:26:41 +01006867 return key->Hash();
6868}
6869
6870
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006871uint32_t NameDictionaryShape::HashForObject(Handle<Name> key, Object* other) {
6872 return Name::cast(other)->Hash();
Steve Block44f0eee2011-05-26 01:26:41 +01006873}
6874
6875
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006876Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
6877 Handle<Name> key) {
6878 DCHECK(key->IsUniqueName());
Steve Block44f0eee2011-05-26 01:26:41 +01006879 return key;
6880}
6881
6882
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006883void NameDictionary::DoGenerateNewEnumerationIndices(
6884 Handle<NameDictionary> dictionary) {
6885 DerivedDictionary::GenerateNewEnumerationIndices(dictionary);
6886}
6887
6888
6889bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) {
6890 return key->SameValue(other);
6891}
6892
6893
6894uint32_t ObjectHashTableShape::Hash(Handle<Object> key) {
6895 return Smi::cast(key->GetHash())->value();
6896}
6897
6898
6899uint32_t ObjectHashTableShape::HashForObject(Handle<Object> key,
6900 Object* other) {
6901 return Smi::cast(other->GetHash())->value();
6902}
6903
6904
6905Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate,
6906 Handle<Object> key) {
6907 return key;
6908}
6909
6910
6911Handle<ObjectHashTable> ObjectHashTable::Shrink(
6912 Handle<ObjectHashTable> table, Handle<Object> key) {
6913 return DerivedHashTable::Shrink(table, key);
6914}
6915
6916
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006917template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006918bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006919 return key->SameValue(other);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006920}
6921
6922
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006923template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006924uint32_t WeakHashTableShape<entrysize>::Hash(Handle<Object> key) {
6925 intptr_t hash = reinterpret_cast<intptr_t>(*key);
6926 return (uint32_t)(hash & 0xFFFFFFFF);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006927}
6928
6929
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006930template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006931uint32_t WeakHashTableShape<entrysize>::HashForObject(Handle<Object> key,
6932 Object* other) {
6933 intptr_t hash = reinterpret_cast<intptr_t>(other);
6934 return (uint32_t)(hash & 0xFFFFFFFF);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006935}
6936
6937
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006938template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006939Handle<Object> WeakHashTableShape<entrysize>::AsHandle(Isolate* isolate,
6940 Handle<Object> key) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006941 return key;
6942}
6943
6944
Steve Block44f0eee2011-05-26 01:26:41 +01006945void Map::ClearCodeCache(Heap* heap) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006946 // No write barrier is needed since empty_fixed_array is not in new space.
6947 // Please note this function is used during marking:
6948 // - MarkCompactCollector::MarkUnmarkedObject
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006949 // - IncrementalMarking::Step
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006950 DCHECK(!heap->InNewSpace(heap->empty_fixed_array()));
6951 WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00006952}
6953
6954
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006955void JSArray::EnsureSize(Handle<JSArray> array, int required_size) {
6956 DCHECK(array->HasFastSmiOrObjectElements());
6957 Handle<FixedArray> elts = handle(FixedArray::cast(array->elements()));
Steve Blockd0582a62009-12-15 09:54:21 +00006958 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
6959 if (elts->length() < required_size) {
6960 // Doubling in size would be overkill, but leave some slack to avoid
6961 // constantly growing.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006962 Expand(array, required_size + (required_size >> 3));
Steve Blockd0582a62009-12-15 09:54:21 +00006963 // It's a performance benefit to keep a frequently used array in new-space.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006964 } else if (!array->GetHeap()->new_space()->Contains(*elts) &&
Steve Blockd0582a62009-12-15 09:54:21 +00006965 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
6966 // Expand will allocate a new backing store in new space even if the size
6967 // we asked for isn't larger than what we had before.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006968 Expand(array, required_size);
Steve Blockd0582a62009-12-15 09:54:21 +00006969 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006970}
6971
6972
Leon Clarke4515c472010-02-03 11:58:03 +00006973void JSArray::set_length(Smi* length) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006974 // Don't need a write barrier for a Smi.
Leon Clarke4515c472010-02-03 11:58:03 +00006975 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
6976}
6977
6978
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006979bool JSArray::AllowsSetElementsLength() {
6980 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006981 DCHECK(result == !HasExternalArrayElements());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006982 return result;
6983}
6984
6985
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006986void JSArray::SetContent(Handle<JSArray> array,
6987 Handle<FixedArrayBase> storage) {
6988 EnsureCanContainElements(array, storage, storage->length(),
6989 ALLOW_COPIED_DOUBLE_ELEMENTS);
6990
6991 DCHECK((storage->map() == array->GetHeap()->fixed_double_array_map() &&
6992 IsFastDoubleElementsKind(array->GetElementsKind())) ||
6993 ((storage->map() != array->GetHeap()->fixed_double_array_map()) &&
6994 (IsFastObjectElementsKind(array->GetElementsKind()) ||
6995 (IsFastSmiElementsKind(array->GetElementsKind()) &&
6996 Handle<FixedArray>::cast(storage)->ContainsOnlySmisOrHoles()))));
6997 array->set_elements(*storage);
6998 array->set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00006999}
7000
7001
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007002int TypeFeedbackInfo::ic_total_count() {
7003 int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7004 return ICTotalCountField::decode(current);
Steve Block44f0eee2011-05-26 01:26:41 +01007005}
7006
7007
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007008void TypeFeedbackInfo::set_ic_total_count(int count) {
7009 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7010 value = ICTotalCountField::update(value,
7011 ICTotalCountField::decode(count));
7012 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007013}
7014
7015
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007016int TypeFeedbackInfo::ic_with_type_info_count() {
7017 int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7018 return ICsWithTypeInfoCountField::decode(current);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007019}
7020
7021
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007022void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) {
7023 if (delta == 0) return;
7024 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7025 int new_count = ICsWithTypeInfoCountField::decode(value) + delta;
7026 // We can get negative count here when the type-feedback info is
7027 // shared between two code objects. The can only happen when
7028 // the debugger made a shallow copy of code object (see Heap::CopyCode).
7029 // Since we do not optimize when the debugger is active, we can skip
7030 // this counter update.
7031 if (new_count >= 0) {
7032 new_count &= ICsWithTypeInfoCountField::kMask;
7033 value = ICsWithTypeInfoCountField::update(value, new_count);
7034 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
7035 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007036}
7037
7038
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007039int TypeFeedbackInfo::ic_generic_count() {
7040 return Smi::cast(READ_FIELD(this, kStorage3Offset))->value();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007041}
7042
7043
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007044void TypeFeedbackInfo::change_ic_generic_count(int delta) {
7045 if (delta == 0) return;
7046 int new_count = ic_generic_count() + delta;
7047 if (new_count >= 0) {
7048 new_count &= ~Smi::kMinValue;
7049 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(new_count));
7050 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007051}
7052
7053
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007054void TypeFeedbackInfo::initialize_storage() {
7055 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0));
7056 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0));
7057 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(0));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007058}
7059
7060
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007061void TypeFeedbackInfo::change_own_type_change_checksum() {
7062 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7063 int checksum = OwnTypeChangeChecksum::decode(value);
7064 checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits);
7065 value = OwnTypeChangeChecksum::update(value, checksum);
7066 // Ensure packed bit field is in Smi range.
7067 if (value > Smi::kMaxValue) value |= Smi::kMinValue;
7068 if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
7069 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007070}
7071
7072
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007073void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) {
7074 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7075 int mask = (1 << kTypeChangeChecksumBits) - 1;
7076 value = InlinedTypeChangeChecksum::update(value, checksum & mask);
7077 // Ensure packed bit field is in Smi range.
7078 if (value > Smi::kMaxValue) value |= Smi::kMinValue;
7079 if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
7080 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007081}
7082
7083
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007084int TypeFeedbackInfo::own_type_change_checksum() {
7085 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7086 return OwnTypeChangeChecksum::decode(value);
7087}
7088
7089
7090bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
7091 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7092 int mask = (1 << kTypeChangeChecksumBits) - 1;
7093 return InlinedTypeChangeChecksum::decode(value) == (checksum & mask);
7094}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007095
7096
7097SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
7098
7099
Steve Block44f0eee2011-05-26 01:26:41 +01007100Relocatable::Relocatable(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01007101 isolate_ = isolate;
7102 prev_ = isolate->relocatable_top();
7103 isolate->set_relocatable_top(this);
7104}
7105
7106
7107Relocatable::~Relocatable() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007108 DCHECK_EQ(isolate_->relocatable_top(), this);
Steve Block44f0eee2011-05-26 01:26:41 +01007109 isolate_->set_relocatable_top(prev_);
Steve Blocka7e24c12009-10-30 11:49:00 +00007110}
7111
7112
Iain Merrick75681382010-08-19 15:07:18 +01007113int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
7114 return map->instance_size();
7115}
7116
7117
Ben Murdoch257744e2011-11-30 15:57:28 +00007118void Foreign::ForeignIterateBody(ObjectVisitor* v) {
Iain Merrick75681382010-08-19 15:07:18 +01007119 v->VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007120 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01007121}
7122
7123
7124template<typename StaticVisitor>
Ben Murdoch257744e2011-11-30 15:57:28 +00007125void Foreign::ForeignIterateBody() {
Iain Merrick75681382010-08-19 15:07:18 +01007126 StaticVisitor::VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007127 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01007128}
7129
7130
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007131void ExternalOneByteString::ExternalOneByteStringIterateBody(ObjectVisitor* v) {
7132 typedef v8::String::ExternalOneByteStringResource Resource;
7133 v->VisitExternalOneByteString(
Iain Merrick75681382010-08-19 15:07:18 +01007134 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7135}
7136
7137
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007138template <typename StaticVisitor>
7139void ExternalOneByteString::ExternalOneByteStringIterateBody() {
7140 typedef v8::String::ExternalOneByteStringResource Resource;
7141 StaticVisitor::VisitExternalOneByteString(
Iain Merrick75681382010-08-19 15:07:18 +01007142 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7143}
7144
7145
7146void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
7147 typedef v8::String::ExternalStringResource Resource;
7148 v->VisitExternalTwoByteString(
7149 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7150}
7151
7152
7153template<typename StaticVisitor>
7154void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
7155 typedef v8::String::ExternalStringResource Resource;
7156 StaticVisitor::VisitExternalTwoByteString(
7157 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7158}
7159
Iain Merrick75681382010-08-19 15:07:18 +01007160
7161template<int start_offset, int end_offset, int size>
7162void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
7163 HeapObject* obj,
7164 ObjectVisitor* v) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007165 v->VisitPointers(HeapObject::RawField(obj, start_offset),
7166 HeapObject::RawField(obj, end_offset));
Iain Merrick75681382010-08-19 15:07:18 +01007167}
7168
7169
7170template<int start_offset>
7171void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
7172 int object_size,
7173 ObjectVisitor* v) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007174 v->VisitPointers(HeapObject::RawField(obj, start_offset),
7175 HeapObject::RawField(obj, object_size));
Iain Merrick75681382010-08-19 15:07:18 +01007176}
7177
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007178
7179template<class Derived, class TableType>
7180Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
7181 TableType* table(TableType::cast(this->table()));
7182 int index = Smi::cast(this->index())->value();
7183 Object* key = table->KeyAt(index);
7184 DCHECK(!key->IsTheHole());
7185 return key;
7186}
7187
7188
7189void JSSetIterator::PopulateValueArray(FixedArray* array) {
7190 array->set(0, CurrentKey());
7191}
7192
7193
7194void JSMapIterator::PopulateValueArray(FixedArray* array) {
7195 array->set(0, CurrentKey());
7196 array->set(1, CurrentValue());
7197}
7198
7199
7200Object* JSMapIterator::CurrentValue() {
7201 OrderedHashMap* table(OrderedHashMap::cast(this->table()));
7202 int index = Smi::cast(this->index())->value();
7203 Object* value = table->ValueAt(index);
7204 DCHECK(!value->IsTheHole());
7205 return value;
7206}
7207
Iain Merrick75681382010-08-19 15:07:18 +01007208
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007209#undef TYPE_CHECKER
Steve Blocka7e24c12009-10-30 11:49:00 +00007210#undef CAST_ACCESSOR
7211#undef INT_ACCESSORS
Ben Murdoch85b71792012-04-11 18:30:58 +01007212#undef ACCESSORS
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007213#undef ACCESSORS_TO_SMI
7214#undef SMI_ACCESSORS
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007215#undef SYNCHRONIZED_SMI_ACCESSORS
7216#undef NOBARRIER_SMI_ACCESSORS
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007217#undef BOOL_GETTER
7218#undef BOOL_ACCESSORS
Steve Blocka7e24c12009-10-30 11:49:00 +00007219#undef FIELD_ADDR
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007220#undef FIELD_ADDR_CONST
Steve Blocka7e24c12009-10-30 11:49:00 +00007221#undef READ_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007222#undef NOBARRIER_READ_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007223#undef WRITE_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007224#undef NOBARRIER_WRITE_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007225#undef WRITE_BARRIER
7226#undef CONDITIONAL_WRITE_BARRIER
Steve Blocka7e24c12009-10-30 11:49:00 +00007227#undef READ_DOUBLE_FIELD
7228#undef WRITE_DOUBLE_FIELD
7229#undef READ_INT_FIELD
7230#undef WRITE_INT_FIELD
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007231#undef READ_INTPTR_FIELD
7232#undef WRITE_INTPTR_FIELD
7233#undef READ_UINT32_FIELD
7234#undef WRITE_UINT32_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007235#undef READ_SHORT_FIELD
7236#undef WRITE_SHORT_FIELD
7237#undef READ_BYTE_FIELD
7238#undef WRITE_BYTE_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007239#undef NOBARRIER_READ_BYTE_FIELD
7240#undef NOBARRIER_WRITE_BYTE_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007241
7242} } // namespace v8::internal
7243
7244#endif // V8_OBJECTS_INL_H_