blob: fdfadb1883905b8f0018284a4ae376df1159cf00 [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"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040029#include "src/layout-descriptor-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/lookup.h"
31#include "src/objects.h"
32#include "src/property.h"
33#include "src/prototype.h"
34#include "src/transitions-inl.h"
35#include "src/type-feedback-vector-inl.h"
36#include "src/v8memory.h"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000037
Steve Blocka7e24c12009-10-30 11:49:00 +000038namespace v8 {
39namespace internal {
40
41PropertyDetails::PropertyDetails(Smi* smi) {
42 value_ = smi->value();
43}
44
45
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046Smi* PropertyDetails::AsSmi() const {
47 // Ensure the upper 2 bits have the same value by sign extending it. This is
48 // necessary to be able to use the 31st bit of the property details.
49 int value = value_ << 1;
50 return Smi::FromInt(value >> 1);
Steve Blocka7e24c12009-10-30 11:49:00 +000051}
52
53
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054PropertyDetails PropertyDetails::AsDeleted() const {
Steve Block1e0659c2011-05-24 12:43:12 +010055 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000056 return PropertyDetails(smi);
57}
58
59
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060int PropertyDetails::field_width_in_words() const {
61 DCHECK(type() == FIELD);
62 if (!FLAG_unbox_double_fields) return 1;
63 if (kDoubleSize == kPointerSize) return 1;
64 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1;
65}
66
67
Ben Murdoch3ef787d2012-04-12 10:51:47 +010068#define TYPE_CHECKER(type, instancetype) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 bool Object::Is##type() const { \
Ben Murdoch3ef787d2012-04-12 10:51:47 +010070 return Object::IsHeapObject() && \
71 HeapObject::cast(this)->map()->instance_type() == instancetype; \
72 }
73
74
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075#define CAST_ACCESSOR(type) \
76 type* type::cast(Object* object) { \
77 SLOW_DCHECK(object->Is##type()); \
78 return reinterpret_cast<type*>(object); \
79 } \
80 const type* type::cast(const Object* object) { \
81 SLOW_DCHECK(object->Is##type()); \
82 return reinterpret_cast<const type*>(object); \
Steve Blocka7e24c12009-10-30 11:49:00 +000083 }
84
85
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086#define INT_ACCESSORS(holder, name, offset) \
87 int holder::name() const { return READ_INT_FIELD(this, offset); } \
Steve Blocka7e24c12009-10-30 11:49:00 +000088 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
89
90
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091#define ACCESSORS(holder, name, type, offset) \
92 type* holder::name() const { return type::cast(READ_FIELD(this, offset)); } \
93 void holder::set_##name(type* value, WriteBarrierMode mode) { \
94 WRITE_FIELD(this, offset, value); \
95 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
Steve Blocka7e24c12009-10-30 11:49:00 +000096 }
97
98
Ben Murdoch3ef787d2012-04-12 10:51:47 +010099// Getter that returns a tagged Smi and setter that writes a tagged Smi.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100#define ACCESSORS_TO_SMI(holder, name, offset) \
101 Smi* holder::name() const { return Smi::cast(READ_FIELD(this, offset)); } \
102 void holder::set_##name(Smi* value, WriteBarrierMode mode) { \
103 WRITE_FIELD(this, offset, value); \
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100104 }
105
106
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100107// Getter that returns a Smi as an int and writes an int as a Smi.
Steve Blocka7e24c12009-10-30 11:49:00 +0000108#define SMI_ACCESSORS(holder, name, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 int holder::name() const { \
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 Object* value = READ_FIELD(this, offset); \
111 return Smi::cast(value)->value(); \
112 } \
113 void holder::set_##name(int value) { \
114 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
115 }
116
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117#define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \
118 int holder::synchronized_##name() const { \
119 Object* value = ACQUIRE_READ_FIELD(this, offset); \
120 return Smi::cast(value)->value(); \
121 } \
122 void holder::synchronized_set_##name(int value) { \
123 RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \
124 }
125
126#define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \
127 int holder::nobarrier_##name() const { \
128 Object* value = NOBARRIER_READ_FIELD(this, offset); \
129 return Smi::cast(value)->value(); \
130 } \
131 void holder::nobarrier_set_##name(int value) { \
132 NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \
133 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000134
135#define BOOL_GETTER(holder, field, name, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 bool holder::name() const { \
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 return BooleanBit::get(field(), offset); \
138 } \
139
140
141#define BOOL_ACCESSORS(holder, field, name, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142 bool holder::name() const { \
Steve Blocka7e24c12009-10-30 11:49:00 +0000143 return BooleanBit::get(field(), offset); \
144 } \
145 void holder::set_##name(bool value) { \
146 set_##field(BooleanBit::set(field(), offset, value)); \
147 }
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150bool Object::IsFixedArrayBase() const {
151 return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
152 IsFixedTypedArrayBase() || IsExternalArray();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100153}
154
155
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156// External objects are not extensible, so the map check is enough.
157bool Object::IsExternal() const {
158 return Object::IsHeapObject() &&
159 HeapObject::cast(this)->map() ==
160 HeapObject::cast(this)->GetHeap()->external_map();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100161}
162
163
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164bool Object::IsAccessorInfo() const {
165 return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
Steve Blocka7e24c12009-10-30 11:49:00 +0000166}
167
168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169bool Object::IsSmi() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 return HAS_SMI_TAG(this);
171}
172
173
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174bool Object::IsHeapObject() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 return Internals::HasHeapObjectTag(this);
176}
177
178
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100179TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
181TYPE_CHECKER(Symbol, SYMBOL_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100182
183
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184bool Object::IsString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 return Object::IsHeapObject()
186 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
187}
188
189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190bool Object::IsName() const {
191 return IsString() || IsSymbol();
192}
193
194
195bool Object::IsUniqueName() const {
196 return IsInternalizedString() || IsSymbol();
197}
198
199
200bool Object::IsSpecObject() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000201 return Object::IsHeapObject()
202 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
203}
204
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206bool Object::IsSpecFunction() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100207 if (!Object::IsHeapObject()) return false;
208 InstanceType type = HeapObject::cast(this)->map()->instance_type();
209 return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
210}
211
212
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213bool Object::IsTemplateInfo() const {
214 return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
Steve Blocka7e24c12009-10-30 11:49:00 +0000215}
216
217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218bool Object::IsInternalizedString() const {
219 if (!this->IsHeapObject()) return false;
220 uint32_t type = HeapObject::cast(this)->map()->instance_type();
221 STATIC_ASSERT(kNotInternalizedTag != 0);
222 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
223 (kStringTag | kInternalizedTag);
224}
225
226
227bool Object::IsConsString() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000228 if (!IsString()) return false;
229 return StringShape(String::cast(this)).IsCons();
230}
231
232
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233bool Object::IsSlicedString() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000234 if (!IsString()) return false;
235 return StringShape(String::cast(this)).IsSliced();
Steve Blocka7e24c12009-10-30 11:49:00 +0000236}
237
238
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239bool Object::IsSeqString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000240 if (!IsString()) return false;
241 return StringShape(String::cast(this)).IsSequential();
242}
243
244
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245bool Object::IsSeqOneByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000246 if (!IsString()) return false;
247 return StringShape(String::cast(this)).IsSequential() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248 String::cast(this)->IsOneByteRepresentation();
Steve Blocka7e24c12009-10-30 11:49:00 +0000249}
250
251
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252bool Object::IsSeqTwoByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000253 if (!IsString()) return false;
254 return StringShape(String::cast(this)).IsSequential() &&
255 String::cast(this)->IsTwoByteRepresentation();
256}
257
258
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259bool Object::IsExternalString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 if (!IsString()) return false;
261 return StringShape(String::cast(this)).IsExternal();
262}
263
264
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265bool Object::IsExternalOneByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 if (!IsString()) return false;
267 return StringShape(String::cast(this)).IsExternal() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 String::cast(this)->IsOneByteRepresentation();
Steve Blocka7e24c12009-10-30 11:49:00 +0000269}
270
271
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272bool Object::IsExternalTwoByteString() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 if (!IsString()) return false;
274 return StringShape(String::cast(this)).IsExternal() &&
275 String::cast(this)->IsTwoByteRepresentation();
276}
277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000279bool Object::HasValidElements() {
280 // Dictionary is covered under FixedArray.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
282 IsFixedTypedArrayBase();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000283}
Steve Blocka7e24c12009-10-30 11:49:00 +0000284
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285
286Handle<Object> Object::NewStorageFor(Isolate* isolate,
287 Handle<Object> object,
288 Representation representation) {
289 if (representation.IsSmi() && object->IsUninitialized()) {
290 return handle(Smi::FromInt(0), isolate);
291 }
292 if (!representation.IsDouble()) return object;
293 double value;
294 if (object->IsUninitialized()) {
295 value = 0;
296 } else if (object->IsMutableHeapNumber()) {
297 value = HeapNumber::cast(*object)->value();
298 } else {
299 value = object->Number();
300 }
301 return isolate->factory()->NewHeapNumber(value, MUTABLE);
302}
303
304
305Handle<Object> Object::WrapForRead(Isolate* isolate,
306 Handle<Object> object,
307 Representation representation) {
308 DCHECK(!object->IsUninitialized());
309 if (!representation.IsDouble()) {
310 DCHECK(object->FitsRepresentation(representation));
311 return object;
312 }
313 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
314}
315
316
317StringShape::StringShape(const String* str)
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 : type_(str->map()->instance_type()) {
319 set_valid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 DCHECK((type_ & kIsNotStringMask) == kStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000321}
322
323
324StringShape::StringShape(Map* map)
325 : type_(map->instance_type()) {
326 set_valid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 DCHECK((type_ & kIsNotStringMask) == kStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000328}
329
330
331StringShape::StringShape(InstanceType t)
332 : type_(static_cast<uint32_t>(t)) {
333 set_valid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 DCHECK((type_ & kIsNotStringMask) == kStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000335}
336
337
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338bool StringShape::IsInternalized() {
339 DCHECK(valid());
340 STATIC_ASSERT(kNotInternalizedTag != 0);
341 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
342 (kStringTag | kInternalizedTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000343}
344
345
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346bool String::IsOneByteRepresentation() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000347 uint32_t type = map()->instance_type();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 return (type & kStringEncodingMask) == kOneByteStringTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000349}
350
351
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352bool String::IsTwoByteRepresentation() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 return (type & kStringEncodingMask) == kTwoByteStringTag;
355}
356
357
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358bool String::IsOneByteRepresentationUnderneath() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000359 uint32_t type = map()->instance_type();
360 STATIC_ASSERT(kIsIndirectStringTag != 0);
361 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 DCHECK(IsFlat());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000363 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 case kOneByteStringTag:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000365 return true;
366 case kTwoByteStringTag:
367 return false;
368 default: // Cons or sliced string. Need to go deeper.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 return GetUnderlying()->IsOneByteRepresentation();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000370 }
371}
372
373
374bool String::IsTwoByteRepresentationUnderneath() {
375 uint32_t type = map()->instance_type();
376 STATIC_ASSERT(kIsIndirectStringTag != 0);
377 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 DCHECK(IsFlat());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000379 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 case kOneByteStringTag:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000381 return false;
382 case kTwoByteStringTag:
383 return true;
384 default: // Cons or sliced string. Need to go deeper.
385 return GetUnderlying()->IsTwoByteRepresentation();
386 }
387}
388
389
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390bool String::HasOnlyOneByteChars() {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100391 uint32_t type = map()->instance_type();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392 return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
393 IsOneByteRepresentation();
Steve Block6ded16b2010-05-10 14:33:55 +0100394}
395
396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397bool StringShape::IsCons() {
398 return (type_ & kStringRepresentationMask) == kConsStringTag;
399}
400
401
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000402bool StringShape::IsSliced() {
403 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
404}
405
406
407bool StringShape::IsIndirect() {
408 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
409}
410
411
Steve Blocka7e24c12009-10-30 11:49:00 +0000412bool StringShape::IsExternal() {
413 return (type_ & kStringRepresentationMask) == kExternalStringTag;
414}
415
416
417bool StringShape::IsSequential() {
418 return (type_ & kStringRepresentationMask) == kSeqStringTag;
419}
420
421
422StringRepresentationTag StringShape::representation_tag() {
423 uint32_t tag = (type_ & kStringRepresentationMask);
424 return static_cast<StringRepresentationTag>(tag);
425}
426
427
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000428uint32_t StringShape::encoding_tag() {
429 return type_ & kStringEncodingMask;
430}
431
432
Steve Blocka7e24c12009-10-30 11:49:00 +0000433uint32_t StringShape::full_representation_tag() {
434 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
435}
436
437
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 Internals::kFullStringRepresentationMask);
440
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
442 Internals::kStringEncodingMask);
Steve Blocka7e24c12009-10-30 11:49:00 +0000443
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000444
445bool StringShape::IsSequentialOneByte() {
446 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447}
448
449
450bool StringShape::IsSequentialTwoByte() {
451 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
452}
453
454
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455bool StringShape::IsExternalOneByte() {
456 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000457}
458
459
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000460STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
461 Internals::kExternalOneByteRepresentationTag);
462
463STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
464
465
Steve Blocka7e24c12009-10-30 11:49:00 +0000466bool StringShape::IsExternalTwoByte() {
467 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
468}
469
470
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
Steve Blocka7e24c12009-10-30 11:49:00 +0000472 Internals::kExternalTwoByteRepresentationTag);
473
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000475
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400476
Steve Blocka7e24c12009-10-30 11:49:00 +0000477uc32 FlatStringReader::Get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 if (is_one_byte_) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400479 return Get<uint8_t>(index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 } else {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400481 return Get<uc16>(index);
482 }
483}
484
485
486template <typename Char>
487Char FlatStringReader::Get(int index) {
488 DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
489 DCHECK(0 <= index && index <= length_);
490 if (sizeof(Char) == 1) {
491 return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
492 } else {
493 return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 }
495}
496
497
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) {
499 return key->AsHandle(isolate);
500}
501
502
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
504 HashTableKey* key) {
505 return key->AsHandle(isolate);
506}
507
508
509Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate,
510 HashTableKey* key) {
511 return key->AsHandle(isolate);
512}
513
514template <typename Char>
515class SequentialStringKey : public HashTableKey {
516 public:
517 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
518 : string_(string), hash_field_(0), seed_(seed) { }
519
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400520 uint32_t Hash() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521 hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
522 string_.length(),
523 seed_);
524
525 uint32_t result = hash_field_ >> String::kHashShift;
526 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
527 return result;
528 }
529
530
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400531 uint32_t HashForObject(Object* other) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 return String::cast(other)->Hash();
533 }
534
535 Vector<const Char> string_;
536 uint32_t hash_field_;
537 uint32_t seed_;
538};
539
540
541class OneByteStringKey : public SequentialStringKey<uint8_t> {
542 public:
543 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
544 : SequentialStringKey<uint8_t>(str, seed) { }
545
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400546 bool IsMatch(Object* string) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 return String::cast(string)->IsOneByteEqualTo(string_);
548 }
549
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400550 Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551};
552
553
554class SeqOneByteSubStringKey : public HashTableKey {
555 public:
556 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length)
557 : string_(string), from_(from), length_(length) {
558 DCHECK(string_->IsSeqOneByteString());
559 }
560
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400561 uint32_t Hash() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562 DCHECK(length_ >= 0);
563 DCHECK(from_ + length_ <= string_->length());
564 const uint8_t* chars = string_->GetChars() + from_;
565 hash_field_ = StringHasher::HashSequentialString(
566 chars, length_, string_->GetHeap()->HashSeed());
567 uint32_t result = hash_field_ >> String::kHashShift;
568 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
569 return result;
570 }
571
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400572 uint32_t HashForObject(Object* other) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 return String::cast(other)->Hash();
574 }
575
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400576 bool IsMatch(Object* string) OVERRIDE;
577 Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578
579 private:
580 Handle<SeqOneByteString> string_;
581 int from_;
582 int length_;
583 uint32_t hash_field_;
584};
585
586
587class TwoByteStringKey : public SequentialStringKey<uc16> {
588 public:
589 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
590 : SequentialStringKey<uc16>(str, seed) { }
591
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400592 bool IsMatch(Object* string) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593 return String::cast(string)->IsTwoByteEqualTo(string_);
594 }
595
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400596 Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597};
598
599
600// Utf8StringKey carries a vector of chars as key.
601class Utf8StringKey : public HashTableKey {
602 public:
603 explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
604 : string_(string), hash_field_(0), seed_(seed) { }
605
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400606 bool IsMatch(Object* string) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 return String::cast(string)->IsUtf8EqualTo(string_);
608 }
609
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400610 uint32_t Hash() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
612 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
613 uint32_t result = hash_field_ >> String::kHashShift;
614 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
615 return result;
616 }
617
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618 uint32_t HashForObject(Object* other) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 return String::cast(other)->Hash();
620 }
621
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400622 Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 if (hash_field_ == 0) Hash();
624 return isolate->factory()->NewInternalizedStringFromUtf8(
625 string_, chars_, hash_field_);
626 }
627
628 Vector<const char> string_;
629 uint32_t hash_field_;
630 int chars_; // Caches the number of characters when computing the hash code.
631 uint32_t seed_;
632};
633
634
635bool Object::IsNumber() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 return IsSmi() || IsHeapNumber();
637}
638
639
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100640TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
641TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
642
643
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644bool Object::IsFiller() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100645 if (!Object::IsHeapObject()) return false;
646 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
647 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000648}
649
650
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651bool Object::IsExternalArray() const {
Steve Block3ce2e202009-11-05 08:53:23 +0000652 if (!Object::IsHeapObject())
653 return false;
654 InstanceType instance_type =
655 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000656 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
657 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000658}
659
660
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
662 TYPE_CHECKER(External##Type##Array, EXTERNAL_##TYPE##_ARRAY_TYPE) \
663 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
664
665TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
666#undef TYPED_ARRAY_TYPE_CHECKER
Ben Murdoch257744e2011-11-30 15:57:28 +0000667
668
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669bool Object::IsFixedTypedArrayBase() const {
670 if (!Object::IsHeapObject()) return false;
671
672 InstanceType instance_type =
673 HeapObject::cast(this)->map()->instance_type();
674 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
675 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000676}
677
678
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679bool Object::IsJSReceiver() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100680 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000681 return IsHeapObject() &&
682 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
683}
684
685
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686bool Object::IsJSObject() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100687 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
688 return IsHeapObject() &&
689 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000690}
691
692
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000693bool Object::IsJSProxy() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100694 if (!Object::IsHeapObject()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 return HeapObject::cast(this)->map()->IsJSProxyMap();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000696}
697
698
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100699TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
700TYPE_CHECKER(JSSet, JS_SET_TYPE)
701TYPE_CHECKER(JSMap, JS_MAP_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000702TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
703TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100704TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000705TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100706TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
707TYPE_CHECKER(Map, MAP_TYPE)
708TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
709TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400710TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000712
713
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714bool Object::IsJSWeakCollection() const {
715 return IsJSWeakMap() || IsJSWeakSet();
716}
717
718
719bool Object::IsDescriptorArray() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000720 return IsFixedArray();
721}
722
723
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400724bool Object::IsLayoutDescriptor() const {
725 return IsSmi() || IsFixedTypedArrayBase();
726}
727
728
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000729bool Object::IsTransitionArray() const {
730 return IsFixedArray();
731}
732
733
734bool Object::IsTypeFeedbackVector() const { return IsFixedArray(); }
735
736
737bool Object::IsDeoptimizationInputData() const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100738 // Must be a fixed array.
739 if (!IsFixedArray()) return false;
740
741 // There's no sure way to detect the difference between a fixed array and
742 // a deoptimization data array. Since this is used for asserts we can
743 // check that the length is zero or else the fixed size plus a multiple of
744 // the entry size.
745 int length = FixedArray::cast(this)->length();
746 if (length == 0) return true;
747
748 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100750}
751
752
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753bool Object::IsDeoptimizationOutputData() const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100754 if (!IsFixedArray()) return false;
755 // There's actually no way to see the difference between a fixed array and
756 // a deoptimization data array. Since this is used for asserts we can check
757 // that the length is plausible though.
758 if (FixedArray::cast(this)->length() % 2 != 0) return false;
759 return true;
760}
761
762
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763bool Object::IsDependentCode() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100764 if (!IsFixedArray()) return false;
765 // There's actually no way to see the difference between a fixed array and
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 // a dependent codes array.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100767 return true;
768}
769
770
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771bool Object::IsContext() const {
772 if (!Object::IsHeapObject()) return false;
773 Map* map = HeapObject::cast(this)->map();
774 Heap* heap = map->GetHeap();
775 return (map == heap->function_context_map() ||
776 map == heap->catch_context_map() ||
777 map == heap->with_context_map() ||
778 map == heap->native_context_map() ||
779 map == heap->block_context_map() ||
780 map == heap->module_context_map() ||
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400781 map == heap->script_context_map());
Steve Blocka7e24c12009-10-30 11:49:00 +0000782}
783
784
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785bool Object::IsNativeContext() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100786 return Object::IsHeapObject() &&
787 HeapObject::cast(this)->map() ==
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788 HeapObject::cast(this)->GetHeap()->native_context_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000789}
790
791
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400792bool Object::IsScriptContextTable() const {
793 if (!Object::IsHeapObject()) return false;
794 Map* map = HeapObject::cast(this)->map();
795 Heap* heap = map->GetHeap();
796 return map == heap->script_context_table_map();
797}
798
799
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800bool Object::IsScopeInfo() const {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000801 return Object::IsHeapObject() &&
802 HeapObject::cast(this)->map() ==
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100803 HeapObject::cast(this)->GetHeap()->scope_info_map();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000804}
805
806
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100807TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000808
809
810template <> inline bool Is<JSFunction>(Object* obj) {
811 return obj->IsJSFunction();
812}
813
814
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100815TYPE_CHECKER(Code, CODE_TYPE)
816TYPE_CHECKER(Oddball, ODDBALL_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817TYPE_CHECKER(Cell, CELL_TYPE)
818TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400819TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100820TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
822TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100823TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
824TYPE_CHECKER(JSDate, JS_DATE_TYPE)
825TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000826
827
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828bool Object::IsStringWrapper() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000829 return IsJSValue() && JSValue::cast(this)->value()->IsString();
830}
831
832
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100833TYPE_CHECKER(Foreign, FOREIGN_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000834
835
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836bool Object::IsBoolean() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100837 return IsOddball() &&
838 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000839}
840
841
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100842TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
844TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
845TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
846
847
848bool Object::IsJSArrayBufferView() const {
849 return IsJSDataView() || IsJSTypedArray();
850}
851
852
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100853TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000854
855
856template <> inline bool Is<JSArray>(Object* obj) {
857 return obj->IsJSArray();
858}
859
860
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861bool Object::IsHashTable() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100862 return Object::IsHeapObject() &&
863 HeapObject::cast(this)->map() ==
864 HeapObject::cast(this)->GetHeap()->hash_table_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000865}
866
867
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000868bool Object::IsWeakHashTable() const {
869 return IsHashTable();
870}
871
872
873bool Object::IsDictionary() const {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000874 return IsHashTable() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 this != HeapObject::cast(this)->GetHeap()->string_table();
Steve Blocka7e24c12009-10-30 11:49:00 +0000876}
877
878
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879bool Object::IsNameDictionary() const {
880 return IsDictionary();
Steve Blocka7e24c12009-10-30 11:49:00 +0000881}
882
883
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884bool Object::IsSeededNumberDictionary() const {
885 return IsDictionary();
886}
887
888
889bool Object::IsUnseededNumberDictionary() const {
890 return IsDictionary();
891}
892
893
894bool Object::IsStringTable() const {
895 return IsHashTable();
896}
897
898
899bool Object::IsJSFunctionResultCache() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100900 if (!IsFixedArray()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 const FixedArray* self = FixedArray::cast(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100902 int length = self->length();
903 if (length < JSFunctionResultCache::kEntriesIndex) return false;
904 if ((length - JSFunctionResultCache::kEntriesIndex)
905 % JSFunctionResultCache::kEntrySize != 0) {
906 return false;
907 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908#ifdef VERIFY_HEAP
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100909 if (FLAG_verify_heap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 // TODO(svenpanne) We use const_cast here and below to break our dependency
911 // cycle between the predicates and the verifiers. This can be removed when
912 // the verifiers are const-correct, too.
913 reinterpret_cast<JSFunctionResultCache*>(const_cast<Object*>(this))->
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100914 JSFunctionResultCacheVerify();
915 }
Steve Block6ded16b2010-05-10 14:33:55 +0100916#endif
917 return true;
918}
919
920
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000921bool Object::IsNormalizedMapCache() const {
922 return NormalizedMapCache::IsNormalizedMapCache(this);
923}
924
925
926int NormalizedMapCache::GetIndex(Handle<Map> map) {
927 return map->Hash() % NormalizedMapCache::kEntries;
928}
929
930
931bool NormalizedMapCache::IsNormalizedMapCache(const Object* obj) {
932 if (!obj->IsFixedArray()) return false;
933 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100934 return false;
935 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936#ifdef VERIFY_HEAP
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100937 if (FLAG_verify_heap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938 reinterpret_cast<NormalizedMapCache*>(const_cast<Object*>(obj))->
939 NormalizedMapCacheVerify();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100940 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100941#endif
942 return true;
943}
944
945
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946bool Object::IsCompilationCacheTable() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 return IsHashTable();
948}
949
950
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951bool Object::IsCodeCacheHashTable() const {
Steve Block6ded16b2010-05-10 14:33:55 +0100952 return IsHashTable();
953}
954
955
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956bool Object::IsPolymorphicCodeCacheHashTable() const {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000957 return IsHashTable();
958}
959
960
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000961bool Object::IsMapCache() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000962 return IsHashTable();
963}
964
965
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966bool Object::IsObjectHashTable() const {
967 return IsHashTable();
968}
969
970
971bool Object::IsOrderedHashTable() const {
972 return IsHeapObject() &&
973 HeapObject::cast(this)->map() ==
974 HeapObject::cast(this)->GetHeap()->ordered_hash_table_map();
975}
976
977
978bool Object::IsOrderedHashSet() const {
979 return IsOrderedHashTable();
980}
981
982
983bool Object::IsOrderedHashMap() const {
984 return IsOrderedHashTable();
985}
986
987
988bool Object::IsPrimitive() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000989 return IsOddball() || IsNumber() || IsString();
990}
991
992
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993bool Object::IsJSGlobalProxy() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 bool result = IsHeapObject() &&
995 (HeapObject::cast(this)->map()->instance_type() ==
996 JS_GLOBAL_PROXY_TYPE);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997 DCHECK(!result ||
998 HeapObject::cast(this)->map()->is_access_check_needed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 return result;
1000}
1001
1002
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003bool Object::IsGlobalObject() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 if (!IsHeapObject()) return false;
1005
1006 InstanceType type = HeapObject::cast(this)->map()->instance_type();
1007 return type == JS_GLOBAL_OBJECT_TYPE ||
1008 type == JS_BUILTINS_OBJECT_TYPE;
1009}
1010
1011
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001012TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
1013TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +00001014
1015
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016bool Object::IsUndetectableObject() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 return IsHeapObject()
1018 && HeapObject::cast(this)->map()->is_undetectable();
1019}
1020
1021
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022bool Object::IsAccessCheckNeeded() const {
1023 if (!IsHeapObject()) return false;
1024 if (IsJSGlobalProxy()) {
1025 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
1026 GlobalObject* global = proxy->GetIsolate()->context()->global_object();
1027 return proxy->IsDetachedFrom(global);
1028 }
1029 return HeapObject::cast(this)->map()->is_access_check_needed();
Steve Blocka7e24c12009-10-30 11:49:00 +00001030}
1031
1032
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033bool Object::IsStruct() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001034 if (!IsHeapObject()) return false;
1035 switch (HeapObject::cast(this)->map()->instance_type()) {
1036#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
1037 STRUCT_LIST(MAKE_STRUCT_CASE)
1038#undef MAKE_STRUCT_CASE
1039 default: return false;
1040 }
1041}
1042
1043
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001044#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
1045 bool Object::Is##Name() const { \
1046 return Object::IsHeapObject() \
Steve Blocka7e24c12009-10-30 11:49:00 +00001047 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
1048 }
1049 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
1050#undef MAKE_STRUCT_PREDICATE
1051
1052
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001053bool Object::IsUndefined() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001054 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
Steve Blocka7e24c12009-10-30 11:49:00 +00001055}
1056
1057
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001058bool Object::IsNull() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001059 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
1060}
1061
1062
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063bool Object::IsTheHole() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001064 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
Steve Blocka7e24c12009-10-30 11:49:00 +00001065}
1066
1067
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068bool Object::IsException() const {
1069 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException;
1070}
1071
1072
1073bool Object::IsUninitialized() const {
1074 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
1075}
1076
1077
1078bool Object::IsTrue() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001079 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001080}
1081
1082
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083bool Object::IsFalse() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001084 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
Steve Blocka7e24c12009-10-30 11:49:00 +00001085}
1086
1087
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001088bool Object::IsArgumentsMarker() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001089 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
Ben Murdoch086aeea2011-05-13 15:57:08 +01001090}
1091
1092
Steve Blocka7e24c12009-10-30 11:49:00 +00001093double Object::Number() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094 DCHECK(IsNumber());
Steve Blocka7e24c12009-10-30 11:49:00 +00001095 return IsSmi()
1096 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
1097 : reinterpret_cast<HeapNumber*>(this)->value();
1098}
1099
1100
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001101bool Object::IsNaN() const {
1102 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001103}
1104
1105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001106bool Object::IsMinusZero() const {
1107 return this->IsHeapNumber() &&
1108 i::IsMinusZero(HeapNumber::cast(this)->value());
1109}
1110
1111
1112MaybeHandle<Smi> Object::ToSmi(Isolate* isolate, Handle<Object> object) {
1113 if (object->IsSmi()) return Handle<Smi>::cast(object);
1114 if (object->IsHeapNumber()) {
1115 double value = Handle<HeapNumber>::cast(object)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001116 int int_value = FastD2I(value);
1117 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 return handle(Smi::FromInt(int_value), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 }
1120 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 return Handle<Smi>();
1122}
1123
1124
1125MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
1126 Handle<Object> object) {
1127 return ToObject(
1128 isolate, object, handle(isolate->context()->native_context(), isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +00001129}
1130
1131
1132bool Object::HasSpecificClassOf(String* name) {
1133 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
1134}
1135
1136
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
1138 Handle<Name> name) {
1139 LookupIterator it(object, name);
1140 return GetProperty(&it);
1141}
1142
1143
1144MaybeHandle<Object> Object::GetElement(Isolate* isolate,
1145 Handle<Object> object,
1146 uint32_t index) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001147 // GetElement can trigger a getter which can cause allocation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148 // This was not always the case. This DCHECK is here to catch
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001149 // leftover incorrect uses.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150 DCHECK(AllowHeapAllocation::IsAllowed());
1151 return Object::GetElementWithReceiver(isolate, object, object, index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001152}
1153
1154
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001155Handle<Object> Object::GetPrototypeSkipHiddenPrototypes(
1156 Isolate* isolate, Handle<Object> receiver) {
1157 PrototypeIterator iter(isolate, receiver);
1158 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
1159 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1160 return PrototypeIterator::GetCurrent(iter);
1161 }
1162 iter.Advance();
1163 }
1164 return PrototypeIterator::GetCurrent(iter);
1165}
1166
1167
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
1169 Handle<Name> name) {
1170 uint32_t index;
1171 Isolate* isolate = name->GetIsolate();
1172 if (name->AsArrayIndex(&index)) return GetElement(isolate, object, index);
1173 return GetProperty(object, name);
John Reck59135872010-11-02 12:39:01 -07001174}
1175
1176
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
1178 Handle<Object> object,
1179 const char* name) {
1180 Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
1181 DCHECK(!str.is_null());
1182#ifdef DEBUG
1183 uint32_t index; // Assert that the name is not an array index.
1184 DCHECK(!str->AsArrayIndex(&index));
1185#endif // DEBUG
1186 return GetProperty(object, str);
Steve Blocka7e24c12009-10-30 11:49:00 +00001187}
1188
1189
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190MaybeHandle<Object> JSProxy::GetElementWithHandler(Handle<JSProxy> proxy,
1191 Handle<Object> receiver,
1192 uint32_t index) {
1193 return GetPropertyWithHandler(
1194 proxy, receiver, proxy->GetIsolate()->factory()->Uint32ToString(index));
1195}
1196
1197
1198MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
1199 Handle<JSReceiver> receiver,
1200 uint32_t index,
1201 Handle<Object> value,
1202 StrictMode strict_mode) {
1203 Isolate* isolate = proxy->GetIsolate();
1204 Handle<String> name = isolate->factory()->Uint32ToString(index);
1205 return SetPropertyWithHandler(proxy, receiver, name, value, strict_mode);
1206}
1207
1208
1209Maybe<bool> JSProxy::HasElementWithHandler(Handle<JSProxy> proxy,
1210 uint32_t index) {
1211 Isolate* isolate = proxy->GetIsolate();
1212 Handle<String> name = isolate->factory()->Uint32ToString(index);
1213 return HasPropertyWithHandler(proxy, name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001214}
1215
1216
1217#define FIELD_ADDR(p, offset) \
1218 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
1219
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220#define FIELD_ADDR_CONST(p, offset) \
1221 (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
1222
Steve Blocka7e24c12009-10-30 11:49:00 +00001223#define READ_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 (*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset)))
1225
1226#define ACQUIRE_READ_FIELD(p, offset) \
1227 reinterpret_cast<Object*>(base::Acquire_Load( \
1228 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
1229
1230#define NOBARRIER_READ_FIELD(p, offset) \
1231 reinterpret_cast<Object*>(base::NoBarrier_Load( \
1232 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
Steve Blocka7e24c12009-10-30 11:49:00 +00001233
1234#define WRITE_FIELD(p, offset, value) \
1235 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
1236
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237#define RELEASE_WRITE_FIELD(p, offset, value) \
1238 base::Release_Store( \
1239 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
1240 reinterpret_cast<base::AtomicWord>(value));
1241
1242#define NOBARRIER_WRITE_FIELD(p, offset, value) \
1243 base::NoBarrier_Store( \
1244 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
1245 reinterpret_cast<base::AtomicWord>(value));
1246
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001247#define WRITE_BARRIER(heap, object, offset, value) \
1248 heap->incremental_marking()->RecordWrite( \
1249 object, HeapObject::RawField(object, offset), value); \
1250 if (heap->InNewSpace(value)) { \
1251 heap->RecordWrite(object->address(), offset); \
1252 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001253
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001254#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
1255 if (mode == UPDATE_WRITE_BARRIER) { \
1256 heap->incremental_marking()->RecordWrite( \
1257 object, HeapObject::RawField(object, offset), value); \
1258 if (heap->InNewSpace(value)) { \
1259 heap->RecordWrite(object->address(), offset); \
1260 } \
Steve Blocka7e24c12009-10-30 11:49:00 +00001261 }
1262
Steve Block44f0eee2011-05-26 01:26:41 +01001263#ifndef V8_TARGET_ARCH_MIPS
1264 #define READ_DOUBLE_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265 (*reinterpret_cast<const double*>(FIELD_ADDR_CONST(p, offset)))
Steve Block44f0eee2011-05-26 01:26:41 +01001266#else // V8_TARGET_ARCH_MIPS
1267 // Prevent gcc from using load-double (mips ldc1) on (possibly)
1268 // non-64-bit aligned HeapNumber::value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269 static inline double read_double_field(const void* p, int offset) {
Steve Block44f0eee2011-05-26 01:26:41 +01001270 union conversion {
1271 double d;
1272 uint32_t u[2];
1273 } c;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274 c.u[0] = (*reinterpret_cast<const uint32_t*>(
1275 FIELD_ADDR_CONST(p, offset)));
1276 c.u[1] = (*reinterpret_cast<const uint32_t*>(
1277 FIELD_ADDR_CONST(p, offset + 4)));
Steve Block44f0eee2011-05-26 01:26:41 +01001278 return c.d;
1279 }
1280 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
1281#endif // V8_TARGET_ARCH_MIPS
Steve Blocka7e24c12009-10-30 11:49:00 +00001282
Steve Block44f0eee2011-05-26 01:26:41 +01001283#ifndef V8_TARGET_ARCH_MIPS
1284 #define WRITE_DOUBLE_FIELD(p, offset, value) \
1285 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
1286#else // V8_TARGET_ARCH_MIPS
1287 // Prevent gcc from using store-double (mips sdc1) on (possibly)
1288 // non-64-bit aligned HeapNumber::value.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001289 static inline void write_double_field(void* p, int offset,
Steve Block44f0eee2011-05-26 01:26:41 +01001290 double value) {
1291 union conversion {
1292 double d;
1293 uint32_t u[2];
1294 } c;
1295 c.d = value;
1296 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
1297 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
1298 }
1299 #define WRITE_DOUBLE_FIELD(p, offset, value) \
1300 write_double_field(p, offset, value)
1301#endif // V8_TARGET_ARCH_MIPS
1302
Steve Blocka7e24c12009-10-30 11:49:00 +00001303
1304#define READ_INT_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 (*reinterpret_cast<const int*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001306
1307#define WRITE_INT_FIELD(p, offset, value) \
1308 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
1309
1310#define READ_INTPTR_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 (*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001312
1313#define WRITE_INTPTR_FIELD(p, offset, value) \
1314 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
1315
1316#define READ_UINT32_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 (*reinterpret_cast<const uint32_t*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001318
1319#define WRITE_UINT32_FIELD(p, offset, value) \
1320 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
1321
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322#define READ_INT32_FIELD(p, offset) \
1323 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
1324
1325#define WRITE_INT32_FIELD(p, offset, value) \
1326 (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
1327
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001328#define READ_INT64_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001330
1331#define WRITE_INT64_FIELD(p, offset, value) \
1332 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
1333
Steve Blocka7e24c12009-10-30 11:49:00 +00001334#define READ_SHORT_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset)))
Steve Blocka7e24c12009-10-30 11:49:00 +00001336
1337#define WRITE_SHORT_FIELD(p, offset, value) \
1338 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
1339
1340#define READ_BYTE_FIELD(p, offset) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
1342
1343#define NOBARRIER_READ_BYTE_FIELD(p, offset) \
1344 static_cast<byte>(base::NoBarrier_Load( \
1345 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset))))
Steve Blocka7e24c12009-10-30 11:49:00 +00001346
1347#define WRITE_BYTE_FIELD(p, offset, value) \
1348 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
1349
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001350#define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \
1351 base::NoBarrier_Store( \
1352 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
1353 static_cast<base::Atomic8>(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001354
1355Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset));
Steve Blocka7e24c12009-10-30 11:49:00 +00001357}
1358
1359
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360int Smi::value() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 return Internals::SmiValue(this);
1362}
1363
1364
1365Smi* Smi::FromInt(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366 DCHECK(Smi::IsValid(value));
1367 return reinterpret_cast<Smi*>(Internals::IntToSmi(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001368}
1369
1370
1371Smi* Smi::FromIntptr(intptr_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 DCHECK(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +00001373 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
1374 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001375}
1376
1377
Steve Blocka7e24c12009-10-30 11:49:00 +00001378bool Smi::IsValid(intptr_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 bool result = Internals::IsValidSmi(value);
1380 DCHECK_EQ(result, value >= kMinValue && value <= kMaxValue);
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 return result;
1382}
1383
1384
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385MapWord MapWord::FromMap(const Map* map) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001386 return MapWord(reinterpret_cast<uintptr_t>(map));
1387}
1388
1389
1390Map* MapWord::ToMap() {
1391 return reinterpret_cast<Map*>(value_);
1392}
1393
1394
1395bool MapWord::IsForwardingAddress() {
1396 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1397}
1398
1399
1400MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1401 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1402 return MapWord(reinterpret_cast<uintptr_t>(raw));
1403}
1404
1405
1406HeapObject* MapWord::ToForwardingAddress() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 DCHECK(IsForwardingAddress());
Steve Blocka7e24c12009-10-30 11:49:00 +00001408 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1409}
1410
1411
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412#ifdef VERIFY_HEAP
Steve Blocka7e24c12009-10-30 11:49:00 +00001413void HeapObject::VerifyObjectField(int offset) {
1414 VerifyPointer(READ_FIELD(this, offset));
1415}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001416
1417void HeapObject::VerifySmiField(int offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418 CHECK(READ_FIELD(this, offset)->IsSmi());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001419}
Steve Blocka7e24c12009-10-30 11:49:00 +00001420#endif
1421
1422
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423Heap* HeapObject::GetHeap() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001424 Heap* heap =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001425 MemoryChunk::FromAddress(reinterpret_cast<const byte*>(this))->heap();
1426 SLOW_DCHECK(heap != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001427 return heap;
Steve Block44f0eee2011-05-26 01:26:41 +01001428}
1429
1430
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431Isolate* HeapObject::GetIsolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +01001432 return GetHeap()->isolate();
1433}
1434
1435
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436Map* HeapObject::map() const {
1437#ifdef DEBUG
1438 // Clear mark potentially added by PathTracer.
1439 uintptr_t raw_value =
1440 map_word().ToRawValue() & ~static_cast<uintptr_t>(PathTracer::kMarkTag);
1441 return MapWord::FromRawValue(raw_value).ToMap();
1442#else
Steve Blocka7e24c12009-10-30 11:49:00 +00001443 return map_word().ToMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001444#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001445}
1446
1447
1448void HeapObject::set_map(Map* value) {
1449 set_map_word(MapWord::FromMap(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001450 if (value != NULL) {
1451 // TODO(1600) We are passing NULL as a slot because maps can never be on
1452 // evacuation candidate.
1453 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1454 }
1455}
1456
1457
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458Map* HeapObject::synchronized_map() {
1459 return synchronized_map_word().ToMap();
1460}
1461
1462
1463void HeapObject::synchronized_set_map(Map* value) {
1464 synchronized_set_map_word(MapWord::FromMap(value));
1465 if (value != NULL) {
1466 // TODO(1600) We are passing NULL as a slot because maps can never be on
1467 // evacuation candidate.
1468 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1469 }
1470}
1471
1472
1473void HeapObject::synchronized_set_map_no_write_barrier(Map* value) {
1474 synchronized_set_map_word(MapWord::FromMap(value));
1475}
1476
1477
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001478// Unsafe accessor omitting write barrier.
1479void HeapObject::set_map_no_write_barrier(Map* value) {
1480 set_map_word(MapWord::FromMap(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001481}
1482
1483
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001484MapWord HeapObject::map_word() const {
1485 return MapWord(
1486 reinterpret_cast<uintptr_t>(NOBARRIER_READ_FIELD(this, kMapOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001487}
1488
1489
1490void HeapObject::set_map_word(MapWord map_word) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 NOBARRIER_WRITE_FIELD(
1492 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1493}
1494
1495
1496MapWord HeapObject::synchronized_map_word() const {
1497 return MapWord(
1498 reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset)));
1499}
1500
1501
1502void HeapObject::synchronized_set_map_word(MapWord map_word) {
1503 RELEASE_WRITE_FIELD(
1504 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001505}
1506
1507
1508HeapObject* HeapObject::FromAddress(Address address) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509 DCHECK_TAG_ALIGNED(address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001510 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1511}
1512
1513
1514Address HeapObject::address() {
1515 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1516}
1517
1518
1519int HeapObject::Size() {
1520 return SizeFromMap(map());
1521}
1522
1523
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524bool HeapObject::MayContainRawValues() {
1525 InstanceType type = map()->instance_type();
1526 if (type <= LAST_NAME_TYPE) {
1527 if (type == SYMBOL_TYPE) {
1528 return false;
1529 }
1530 DCHECK(type < FIRST_NONSTRING_TYPE);
1531 // There are four string representations: sequential strings, external
1532 // strings, cons strings, and sliced strings.
1533 // Only the former two contain raw values and no heap pointers (besides the
1534 // map-word).
1535 return ((type & kIsIndirectStringMask) != kIsIndirectStringTag);
1536 }
1537 // The ConstantPoolArray contains heap pointers, but also raw values.
1538 if (type == CONSTANT_POOL_ARRAY_TYPE) return true;
1539 return (type <= LAST_DATA_TYPE);
1540}
1541
1542
Steve Blocka7e24c12009-10-30 11:49:00 +00001543void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1544 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1545 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1546}
1547
1548
1549void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1550 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1551}
1552
1553
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001554void HeapObject::IterateNextCodeLink(ObjectVisitor* v, int offset) {
1555 v->VisitNextCodeLink(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1556}
1557
1558
1559double HeapNumber::value() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001560 return READ_DOUBLE_FIELD(this, kValueOffset);
1561}
1562
1563
1564void HeapNumber::set_value(double value) {
1565 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1566}
1567
1568
Steve Block6ded16b2010-05-10 14:33:55 +01001569int HeapNumber::get_exponent() {
1570 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1571 kExponentShift) - kExponentBias;
1572}
1573
1574
1575int HeapNumber::get_sign() {
1576 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1577}
1578
1579
Steve Blocka7e24c12009-10-30 11:49:00 +00001580ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1581
1582
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001583Object** FixedArray::GetFirstElementAddress() {
1584 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1585}
1586
1587
1588bool FixedArray::ContainsOnlySmisOrHoles() {
1589 Object* the_hole = GetHeap()->the_hole_value();
1590 Object** current = GetFirstElementAddress();
1591 for (int i = 0; i < length(); ++i) {
1592 Object* candidate = *current++;
1593 if (!candidate->IsSmi() && candidate != the_hole) return false;
1594 }
1595 return true;
1596}
1597
1598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001599FixedArrayBase* JSObject::elements() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 Object* array = READ_FIELD(this, kElementsOffset);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001601 return static_cast<FixedArrayBase*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001602}
1603
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001604
1605void JSObject::ValidateElements(Handle<JSObject> object) {
1606#ifdef ENABLE_SLOW_DCHECKS
1607 if (FLAG_enable_slow_asserts) {
1608 ElementsAccessor* accessor = object->GetElementsAccessor();
1609 accessor->Validate(object);
1610 }
1611#endif
1612}
1613
1614
1615void AllocationSite::Initialize() {
1616 set_transition_info(Smi::FromInt(0));
1617 SetElementsKind(GetInitialFastElementsKind());
1618 set_nested_site(Smi::FromInt(0));
1619 set_pretenure_data(Smi::FromInt(0));
1620 set_pretenure_create_count(Smi::FromInt(0));
1621 set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1622 SKIP_WRITE_BARRIER);
1623}
1624
1625
1626void AllocationSite::MarkZombie() {
1627 DCHECK(!IsZombie());
1628 Initialize();
1629 set_pretenure_decision(kZombie);
1630}
1631
1632
1633// Heuristic: We only need to create allocation site info if the boilerplate
1634// elements kind is the initial elements kind.
1635AllocationSiteMode AllocationSite::GetMode(
1636 ElementsKind boilerplate_elements_kind) {
1637 if (FLAG_pretenuring_call_new ||
1638 IsFastSmiElementsKind(boilerplate_elements_kind)) {
1639 return TRACK_ALLOCATION_SITE;
1640 }
1641
1642 return DONT_TRACK_ALLOCATION_SITE;
1643}
1644
1645
1646AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
1647 ElementsKind to) {
1648 if (FLAG_pretenuring_call_new ||
1649 (IsFastSmiElementsKind(from) &&
1650 IsMoreGeneralElementsKindTransition(from, to))) {
1651 return TRACK_ALLOCATION_SITE;
1652 }
1653
1654 return DONT_TRACK_ALLOCATION_SITE;
1655}
1656
1657
1658inline bool AllocationSite::CanTrack(InstanceType type) {
1659 if (FLAG_allocation_site_pretenuring) {
1660 return type == JS_ARRAY_TYPE ||
1661 type == JS_OBJECT_TYPE ||
1662 type < FIRST_NONSTRING_TYPE;
1663 }
1664 return type == JS_ARRAY_TYPE;
1665}
1666
1667
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001668inline void AllocationSite::set_memento_found_count(int count) {
1669 int value = pretenure_data()->value();
1670 // Verify that we can count more mementos than we can possibly find in one
1671 // new space collection.
1672 DCHECK((GetHeap()->MaxSemiSpaceSize() /
1673 (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
1674 AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
1675 DCHECK(count < MementoFoundCountBits::kMax);
1676 set_pretenure_data(
1677 Smi::FromInt(MementoFoundCountBits::update(value, count)),
1678 SKIP_WRITE_BARRIER);
1679}
1680
1681inline bool AllocationSite::IncrementMementoFoundCount() {
1682 if (IsZombie()) return false;
1683
1684 int value = memento_found_count();
1685 set_memento_found_count(value + 1);
1686 return memento_found_count() == kPretenureMinimumCreated;
1687}
1688
1689
1690inline void AllocationSite::IncrementMementoCreateCount() {
1691 DCHECK(FLAG_allocation_site_pretenuring);
1692 int value = memento_create_count();
1693 set_memento_create_count(value + 1);
1694}
1695
1696
1697inline bool AllocationSite::MakePretenureDecision(
1698 PretenureDecision current_decision,
1699 double ratio,
1700 bool maximum_size_scavenge) {
1701 // Here we just allow state transitions from undecided or maybe tenure
1702 // to don't tenure, maybe tenure, or tenure.
1703 if ((current_decision == kUndecided || current_decision == kMaybeTenure)) {
1704 if (ratio >= kPretenureRatio) {
1705 // We just transition into tenure state when the semi-space was at
1706 // maximum capacity.
1707 if (maximum_size_scavenge) {
1708 set_deopt_dependent_code(true);
1709 set_pretenure_decision(kTenure);
1710 // Currently we just need to deopt when we make a state transition to
1711 // tenure.
1712 return true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001713 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001714 set_pretenure_decision(kMaybeTenure);
1715 } else {
1716 set_pretenure_decision(kDontTenure);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001717 }
1718 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001719 return false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001720}
1721
1722
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001723inline bool AllocationSite::DigestPretenuringFeedback(
1724 bool maximum_size_scavenge) {
1725 bool deopt = false;
1726 int create_count = memento_create_count();
1727 int found_count = memento_found_count();
1728 bool minimum_mementos_created = create_count >= kPretenureMinimumCreated;
1729 double ratio =
1730 minimum_mementos_created || FLAG_trace_pretenuring_statistics ?
1731 static_cast<double>(found_count) / create_count : 0.0;
1732 PretenureDecision current_decision = pretenure_decision();
1733
1734 if (minimum_mementos_created) {
1735 deopt = MakePretenureDecision(
1736 current_decision, ratio, maximum_size_scavenge);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001737 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001738
1739 if (FLAG_trace_pretenuring_statistics) {
1740 PrintF(
1741 "AllocationSite(%p): (created, found, ratio) (%d, %d, %f) %s => %s\n",
1742 static_cast<void*>(this), create_count, found_count, ratio,
1743 PretenureDecisionName(current_decision),
1744 PretenureDecisionName(pretenure_decision()));
1745 }
1746
1747 // Clear feedback calculation fields until the next gc.
1748 set_memento_found_count(0);
1749 set_memento_create_count(0);
1750 return deopt;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001751}
1752
1753
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001754void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1755 JSObject::ValidateElements(object);
1756 ElementsKind elements_kind = object->map()->elements_kind();
1757 if (!IsFastObjectElementsKind(elements_kind)) {
1758 if (IsFastHoleyElementsKind(elements_kind)) {
1759 TransitionElementsKind(object, FAST_HOLEY_ELEMENTS);
1760 } else {
1761 TransitionElementsKind(object, FAST_ELEMENTS);
1762 }
1763 }
1764}
1765
1766
1767void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1768 Object** objects,
1769 uint32_t count,
1770 EnsureElementsMode mode) {
1771 ElementsKind current_kind = object->map()->elements_kind();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001772 ElementsKind target_kind = current_kind;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001773 {
1774 DisallowHeapAllocation no_allocation;
1775 DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1776 bool is_holey = IsFastHoleyElementsKind(current_kind);
1777 if (current_kind == FAST_HOLEY_ELEMENTS) return;
1778 Heap* heap = object->GetHeap();
1779 Object* the_hole = heap->the_hole_value();
1780 for (uint32_t i = 0; i < count; ++i) {
1781 Object* current = *objects++;
1782 if (current == the_hole) {
1783 is_holey = true;
1784 target_kind = GetHoleyElementsKind(target_kind);
1785 } else if (!current->IsSmi()) {
1786 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1787 if (IsFastSmiElementsKind(target_kind)) {
1788 if (is_holey) {
1789 target_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
1790 } else {
1791 target_kind = FAST_DOUBLE_ELEMENTS;
1792 }
1793 }
1794 } else if (is_holey) {
1795 target_kind = FAST_HOLEY_ELEMENTS;
1796 break;
1797 } else {
1798 target_kind = FAST_ELEMENTS;
1799 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001800 }
1801 }
1802 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001803 if (target_kind != current_kind) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 TransitionElementsKind(object, target_kind);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001805 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001806}
1807
1808
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001809void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1810 Handle<FixedArrayBase> elements,
1811 uint32_t length,
1812 EnsureElementsMode mode) {
1813 Heap* heap = object->GetHeap();
1814 if (elements->map() != heap->fixed_double_array_map()) {
1815 DCHECK(elements->map() == heap->fixed_array_map() ||
1816 elements->map() == heap->fixed_cow_array_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001817 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1818 mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1819 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001820 Object** objects =
1821 Handle<FixedArray>::cast(elements)->GetFirstElementAddress();
1822 EnsureCanContainElements(object, objects, length, mode);
1823 return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001824 }
1825
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001826 DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1827 if (object->GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) {
1828 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS);
1829 } else if (object->GetElementsKind() == FAST_SMI_ELEMENTS) {
1830 Handle<FixedDoubleArray> double_array =
1831 Handle<FixedDoubleArray>::cast(elements);
1832 for (uint32_t i = 0; i < length; ++i) {
1833 if (double_array->is_the_hole(i)) {
1834 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS);
1835 return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001836 }
1837 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001838 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001839 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001840}
1841
1842
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843void JSObject::SetMapAndElements(Handle<JSObject> object,
1844 Handle<Map> new_map,
1845 Handle<FixedArrayBase> value) {
1846 JSObject::MigrateToMap(object, new_map);
1847 DCHECK((object->map()->has_fast_smi_or_object_elements() ||
1848 (*value == object->GetHeap()->empty_fixed_array())) ==
1849 (value->map() == object->GetHeap()->fixed_array_map() ||
1850 value->map() == object->GetHeap()->fixed_cow_array_map()));
1851 DCHECK((*value == object->GetHeap()->empty_fixed_array()) ||
1852 (object->map()->has_fast_double_elements() ==
1853 value->IsFixedDoubleArray()));
1854 object->set_elements(*value);
1855}
1856
1857
1858void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001859 WRITE_FIELD(this, kElementsOffset, value);
1860 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1861}
1862
Steve Blocka7e24c12009-10-30 11:49:00 +00001863
1864void JSObject::initialize_properties() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
Steve Block44f0eee2011-05-26 01:26:41 +01001866 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001867}
1868
1869
1870void JSObject::initialize_elements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001871 FixedArrayBase* elements = map()->GetInitialElements();
1872 WRITE_FIELD(this, kElementsOffset, elements);
Steve Blocka7e24c12009-10-30 11:49:00 +00001873}
1874
1875
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876Handle<String> Map::ExpectedTransitionKey(Handle<Map> map) {
1877 DisallowHeapAllocation no_gc;
1878 if (!map->HasTransitionArray()) return Handle<String>::null();
1879 TransitionArray* transitions = map->transitions();
1880 if (!transitions->IsSimpleTransition()) return Handle<String>::null();
1881 int transition = TransitionArray::kSimpleTransitionIndex;
1882 PropertyDetails details = transitions->GetTargetDetails(transition);
1883 Name* name = transitions->GetKey(transition);
1884 if (details.type() != FIELD) return Handle<String>::null();
1885 if (details.attributes() != NONE) return Handle<String>::null();
1886 if (!name->IsString()) return Handle<String>::null();
1887 return Handle<String>(String::cast(name));
1888}
1889
1890
1891Handle<Map> Map::ExpectedTransitionTarget(Handle<Map> map) {
1892 DCHECK(!ExpectedTransitionKey(map).is_null());
1893 return Handle<Map>(map->transitions()->GetTarget(
1894 TransitionArray::kSimpleTransitionIndex));
1895}
1896
1897
1898Handle<Map> Map::FindTransitionToField(Handle<Map> map, Handle<Name> key) {
1899 DisallowHeapAllocation no_allocation;
1900 if (!map->HasTransitionArray()) return Handle<Map>::null();
1901 TransitionArray* transitions = map->transitions();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001902 int transition = transitions->Search(DATA, *key, NONE);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001903 if (transition == TransitionArray::kNotFound) return Handle<Map>::null();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001904 PropertyDetails details = transitions->GetTargetDetails(transition);
1905 if (details.type() != FIELD) return Handle<Map>::null();
1906 DCHECK_EQ(NONE, details.attributes());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001907 return Handle<Map>(transitions->GetTarget(transition));
Steve Block8defd9f2010-07-08 12:39:36 +01001908}
1909
1910
Steve Blocka7e24c12009-10-30 11:49:00 +00001911ACCESSORS(Oddball, to_string, String, kToStringOffset)
1912ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1913
1914
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001915byte Oddball::kind() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001916 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
Steve Block44f0eee2011-05-26 01:26:41 +01001917}
1918
1919
1920void Oddball::set_kind(byte value) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001921 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
Steve Block44f0eee2011-05-26 01:26:41 +01001922}
1923
1924
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001925Object* Cell::value() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001926 return READ_FIELD(this, kValueOffset);
1927}
1928
1929
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001930void Cell::set_value(Object* val, WriteBarrierMode ignored) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001931 // The write barrier is not used for global property cells.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001932 DCHECK(!val->IsPropertyCell() && !val->IsCell());
Steve Blocka7e24c12009-10-30 11:49:00 +00001933 WRITE_FIELD(this, kValueOffset, val);
1934}
1935
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1937
1938Object* PropertyCell::type_raw() const {
1939 return READ_FIELD(this, kTypeOffset);
1940}
1941
1942
1943void PropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
1944 WRITE_FIELD(this, kTypeOffset, val);
1945}
1946
Steve Blocka7e24c12009-10-30 11:49:00 +00001947
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001948Object* WeakCell::value() const { return READ_FIELD(this, kValueOffset); }
1949
1950
1951void WeakCell::clear() {
1952 DCHECK(GetHeap()->gc_state() == Heap::MARK_COMPACT);
1953 WRITE_FIELD(this, kValueOffset, Smi::FromInt(0));
1954}
1955
1956
1957void WeakCell::initialize(HeapObject* val) {
1958 WRITE_FIELD(this, kValueOffset, val);
1959 WRITE_BARRIER(GetHeap(), this, kValueOffset, val);
1960}
1961
1962
1963bool WeakCell::cleared() const { return value() == Smi::FromInt(0); }
1964
1965
1966Object* WeakCell::next() const { return READ_FIELD(this, kNextOffset); }
1967
1968
1969void WeakCell::set_next(Object* val, WriteBarrierMode mode) {
1970 WRITE_FIELD(this, kNextOffset, val);
1971 if (mode == UPDATE_WRITE_BARRIER) {
1972 WRITE_BARRIER(GetHeap(), this, kNextOffset, val);
1973 }
1974}
1975
1976
Steve Blocka7e24c12009-10-30 11:49:00 +00001977int JSObject::GetHeaderSize() {
1978 InstanceType type = map()->instance_type();
1979 // Check for the most common kind of JavaScript object before
1980 // falling into the generic switch. This speeds up the internal
1981 // field operations considerably on average.
1982 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1983 switch (type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001984 case JS_GENERATOR_OBJECT_TYPE:
1985 return JSGeneratorObject::kSize;
1986 case JS_MODULE_TYPE:
1987 return JSModule::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001988 case JS_GLOBAL_PROXY_TYPE:
1989 return JSGlobalProxy::kSize;
1990 case JS_GLOBAL_OBJECT_TYPE:
1991 return JSGlobalObject::kSize;
1992 case JS_BUILTINS_OBJECT_TYPE:
1993 return JSBuiltinsObject::kSize;
1994 case JS_FUNCTION_TYPE:
1995 return JSFunction::kSize;
1996 case JS_VALUE_TYPE:
1997 return JSValue::kSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001998 case JS_DATE_TYPE:
1999 return JSDate::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002000 case JS_ARRAY_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002001 return JSArray::kSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002002 case JS_ARRAY_BUFFER_TYPE:
2003 return JSArrayBuffer::kSize;
2004 case JS_TYPED_ARRAY_TYPE:
2005 return JSTypedArray::kSize;
2006 case JS_DATA_VIEW_TYPE:
2007 return JSDataView::kSize;
2008 case JS_SET_TYPE:
2009 return JSSet::kSize;
2010 case JS_MAP_TYPE:
2011 return JSMap::kSize;
2012 case JS_SET_ITERATOR_TYPE:
2013 return JSSetIterator::kSize;
2014 case JS_MAP_ITERATOR_TYPE:
2015 return JSMapIterator::kSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002016 case JS_WEAK_MAP_TYPE:
2017 return JSWeakMap::kSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002018 case JS_WEAK_SET_TYPE:
2019 return JSWeakSet::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002020 case JS_REGEXP_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002021 return JSRegExp::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002022 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
2023 return JSObject::kHeaderSize;
Steve Block1e0659c2011-05-24 12:43:12 +01002024 case JS_MESSAGE_OBJECT_TYPE:
2025 return JSMessageObject::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002026 default:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002027 // TODO(jkummerow): Re-enable this. Blink currently hits this
2028 // from its CustomElementConstructorBuilder.
2029 // UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +00002030 return 0;
2031 }
2032}
2033
2034
2035int JSObject::GetInternalFieldCount() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002036 DCHECK(1 << kPointerSizeLog2 == kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002037 // Make sure to adjust for the number of in-object properties. These
2038 // properties do contribute to the size, but are not internal fields.
2039 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
2040 map()->inobject_properties();
2041}
2042
2043
Steve Block44f0eee2011-05-26 01:26:41 +01002044int JSObject::GetInternalFieldOffset(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002045 DCHECK(index < GetInternalFieldCount() && index >= 0);
Steve Block44f0eee2011-05-26 01:26:41 +01002046 return GetHeaderSize() + (kPointerSize * index);
2047}
2048
2049
Steve Blocka7e24c12009-10-30 11:49:00 +00002050Object* JSObject::GetInternalField(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002051 DCHECK(index < GetInternalFieldCount() && index >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002052 // Internal objects do follow immediately after the header, whereas in-object
2053 // properties are at the end of the object. Therefore there is no need
2054 // to adjust the index here.
2055 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
2056}
2057
2058
2059void JSObject::SetInternalField(int index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002060 DCHECK(index < GetInternalFieldCount() && index >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002061 // Internal objects do follow immediately after the header, whereas in-object
2062 // properties are at the end of the object. Therefore there is no need
2063 // to adjust the index here.
2064 int offset = GetHeaderSize() + (kPointerSize * index);
2065 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002066 WRITE_BARRIER(GetHeap(), this, offset, value);
2067}
2068
2069
2070void JSObject::SetInternalField(int index, Smi* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071 DCHECK(index < GetInternalFieldCount() && index >= 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002072 // Internal objects do follow immediately after the header, whereas in-object
2073 // properties are at the end of the object. Therefore there is no need
2074 // to adjust the index here.
2075 int offset = GetHeaderSize() + (kPointerSize * index);
2076 WRITE_FIELD(this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002077}
2078
2079
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002080bool JSObject::IsUnboxedDoubleField(FieldIndex index) {
2081 if (!FLAG_unbox_double_fields) return false;
2082 return map()->IsUnboxedDoubleField(index);
2083}
2084
2085
2086bool Map::IsUnboxedDoubleField(FieldIndex index) {
2087 if (!FLAG_unbox_double_fields) return false;
2088 if (index.is_hidden_field() || !index.is_inobject()) return false;
2089 return !layout_descriptor()->IsTagged(index.property_index());
2090}
2091
2092
Steve Blocka7e24c12009-10-30 11:49:00 +00002093// Access fast-case object properties at index. The use of these routines
2094// is needed to correctly distinguish between properties stored in-object and
2095// properties stored in the properties array.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002096Object* JSObject::RawFastPropertyAt(FieldIndex index) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002097 DCHECK(!IsUnboxedDoubleField(index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002098 if (index.is_inobject()) {
2099 return READ_FIELD(this, index.offset());
Steve Blocka7e24c12009-10-30 11:49:00 +00002100 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002101 return properties()->get(index.outobject_array_index());
Steve Blocka7e24c12009-10-30 11:49:00 +00002102 }
2103}
2104
2105
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002106double JSObject::RawFastDoublePropertyAt(FieldIndex index) {
2107 DCHECK(IsUnboxedDoubleField(index));
2108 return READ_DOUBLE_FIELD(this, index.offset());
2109}
2110
2111
2112void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002113 if (index.is_inobject()) {
2114 int offset = index.offset();
Steve Blocka7e24c12009-10-30 11:49:00 +00002115 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002116 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002117 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002118 properties()->set(index.outobject_array_index(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002119 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002120}
2121
2122
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002123void JSObject::RawFastDoublePropertyAtPut(FieldIndex index, double value) {
2124 WRITE_DOUBLE_FIELD(this, index.offset(), value);
2125}
2126
2127
2128void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
2129 if (IsUnboxedDoubleField(index)) {
2130 DCHECK(value->IsMutableHeapNumber());
2131 RawFastDoublePropertyAtPut(index, HeapNumber::cast(value)->value());
2132 } else {
2133 RawFastPropertyAtPut(index, value);
2134 }
2135}
2136
2137
Steve Block44f0eee2011-05-26 01:26:41 +01002138int JSObject::GetInObjectPropertyOffset(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002139 return map()->GetInObjectPropertyOffset(index);
Steve Block44f0eee2011-05-26 01:26:41 +01002140}
2141
2142
Steve Blocka7e24c12009-10-30 11:49:00 +00002143Object* JSObject::InObjectPropertyAt(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002144 int offset = GetInObjectPropertyOffset(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002145 return READ_FIELD(this, offset);
2146}
2147
2148
2149Object* JSObject::InObjectPropertyAtPut(int index,
2150 Object* value,
2151 WriteBarrierMode mode) {
2152 // Adjust for the number of properties stored in the object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153 int offset = GetInObjectPropertyOffset(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002154 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002155 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002156 return value;
2157}
2158
2159
2160
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002161void JSObject::InitializeBody(Map* map,
2162 Object* pre_allocated_value,
2163 Object* filler_value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002164 DCHECK(!filler_value->IsHeapObject() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002165 !GetHeap()->InNewSpace(filler_value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002166 DCHECK(!pre_allocated_value->IsHeapObject() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002167 !GetHeap()->InNewSpace(pre_allocated_value));
2168 int size = map->instance_size();
2169 int offset = kHeaderSize;
2170 if (filler_value != pre_allocated_value) {
2171 int pre_allocated = map->pre_allocated_property_fields();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002172 DCHECK(pre_allocated * kPointerSize + kHeaderSize <= size);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002173 for (int i = 0; i < pre_allocated; i++) {
2174 WRITE_FIELD(this, offset, pre_allocated_value);
2175 offset += kPointerSize;
2176 }
2177 }
2178 while (offset < size) {
2179 WRITE_FIELD(this, offset, filler_value);
2180 offset += kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002181 }
2182}
2183
2184
Steve Block8defd9f2010-07-08 12:39:36 +01002185bool JSObject::HasFastProperties() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002186 DCHECK(properties()->IsDictionary() == map()->is_dictionary_map());
Steve Block8defd9f2010-07-08 12:39:36 +01002187 return !properties()->IsDictionary();
2188}
2189
2190
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002191bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
2192 if (unused_property_fields() != 0) return false;
2193 if (is_prototype_map()) return false;
2194 int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12;
2195 int limit = Max(minimum, inobject_properties());
2196 int external = NumberOfFields() - inobject_properties();
2197 return external > limit;
Steve Block8defd9f2010-07-08 12:39:36 +01002198}
2199
2200
Steve Blocka7e24c12009-10-30 11:49:00 +00002201void Struct::InitializeBody(int object_size) {
Steve Block44f0eee2011-05-26 01:26:41 +01002202 Object* value = GetHeap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002203 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
2204 WRITE_FIELD(this, offset, value);
2205 }
2206}
2207
2208
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002209bool Object::ToArrayIndex(uint32_t* index) {
2210 if (IsSmi()) {
2211 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002212 if (value < 0) return false;
2213 *index = value;
2214 return true;
2215 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002216 if (IsHeapNumber()) {
2217 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002218 uint32_t uint_value = static_cast<uint32_t>(value);
2219 if (value == static_cast<double>(uint_value)) {
2220 *index = uint_value;
2221 return true;
2222 }
2223 }
2224 return false;
2225}
2226
2227
2228bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
2229 if (!this->IsJSValue()) return false;
2230
2231 JSValue* js_value = JSValue::cast(this);
2232 if (!js_value->value()->IsString()) return false;
2233
2234 String* str = String::cast(js_value->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002235 if (index >= static_cast<uint32_t>(str->length())) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00002236
2237 return true;
2238}
2239
2240
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002241void Object::VerifyApiCallResultType() {
2242#if ENABLE_EXTRA_CHECKS
2243 if (!(IsSmi() ||
2244 IsString() ||
2245 IsSymbol() ||
2246 IsSpecObject() ||
2247 IsHeapNumber() ||
2248 IsUndefined() ||
2249 IsTrue() ||
2250 IsFalse() ||
2251 IsNull())) {
2252 FATAL("API call returned invalid object");
2253 }
2254#endif // ENABLE_EXTRA_CHECKS
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002255}
2256
2257
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002258Object* FixedArray::get(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002259 SLOW_DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002260 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
2261}
2262
2263
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002264Handle<Object> FixedArray::get(Handle<FixedArray> array, int index) {
2265 return handle(array->get(index), array->GetIsolate());
2266}
2267
2268
2269bool FixedArray::is_the_hole(int index) {
2270 return get(index) == GetHeap()->the_hole_value();
2271}
2272
2273
Steve Blocka7e24c12009-10-30 11:49:00 +00002274void FixedArray::set(int index, Smi* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002275 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2276 DCHECK(index >= 0 && index < this->length());
2277 DCHECK(reinterpret_cast<Object*>(value)->IsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002278 int offset = kHeaderSize + index * kPointerSize;
2279 WRITE_FIELD(this, offset, value);
2280}
2281
2282
2283void FixedArray::set(int index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002284 DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
2285 DCHECK_EQ(FIXED_ARRAY_TYPE, map()->instance_type());
2286 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002287 int offset = kHeaderSize + index * kPointerSize;
2288 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002289 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002290}
2291
2292
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002293inline bool FixedDoubleArray::is_the_hole_nan(double value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002294 return bit_cast<uint64_t, double>(value) == kHoleNanInt64;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002295}
2296
2297
2298inline double FixedDoubleArray::hole_nan_as_double() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002299 return bit_cast<double, uint64_t>(kHoleNanInt64);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002300}
2301
2302
2303inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002304 DCHECK(bit_cast<uint64_t>(base::OS::nan_value()) != kHoleNanInt64);
2305 DCHECK((bit_cast<uint64_t>(base::OS::nan_value()) >> 32) != kHoleNanUpper32);
2306 return base::OS::nan_value();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002307}
2308
2309
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002310double FixedDoubleArray::get_scalar(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002311 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2312 map() != GetHeap()->fixed_array_map());
2313 DCHECK(index >= 0 && index < this->length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002314 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002315 DCHECK(!is_the_hole_nan(result));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002316 return result;
2317}
2318
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002319int64_t FixedDoubleArray::get_representation(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002320 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2321 map() != GetHeap()->fixed_array_map());
2322 DCHECK(index >= 0 && index < this->length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002323 return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
2324}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002325
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002326
2327Handle<Object> FixedDoubleArray::get(Handle<FixedDoubleArray> array,
2328 int index) {
2329 if (array->is_the_hole(index)) {
2330 return array->GetIsolate()->factory()->the_hole_value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002331 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002332 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002333 }
2334}
2335
2336
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002337void FixedDoubleArray::set(int index, double value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2339 map() != GetHeap()->fixed_array_map());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002340 int offset = kHeaderSize + index * kDoubleSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002341 if (std::isnan(value)) value = canonical_not_the_hole_nan_as_double();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002342 WRITE_DOUBLE_FIELD(this, offset, value);
2343}
2344
2345
2346void FixedDoubleArray::set_the_hole(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002347 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2348 map() != GetHeap()->fixed_array_map());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002349 int offset = kHeaderSize + index * kDoubleSize;
2350 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
2351}
2352
2353
2354bool FixedDoubleArray::is_the_hole(int index) {
2355 int offset = kHeaderSize + index * kDoubleSize;
2356 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
2357}
2358
2359
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002360double* FixedDoubleArray::data_start() {
2361 return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
2362}
2363
2364
2365void FixedDoubleArray::FillWithHoles(int from, int to) {
2366 for (int i = from; i < to; i++) {
2367 set_the_hole(i);
2368 }
2369}
2370
2371
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002372Object* WeakFixedArray::Get(int index) const {
2373 Object* raw = FixedArray::cast(this)->get(index + kFirstIndex);
2374 if (raw->IsSmi()) return raw;
2375 return WeakCell::cast(raw)->value();
2376}
2377
2378
2379bool WeakFixedArray::IsEmptySlot(int index) const {
2380 DCHECK(index < Length());
2381 return Get(index)->IsSmi();
2382}
2383
2384
2385void WeakFixedArray::clear(int index) {
2386 FixedArray::cast(this)->set(index + kFirstIndex, Smi::FromInt(0));
2387}
2388
2389
2390int WeakFixedArray::Length() const {
2391 return FixedArray::cast(this)->length() - kFirstIndex;
2392}
2393
2394
2395int WeakFixedArray::last_used_index() const {
2396 return Smi::cast(FixedArray::cast(this)->get(kLastUsedIndexIndex))->value();
2397}
2398
2399
2400void WeakFixedArray::set_last_used_index(int index) {
2401 FixedArray::cast(this)->set(kLastUsedIndexIndex, Smi::FromInt(index));
2402}
2403
2404
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002405void ConstantPoolArray::NumberOfEntries::increment(Type type) {
2406 DCHECK(type < NUMBER_OF_TYPES);
2407 element_counts_[type]++;
2408}
2409
2410
2411int ConstantPoolArray::NumberOfEntries::equals(
2412 const ConstantPoolArray::NumberOfEntries& other) const {
2413 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2414 if (element_counts_[i] != other.element_counts_[i]) return false;
2415 }
2416 return true;
2417}
2418
2419
2420bool ConstantPoolArray::NumberOfEntries::is_empty() const {
2421 return total_count() == 0;
2422}
2423
2424
2425int ConstantPoolArray::NumberOfEntries::count_of(Type type) const {
2426 DCHECK(type < NUMBER_OF_TYPES);
2427 return element_counts_[type];
2428}
2429
2430
2431int ConstantPoolArray::NumberOfEntries::base_of(Type type) const {
2432 int base = 0;
2433 DCHECK(type < NUMBER_OF_TYPES);
2434 for (int i = 0; i < type; i++) {
2435 base += element_counts_[i];
2436 }
2437 return base;
2438}
2439
2440
2441int ConstantPoolArray::NumberOfEntries::total_count() const {
2442 int count = 0;
2443 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2444 count += element_counts_[i];
2445 }
2446 return count;
2447}
2448
2449
2450int ConstantPoolArray::NumberOfEntries::are_in_range(int min, int max) const {
2451 for (int i = FIRST_TYPE; i < NUMBER_OF_TYPES; i++) {
2452 if (element_counts_[i] < min || element_counts_[i] > max) {
2453 return false;
2454 }
2455 }
2456 return true;
2457}
2458
2459
2460int ConstantPoolArray::Iterator::next_index() {
2461 DCHECK(!is_finished());
2462 int ret = next_index_++;
2463 update_section();
2464 return ret;
2465}
2466
2467
2468bool ConstantPoolArray::Iterator::is_finished() {
2469 return next_index_ > array_->last_index(type_, final_section_);
2470}
2471
2472
2473void ConstantPoolArray::Iterator::update_section() {
2474 if (next_index_ > array_->last_index(type_, current_section_) &&
2475 current_section_ != final_section_) {
2476 DCHECK(final_section_ == EXTENDED_SECTION);
2477 current_section_ = EXTENDED_SECTION;
2478 next_index_ = array_->first_index(type_, EXTENDED_SECTION);
2479 }
2480}
2481
2482
2483bool ConstantPoolArray::is_extended_layout() {
2484 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2485 return IsExtendedField::decode(small_layout_1);
2486}
2487
2488
2489ConstantPoolArray::LayoutSection ConstantPoolArray::final_section() {
2490 return is_extended_layout() ? EXTENDED_SECTION : SMALL_SECTION;
2491}
2492
2493
2494int ConstantPoolArray::first_extended_section_index() {
2495 DCHECK(is_extended_layout());
2496 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2497 return TotalCountField::decode(small_layout_2);
2498}
2499
2500
2501int ConstantPoolArray::get_extended_section_header_offset() {
2502 return RoundUp(SizeFor(NumberOfEntries(this, SMALL_SECTION)), kInt64Size);
2503}
2504
2505
2506ConstantPoolArray::WeakObjectState ConstantPoolArray::get_weak_object_state() {
2507 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2508 return WeakObjectStateField::decode(small_layout_2);
2509}
2510
2511
2512void ConstantPoolArray::set_weak_object_state(
2513 ConstantPoolArray::WeakObjectState state) {
2514 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2515 small_layout_2 = WeakObjectStateField::update(small_layout_2, state);
2516 WRITE_INT32_FIELD(this, kSmallLayout2Offset, small_layout_2);
2517}
2518
2519
2520int ConstantPoolArray::first_index(Type type, LayoutSection section) {
2521 int index = 0;
2522 if (section == EXTENDED_SECTION) {
2523 DCHECK(is_extended_layout());
2524 index += first_extended_section_index();
2525 }
2526
2527 for (Type type_iter = FIRST_TYPE; type_iter < type;
2528 type_iter = next_type(type_iter)) {
2529 index += number_of_entries(type_iter, section);
2530 }
2531
2532 return index;
2533}
2534
2535
2536int ConstantPoolArray::last_index(Type type, LayoutSection section) {
2537 return first_index(type, section) + number_of_entries(type, section) - 1;
2538}
2539
2540
2541int ConstantPoolArray::number_of_entries(Type type, LayoutSection section) {
2542 if (section == SMALL_SECTION) {
2543 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2544 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2545 switch (type) {
2546 case INT64:
2547 return Int64CountField::decode(small_layout_1);
2548 case CODE_PTR:
2549 return CodePtrCountField::decode(small_layout_1);
2550 case HEAP_PTR:
2551 return HeapPtrCountField::decode(small_layout_1);
2552 case INT32:
2553 return Int32CountField::decode(small_layout_2);
2554 default:
2555 UNREACHABLE();
2556 return 0;
2557 }
2558 } else {
2559 DCHECK(section == EXTENDED_SECTION && is_extended_layout());
2560 int offset = get_extended_section_header_offset();
2561 switch (type) {
2562 case INT64:
2563 offset += kExtendedInt64CountOffset;
2564 break;
2565 case CODE_PTR:
2566 offset += kExtendedCodePtrCountOffset;
2567 break;
2568 case HEAP_PTR:
2569 offset += kExtendedHeapPtrCountOffset;
2570 break;
2571 case INT32:
2572 offset += kExtendedInt32CountOffset;
2573 break;
2574 default:
2575 UNREACHABLE();
2576 }
2577 return READ_INT_FIELD(this, offset);
2578 }
2579}
2580
2581
2582bool ConstantPoolArray::offset_is_type(int offset, Type type) {
2583 return (offset >= OffsetOfElementAt(first_index(type, SMALL_SECTION)) &&
2584 offset <= OffsetOfElementAt(last_index(type, SMALL_SECTION))) ||
2585 (is_extended_layout() &&
2586 offset >= OffsetOfElementAt(first_index(type, EXTENDED_SECTION)) &&
2587 offset <= OffsetOfElementAt(last_index(type, EXTENDED_SECTION)));
2588}
2589
2590
2591ConstantPoolArray::Type ConstantPoolArray::get_type(int index) {
2592 LayoutSection section;
2593 if (is_extended_layout() && index >= first_extended_section_index()) {
2594 section = EXTENDED_SECTION;
2595 } else {
2596 section = SMALL_SECTION;
2597 }
2598
2599 Type type = FIRST_TYPE;
2600 while (index > last_index(type, section)) {
2601 type = next_type(type);
2602 }
2603 DCHECK(type <= LAST_TYPE);
2604 return type;
2605}
2606
2607
2608int64_t ConstantPoolArray::get_int64_entry(int index) {
2609 DCHECK(map() == GetHeap()->constant_pool_array_map());
2610 DCHECK(get_type(index) == INT64);
2611 return READ_INT64_FIELD(this, OffsetOfElementAt(index));
2612}
2613
2614
2615double ConstantPoolArray::get_int64_entry_as_double(int index) {
2616 STATIC_ASSERT(kDoubleSize == kInt64Size);
2617 DCHECK(map() == GetHeap()->constant_pool_array_map());
2618 DCHECK(get_type(index) == INT64);
2619 return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
2620}
2621
2622
2623Address ConstantPoolArray::get_code_ptr_entry(int index) {
2624 DCHECK(map() == GetHeap()->constant_pool_array_map());
2625 DCHECK(get_type(index) == CODE_PTR);
2626 return reinterpret_cast<Address>(READ_FIELD(this, OffsetOfElementAt(index)));
2627}
2628
2629
2630Object* ConstantPoolArray::get_heap_ptr_entry(int index) {
2631 DCHECK(map() == GetHeap()->constant_pool_array_map());
2632 DCHECK(get_type(index) == HEAP_PTR);
2633 return READ_FIELD(this, OffsetOfElementAt(index));
2634}
2635
2636
2637int32_t ConstantPoolArray::get_int32_entry(int index) {
2638 DCHECK(map() == GetHeap()->constant_pool_array_map());
2639 DCHECK(get_type(index) == INT32);
2640 return READ_INT32_FIELD(this, OffsetOfElementAt(index));
2641}
2642
2643
2644void ConstantPoolArray::set(int index, int64_t value) {
2645 DCHECK(map() == GetHeap()->constant_pool_array_map());
2646 DCHECK(get_type(index) == INT64);
2647 WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
2648}
2649
2650
2651void ConstantPoolArray::set(int index, double value) {
2652 STATIC_ASSERT(kDoubleSize == kInt64Size);
2653 DCHECK(map() == GetHeap()->constant_pool_array_map());
2654 DCHECK(get_type(index) == INT64);
2655 WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
2656}
2657
2658
2659void ConstantPoolArray::set(int index, Address value) {
2660 DCHECK(map() == GetHeap()->constant_pool_array_map());
2661 DCHECK(get_type(index) == CODE_PTR);
2662 WRITE_FIELD(this, OffsetOfElementAt(index), reinterpret_cast<Object*>(value));
2663}
2664
2665
2666void ConstantPoolArray::set(int index, Object* value) {
2667 DCHECK(map() == GetHeap()->constant_pool_array_map());
2668 DCHECK(!GetHeap()->InNewSpace(value));
2669 DCHECK(get_type(index) == HEAP_PTR);
2670 WRITE_FIELD(this, OffsetOfElementAt(index), value);
2671 WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
2672}
2673
2674
2675void ConstantPoolArray::set(int index, int32_t value) {
2676 DCHECK(map() == GetHeap()->constant_pool_array_map());
2677 DCHECK(get_type(index) == INT32);
2678 WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value);
2679}
2680
2681
2682void ConstantPoolArray::set_at_offset(int offset, int32_t value) {
2683 DCHECK(map() == GetHeap()->constant_pool_array_map());
2684 DCHECK(offset_is_type(offset, INT32));
2685 WRITE_INT32_FIELD(this, offset, value);
2686}
2687
2688
2689void ConstantPoolArray::set_at_offset(int offset, int64_t value) {
2690 DCHECK(map() == GetHeap()->constant_pool_array_map());
2691 DCHECK(offset_is_type(offset, INT64));
2692 WRITE_INT64_FIELD(this, offset, value);
2693}
2694
2695
2696void ConstantPoolArray::set_at_offset(int offset, double value) {
2697 DCHECK(map() == GetHeap()->constant_pool_array_map());
2698 DCHECK(offset_is_type(offset, INT64));
2699 WRITE_DOUBLE_FIELD(this, offset, value);
2700}
2701
2702
2703void ConstantPoolArray::set_at_offset(int offset, Address value) {
2704 DCHECK(map() == GetHeap()->constant_pool_array_map());
2705 DCHECK(offset_is_type(offset, CODE_PTR));
2706 WRITE_FIELD(this, offset, reinterpret_cast<Object*>(value));
2707 WRITE_BARRIER(GetHeap(), this, offset, reinterpret_cast<Object*>(value));
2708}
2709
2710
2711void ConstantPoolArray::set_at_offset(int offset, Object* value) {
2712 DCHECK(map() == GetHeap()->constant_pool_array_map());
2713 DCHECK(!GetHeap()->InNewSpace(value));
2714 DCHECK(offset_is_type(offset, HEAP_PTR));
2715 WRITE_FIELD(this, offset, value);
2716 WRITE_BARRIER(GetHeap(), this, offset, value);
2717}
2718
2719
2720void ConstantPoolArray::Init(const NumberOfEntries& small) {
2721 uint32_t small_layout_1 =
2722 Int64CountField::encode(small.count_of(INT64)) |
2723 CodePtrCountField::encode(small.count_of(CODE_PTR)) |
2724 HeapPtrCountField::encode(small.count_of(HEAP_PTR)) |
2725 IsExtendedField::encode(false);
2726 uint32_t small_layout_2 =
2727 Int32CountField::encode(small.count_of(INT32)) |
2728 TotalCountField::encode(small.total_count()) |
2729 WeakObjectStateField::encode(NO_WEAK_OBJECTS);
2730 WRITE_UINT32_FIELD(this, kSmallLayout1Offset, small_layout_1);
2731 WRITE_UINT32_FIELD(this, kSmallLayout2Offset, small_layout_2);
2732 if (kHeaderSize != kFirstEntryOffset) {
2733 DCHECK(kFirstEntryOffset - kHeaderSize == kInt32Size);
2734 WRITE_UINT32_FIELD(this, kHeaderSize, 0); // Zero out header padding.
2735 }
2736}
2737
2738
2739void ConstantPoolArray::InitExtended(const NumberOfEntries& small,
2740 const NumberOfEntries& extended) {
2741 // Initialize small layout fields first.
2742 Init(small);
2743
2744 // Set is_extended_layout field.
2745 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2746 small_layout_1 = IsExtendedField::update(small_layout_1, true);
2747 WRITE_INT32_FIELD(this, kSmallLayout1Offset, small_layout_1);
2748
2749 // Initialize the extended layout fields.
2750 int extended_header_offset = get_extended_section_header_offset();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002751 WRITE_INT32_FIELD(this, extended_header_offset + kExtendedInt64CountOffset,
2752 extended.count_of(INT64));
2753 WRITE_INT32_FIELD(this, extended_header_offset + kExtendedCodePtrCountOffset,
2754 extended.count_of(CODE_PTR));
2755 WRITE_INT32_FIELD(this, extended_header_offset + kExtendedHeapPtrCountOffset,
2756 extended.count_of(HEAP_PTR));
2757 WRITE_INT32_FIELD(this, extended_header_offset + kExtendedInt32CountOffset,
2758 extended.count_of(INT32));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002759}
2760
2761
2762int ConstantPoolArray::size() {
2763 NumberOfEntries small(this, SMALL_SECTION);
2764 if (!is_extended_layout()) {
2765 return SizeFor(small);
2766 } else {
2767 NumberOfEntries extended(this, EXTENDED_SECTION);
2768 return SizeForExtended(small, extended);
2769 }
2770}
2771
2772
2773int ConstantPoolArray::length() {
2774 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2775 int length = TotalCountField::decode(small_layout_2);
2776 if (is_extended_layout()) {
2777 length += number_of_entries(INT64, EXTENDED_SECTION) +
2778 number_of_entries(CODE_PTR, EXTENDED_SECTION) +
2779 number_of_entries(HEAP_PTR, EXTENDED_SECTION) +
2780 number_of_entries(INT32, EXTENDED_SECTION);
2781 }
2782 return length;
2783}
2784
2785
2786WriteBarrierMode HeapObject::GetWriteBarrierMode(
2787 const DisallowHeapAllocation& promise) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002788 Heap* heap = GetHeap();
2789 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
2790 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
Steve Blocka7e24c12009-10-30 11:49:00 +00002791 return UPDATE_WRITE_BARRIER;
2792}
2793
2794
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002795bool HeapObject::NeedsToEnsureDoubleAlignment() {
2796#ifndef V8_HOST_ARCH_64_BIT
2797 return (IsFixedFloat64Array() || IsFixedDoubleArray() ||
2798 IsConstantPoolArray()) &&
2799 FixedArrayBase::cast(this)->length() != 0;
2800#else
2801 return false;
2802#endif // V8_HOST_ARCH_64_BIT
2803}
2804
2805
Steve Blocka7e24c12009-10-30 11:49:00 +00002806void FixedArray::set(int index,
2807 Object* value,
2808 WriteBarrierMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002809 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2810 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002811 int offset = kHeaderSize + index * kPointerSize;
2812 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002813 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002814}
2815
2816
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002817void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
2818 int index,
2819 Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002820 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map());
2821 DCHECK(index >= 0 && index < array->length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002822 int offset = kHeaderSize + index * kPointerSize;
2823 WRITE_FIELD(array, offset, value);
2824 Heap* heap = array->GetHeap();
2825 if (heap->InNewSpace(value)) {
2826 heap->RecordWrite(array->address(), offset);
2827 }
2828}
2829
2830
2831void FixedArray::NoWriteBarrierSet(FixedArray* array,
2832 int index,
2833 Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002834 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map());
2835 DCHECK(index >= 0 && index < array->length());
2836 DCHECK(!array->GetHeap()->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002837 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
2838}
2839
2840
2841void FixedArray::set_undefined(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002842 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2843 DCHECK(index >= 0 && index < this->length());
2844 DCHECK(!GetHeap()->InNewSpace(GetHeap()->undefined_value()));
2845 WRITE_FIELD(this,
2846 kHeaderSize + index * kPointerSize,
2847 GetHeap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002848}
2849
2850
2851void FixedArray::set_null(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002852 DCHECK(index >= 0 && index < this->length());
2853 DCHECK(!GetHeap()->InNewSpace(GetHeap()->null_value()));
2854 WRITE_FIELD(this,
2855 kHeaderSize + index * kPointerSize,
2856 GetHeap()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002857}
2858
2859
2860void FixedArray::set_the_hole(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002861 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2862 DCHECK(index >= 0 && index < this->length());
2863 DCHECK(!GetHeap()->InNewSpace(GetHeap()->the_hole_value()));
Steve Block44f0eee2011-05-26 01:26:41 +01002864 WRITE_FIELD(this,
2865 kHeaderSize + index * kPointerSize,
2866 GetHeap()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002867}
2868
2869
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002870void FixedArray::FillWithHoles(int from, int to) {
2871 for (int i = from; i < to; i++) {
2872 set_the_hole(i);
2873 }
Iain Merrick75681382010-08-19 15:07:18 +01002874}
2875
2876
Steve Block6ded16b2010-05-10 14:33:55 +01002877Object** FixedArray::data_start() {
2878 return HeapObject::RawField(this, kHeaderSize);
2879}
2880
2881
Steve Blocka7e24c12009-10-30 11:49:00 +00002882bool DescriptorArray::IsEmpty() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002883 DCHECK(length() >= kFirstIndex ||
2884 this == GetHeap()->empty_descriptor_array());
2885 return length() < kFirstIndex;
Ben Murdoch257744e2011-11-30 15:57:28 +00002886}
2887
2888
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002889void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
2890 WRITE_FIELD(
2891 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
Steve Blocka7e24c12009-10-30 11:49:00 +00002892}
2893
2894
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002895// Perform a binary search in a fixed array. Low and high are entry indices. If
2896// there are three entries in this array it should be called with low=0 and
2897// high=2.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002898template <SearchMode search_mode, typename T>
2899int BinarySearch(T* array, Name* name, int low, int high, int valid_entries,
2900 int* out_insertion_index) {
2901 DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002902 uint32_t hash = name->Hash();
2903 int limit = high;
2904
2905 DCHECK(low <= high);
2906
2907 while (low != high) {
2908 int mid = (low + high) / 2;
2909 Name* mid_name = array->GetSortedKey(mid);
2910 uint32_t mid_hash = mid_name->Hash();
2911
2912 if (mid_hash >= hash) {
2913 high = mid;
2914 } else {
2915 low = mid + 1;
2916 }
2917 }
2918
2919 for (; low <= limit; ++low) {
2920 int sort_index = array->GetSortedKeyIndex(low);
2921 Name* entry = array->GetKey(sort_index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002922 uint32_t current_hash = entry->Hash();
2923 if (current_hash != hash) {
2924 if (out_insertion_index != NULL) {
2925 *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
2926 }
2927 return T::kNotFound;
2928 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002929 if (entry->Equals(name)) {
2930 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
2931 return sort_index;
2932 }
2933 return T::kNotFound;
2934 }
2935 }
2936
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002937 if (out_insertion_index != NULL) *out_insertion_index = limit + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002938 return T::kNotFound;
Steve Blocka7e24c12009-10-30 11:49:00 +00002939}
2940
2941
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002942// Perform a linear search in this fixed array. len is the number of entry
2943// indices that are valid.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002944template <SearchMode search_mode, typename T>
2945int LinearSearch(T* array, Name* name, int len, int valid_entries,
2946 int* out_insertion_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002947 uint32_t hash = name->Hash();
2948 if (search_mode == ALL_ENTRIES) {
2949 for (int number = 0; number < len; number++) {
2950 int sorted_index = array->GetSortedKeyIndex(number);
2951 Name* entry = array->GetKey(sorted_index);
2952 uint32_t current_hash = entry->Hash();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002953 if (current_hash > hash) {
2954 if (out_insertion_index != NULL) *out_insertion_index = sorted_index;
2955 return T::kNotFound;
2956 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002957 if (current_hash == hash && entry->Equals(name)) return sorted_index;
2958 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002959 if (out_insertion_index != NULL) *out_insertion_index = len;
2960 return T::kNotFound;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002961 } else {
2962 DCHECK(len >= valid_entries);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002963 DCHECK_EQ(NULL, out_insertion_index); // Not supported here.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002964 for (int number = 0; number < valid_entries; number++) {
2965 Name* entry = array->GetKey(number);
2966 uint32_t current_hash = entry->Hash();
2967 if (current_hash == hash && entry->Equals(name)) return number;
2968 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002969 return T::kNotFound;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002970 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002971}
Steve Blocka7e24c12009-10-30 11:49:00 +00002972
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002973
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002974template <SearchMode search_mode, typename T>
2975int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002976 if (search_mode == VALID_ENTRIES) {
2977 SLOW_DCHECK(array->IsSortedNoDuplicates(valid_entries));
2978 } else {
2979 SLOW_DCHECK(array->IsSortedNoDuplicates());
2980 }
2981
2982 int nof = array->number_of_entries();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002983 if (nof == 0) {
2984 if (out_insertion_index != NULL) *out_insertion_index = 0;
2985 return T::kNotFound;
2986 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002987
2988 // Fast case: do linear search for small arrays.
2989 const int kMaxElementsForLinearSearch = 8;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002990 if ((search_mode == ALL_ENTRIES &&
2991 nof <= kMaxElementsForLinearSearch) ||
2992 (search_mode == VALID_ENTRIES &&
2993 valid_entries <= (kMaxElementsForLinearSearch * 3))) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002994 return LinearSearch<search_mode>(array, name, nof, valid_entries,
2995 out_insertion_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002996 }
2997
2998 // Slow case: perform binary search.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002999 return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries,
3000 out_insertion_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003001}
3002
3003
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003004int DescriptorArray::Search(Name* name, int valid_descriptors) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003005 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003006}
3007
3008
3009int DescriptorArray::SearchWithCache(Name* name, Map* map) {
3010 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3011 if (number_of_own_descriptors == 0) return kNotFound;
3012
3013 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
3014 int number = cache->Lookup(map, name);
3015
Iain Merrick75681382010-08-19 15:07:18 +01003016 if (number == DescriptorLookupCache::kAbsent) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003017 number = Search(name, number_of_own_descriptors);
3018 cache->Update(map, name, number);
Iain Merrick75681382010-08-19 15:07:18 +01003019 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003020
Iain Merrick75681382010-08-19 15:07:18 +01003021 return number;
3022}
3023
3024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003025PropertyDetails Map::GetLastDescriptorDetails() {
3026 return instance_descriptors()->GetDetails(LastAdded());
3027}
3028
3029
3030void Map::LookupDescriptor(JSObject* holder,
3031 Name* name,
3032 LookupResult* result) {
3033 DescriptorArray* descriptors = this->instance_descriptors();
3034 int number = descriptors->SearchWithCache(name, this);
3035 if (number == DescriptorArray::kNotFound) return result->NotFound();
3036 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
3037}
3038
3039
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003040void Map::LookupTransition(JSObject* holder, Name* name,
3041 PropertyAttributes attributes,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003042 LookupResult* result) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003043 int transition_index = this->SearchTransition(DATA, name, attributes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003044 if (transition_index == TransitionArray::kNotFound) return result->NotFound();
3045 result->TransitionResult(holder, this->GetTransition(transition_index));
3046}
3047
3048
3049FixedArrayBase* Map::GetInitialElements() {
3050 if (has_fast_smi_or_object_elements() ||
3051 has_fast_double_elements()) {
3052 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
3053 return GetHeap()->empty_fixed_array();
3054 } else if (has_external_array_elements()) {
3055 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this);
3056 DCHECK(!GetHeap()->InNewSpace(empty_array));
3057 return empty_array;
3058 } else if (has_fixed_typed_array_elements()) {
3059 FixedTypedArrayBase* empty_array =
3060 GetHeap()->EmptyFixedTypedArrayForMap(this);
3061 DCHECK(!GetHeap()->InNewSpace(empty_array));
3062 return empty_array;
3063 } else {
3064 UNREACHABLE();
3065 }
3066 return NULL;
3067}
3068
3069
3070Object** DescriptorArray::GetKeySlot(int descriptor_number) {
3071 DCHECK(descriptor_number < number_of_descriptors());
3072 return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
3073}
3074
3075
3076Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
3077 return GetKeySlot(descriptor_number);
3078}
3079
3080
3081Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
3082 return GetValueSlot(descriptor_number - 1) + 1;
3083}
3084
3085
3086Name* DescriptorArray::GetKey(int descriptor_number) {
3087 DCHECK(descriptor_number < number_of_descriptors());
3088 return Name::cast(get(ToKeyIndex(descriptor_number)));
3089}
3090
3091
3092int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
3093 return GetDetails(descriptor_number).pointer();
3094}
3095
3096
3097Name* DescriptorArray::GetSortedKey(int descriptor_number) {
3098 return GetKey(GetSortedKeyIndex(descriptor_number));
3099}
3100
3101
3102void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
3103 PropertyDetails details = GetDetails(descriptor_index);
3104 set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
3105}
3106
3107
3108void DescriptorArray::SetRepresentation(int descriptor_index,
3109 Representation representation) {
3110 DCHECK(!representation.IsNone());
3111 PropertyDetails details = GetDetails(descriptor_index);
3112 set(ToDetailsIndex(descriptor_index),
3113 details.CopyWithRepresentation(representation).AsSmi());
3114}
3115
3116
3117Object** DescriptorArray::GetValueSlot(int descriptor_number) {
3118 DCHECK(descriptor_number < number_of_descriptors());
3119 return RawFieldOfElementAt(ToValueIndex(descriptor_number));
3120}
3121
3122
3123int DescriptorArray::GetValueOffset(int descriptor_number) {
3124 return OffsetOfElementAt(ToValueIndex(descriptor_number));
Steve Blocka7e24c12009-10-30 11:49:00 +00003125}
3126
3127
3128Object* DescriptorArray::GetValue(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003129 DCHECK(descriptor_number < number_of_descriptors());
3130 return get(ToValueIndex(descriptor_number));
Steve Blocka7e24c12009-10-30 11:49:00 +00003131}
3132
3133
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003134void DescriptorArray::SetValue(int descriptor_index, Object* value) {
3135 set(ToValueIndex(descriptor_index), value);
3136}
3137
3138
3139PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
3140 DCHECK(descriptor_number < number_of_descriptors());
3141 Object* details = get(ToDetailsIndex(descriptor_number));
3142 return PropertyDetails(Smi::cast(details));
Steve Blocka7e24c12009-10-30 11:49:00 +00003143}
3144
3145
3146PropertyType DescriptorArray::GetType(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003147 return GetDetails(descriptor_number).type();
Steve Blocka7e24c12009-10-30 11:49:00 +00003148}
3149
3150
3151int DescriptorArray::GetFieldIndex(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003152 DCHECK(GetDetails(descriptor_number).type() == FIELD);
3153 return GetDetails(descriptor_number).field_index();
Steve Blocka7e24c12009-10-30 11:49:00 +00003154}
3155
3156
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003157HeapType* DescriptorArray::GetFieldType(int descriptor_number) {
3158 DCHECK(GetDetails(descriptor_number).type() == FIELD);
3159 return HeapType::cast(GetValue(descriptor_number));
3160}
3161
3162
3163Object* DescriptorArray::GetConstant(int descriptor_number) {
3164 return GetValue(descriptor_number);
Steve Blocka7e24c12009-10-30 11:49:00 +00003165}
3166
3167
3168Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003169 DCHECK(GetType(descriptor_number) == CALLBACKS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003170 return GetValue(descriptor_number);
3171}
3172
3173
3174AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003175 DCHECK(GetType(descriptor_number) == CALLBACKS);
Ben Murdoch257744e2011-11-30 15:57:28 +00003176 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003177 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00003178}
3179
3180
Steve Blocka7e24c12009-10-30 11:49:00 +00003181void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003182 desc->Init(handle(GetKey(descriptor_number), GetIsolate()),
3183 handle(GetValue(descriptor_number), GetIsolate()),
3184 GetDetails(descriptor_number));
Steve Blocka7e24c12009-10-30 11:49:00 +00003185}
3186
3187
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003188void DescriptorArray::Set(int descriptor_number,
3189 Descriptor* desc,
3190 const WhitenessWitness&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003191 // Range check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003192 DCHECK(descriptor_number < number_of_descriptors());
Steve Blocka7e24c12009-10-30 11:49:00 +00003193
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003194 NoIncrementalWriteBarrierSet(this,
3195 ToKeyIndex(descriptor_number),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003196 *desc->GetKey());
3197 NoIncrementalWriteBarrierSet(this,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003198 ToValueIndex(descriptor_number),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003199 *desc->GetValue());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003200 NoIncrementalWriteBarrierSet(this, ToDetailsIndex(descriptor_number),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003201 desc->GetDetails().AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00003202}
3203
3204
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003205void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
3206 // Range check.
3207 DCHECK(descriptor_number < number_of_descriptors());
3208
3209 set(ToKeyIndex(descriptor_number), *desc->GetKey());
3210 set(ToValueIndex(descriptor_number), *desc->GetValue());
3211 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
3212}
3213
3214
3215void DescriptorArray::Append(Descriptor* desc) {
3216 DisallowHeapAllocation no_gc;
3217 int descriptor_number = number_of_descriptors();
3218 SetNumberOfDescriptors(descriptor_number + 1);
3219 Set(descriptor_number, desc);
3220
3221 uint32_t hash = desc->GetKey()->Hash();
3222
3223 int insertion;
3224
3225 for (insertion = descriptor_number; insertion > 0; --insertion) {
3226 Name* key = GetSortedKey(insertion - 1);
3227 if (key->Hash() <= hash) break;
3228 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
3229 }
3230
3231 SetSortedKey(insertion, descriptor_number);
3232}
3233
3234
3235void DescriptorArray::SwapSortedKeys(int first, int second) {
3236 int first_key = GetSortedKeyIndex(first);
3237 SetSortedKey(first, GetSortedKeyIndex(second));
3238 SetSortedKey(second, first_key);
Ben Murdoch85b71792012-04-11 18:30:58 +01003239}
3240
3241
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003242DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
3243 : marking_(array->GetHeap()->incremental_marking()) {
3244 marking_->EnterNoMarkingScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003245 DCHECK(!marking_->IsMarking() ||
3246 Marking::Color(array) == Marking::WHITE_OBJECT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003247}
3248
3249
3250DescriptorArray::WhitenessWitness::~WhitenessWitness() {
3251 marking_->LeaveNoMarkingScope();
Steve Blocka7e24c12009-10-30 11:49:00 +00003252}
3253
3254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003255template<typename Derived, typename Shape, typename Key>
3256int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003257 const int kMinCapacity = 32;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003258 int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003259 if (capacity < kMinCapacity) {
3260 capacity = kMinCapacity; // Guarantee min capacity.
3261 }
3262 return capacity;
3263}
3264
3265
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003266template<typename Derived, typename Shape, typename Key>
3267int HashTable<Derived, Shape, Key>::FindEntry(Key key) {
Steve Block44f0eee2011-05-26 01:26:41 +01003268 return FindEntry(GetIsolate(), key);
3269}
3270
3271
3272// Find entry for key otherwise return kNotFound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003273template<typename Derived, typename Shape, typename Key>
3274int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key) {
Steve Block44f0eee2011-05-26 01:26:41 +01003275 uint32_t capacity = Capacity();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003276 uint32_t entry = FirstProbe(HashTable::Hash(key), capacity);
Steve Block44f0eee2011-05-26 01:26:41 +01003277 uint32_t count = 1;
3278 // EnsureCapacity will guarantee the hash table is never full.
3279 while (true) {
3280 Object* element = KeyAt(entry);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003281 // Empty entry. Uses raw unchecked accessors because it is called by the
3282 // string table during bootstrapping.
Ben Murdochc7cc0282012-03-05 14:35:55 +00003283 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003284 if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
Steve Block44f0eee2011-05-26 01:26:41 +01003285 Shape::IsMatch(key, element)) return entry;
3286 entry = NextProbe(entry, count++, capacity);
3287 }
3288 return kNotFound;
3289}
3290
3291
Ben Murdochc7cc0282012-03-05 14:35:55 +00003292bool SeededNumberDictionary::requires_slow_elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003293 Object* max_index_object = get(kMaxNumberKeyIndex);
3294 if (!max_index_object->IsSmi()) return false;
3295 return 0 !=
3296 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
3297}
3298
Ben Murdochc7cc0282012-03-05 14:35:55 +00003299uint32_t SeededNumberDictionary::max_number_key() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003300 DCHECK(!requires_slow_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003301 Object* max_index_object = get(kMaxNumberKeyIndex);
3302 if (!max_index_object->IsSmi()) return 0;
3303 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
3304 return value >> kRequiresSlowElementsTagSize;
3305}
3306
Ben Murdochc7cc0282012-03-05 14:35:55 +00003307void SeededNumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00003308 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00003309}
3310
3311
3312// ------------------------------------
3313// Cast operations
3314
3315
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003316CAST_ACCESSOR(AccessorInfo)
3317CAST_ACCESSOR(ByteArray)
3318CAST_ACCESSOR(Cell)
3319CAST_ACCESSOR(Code)
3320CAST_ACCESSOR(CodeCacheHashTable)
3321CAST_ACCESSOR(CompilationCacheTable)
3322CAST_ACCESSOR(ConsString)
3323CAST_ACCESSOR(ConstantPoolArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003324CAST_ACCESSOR(DeoptimizationInputData)
3325CAST_ACCESSOR(DeoptimizationOutputData)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003326CAST_ACCESSOR(DependentCode)
3327CAST_ACCESSOR(DescriptorArray)
Steve Block3ce2e202009-11-05 08:53:23 +00003328CAST_ACCESSOR(ExternalArray)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003329CAST_ACCESSOR(ExternalOneByteString)
3330CAST_ACCESSOR(ExternalFloat32Array)
3331CAST_ACCESSOR(ExternalFloat64Array)
3332CAST_ACCESSOR(ExternalInt16Array)
3333CAST_ACCESSOR(ExternalInt32Array)
3334CAST_ACCESSOR(ExternalInt8Array)
3335CAST_ACCESSOR(ExternalString)
3336CAST_ACCESSOR(ExternalTwoByteString)
3337CAST_ACCESSOR(ExternalUint16Array)
3338CAST_ACCESSOR(ExternalUint32Array)
3339CAST_ACCESSOR(ExternalUint8Array)
3340CAST_ACCESSOR(ExternalUint8ClampedArray)
3341CAST_ACCESSOR(FixedArray)
3342CAST_ACCESSOR(FixedArrayBase)
3343CAST_ACCESSOR(FixedDoubleArray)
3344CAST_ACCESSOR(FixedTypedArrayBase)
3345CAST_ACCESSOR(Foreign)
3346CAST_ACCESSOR(FreeSpace)
3347CAST_ACCESSOR(GlobalObject)
3348CAST_ACCESSOR(HeapObject)
3349CAST_ACCESSOR(JSArray)
3350CAST_ACCESSOR(JSArrayBuffer)
3351CAST_ACCESSOR(JSArrayBufferView)
3352CAST_ACCESSOR(JSBuiltinsObject)
3353CAST_ACCESSOR(JSDataView)
3354CAST_ACCESSOR(JSDate)
3355CAST_ACCESSOR(JSFunction)
3356CAST_ACCESSOR(JSFunctionProxy)
3357CAST_ACCESSOR(JSFunctionResultCache)
3358CAST_ACCESSOR(JSGeneratorObject)
3359CAST_ACCESSOR(JSGlobalObject)
3360CAST_ACCESSOR(JSGlobalProxy)
3361CAST_ACCESSOR(JSMap)
3362CAST_ACCESSOR(JSMapIterator)
3363CAST_ACCESSOR(JSMessageObject)
3364CAST_ACCESSOR(JSModule)
3365CAST_ACCESSOR(JSObject)
3366CAST_ACCESSOR(JSProxy)
3367CAST_ACCESSOR(JSReceiver)
3368CAST_ACCESSOR(JSRegExp)
3369CAST_ACCESSOR(JSSet)
3370CAST_ACCESSOR(JSSetIterator)
3371CAST_ACCESSOR(JSTypedArray)
3372CAST_ACCESSOR(JSValue)
3373CAST_ACCESSOR(JSWeakMap)
3374CAST_ACCESSOR(JSWeakSet)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003375CAST_ACCESSOR(LayoutDescriptor)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003376CAST_ACCESSOR(Map)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003377CAST_ACCESSOR(Name)
3378CAST_ACCESSOR(NameDictionary)
3379CAST_ACCESSOR(NormalizedMapCache)
3380CAST_ACCESSOR(Object)
3381CAST_ACCESSOR(ObjectHashTable)
3382CAST_ACCESSOR(Oddball)
3383CAST_ACCESSOR(OrderedHashMap)
3384CAST_ACCESSOR(OrderedHashSet)
3385CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
3386CAST_ACCESSOR(PropertyCell)
3387CAST_ACCESSOR(ScopeInfo)
3388CAST_ACCESSOR(SeededNumberDictionary)
3389CAST_ACCESSOR(SeqOneByteString)
3390CAST_ACCESSOR(SeqString)
3391CAST_ACCESSOR(SeqTwoByteString)
3392CAST_ACCESSOR(SharedFunctionInfo)
3393CAST_ACCESSOR(SlicedString)
3394CAST_ACCESSOR(Smi)
3395CAST_ACCESSOR(String)
3396CAST_ACCESSOR(StringTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00003397CAST_ACCESSOR(Struct)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003398CAST_ACCESSOR(Symbol)
3399CAST_ACCESSOR(UnseededNumberDictionary)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003400CAST_ACCESSOR(WeakCell)
3401CAST_ACCESSOR(WeakFixedArray)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003402CAST_ACCESSOR(WeakHashTable)
3403
3404
3405template <class Traits>
3406FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
3407 SLOW_DCHECK(object->IsHeapObject() &&
3408 HeapObject::cast(object)->map()->instance_type() ==
3409 Traits::kInstanceType);
3410 return reinterpret_cast<FixedTypedArray<Traits>*>(object);
3411}
3412
3413
3414template <class Traits>
3415const FixedTypedArray<Traits>*
3416FixedTypedArray<Traits>::cast(const Object* object) {
3417 SLOW_DCHECK(object->IsHeapObject() &&
3418 HeapObject::cast(object)->map()->instance_type() ==
3419 Traits::kInstanceType);
3420 return reinterpret_cast<FixedTypedArray<Traits>*>(object);
3421}
Steve Blocka7e24c12009-10-30 11:49:00 +00003422
3423
3424#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
3425 STRUCT_LIST(MAKE_STRUCT_CAST)
3426#undef MAKE_STRUCT_CAST
3427
3428
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003429template <typename Derived, typename Shape, typename Key>
3430HashTable<Derived, Shape, Key>*
3431HashTable<Derived, Shape, Key>::cast(Object* obj) {
3432 SLOW_DCHECK(obj->IsHashTable());
Steve Blocka7e24c12009-10-30 11:49:00 +00003433 return reinterpret_cast<HashTable*>(obj);
3434}
3435
3436
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003437template <typename Derived, typename Shape, typename Key>
3438const HashTable<Derived, Shape, Key>*
3439HashTable<Derived, Shape, Key>::cast(const Object* obj) {
3440 SLOW_DCHECK(obj->IsHashTable());
3441 return reinterpret_cast<const HashTable*>(obj);
3442}
3443
3444
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003445SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003446SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
3447
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003448SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003449NOBARRIER_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003450
Steve Block6ded16b2010-05-10 14:33:55 +01003451SMI_ACCESSORS(String, length, kLengthOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003452SYNCHRONIZED_SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00003453
3454
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003455uint32_t Name::hash_field() {
Steve Blockd0582a62009-12-15 09:54:21 +00003456 return READ_UINT32_FIELD(this, kHashFieldOffset);
3457}
3458
3459
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003460void Name::set_hash_field(uint32_t value) {
Steve Blockd0582a62009-12-15 09:54:21 +00003461 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003462#if V8_HOST_ARCH_64_BIT
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003463#if V8_TARGET_LITTLE_ENDIAN
3464 WRITE_UINT32_FIELD(this, kHashFieldSlot + kIntSize, 0);
3465#else
3466 WRITE_UINT32_FIELD(this, kHashFieldSlot, 0);
3467#endif
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003468#endif
Steve Blockd0582a62009-12-15 09:54:21 +00003469}
3470
3471
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003472bool Name::Equals(Name* other) {
3473 if (other == this) return true;
3474 if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
3475 this->IsSymbol() || other->IsSymbol()) {
3476 return false;
3477 }
3478 return String::cast(this)->SlowEquals(String::cast(other));
3479}
3480
3481
3482bool Name::Equals(Handle<Name> one, Handle<Name> two) {
3483 if (one.is_identical_to(two)) return true;
3484 if ((one->IsInternalizedString() && two->IsInternalizedString()) ||
3485 one->IsSymbol() || two->IsSymbol()) {
3486 return false;
3487 }
3488 return String::SlowEquals(Handle<String>::cast(one),
3489 Handle<String>::cast(two));
3490}
3491
3492
3493ACCESSORS(Symbol, name, Object, kNameOffset)
3494ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
3495BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
3496BOOL_ACCESSORS(Symbol, flags, is_own, kOwnBit)
3497
3498
Steve Blocka7e24c12009-10-30 11:49:00 +00003499bool String::Equals(String* other) {
3500 if (other == this) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003501 if (this->IsInternalizedString() && other->IsInternalizedString()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003502 return false;
3503 }
3504 return SlowEquals(other);
3505}
3506
3507
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003508bool String::Equals(Handle<String> one, Handle<String> two) {
3509 if (one.is_identical_to(two)) return true;
3510 if (one->IsInternalizedString() && two->IsInternalizedString()) {
3511 return false;
3512 }
3513 return SlowEquals(one, two);
Steve Blocka7e24c12009-10-30 11:49:00 +00003514}
3515
3516
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003517Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
3518 if (!string->IsConsString()) return string;
3519 Handle<ConsString> cons = Handle<ConsString>::cast(string);
3520 if (cons->IsFlat()) return handle(cons->first());
3521 return SlowFlatten(cons, pretenure);
Leon Clarkef7060e22010-06-03 12:02:55 +01003522}
3523
3524
Steve Blocka7e24c12009-10-30 11:49:00 +00003525uint16_t String::Get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003526 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003527 switch (StringShape(this).full_representation_tag()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003528 case kSeqStringTag | kOneByteStringTag:
3529 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003530 case kSeqStringTag | kTwoByteStringTag:
3531 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003532 case kConsStringTag | kOneByteStringTag:
Steve Blocka7e24c12009-10-30 11:49:00 +00003533 case kConsStringTag | kTwoByteStringTag:
3534 return ConsString::cast(this)->ConsStringGet(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003535 case kExternalStringTag | kOneByteStringTag:
3536 return ExternalOneByteString::cast(this)->ExternalOneByteStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003537 case kExternalStringTag | kTwoByteStringTag:
3538 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003539 case kSlicedStringTag | kOneByteStringTag:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003540 case kSlicedStringTag | kTwoByteStringTag:
3541 return SlicedString::cast(this)->SlicedStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003542 default:
3543 break;
3544 }
3545
3546 UNREACHABLE();
3547 return 0;
3548}
3549
3550
3551void String::Set(int index, uint16_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003552 DCHECK(index >= 0 && index < length());
3553 DCHECK(StringShape(this).IsSequential());
Steve Blocka7e24c12009-10-30 11:49:00 +00003554
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003555 return this->IsOneByteRepresentation()
3556 ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value)
Steve Blocka7e24c12009-10-30 11:49:00 +00003557 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
3558}
3559
3560
3561bool String::IsFlat() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003562 if (!StringShape(this).IsCons()) return true;
3563 return ConsString::cast(this)->second()->length() == 0;
3564}
3565
3566
3567String* String::GetUnderlying() {
3568 // Giving direct access to underlying string only makes sense if the
3569 // wrapping string is already flattened.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003570 DCHECK(this->IsFlat());
3571 DCHECK(StringShape(this).IsIndirect());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003572 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
3573 const int kUnderlyingOffset = SlicedString::kParentOffset;
3574 return String::cast(READ_FIELD(this, kUnderlyingOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00003575}
3576
3577
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003578template<class Visitor>
3579ConsString* String::VisitFlat(Visitor* visitor,
3580 String* string,
3581 const int offset) {
3582 int slice_offset = offset;
3583 const int length = string->length();
3584 DCHECK(offset <= length);
3585 while (true) {
3586 int32_t type = string->map()->instance_type();
3587 switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
3588 case kSeqStringTag | kOneByteStringTag:
3589 visitor->VisitOneByteString(
3590 SeqOneByteString::cast(string)->GetChars() + slice_offset,
3591 length - offset);
3592 return NULL;
3593
3594 case kSeqStringTag | kTwoByteStringTag:
3595 visitor->VisitTwoByteString(
3596 SeqTwoByteString::cast(string)->GetChars() + slice_offset,
3597 length - offset);
3598 return NULL;
3599
3600 case kExternalStringTag | kOneByteStringTag:
3601 visitor->VisitOneByteString(
3602 ExternalOneByteString::cast(string)->GetChars() + slice_offset,
3603 length - offset);
3604 return NULL;
3605
3606 case kExternalStringTag | kTwoByteStringTag:
3607 visitor->VisitTwoByteString(
3608 ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
3609 length - offset);
3610 return NULL;
3611
3612 case kSlicedStringTag | kOneByteStringTag:
3613 case kSlicedStringTag | kTwoByteStringTag: {
3614 SlicedString* slicedString = SlicedString::cast(string);
3615 slice_offset += slicedString->offset();
3616 string = slicedString->parent();
3617 continue;
3618 }
3619
3620 case kConsStringTag | kOneByteStringTag:
3621 case kConsStringTag | kTwoByteStringTag:
3622 return ConsString::cast(string);
3623
3624 default:
3625 UNREACHABLE();
3626 return NULL;
3627 }
3628 }
3629}
3630
3631
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003632template <>
3633inline Vector<const uint8_t> String::GetCharVector() {
3634 String::FlatContent flat = GetFlatContent();
3635 DCHECK(flat.IsOneByte());
3636 return flat.ToOneByteVector();
3637}
3638
3639
3640template <>
3641inline Vector<const uc16> String::GetCharVector() {
3642 String::FlatContent flat = GetFlatContent();
3643 DCHECK(flat.IsTwoByte());
3644 return flat.ToUC16Vector();
3645}
3646
3647
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003648uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
3649 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003650 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3651}
3652
3653
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003654void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
3655 DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003656 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
3657 static_cast<byte>(value));
3658}
3659
3660
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003661Address SeqOneByteString::GetCharsAddress() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003662 return FIELD_ADDR(this, kHeaderSize);
3663}
3664
3665
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003666uint8_t* SeqOneByteString::GetChars() {
3667 return reinterpret_cast<uint8_t*>(GetCharsAddress());
Steve Blocka7e24c12009-10-30 11:49:00 +00003668}
3669
3670
3671Address SeqTwoByteString::GetCharsAddress() {
3672 return FIELD_ADDR(this, kHeaderSize);
3673}
3674
3675
3676uc16* SeqTwoByteString::GetChars() {
3677 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
3678}
3679
3680
3681uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003682 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003683 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
3684}
3685
3686
3687void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003688 DCHECK(index >= 0 && index < length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003689 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
3690}
3691
3692
3693int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01003694 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003695}
3696
3697
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003698int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01003699 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003700}
3701
3702
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003703String* SlicedString::parent() {
3704 return String::cast(READ_FIELD(this, kParentOffset));
3705}
3706
3707
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003708void SlicedString::set_parent(String* parent, WriteBarrierMode mode) {
3709 DCHECK(parent->IsSeqString() || parent->IsExternalString());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003710 WRITE_FIELD(this, kParentOffset, parent);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003711 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003712}
3713
3714
3715SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
3716
3717
Steve Blocka7e24c12009-10-30 11:49:00 +00003718String* ConsString::first() {
3719 return String::cast(READ_FIELD(this, kFirstOffset));
3720}
3721
3722
3723Object* ConsString::unchecked_first() {
3724 return READ_FIELD(this, kFirstOffset);
3725}
3726
3727
3728void ConsString::set_first(String* value, WriteBarrierMode mode) {
3729 WRITE_FIELD(this, kFirstOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003730 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003731}
3732
3733
3734String* ConsString::second() {
3735 return String::cast(READ_FIELD(this, kSecondOffset));
3736}
3737
3738
3739Object* ConsString::unchecked_second() {
3740 return READ_FIELD(this, kSecondOffset);
3741}
3742
3743
3744void ConsString::set_second(String* value, WriteBarrierMode mode) {
3745 WRITE_FIELD(this, kSecondOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003746 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003747}
3748
3749
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003750bool ExternalString::is_short() {
3751 InstanceType type = map()->instance_type();
3752 return (type & kShortExternalStringMask) == kShortExternalStringTag;
3753}
3754
3755
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003756const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003757 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3758}
3759
3760
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003761void ExternalOneByteString::update_data_cache() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003762 if (is_short()) return;
3763 const char** data_field =
3764 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
3765 *data_field = resource()->data();
3766}
3767
3768
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003769void ExternalOneByteString::set_resource(
3770 const ExternalOneByteString::Resource* resource) {
3771 DCHECK(IsAligned(reinterpret_cast<intptr_t>(resource), kPointerSize));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003772 *reinterpret_cast<const Resource**>(
3773 FIELD_ADDR(this, kResourceOffset)) = resource;
3774 if (resource != NULL) update_data_cache();
Steve Blocka7e24c12009-10-30 11:49:00 +00003775}
3776
3777
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003778const uint8_t* ExternalOneByteString::GetChars() {
3779 return reinterpret_cast<const uint8_t*>(resource()->data());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003780}
3781
3782
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003783uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
3784 DCHECK(index >= 0 && index < length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003785 return GetChars()[index];
3786}
3787
3788
3789const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003790 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3791}
3792
3793
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003794void ExternalTwoByteString::update_data_cache() {
3795 if (is_short()) return;
3796 const uint16_t** data_field =
3797 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
3798 *data_field = resource()->data();
3799}
3800
3801
Steve Blocka7e24c12009-10-30 11:49:00 +00003802void ExternalTwoByteString::set_resource(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003803 const ExternalTwoByteString::Resource* resource) {
3804 *reinterpret_cast<const Resource**>(
3805 FIELD_ADDR(this, kResourceOffset)) = resource;
3806 if (resource != NULL) update_data_cache();
3807}
3808
3809
3810const uint16_t* ExternalTwoByteString::GetChars() {
3811 return resource()->data();
3812}
3813
3814
3815uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003816 DCHECK(index >= 0 && index < length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003817 return GetChars()[index];
3818}
3819
3820
3821const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
3822 unsigned start) {
3823 return GetChars() + start;
Steve Blocka7e24c12009-10-30 11:49:00 +00003824}
3825
3826
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003827int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003828
3829
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003830void ConsStringIterator::PushLeft(ConsString* string) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003831 frames_[depth_++ & kDepthMask] = string;
3832}
3833
3834
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003835void ConsStringIterator::PushRight(ConsString* string) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003836 // Inplace update.
3837 frames_[(depth_-1) & kDepthMask] = string;
3838}
3839
3840
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003841void ConsStringIterator::AdjustMaximumDepth() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003842 if (depth_ > maximum_depth_) maximum_depth_ = depth_;
3843}
3844
3845
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003846void ConsStringIterator::Pop() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003847 DCHECK(depth_ > 0);
3848 DCHECK(depth_ <= maximum_depth_);
3849 depth_--;
3850}
3851
3852
3853uint16_t StringCharacterStream::GetNext() {
3854 DCHECK(buffer8_ != NULL && end_ != NULL);
3855 // Advance cursor if needed.
3856 if (buffer8_ == end_) HasMore();
3857 DCHECK(buffer8_ < end_);
3858 return is_one_byte_ ? *buffer8_++ : *buffer16_++;
3859}
3860
3861
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003862StringCharacterStream::StringCharacterStream(String* string, int offset)
3863 : is_one_byte_(false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003864 Reset(string, offset);
3865}
3866
3867
3868void StringCharacterStream::Reset(String* string, int offset) {
3869 buffer8_ = NULL;
3870 end_ = NULL;
3871 ConsString* cons_string = String::VisitFlat(this, string, offset);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003872 iter_.Reset(cons_string, offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003873 if (cons_string != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003874 string = iter_.Next(&offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003875 if (string != NULL) String::VisitFlat(this, string, offset);
3876 }
3877}
3878
3879
3880bool StringCharacterStream::HasMore() {
3881 if (buffer8_ != end_) return true;
3882 int offset;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003883 String* string = iter_.Next(&offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003884 DCHECK_EQ(offset, 0);
3885 if (string == NULL) return false;
3886 String::VisitFlat(this, string);
3887 DCHECK(buffer8_ != end_);
3888 return true;
3889}
3890
3891
3892void StringCharacterStream::VisitOneByteString(
3893 const uint8_t* chars, int length) {
3894 is_one_byte_ = true;
3895 buffer8_ = chars;
3896 end_ = chars + length;
3897}
3898
3899
3900void StringCharacterStream::VisitTwoByteString(
3901 const uint16_t* chars, int length) {
3902 is_one_byte_ = false;
3903 buffer16_ = chars;
3904 end_ = reinterpret_cast<const uint8_t*>(chars + length);
3905}
3906
3907
Steve Block6ded16b2010-05-10 14:33:55 +01003908void JSFunctionResultCache::MakeZeroSize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003909 set_finger_index(kEntriesIndex);
3910 set_size(kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01003911}
3912
3913
3914void JSFunctionResultCache::Clear() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003915 int cache_size = size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003916 Object** entries_start = RawFieldOfElementAt(kEntriesIndex);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003917 MemsetPointer(entries_start,
Steve Block44f0eee2011-05-26 01:26:41 +01003918 GetHeap()->the_hole_value(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003919 cache_size - kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01003920 MakeZeroSize();
3921}
3922
3923
Ben Murdochb8e0da22011-05-16 14:20:40 +01003924int JSFunctionResultCache::size() {
3925 return Smi::cast(get(kCacheSizeIndex))->value();
3926}
3927
3928
3929void JSFunctionResultCache::set_size(int size) {
3930 set(kCacheSizeIndex, Smi::FromInt(size));
3931}
3932
3933
3934int JSFunctionResultCache::finger_index() {
3935 return Smi::cast(get(kFingerIndex))->value();
3936}
3937
3938
3939void JSFunctionResultCache::set_finger_index(int finger_index) {
3940 set(kFingerIndex, Smi::FromInt(finger_index));
3941}
3942
3943
Steve Blocka7e24c12009-10-30 11:49:00 +00003944byte ByteArray::get(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003945 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003946 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3947}
3948
3949
3950void ByteArray::set(int index, byte value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003951 DCHECK(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003952 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
3953}
3954
3955
3956int ByteArray::get_int(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003957 DCHECK(index >= 0 && (index * kIntSize) < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00003958 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
3959}
3960
3961
3962ByteArray* ByteArray::FromDataStartAddress(Address address) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003963 DCHECK_TAG_ALIGNED(address);
Steve Blocka7e24c12009-10-30 11:49:00 +00003964 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
3965}
3966
3967
3968Address ByteArray::GetDataStartAddress() {
3969 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
3970}
3971
3972
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003973uint8_t* ExternalUint8ClampedArray::external_uint8_clamped_pointer() {
Steve Block44f0eee2011-05-26 01:26:41 +01003974 return reinterpret_cast<uint8_t*>(external_pointer());
Steve Blocka7e24c12009-10-30 11:49:00 +00003975}
3976
3977
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003978uint8_t ExternalUint8ClampedArray::get_scalar(int index) {
3979 DCHECK((index >= 0) && (index < this->length()));
3980 uint8_t* ptr = external_uint8_clamped_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00003981 return ptr[index];
3982}
3983
3984
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003985Handle<Object> ExternalUint8ClampedArray::get(
3986 Handle<ExternalUint8ClampedArray> array,
3987 int index) {
3988 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3989 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003990}
3991
3992
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003993void ExternalUint8ClampedArray::set(int index, uint8_t value) {
3994 DCHECK((index >= 0) && (index < this->length()));
3995 uint8_t* ptr = external_uint8_clamped_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00003996 ptr[index] = value;
3997}
3998
3999
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004000void* ExternalArray::external_pointer() const {
Steve Block3ce2e202009-11-05 08:53:23 +00004001 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
4002 return reinterpret_cast<void*>(ptr);
4003}
4004
4005
4006void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
4007 intptr_t ptr = reinterpret_cast<intptr_t>(value);
4008 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
4009}
4010
4011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004012int8_t ExternalInt8Array::get_scalar(int index) {
4013 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004014 int8_t* ptr = static_cast<int8_t*>(external_pointer());
4015 return ptr[index];
4016}
4017
4018
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004019Handle<Object> ExternalInt8Array::get(Handle<ExternalInt8Array> array,
4020 int index) {
4021 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
4022 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004023}
4024
4025
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004026void ExternalInt8Array::set(int index, int8_t value) {
4027 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004028 int8_t* ptr = static_cast<int8_t*>(external_pointer());
4029 ptr[index] = value;
4030}
4031
4032
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004033uint8_t ExternalUint8Array::get_scalar(int index) {
4034 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004035 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
4036 return ptr[index];
4037}
4038
4039
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004040Handle<Object> ExternalUint8Array::get(Handle<ExternalUint8Array> array,
4041 int index) {
4042 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
4043 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004044}
4045
4046
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004047void ExternalUint8Array::set(int index, uint8_t value) {
4048 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004049 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
4050 ptr[index] = value;
4051}
4052
4053
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004054int16_t ExternalInt16Array::get_scalar(int index) {
4055 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004056 int16_t* ptr = static_cast<int16_t*>(external_pointer());
4057 return ptr[index];
4058}
4059
4060
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004061Handle<Object> ExternalInt16Array::get(Handle<ExternalInt16Array> array,
4062 int index) {
4063 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
4064 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004065}
4066
4067
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004068void ExternalInt16Array::set(int index, int16_t value) {
4069 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004070 int16_t* ptr = static_cast<int16_t*>(external_pointer());
4071 ptr[index] = value;
4072}
4073
4074
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004075uint16_t ExternalUint16Array::get_scalar(int index) {
4076 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004077 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
4078 return ptr[index];
4079}
4080
4081
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004082Handle<Object> ExternalUint16Array::get(Handle<ExternalUint16Array> array,
4083 int index) {
4084 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
4085 array->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004086}
4087
4088
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004089void ExternalUint16Array::set(int index, uint16_t value) {
4090 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004091 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
4092 ptr[index] = value;
4093}
4094
4095
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004096int32_t ExternalInt32Array::get_scalar(int index) {
4097 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004098 int32_t* ptr = static_cast<int32_t*>(external_pointer());
4099 return ptr[index];
4100}
4101
4102
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004103Handle<Object> ExternalInt32Array::get(Handle<ExternalInt32Array> array,
4104 int index) {
4105 return array->GetIsolate()->factory()->
4106 NewNumberFromInt(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004107}
4108
4109
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004110void ExternalInt32Array::set(int index, int32_t value) {
4111 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004112 int32_t* ptr = static_cast<int32_t*>(external_pointer());
4113 ptr[index] = value;
4114}
4115
4116
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004117uint32_t ExternalUint32Array::get_scalar(int index) {
4118 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004119 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
4120 return ptr[index];
4121}
4122
4123
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004124Handle<Object> ExternalUint32Array::get(Handle<ExternalUint32Array> array,
4125 int index) {
4126 return array->GetIsolate()->factory()->
4127 NewNumberFromUint(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004128}
4129
4130
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004131void ExternalUint32Array::set(int index, uint32_t value) {
4132 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004133 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
4134 ptr[index] = value;
4135}
4136
4137
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004138float ExternalFloat32Array::get_scalar(int index) {
4139 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004140 float* ptr = static_cast<float*>(external_pointer());
4141 return ptr[index];
4142}
4143
4144
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004145Handle<Object> ExternalFloat32Array::get(Handle<ExternalFloat32Array> array,
4146 int index) {
4147 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004148}
4149
4150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004151void ExternalFloat32Array::set(int index, float value) {
4152 DCHECK((index >= 0) && (index < this->length()));
Steve Block3ce2e202009-11-05 08:53:23 +00004153 float* ptr = static_cast<float*>(external_pointer());
4154 ptr[index] = value;
4155}
4156
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004157
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004158double ExternalFloat64Array::get_scalar(int index) {
4159 DCHECK((index >= 0) && (index < this->length()));
Ben Murdoch257744e2011-11-30 15:57:28 +00004160 double* ptr = static_cast<double*>(external_pointer());
4161 return ptr[index];
4162}
4163
4164
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004165Handle<Object> ExternalFloat64Array::get(Handle<ExternalFloat64Array> array,
4166 int index) {
4167 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004168}
4169
4170
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004171void ExternalFloat64Array::set(int index, double value) {
4172 DCHECK((index >= 0) && (index < this->length()));
Ben Murdoch257744e2011-11-30 15:57:28 +00004173 double* ptr = static_cast<double*>(external_pointer());
4174 ptr[index] = value;
4175}
4176
4177
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004178void* FixedTypedArrayBase::DataPtr() {
4179 return FIELD_ADDR(this, kDataOffset);
4180}
4181
4182
4183int FixedTypedArrayBase::DataSize(InstanceType type) {
4184 int element_size;
4185 switch (type) {
4186#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
4187 case FIXED_##TYPE##_ARRAY_TYPE: \
4188 element_size = size; \
4189 break;
4190
4191 TYPED_ARRAYS(TYPED_ARRAY_CASE)
4192#undef TYPED_ARRAY_CASE
4193 default:
4194 UNREACHABLE();
4195 return 0;
4196 }
4197 return length() * element_size;
4198}
4199
4200
4201int FixedTypedArrayBase::DataSize() {
4202 return DataSize(map()->instance_type());
4203}
4204
4205
4206int FixedTypedArrayBase::size() {
4207 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
4208}
4209
4210
4211int FixedTypedArrayBase::TypedArraySize(InstanceType type) {
4212 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
4213}
4214
4215
4216uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
4217
4218
4219uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
4220
4221
4222int8_t Int8ArrayTraits::defaultValue() { return 0; }
4223
4224
4225uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
4226
4227
4228int16_t Int16ArrayTraits::defaultValue() { return 0; }
4229
4230
4231uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
4232
4233
4234int32_t Int32ArrayTraits::defaultValue() { return 0; }
4235
4236
4237float Float32ArrayTraits::defaultValue() {
4238 return static_cast<float>(base::OS::nan_value());
4239}
4240
4241
4242double Float64ArrayTraits::defaultValue() { return base::OS::nan_value(); }
4243
4244
4245template <class Traits>
4246typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
4247 DCHECK((index >= 0) && (index < this->length()));
4248 ElementType* ptr = reinterpret_cast<ElementType*>(
4249 FIELD_ADDR(this, kDataOffset));
4250 return ptr[index];
4251}
4252
4253
4254template<> inline
4255FixedTypedArray<Float64ArrayTraits>::ElementType
4256 FixedTypedArray<Float64ArrayTraits>::get_scalar(int index) {
4257 DCHECK((index >= 0) && (index < this->length()));
4258 return READ_DOUBLE_FIELD(this, ElementOffset(index));
4259}
4260
4261
4262template <class Traits>
4263void FixedTypedArray<Traits>::set(int index, ElementType value) {
4264 DCHECK((index >= 0) && (index < this->length()));
4265 ElementType* ptr = reinterpret_cast<ElementType*>(
4266 FIELD_ADDR(this, kDataOffset));
4267 ptr[index] = value;
4268}
4269
4270
4271template<> inline
4272void FixedTypedArray<Float64ArrayTraits>::set(
4273 int index, Float64ArrayTraits::ElementType value) {
4274 DCHECK((index >= 0) && (index < this->length()));
4275 WRITE_DOUBLE_FIELD(this, ElementOffset(index), value);
4276}
4277
4278
4279template <class Traits>
4280typename Traits::ElementType FixedTypedArray<Traits>::from_int(int value) {
4281 return static_cast<ElementType>(value);
4282}
4283
4284
4285template <> inline
4286uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_int(int value) {
4287 if (value < 0) return 0;
4288 if (value > 0xFF) return 0xFF;
4289 return static_cast<uint8_t>(value);
4290}
4291
4292
4293template <class Traits>
4294typename Traits::ElementType FixedTypedArray<Traits>::from_double(
4295 double value) {
4296 return static_cast<ElementType>(DoubleToInt32(value));
4297}
4298
4299
4300template<> inline
4301uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_double(double value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004302 // Handle NaNs and less than zero values which clamp to zero.
4303 if (!(value > 0)) return 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004304 if (value > 0xFF) return 0xFF;
4305 return static_cast<uint8_t>(lrint(value));
4306}
4307
4308
4309template<> inline
4310float FixedTypedArray<Float32ArrayTraits>::from_double(double value) {
4311 return static_cast<float>(value);
4312}
4313
4314
4315template<> inline
4316double FixedTypedArray<Float64ArrayTraits>::from_double(double value) {
4317 return value;
4318}
4319
4320
4321template <class Traits>
4322Handle<Object> FixedTypedArray<Traits>::get(
4323 Handle<FixedTypedArray<Traits> > array,
4324 int index) {
4325 return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index));
4326}
4327
4328
4329template <class Traits>
4330Handle<Object> FixedTypedArray<Traits>::SetValue(
4331 Handle<FixedTypedArray<Traits> > array,
4332 uint32_t index,
4333 Handle<Object> value) {
4334 ElementType cast_value = Traits::defaultValue();
4335 if (index < static_cast<uint32_t>(array->length())) {
4336 if (value->IsSmi()) {
4337 int int_value = Handle<Smi>::cast(value)->value();
4338 cast_value = from_int(int_value);
4339 } else if (value->IsHeapNumber()) {
4340 double double_value = Handle<HeapNumber>::cast(value)->value();
4341 cast_value = from_double(double_value);
4342 } else {
4343 // Clamp undefined to the default value. All other types have been
4344 // converted to a number type further up in the call chain.
4345 DCHECK(value->IsUndefined());
4346 }
4347 array->set(index, cast_value);
4348 }
4349 return Traits::ToHandle(array->GetIsolate(), cast_value);
4350}
4351
4352
4353Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
4354 return handle(Smi::FromInt(scalar), isolate);
4355}
4356
4357
4358Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
4359 uint8_t scalar) {
4360 return handle(Smi::FromInt(scalar), isolate);
4361}
4362
4363
4364Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
4365 return handle(Smi::FromInt(scalar), isolate);
4366}
4367
4368
4369Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
4370 return handle(Smi::FromInt(scalar), isolate);
4371}
4372
4373
4374Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
4375 return handle(Smi::FromInt(scalar), isolate);
4376}
4377
4378
4379Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
4380 return isolate->factory()->NewNumberFromUint(scalar);
4381}
4382
4383
4384Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
4385 return isolate->factory()->NewNumberFromInt(scalar);
4386}
4387
4388
4389Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
4390 return isolate->factory()->NewNumber(scalar);
4391}
4392
4393
4394Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
4395 return isolate->factory()->NewNumber(scalar);
4396}
4397
4398
Iain Merrick9ac36c92010-09-13 15:29:50 +01004399int Map::visitor_id() {
4400 return READ_BYTE_FIELD(this, kVisitorIdOffset);
4401}
4402
4403
4404void Map::set_visitor_id(int id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004405 DCHECK(0 <= id && id < 256);
Iain Merrick9ac36c92010-09-13 15:29:50 +01004406 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
4407}
4408
Steve Block3ce2e202009-11-05 08:53:23 +00004409
Steve Blocka7e24c12009-10-30 11:49:00 +00004410int Map::instance_size() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004411 return NOBARRIER_READ_BYTE_FIELD(
4412 this, kInstanceSizeOffset) << kPointerSizeLog2;
Steve Blocka7e24c12009-10-30 11:49:00 +00004413}
4414
4415
4416int Map::inobject_properties() {
4417 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
4418}
4419
4420
4421int Map::pre_allocated_property_fields() {
4422 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
4423}
4424
4425
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004426int Map::GetInObjectPropertyOffset(int index) {
4427 // Adjust for the number of properties stored in the object.
4428 index -= inobject_properties();
4429 DCHECK(index <= 0);
4430 return instance_size() + (index * kPointerSize);
4431}
4432
4433
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004434Handle<Map> Map::CopyInstallDescriptorsForTesting(
4435 Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
4436 Handle<LayoutDescriptor> layout_descriptor) {
4437 return CopyInstallDescriptors(map, new_descriptor, descriptors,
4438 layout_descriptor);
4439}
4440
4441
Steve Blocka7e24c12009-10-30 11:49:00 +00004442int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01004443 int instance_size = map->instance_size();
4444 if (instance_size != kVariableSizeSentinel) return instance_size;
Steve Blocka7e24c12009-10-30 11:49:00 +00004445 // Only inline the most frequent cases.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004446 InstanceType instance_type = map->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +00004447 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01004448 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00004449 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004450 if (instance_type == ONE_BYTE_STRING_TYPE ||
4451 instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004452 // Strings may get concurrently truncated, hence we have to access its
4453 // length synchronized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004454 return SeqOneByteString::SizeFor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004455 reinterpret_cast<SeqOneByteString*>(this)->synchronized_length());
Steve Block791712a2010-08-27 10:21:07 +01004456 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004457 if (instance_type == BYTE_ARRAY_TYPE) {
4458 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
4459 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004460 if (instance_type == FREE_SPACE_TYPE) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004461 return reinterpret_cast<FreeSpace*>(this)->nobarrier_size();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004462 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004463 if (instance_type == STRING_TYPE ||
4464 instance_type == INTERNALIZED_STRING_TYPE) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004465 // Strings may get concurrently truncated, hence we have to access its
4466 // length synchronized.
Steve Block791712a2010-08-27 10:21:07 +01004467 return SeqTwoByteString::SizeFor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004468 reinterpret_cast<SeqTwoByteString*>(this)->synchronized_length());
Steve Block791712a2010-08-27 10:21:07 +01004469 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004470 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
4471 return FixedDoubleArray::SizeFor(
4472 reinterpret_cast<FixedDoubleArray*>(this)->length());
4473 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004474 if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
4475 return reinterpret_cast<ConstantPoolArray*>(this)->size();
4476 }
4477 if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
4478 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
4479 return reinterpret_cast<FixedTypedArrayBase*>(
4480 this)->TypedArraySize(instance_type);
4481 }
4482 DCHECK(instance_type == CODE_TYPE);
Steve Block791712a2010-08-27 10:21:07 +01004483 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00004484}
4485
4486
4487void Map::set_instance_size(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004488 DCHECK_EQ(0, value & (kPointerSize - 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00004489 value >>= kPointerSizeLog2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004490 DCHECK(0 <= value && value < 256);
4491 NOBARRIER_WRITE_BYTE_FIELD(
4492 this, kInstanceSizeOffset, static_cast<byte>(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00004493}
4494
4495
4496void Map::set_inobject_properties(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004497 DCHECK(0 <= value && value < 256);
Steve Blocka7e24c12009-10-30 11:49:00 +00004498 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
4499}
4500
4501
4502void Map::set_pre_allocated_property_fields(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004503 DCHECK(0 <= value && value < 256);
Steve Blocka7e24c12009-10-30 11:49:00 +00004504 WRITE_BYTE_FIELD(this,
4505 kPreAllocatedPropertyFieldsOffset,
4506 static_cast<byte>(value));
4507}
4508
4509
4510InstanceType Map::instance_type() {
4511 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
4512}
4513
4514
4515void Map::set_instance_type(InstanceType value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004516 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
4517}
4518
4519
4520int Map::unused_property_fields() {
4521 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
4522}
4523
4524
4525void Map::set_unused_property_fields(int value) {
4526 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
4527}
4528
4529
4530byte Map::bit_field() {
4531 return READ_BYTE_FIELD(this, kBitFieldOffset);
4532}
4533
4534
4535void Map::set_bit_field(byte value) {
4536 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
4537}
4538
4539
4540byte Map::bit_field2() {
4541 return READ_BYTE_FIELD(this, kBitField2Offset);
4542}
4543
4544
4545void Map::set_bit_field2(byte value) {
4546 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
4547}
4548
4549
4550void Map::set_non_instance_prototype(bool value) {
4551 if (value) {
4552 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
4553 } else {
4554 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
4555 }
4556}
4557
4558
4559bool Map::has_non_instance_prototype() {
4560 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
4561}
4562
4563
Steve Block6ded16b2010-05-10 14:33:55 +01004564void Map::set_function_with_prototype(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004565 set_bit_field(FunctionWithPrototype::update(bit_field(), value));
Steve Block6ded16b2010-05-10 14:33:55 +01004566}
4567
4568
4569bool Map::function_with_prototype() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004570 return FunctionWithPrototype::decode(bit_field());
Steve Block6ded16b2010-05-10 14:33:55 +01004571}
4572
4573
Steve Blocka7e24c12009-10-30 11:49:00 +00004574void Map::set_is_access_check_needed(bool access_check_needed) {
4575 if (access_check_needed) {
4576 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
4577 } else {
4578 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
4579 }
4580}
4581
4582
4583bool Map::is_access_check_needed() {
4584 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
4585}
4586
4587
Steve Block8defd9f2010-07-08 12:39:36 +01004588void Map::set_is_extensible(bool value) {
4589 if (value) {
4590 set_bit_field2(bit_field2() | (1 << kIsExtensible));
4591 } else {
4592 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
4593 }
4594}
4595
4596bool Map::is_extensible() {
4597 return ((1 << kIsExtensible) & bit_field2()) != 0;
4598}
4599
4600
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004601void Map::set_is_prototype_map(bool value) {
4602 set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004603}
4604
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004605bool Map::is_prototype_map() {
4606 return IsPrototypeMapBits::decode(bit_field2());
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004607}
4608
4609
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004610void Map::set_dictionary_map(bool value) {
4611 uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value);
4612 new_bit_field3 = IsUnstable::update(new_bit_field3, value);
4613 set_bit_field3(new_bit_field3);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004614}
4615
4616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004617bool Map::is_dictionary_map() {
4618 return DictionaryMap::decode(bit_field3());
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004619}
4620
Steve Block8defd9f2010-07-08 12:39:36 +01004621
Steve Blocka7e24c12009-10-30 11:49:00 +00004622Code::Flags Code::flags() {
4623 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
4624}
4625
4626
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004627void Map::set_owns_descriptors(bool owns_descriptors) {
4628 set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors));
4629}
4630
4631
4632bool Map::owns_descriptors() {
4633 return OwnsDescriptors::decode(bit_field3());
4634}
4635
4636
4637void Map::set_has_instance_call_handler() {
4638 set_bit_field3(HasInstanceCallHandler::update(bit_field3(), true));
4639}
4640
4641
4642bool Map::has_instance_call_handler() {
4643 return HasInstanceCallHandler::decode(bit_field3());
4644}
4645
4646
4647void Map::deprecate() {
4648 set_bit_field3(Deprecated::update(bit_field3(), true));
4649}
4650
4651
4652bool Map::is_deprecated() {
4653 return Deprecated::decode(bit_field3());
4654}
4655
4656
4657void Map::set_migration_target(bool value) {
4658 set_bit_field3(IsMigrationTarget::update(bit_field3(), value));
4659}
4660
4661
4662bool Map::is_migration_target() {
4663 return IsMigrationTarget::decode(bit_field3());
4664}
4665
4666
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004667void Map::set_counter(int value) {
4668 set_bit_field3(Counter::update(bit_field3(), value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004669}
4670
4671
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004672int Map::counter() { return Counter::decode(bit_field3()); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004673
4674
4675void Map::mark_unstable() {
4676 set_bit_field3(IsUnstable::update(bit_field3(), true));
4677}
4678
4679
4680bool Map::is_stable() {
4681 return !IsUnstable::decode(bit_field3());
4682}
4683
4684
4685bool Map::has_code_cache() {
4686 return code_cache() != GetIsolate()->heap()->empty_fixed_array();
4687}
4688
4689
4690bool Map::CanBeDeprecated() {
4691 int descriptor = LastAdded();
4692 for (int i = 0; i <= descriptor; i++) {
4693 PropertyDetails details = instance_descriptors()->GetDetails(i);
4694 if (details.representation().IsNone()) return true;
4695 if (details.representation().IsSmi()) return true;
4696 if (details.representation().IsDouble()) return true;
4697 if (details.representation().IsHeapObject()) return true;
4698 if (details.type() == CONSTANT) return true;
4699 }
4700 return false;
4701}
4702
4703
4704void Map::NotifyLeafMapLayoutChange() {
4705 if (is_stable()) {
4706 mark_unstable();
4707 dependent_code()->DeoptimizeDependentCodeGroup(
4708 GetIsolate(),
4709 DependentCode::kPrototypeCheckGroup);
4710 }
4711}
4712
4713
4714bool Map::CanOmitMapChecks() {
4715 return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
4716}
4717
4718
4719int DependentCode::number_of_entries(DependencyGroup group) {
4720 if (length() == 0) return 0;
4721 return Smi::cast(get(group))->value();
4722}
4723
4724
4725void DependentCode::set_number_of_entries(DependencyGroup group, int value) {
4726 set(group, Smi::FromInt(value));
4727}
4728
4729
4730bool DependentCode::is_code_at(int i) {
4731 return get(kCodesStartIndex + i)->IsCode();
4732}
4733
4734Code* DependentCode::code_at(int i) {
4735 return Code::cast(get(kCodesStartIndex + i));
4736}
4737
4738
4739CompilationInfo* DependentCode::compilation_info_at(int i) {
4740 return reinterpret_cast<CompilationInfo*>(
4741 Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
4742}
4743
4744
4745void DependentCode::set_object_at(int i, Object* object) {
4746 set(kCodesStartIndex + i, object);
4747}
4748
4749
4750Object* DependentCode::object_at(int i) {
4751 return get(kCodesStartIndex + i);
4752}
4753
4754
4755Object** DependentCode::slot_at(int i) {
4756 return RawFieldOfElementAt(kCodesStartIndex + i);
4757}
4758
4759
4760void DependentCode::clear_at(int i) {
4761 set_undefined(kCodesStartIndex + i);
4762}
4763
4764
4765void DependentCode::copy(int from, int to) {
4766 set(kCodesStartIndex + to, get(kCodesStartIndex + from));
4767}
4768
4769
4770void DependentCode::ExtendGroup(DependencyGroup group) {
4771 GroupStartIndexes starts(this);
4772 for (int g = kGroupCount - 1; g > group; g--) {
4773 if (starts.at(g) < starts.at(g + 1)) {
4774 copy(starts.at(g), starts.at(g + 1));
4775 }
4776 }
4777}
4778
4779
Steve Blocka7e24c12009-10-30 11:49:00 +00004780void Code::set_flags(Code::Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004781 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00004782 WRITE_INT_FIELD(this, kFlagsOffset, flags);
4783}
4784
4785
4786Code::Kind Code::kind() {
4787 return ExtractKindFromFlags(flags());
4788}
4789
4790
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004791bool Code::IsCodeStubOrIC() {
4792 return kind() == STUB || kind() == HANDLER || kind() == LOAD_IC ||
4793 kind() == KEYED_LOAD_IC || kind() == CALL_IC || kind() == STORE_IC ||
4794 kind() == KEYED_STORE_IC || kind() == BINARY_OP_IC ||
4795 kind() == COMPARE_IC || kind() == COMPARE_NIL_IC ||
4796 kind() == TO_BOOLEAN_IC;
4797}
4798
4799
Steve Blocka7e24c12009-10-30 11:49:00 +00004800InlineCacheState Code::ic_state() {
4801 InlineCacheState result = ExtractICStateFromFlags(flags());
4802 // Only allow uninitialized or debugger states for non-IC code
4803 // objects. This is used in the debugger to determine whether or not
4804 // a call to code object has been replaced with a debug break call.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004805 DCHECK(is_inline_cache_stub() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00004806 result == UNINITIALIZED ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004807 result == DEBUG_STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00004808 return result;
4809}
4810
4811
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004812ExtraICState Code::extra_ic_state() {
4813 DCHECK(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
Ben Murdochb8e0da22011-05-16 14:20:40 +01004814 return ExtractExtraICStateFromFlags(flags());
4815}
4816
4817
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004818Code::StubType Code::type() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004819 return ExtractTypeFromFlags(flags());
4820}
4821
4822
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004823// For initialization.
4824void Code::set_raw_kind_specific_flags1(int value) {
4825 WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004826}
4827
4828
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004829void Code::set_raw_kind_specific_flags2(int value) {
4830 WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004831}
4832
4833
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004834inline bool Code::is_crankshafted() {
4835 return IsCrankshaftedField::decode(
4836 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
Steve Blocka7e24c12009-10-30 11:49:00 +00004837}
4838
4839
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004840inline bool Code::is_hydrogen_stub() {
4841 return is_crankshafted() && kind() != OPTIMIZED_FUNCTION;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004842}
4843
4844
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004845inline void Code::set_is_crankshafted(bool value) {
4846 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4847 int updated = IsCrankshaftedField::update(previous, value);
4848 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4849}
4850
4851
4852inline bool Code::is_turbofanned() {
4853 DCHECK(kind() == OPTIMIZED_FUNCTION || kind() == STUB);
4854 return IsTurbofannedField::decode(
4855 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4856}
4857
4858
4859inline void Code::set_is_turbofanned(bool value) {
4860 DCHECK(kind() == OPTIMIZED_FUNCTION || kind() == STUB);
4861 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4862 int updated = IsTurbofannedField::update(previous, value);
4863 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004864}
4865
4866
Ben Murdochb0fe1622011-05-05 13:52:32 +01004867bool Code::optimizable() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004868 DCHECK_EQ(FUNCTION, kind());
Ben Murdochb0fe1622011-05-05 13:52:32 +01004869 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
4870}
4871
4872
4873void Code::set_optimizable(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004874 DCHECK_EQ(FUNCTION, kind());
Ben Murdochb0fe1622011-05-05 13:52:32 +01004875 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
4876}
4877
4878
4879bool Code::has_deoptimization_support() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004880 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004881 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4882 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004883}
4884
4885
4886void Code::set_has_deoptimization_support(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004887 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004888 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4889 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
4890 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4891}
4892
4893
4894bool Code::has_debug_break_slots() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004895 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004896 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4897 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
4898}
4899
4900
4901void Code::set_has_debug_break_slots(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004902 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch589d6972011-11-30 16:04:58 +00004903 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4904 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
4905 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004906}
4907
4908
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004909bool Code::is_compiled_optimizable() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004910 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004911 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4912 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
4913}
4914
4915
4916void Code::set_compiled_optimizable(bool value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004917 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004918 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4919 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
4920 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4921}
4922
4923
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004924bool Code::has_reloc_info_for_serialization() {
4925 DCHECK_EQ(FUNCTION, kind());
4926 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4927 return FullCodeFlagsHasRelocInfoForSerialization::decode(flags);
4928}
4929
4930
4931void Code::set_has_reloc_info_for_serialization(bool value) {
4932 DCHECK_EQ(FUNCTION, kind());
4933 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4934 flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value);
4935 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4936}
4937
4938
Ben Murdochb0fe1622011-05-05 13:52:32 +01004939int Code::allow_osr_at_loop_nesting_level() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004940 DCHECK_EQ(FUNCTION, kind());
4941 int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4942 return AllowOSRAtLoopNestingLevelField::decode(fields);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004943}
4944
4945
4946void Code::set_allow_osr_at_loop_nesting_level(int level) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004947 DCHECK_EQ(FUNCTION, kind());
4948 DCHECK(level >= 0 && level <= kMaxLoopNestingMarker);
4949 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4950 int updated = AllowOSRAtLoopNestingLevelField::update(previous, level);
4951 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004952}
4953
4954
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004955int Code::profiler_ticks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004956 DCHECK_EQ(FUNCTION, kind());
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004957 return READ_BYTE_FIELD(this, kProfilerTicksOffset);
4958}
4959
4960
4961void Code::set_profiler_ticks(int ticks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004962 DCHECK(ticks < 256);
4963 if (kind() == FUNCTION) {
4964 WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
4965 }
4966}
4967
4968
4969int Code::builtin_index() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004970 return READ_INT32_FIELD(this, kKindSpecificFlags1Offset);
4971}
4972
4973
4974void Code::set_builtin_index(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004975 WRITE_INT32_FIELD(this, kKindSpecificFlags1Offset, index);
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004976}
4977
4978
Ben Murdochb0fe1622011-05-05 13:52:32 +01004979unsigned Code::stack_slots() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004980 DCHECK(is_crankshafted());
4981 return StackSlotsField::decode(
4982 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004983}
4984
4985
4986void Code::set_stack_slots(unsigned slots) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004987 CHECK(slots <= (1 << kStackSlotsBitCount));
4988 DCHECK(is_crankshafted());
4989 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4990 int updated = StackSlotsField::update(previous, slots);
4991 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004992}
4993
4994
Steve Block1e0659c2011-05-24 12:43:12 +01004995unsigned Code::safepoint_table_offset() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004996 DCHECK(is_crankshafted());
4997 return SafepointTableOffsetField::decode(
4998 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004999}
5000
5001
Steve Block1e0659c2011-05-24 12:43:12 +01005002void Code::set_safepoint_table_offset(unsigned offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005003 CHECK(offset <= (1 << kSafepointTableOffsetBitCount));
5004 DCHECK(is_crankshafted());
5005 DCHECK(IsAligned(offset, static_cast<unsigned>(kIntSize)));
5006 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
5007 int updated = SafepointTableOffsetField::update(previous, offset);
5008 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005009}
5010
5011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005012unsigned Code::back_edge_table_offset() {
5013 DCHECK_EQ(FUNCTION, kind());
5014 return BackEdgeTableOffsetField::decode(
5015 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005016}
5017
5018
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005019void Code::set_back_edge_table_offset(unsigned offset) {
5020 DCHECK_EQ(FUNCTION, kind());
5021 DCHECK(IsAligned(offset, static_cast<unsigned>(kPointerSize)));
5022 offset = offset >> kPointerSizeLog2;
5023 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
5024 int updated = BackEdgeTableOffsetField::update(previous, offset);
5025 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005026}
5027
5028
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005029bool Code::back_edges_patched_for_osr() {
5030 DCHECK_EQ(FUNCTION, kind());
5031 return allow_osr_at_loop_nesting_level() > 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005032}
5033
5034
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005035byte Code::to_boolean_state() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005036 return extra_ic_state();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005037}
5038
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005039
5040bool Code::has_function_cache() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005041 DCHECK(kind() == STUB);
5042 return HasFunctionCacheField::decode(
5043 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005044}
5045
5046
5047void Code::set_has_function_cache(bool flag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005048 DCHECK(kind() == STUB);
5049 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
5050 int updated = HasFunctionCacheField::update(previous, flag);
5051 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
5052}
5053
5054
5055bool Code::marked_for_deoptimization() {
5056 DCHECK(kind() == OPTIMIZED_FUNCTION);
5057 return MarkedForDeoptimizationField::decode(
5058 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
5059}
5060
5061
5062void Code::set_marked_for_deoptimization(bool flag) {
5063 DCHECK(kind() == OPTIMIZED_FUNCTION);
5064 DCHECK(!flag || AllowDeoptimization::IsAllowed(GetIsolate()));
5065 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
5066 int updated = MarkedForDeoptimizationField::update(previous, flag);
5067 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
5068}
5069
5070
Steve Blocka7e24c12009-10-30 11:49:00 +00005071bool Code::is_inline_cache_stub() {
5072 Kind kind = this->kind();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005073 switch (kind) {
5074#define CASE(name) case name: return true;
5075 IC_KIND_LIST(CASE)
5076#undef CASE
5077 default: return false;
5078 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005079}
5080
5081
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005082bool Code::is_keyed_stub() {
5083 return is_keyed_load_stub() || is_keyed_store_stub();
5084}
5085
5086
5087bool Code::is_debug_stub() {
5088 return ic_state() == DEBUG_STUB;
5089}
5090
5091
5092ConstantPoolArray* Code::constant_pool() {
5093 return ConstantPoolArray::cast(READ_FIELD(this, kConstantPoolOffset));
5094}
5095
5096
5097void Code::set_constant_pool(Object* value) {
5098 DCHECK(value->IsConstantPoolArray());
5099 WRITE_FIELD(this, kConstantPoolOffset, value);
5100 WRITE_BARRIER(GetHeap(), this, kConstantPoolOffset, value);
5101}
5102
5103
5104Code::Flags Code::ComputeFlags(Kind kind, InlineCacheState ic_state,
5105 ExtraICState extra_ic_state, StubType type,
5106 CacheHolderFlag holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005107 // Compute the bit mask.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005108 unsigned int bits = KindField::encode(kind)
Ben Murdoch589d6972011-11-30 16:04:58 +00005109 | ICStateField::encode(ic_state)
5110 | TypeField::encode(type)
5111 | ExtraICStateField::encode(extra_ic_state)
Ben Murdoch589d6972011-11-30 16:04:58 +00005112 | CacheHolderField::encode(holder);
5113 return static_cast<Flags>(bits);
Steve Blocka7e24c12009-10-30 11:49:00 +00005114}
5115
5116
5117Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01005118 ExtraICState extra_ic_state,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005119 CacheHolderFlag holder,
5120 StubType type) {
5121 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, holder);
5122}
5123
5124
5125Code::Flags Code::ComputeHandlerFlags(Kind handler_kind, StubType type,
5126 CacheHolderFlag holder) {
5127 return ComputeFlags(Code::HANDLER, MONOMORPHIC, handler_kind, type, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00005128}
5129
5130
5131Code::Kind Code::ExtractKindFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005132 return KindField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00005133}
5134
5135
5136InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005137 return ICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00005138}
5139
5140
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005141ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005142 return ExtraICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00005143}
5144
5145
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005146Code::StubType Code::ExtractTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005147 return TypeField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00005148}
5149
5150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005151CacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005152 return CacheHolderField::decode(flags);
Steve Block8defd9f2010-07-08 12:39:36 +01005153}
5154
5155
Steve Blocka7e24c12009-10-30 11:49:00 +00005156Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00005157 int bits = flags & ~TypeField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00005158 return static_cast<Flags>(bits);
5159}
5160
5161
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005162Code::Flags Code::RemoveTypeAndHolderFromFlags(Flags flags) {
5163 int bits = flags & ~TypeField::kMask & ~CacheHolderField::kMask;
5164 return static_cast<Flags>(bits);
5165}
5166
5167
Steve Blocka7e24c12009-10-30 11:49:00 +00005168Code* Code::GetCodeFromTargetAddress(Address address) {
5169 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
5170 // GetCodeFromTargetAddress might be called when marking objects during mark
5171 // sweep. reinterpret_cast is therefore used instead of the more appropriate
5172 // Code::cast. Code::cast does not work when the object's map is
5173 // marked.
5174 Code* result = reinterpret_cast<Code*>(code);
5175 return result;
5176}
5177
5178
Steve Block791712a2010-08-27 10:21:07 +01005179Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
5180 return HeapObject::
5181 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
5182}
5183
5184
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005185bool Code::IsWeakObjectInOptimizedCode(Object* object) {
5186 if (!FLAG_collect_maps) return false;
5187 if (object->IsMap()) {
5188 return Map::cast(object)->CanTransition() &&
5189 FLAG_weak_embedded_maps_in_optimized_code;
5190 }
5191 if (object->IsJSObject() ||
5192 (object->IsCell() && Cell::cast(object)->value()->IsJSObject())) {
5193 return FLAG_weak_embedded_objects_in_optimized_code;
5194 }
5195 return false;
5196}
5197
5198
5199class Code::FindAndReplacePattern {
5200 public:
5201 FindAndReplacePattern() : count_(0) { }
5202 void Add(Handle<Map> map_to_find, Handle<Object> obj_to_replace) {
5203 DCHECK(count_ < kMaxCount);
5204 find_[count_] = map_to_find;
5205 replace_[count_] = obj_to_replace;
5206 ++count_;
5207 }
5208 private:
5209 static const int kMaxCount = 4;
5210 int count_;
5211 Handle<Map> find_[kMaxCount];
5212 Handle<Object> replace_[kMaxCount];
5213 friend class Code;
5214};
5215
5216
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005217Object* Map::prototype() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00005218 return READ_FIELD(this, kPrototypeOffset);
5219}
5220
5221
5222void Map::set_prototype(Object* value, WriteBarrierMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005223 DCHECK(value->IsNull() || value->IsJSReceiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00005224 WRITE_FIELD(this, kPrototypeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005225 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
Steve Block1e0659c2011-05-24 12:43:12 +01005226}
5227
5228
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005229// If the descriptor is using the empty transition array, install a new empty
5230// transition array that will have place for an element transition.
5231static void EnsureHasTransitionArray(Handle<Map> map) {
5232 Handle<TransitionArray> transitions;
5233 if (!map->HasTransitionArray()) {
5234 transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
5235 transitions->set_back_pointer_storage(map->GetBackPointer());
5236 } else if (!map->transitions()->IsFullTransitionArray()) {
5237 transitions = TransitionArray::ExtendToFullTransitionArray(map);
Ben Murdoch257744e2011-11-30 15:57:28 +00005238 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00005239 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005240 }
5241 map->set_transitions(*transitions);
5242}
5243
5244
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005245LayoutDescriptor* Map::layout_descriptor_gc_safe() {
5246 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset);
5247 return LayoutDescriptor::cast_gc_safe(layout_desc);
5248}
5249
5250
5251bool Map::HasFastPointerLayout() const {
5252 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset);
5253 return LayoutDescriptor::IsFastPointerLayout(layout_desc);
5254}
5255
5256
5257void Map::UpdateDescriptors(DescriptorArray* descriptors,
5258 LayoutDescriptor* layout_desc) {
5259 set_instance_descriptors(descriptors);
5260 if (FLAG_unbox_double_fields) {
5261 if (layout_descriptor()->IsSlowLayout()) {
5262 set_layout_descriptor(layout_desc);
5263 }
5264 SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this));
5265 DCHECK(visitor_id() == StaticVisitorBase::GetVisitorId(this));
5266 }
5267}
5268
5269
5270void Map::InitializeDescriptors(DescriptorArray* descriptors,
5271 LayoutDescriptor* layout_desc) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005272 int len = descriptors->number_of_descriptors();
5273 set_instance_descriptors(descriptors);
5274 SetNumberOfOwnDescriptors(len);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005275
5276 if (FLAG_unbox_double_fields) {
5277 set_layout_descriptor(layout_desc);
5278 SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this));
5279 set_visitor_id(StaticVisitorBase::GetVisitorId(this));
5280 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005281}
5282
5283
5284ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005285ACCESSORS(Map, layout_descriptor, LayoutDescriptor, kLayoutDecriptorOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005286
5287
5288void Map::set_bit_field3(uint32_t bits) {
5289 if (kInt32Size != kPointerSize) {
5290 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0);
5291 }
5292 WRITE_UINT32_FIELD(this, kBitField3Offset, bits);
5293}
5294
5295
5296uint32_t Map::bit_field3() {
5297 return READ_UINT32_FIELD(this, kBitField3Offset);
5298}
5299
5300
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005301LayoutDescriptor* Map::GetLayoutDescriptor() {
5302 return FLAG_unbox_double_fields ? layout_descriptor()
5303 : LayoutDescriptor::FastPointerLayout();
5304}
5305
5306
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005307void Map::AppendDescriptor(Descriptor* desc) {
5308 DescriptorArray* descriptors = instance_descriptors();
5309 int number_of_own_descriptors = NumberOfOwnDescriptors();
5310 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
5311 descriptors->Append(desc);
5312 SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005313
5314// This function does not support appending double field descriptors and
5315// it should never try to (otherwise, layout descriptor must be updated too).
5316#ifdef DEBUG
5317 PropertyDetails details = desc->GetDetails();
5318 CHECK(details.type() != FIELD || !details.representation().IsDouble());
5319#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005320}
5321
5322
5323Object* Map::GetBackPointer() {
5324 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005325 if (object->IsTransitionArray()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005326 return TransitionArray::cast(object)->back_pointer_storage();
Ben Murdoch257744e2011-11-30 15:57:28 +00005327 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005328 DCHECK(object->IsMap() || object->IsUndefined());
5329 return object;
5330 }
5331}
5332
5333
5334bool Map::HasElementsTransition() {
5335 return HasTransitionArray() && transitions()->HasElementsTransition();
5336}
5337
5338
5339bool Map::HasTransitionArray() const {
5340 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5341 return object->IsTransitionArray();
5342}
5343
5344
5345Map* Map::elements_transition_map() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005346 int index =
5347 transitions()->SearchSpecial(GetHeap()->elements_transition_symbol());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005348 return transitions()->GetTarget(index);
5349}
5350
5351
5352bool Map::CanHaveMoreTransitions() {
5353 if (!HasTransitionArray()) return true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005354 return transitions()->number_of_transitions() <
5355 TransitionArray::kMaxNumberOfTransitions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005356}
5357
5358
5359Map* Map::GetTransition(int transition_index) {
5360 return transitions()->GetTarget(transition_index);
5361}
5362
5363
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005364int Map::SearchSpecialTransition(Symbol* name) {
5365 if (HasTransitionArray()) {
5366 return transitions()->SearchSpecial(name);
5367 }
5368 return TransitionArray::kNotFound;
5369}
5370
5371
5372int Map::SearchTransition(PropertyKind kind, Name* name,
5373 PropertyAttributes attributes) {
5374 if (HasTransitionArray()) {
5375 return transitions()->Search(kind, name, attributes);
5376 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005377 return TransitionArray::kNotFound;
5378}
5379
5380
5381FixedArray* Map::GetPrototypeTransitions() {
5382 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
5383 if (!transitions()->HasPrototypeTransitions()) {
5384 return GetHeap()->empty_fixed_array();
5385 }
5386 return transitions()->GetPrototypeTransitions();
5387}
5388
5389
5390void Map::SetPrototypeTransitions(
5391 Handle<Map> map, Handle<FixedArray> proto_transitions) {
5392 EnsureHasTransitionArray(map);
5393 int old_number_of_transitions = map->NumberOfProtoTransitions();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005394 if (Heap::ShouldZapGarbage() && map->HasPrototypeTransitions()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005395 DCHECK(map->GetPrototypeTransitions() != *proto_transitions);
5396 map->ZapPrototypeTransitions();
5397 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005398 map->transitions()->SetPrototypeTransitions(*proto_transitions);
5399 map->SetNumberOfProtoTransitions(old_number_of_transitions);
5400}
5401
5402
5403bool Map::HasPrototypeTransitions() {
5404 return HasTransitionArray() && transitions()->HasPrototypeTransitions();
5405}
5406
5407
5408TransitionArray* Map::transitions() const {
5409 DCHECK(HasTransitionArray());
5410 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5411 return TransitionArray::cast(object);
5412}
5413
5414
5415void Map::set_transitions(TransitionArray* transition_array,
5416 WriteBarrierMode mode) {
5417 // Transition arrays are not shared. When one is replaced, it should not
5418 // keep referenced objects alive, so we zap it.
5419 // When there is another reference to the array somewhere (e.g. a handle),
5420 // not zapping turns from a waste of memory into a source of crashes.
5421 if (HasTransitionArray()) {
5422#ifdef DEBUG
5423 for (int i = 0; i < transitions()->number_of_transitions(); i++) {
5424 Map* target = transitions()->GetTarget(i);
5425 if (target->instance_descriptors() == instance_descriptors()) {
5426 Name* key = transitions()->GetKey(i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005427 int new_target_index;
5428 if (TransitionArray::IsSpecialTransition(key)) {
5429 new_target_index = transition_array->SearchSpecial(Symbol::cast(key));
5430 } else {
5431 PropertyDetails details =
5432 TransitionArray::GetTargetDetails(key, target);
5433 new_target_index = transition_array->Search(details.kind(), key,
5434 details.attributes());
5435 }
5436 DCHECK_NE(TransitionArray::kNotFound, new_target_index);
5437 DCHECK_EQ(target, transition_array->GetTarget(new_target_index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005438 }
Ben Murdoch257744e2011-11-30 15:57:28 +00005439 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005440#endif
5441 DCHECK(transitions() != transition_array);
5442 ZapTransitions();
Ben Murdoch257744e2011-11-30 15:57:28 +00005443 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005444
5445 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005446 CONDITIONAL_WRITE_BARRIER(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005447 GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00005448}
5449
5450
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005451void Map::init_back_pointer(Object* undefined) {
5452 DCHECK(undefined->IsUndefined());
5453 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined);
5454}
5455
5456
5457void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
5458 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
5459 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) ||
5460 (value->IsMap() && GetBackPointer()->IsUndefined()));
5461 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5462 if (object->IsTransitionArray()) {
5463 TransitionArray::cast(object)->set_back_pointer_storage(value);
Ben Murdoch257744e2011-11-30 15:57:28 +00005464 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005465 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value);
5466 CONDITIONAL_WRITE_BARRIER(
5467 GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00005468 }
5469}
5470
5471
Steve Block6ded16b2010-05-10 14:33:55 +01005472ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005473ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005474ACCESSORS(Map, constructor, Object, kConstructorOffset)
5475
5476ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005477ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005478ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005479
5480ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005481ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005482ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005483
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005484ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
5485ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005486
Steve Blocka7e24c12009-10-30 11:49:00 +00005487ACCESSORS(AccessorInfo, name, Object, kNameOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005488ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005489ACCESSORS(AccessorInfo, expected_receiver_type, Object,
5490 kExpectedReceiverTypeOffset)
5491
5492ACCESSORS(DeclaredAccessorDescriptor, serialized_data, ByteArray,
5493 kSerializedDataOffset)
5494
5495ACCESSORS(DeclaredAccessorInfo, descriptor, DeclaredAccessorDescriptor,
5496 kDescriptorOffset)
5497
5498ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset)
5499ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
5500ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
5501
5502ACCESSORS(Box, value, Object, kValueOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005503
5504ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
5505ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
Ben Murdochc7cc0282012-03-05 14:35:55 +00005506
Steve Blocka7e24c12009-10-30 11:49:00 +00005507ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
5508ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
5509ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
5510
5511ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
5512ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
5513ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
5514ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
5515ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
5516ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005517SMI_ACCESSORS(InterceptorInfo, flags, kFlagsOffset)
5518BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols,
5519 kCanInterceptSymbolsBit)
5520BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, kAllCanReadBit)
Steve Blocka7e24c12009-10-30 11:49:00 +00005521
5522ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
5523ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
5524
5525ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
5526ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005527ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005528
5529ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
5530ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005531ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
5532 kPrototypeTemplateOffset)
5533ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
5534ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
5535 kNamedPropertyHandlerOffset)
5536ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
5537 kIndexedPropertyHandlerOffset)
5538ACCESSORS(FunctionTemplateInfo, instance_template, Object,
5539 kInstanceTemplateOffset)
5540ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
5541ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
5542ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
5543 kInstanceCallHandlerOffset)
5544ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
5545 kAccessCheckInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005546ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005547
5548ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
5549ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
5550 kInternalFieldCountOffset)
5551
5552ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
5553ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
5554
5555ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
5556
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005557ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
5558ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
5559ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
5560ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
5561 kPretenureCreateCountOffset)
5562ACCESSORS(AllocationSite, dependent_code, DependentCode,
5563 kDependentCodeOffset)
5564ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
5565ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
5566
Steve Blocka7e24c12009-10-30 11:49:00 +00005567ACCESSORS(Script, source, Object, kSourceOffset)
5568ACCESSORS(Script, name, Object, kNameOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005569ACCESSORS(Script, id, Smi, kIdOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005570ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
5571ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005572ACCESSORS(Script, context_data, Object, kContextOffset)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005573ACCESSORS(Script, wrapper, HeapObject, kWrapperOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005574ACCESSORS_TO_SMI(Script, type, kTypeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005575ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00005576ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005577ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
5578 kEvalFrominstructionsOffsetOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005579ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
5580BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
5581ACCESSORS(Script, source_url, Object, kSourceUrlOffset)
5582ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005583
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005584Script::CompilationType Script::compilation_type() {
5585 return BooleanBit::get(flags(), kCompilationTypeBit) ?
5586 COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST;
5587}
5588void Script::set_compilation_type(CompilationType type) {
5589 set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
5590 type == COMPILATION_TYPE_EVAL));
5591}
5592Script::CompilationState Script::compilation_state() {
5593 return BooleanBit::get(flags(), kCompilationStateBit) ?
5594 COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
5595}
5596void Script::set_compilation_state(CompilationState state) {
5597 set_flags(BooleanBit::set(flags(), kCompilationStateBit,
5598 state == COMPILATION_STATE_COMPILED));
5599}
5600
5601
Steve Blocka7e24c12009-10-30 11:49:00 +00005602ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
5603ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
5604ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
5605ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
5606
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005607ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
5608ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
5609ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00005610ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00005611
Steve Blocka7e24c12009-10-30 11:49:00 +00005612ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005613ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
5614 kOptimizedCodeMapOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005615ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005616ACCESSORS(SharedFunctionInfo, feedback_vector, TypeFeedbackVector,
5617 kFeedbackVectorOffset)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005618#if TRACE_MAPS
5619SMI_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
5620#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005621ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
5622 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01005623ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005624ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
5625ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
5626ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005627
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005628
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005629SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00005630BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
5631 kHiddenPrototypeBit)
5632BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
5633BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
5634 kNeedsAccessCheckBit)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005635BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
5636 kReadOnlyPrototypeBit)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005637BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
5638 kRemovePrototypeBit)
5639BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
5640 kDoNotCacheBit)
Steve Blocka7e24c12009-10-30 11:49:00 +00005641BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
5642 kIsExpressionBit)
5643BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
5644 kIsTopLevelBit)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005645
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005646BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, allows_lazy_compilation,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005647 kAllowLazyCompilation)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005648BOOL_ACCESSORS(SharedFunctionInfo,
5649 compiler_hints,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005650 allows_lazy_compilation_without_context,
5651 kAllowLazyCompilationWithoutContext)
5652BOOL_ACCESSORS(SharedFunctionInfo,
5653 compiler_hints,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005654 uses_arguments,
5655 kUsesArguments)
5656BOOL_ACCESSORS(SharedFunctionInfo,
5657 compiler_hints,
5658 has_duplicate_parameters,
5659 kHasDuplicateParameters)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005660BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, asm_function, kIsAsmFunction)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005661BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, deserialized, kDeserialized)
Steve Blocka7e24c12009-10-30 11:49:00 +00005662
Iain Merrick75681382010-08-19 15:07:18 +01005663
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005664#if V8_HOST_ARCH_32_BIT
5665SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
5666SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00005667 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005668SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00005669 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005670SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5671SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00005672 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005673SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
5674SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00005675 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005676SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00005677 kCompilerHintsOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005678SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
5679 kOptCountAndBailoutReasonOffset)
5680SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005681SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005682SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
5683
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005684#else
Steve Blocka7e24c12009-10-30 11:49:00 +00005685
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005686#if V8_TARGET_LITTLE_ENDIAN
5687#define PSEUDO_SMI_LO_ALIGN 0
5688#define PSEUDO_SMI_HI_ALIGN kIntSize
5689#else
5690#define PSEUDO_SMI_LO_ALIGN kIntSize
5691#define PSEUDO_SMI_HI_ALIGN 0
5692#endif
5693
5694#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
5695 STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_LO_ALIGN); \
5696 int holder::name() const { \
5697 int value = READ_INT_FIELD(this, offset); \
5698 DCHECK(kHeapObjectTag == 1); \
5699 DCHECK((value & kHeapObjectTag) == 0); \
5700 return value >> 1; \
5701 } \
5702 void holder::set_##name(int value) { \
5703 DCHECK(kHeapObjectTag == 1); \
5704 DCHECK((value & 0xC0000000) == 0xC0000000 || (value & 0xC0000000) == 0x0); \
5705 WRITE_INT_FIELD(this, offset, (value << 1) & ~kHeapObjectTag); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005706 }
5707
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005708#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
5709 STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_HI_ALIGN); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005710 INT_ACCESSORS(holder, name, offset)
5711
5712
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005713PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005714PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5715 formal_parameter_count,
5716 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005717
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005718PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5719 expected_nof_properties,
5720 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005721PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5722
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005723PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
5724PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5725 start_position_and_type,
5726 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005727
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005728PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5729 function_token_position,
5730 kFunctionTokenPositionOffset)
5731PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5732 compiler_hints,
5733 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005734
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005735PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005736 opt_count_and_bailout_reason,
5737 kOptCountAndBailoutReasonOffset)
5738PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005739
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005740PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5741 ast_node_count,
5742 kAstNodeCountOffset)
5743PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5744 profiler_ticks,
5745 kProfilerTicksOffset)
5746
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005747#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005748
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005749
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005750BOOL_GETTER(SharedFunctionInfo,
5751 compiler_hints,
5752 optimization_disabled,
5753 kOptimizationDisabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01005754
5755
5756void SharedFunctionInfo::set_optimization_disabled(bool disable) {
5757 set_compiler_hints(BooleanBit::set(compiler_hints(),
5758 kOptimizationDisabled,
5759 disable));
5760 // If disabling optimizations we reflect that in the code object so
5761 // it will not be counted as optimizable code.
5762 if ((code()->kind() == Code::FUNCTION) && disable) {
5763 code()->set_optimizable(false);
5764 }
5765}
5766
5767
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005768StrictMode SharedFunctionInfo::strict_mode() {
5769 return BooleanBit::get(compiler_hints(), kStrictModeFunction)
5770 ? STRICT : SLOPPY;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005771}
5772
5773
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005774void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
5775 // We only allow mode transitions from sloppy to strict.
5776 DCHECK(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005777 int hints = compiler_hints();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005778 hints = BooleanBit::set(hints, kStrictModeFunction, strict_mode == STRICT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005779 set_compiler_hints(hints);
5780}
5781
5782
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005783FunctionKind SharedFunctionInfo::kind() {
5784 return FunctionKindBits::decode(compiler_hints());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005785}
5786
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005787
5788void SharedFunctionInfo::set_kind(FunctionKind kind) {
5789 DCHECK(IsValidFunctionKind(kind));
5790 int hints = compiler_hints();
5791 hints = FunctionKindBits::update(hints, kind);
5792 set_compiler_hints(hints);
5793}
5794
5795
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005796BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, uses_super_property,
5797 kUsesSuperProperty)
5798BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, uses_super_constructor_call,
5799 kUsesSuperConstructorCall)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005800BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005801BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
5802 kInlineBuiltin)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005803BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
5804 name_should_print_as_anonymous,
5805 kNameShouldPrintAsAnonymous)
5806BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
5807BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005808BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005809BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
5810BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
5811BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
5812BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
5813BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
5814 kIsConciseMethod)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005815BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_default_constructor,
5816 kIsDefaultConstructor)
Ben Murdoch257744e2011-11-30 15:57:28 +00005817
Steve Block6ded16b2010-05-10 14:33:55 +01005818ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
5819ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005820ACCESSORS(CodeCache, weak_cell_cache, Object, kWeakCellCacheOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01005821
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005822ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
5823
Steve Block3ce2e202009-11-05 08:53:23 +00005824bool Script::HasValidSource() {
5825 Object* src = this->source();
5826 if (!src->IsString()) return true;
5827 String* src_str = String::cast(src);
5828 if (!StringShape(src_str).IsExternal()) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005829 if (src_str->IsOneByteRepresentation()) {
5830 return ExternalOneByteString::cast(src)->resource() != NULL;
Steve Block3ce2e202009-11-05 08:53:23 +00005831 } else if (src_str->IsTwoByteRepresentation()) {
5832 return ExternalTwoByteString::cast(src)->resource() != NULL;
5833 }
5834 return true;
5835}
5836
5837
Steve Blocka7e24c12009-10-30 11:49:00 +00005838void SharedFunctionInfo::DontAdaptArguments() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005839 DCHECK(code()->kind() == Code::BUILTIN);
Steve Blocka7e24c12009-10-30 11:49:00 +00005840 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
5841}
5842
5843
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005844int SharedFunctionInfo::start_position() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00005845 return start_position_and_type() >> kStartPositionShift;
5846}
5847
5848
5849void SharedFunctionInfo::set_start_position(int start_position) {
5850 set_start_position_and_type((start_position << kStartPositionShift)
5851 | (start_position_and_type() & ~kStartPositionMask));
5852}
5853
5854
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005855Code* SharedFunctionInfo::code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00005856 return Code::cast(READ_FIELD(this, kCodeOffset));
5857}
5858
5859
5860void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005861 DCHECK(value->kind() != Code::OPTIMIZED_FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00005862 WRITE_FIELD(this, kCodeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005863 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00005864}
5865
5866
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005867void SharedFunctionInfo::ReplaceCode(Code* value) {
5868 // If the GC metadata field is already used then the function was
5869 // enqueued as a code flushing candidate and we remove it now.
5870 if (code()->gc_metadata() != NULL) {
5871 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
5872 flusher->EvictCandidate(this);
5873 }
5874
5875 DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
5876
5877 set_code(value);
5878}
5879
5880
5881ScopeInfo* SharedFunctionInfo::scope_info() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005882 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005883}
5884
5885
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005886void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005887 WriteBarrierMode mode) {
5888 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005889 CONDITIONAL_WRITE_BARRIER(GetHeap(),
5890 this,
5891 kScopeInfoOffset,
5892 reinterpret_cast<Object*>(value),
5893 mode);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005894}
5895
5896
Steve Blocka7e24c12009-10-30 11:49:00 +00005897bool SharedFunctionInfo::is_compiled() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005898 return code() != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy);
Steve Blocka7e24c12009-10-30 11:49:00 +00005899}
5900
5901
Steve Block6ded16b2010-05-10 14:33:55 +01005902bool SharedFunctionInfo::IsApiFunction() {
5903 return function_data()->IsFunctionTemplateInfo();
5904}
5905
5906
5907FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005908 DCHECK(IsApiFunction());
Steve Block6ded16b2010-05-10 14:33:55 +01005909 return FunctionTemplateInfo::cast(function_data());
5910}
5911
5912
Ben Murdochb0fe1622011-05-05 13:52:32 +01005913bool SharedFunctionInfo::HasBuiltinFunctionId() {
Kristian Monsen25f61362010-05-21 11:50:48 +01005914 return function_data()->IsSmi();
5915}
5916
5917
Ben Murdochb0fe1622011-05-05 13:52:32 +01005918BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005919 DCHECK(HasBuiltinFunctionId());
Ben Murdochb0fe1622011-05-05 13:52:32 +01005920 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00005921}
5922
5923
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005924int SharedFunctionInfo::ic_age() {
5925 return ICAgeBits::decode(counters());
Iain Merrick75681382010-08-19 15:07:18 +01005926}
5927
5928
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005929void SharedFunctionInfo::set_ic_age(int ic_age) {
5930 set_counters(ICAgeBits::update(counters(), ic_age));
5931}
5932
5933
5934int SharedFunctionInfo::deopt_count() {
5935 return DeoptCountBits::decode(counters());
5936}
5937
5938
5939void SharedFunctionInfo::set_deopt_count(int deopt_count) {
5940 set_counters(DeoptCountBits::update(counters(), deopt_count));
5941}
5942
5943
5944void SharedFunctionInfo::increment_deopt_count() {
5945 int value = counters();
5946 int deopt_count = DeoptCountBits::decode(value);
5947 deopt_count = (deopt_count + 1) & DeoptCountBits::kMax;
5948 set_counters(DeoptCountBits::update(value, deopt_count));
5949}
5950
5951
5952int SharedFunctionInfo::opt_reenable_tries() {
5953 return OptReenableTriesBits::decode(counters());
5954}
5955
5956
5957void SharedFunctionInfo::set_opt_reenable_tries(int tries) {
5958 set_counters(OptReenableTriesBits::update(counters(), tries));
5959}
5960
5961
5962int SharedFunctionInfo::opt_count() {
5963 return OptCountBits::decode(opt_count_and_bailout_reason());
5964}
5965
5966
5967void SharedFunctionInfo::set_opt_count(int opt_count) {
5968 set_opt_count_and_bailout_reason(
5969 OptCountBits::update(opt_count_and_bailout_reason(), opt_count));
5970}
5971
5972
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005973BailoutReason SharedFunctionInfo::disable_optimization_reason() {
5974 return static_cast<BailoutReason>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005975 DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason()));
Iain Merrick75681382010-08-19 15:07:18 +01005976}
5977
5978
Ben Murdochb0fe1622011-05-05 13:52:32 +01005979bool SharedFunctionInfo::has_deoptimization_support() {
5980 Code* code = this->code();
5981 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
5982}
5983
5984
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005985void SharedFunctionInfo::TryReenableOptimization() {
5986 int tries = opt_reenable_tries();
5987 set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
5988 // We reenable optimization whenever the number of tries is a large
5989 // enough power of 2.
5990 if (tries >= 16 && (((tries - 1) & tries) == 0)) {
5991 set_optimization_disabled(false);
5992 set_opt_count(0);
5993 set_deopt_count(0);
5994 code()->set_optimizable(true);
5995 }
5996}
5997
5998
Steve Blocka7e24c12009-10-30 11:49:00 +00005999bool JSFunction::IsBuiltin() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006000 return context()->global_object()->IsJSBuiltinsObject();
6001}
6002
6003
6004bool JSFunction::IsFromNativeScript() {
6005 Object* script = shared()->script();
6006 bool native = script->IsScript() &&
6007 Script::cast(script)->type()->value() == Script::TYPE_NATIVE;
6008 DCHECK(!IsBuiltin() || native); // All builtins are also native.
6009 return native;
6010}
6011
6012
6013bool JSFunction::IsFromExtensionScript() {
6014 Object* script = shared()->script();
6015 return script->IsScript() &&
6016 Script::cast(script)->type()->value() == Script::TYPE_EXTENSION;
Steve Blocka7e24c12009-10-30 11:49:00 +00006017}
6018
6019
Ben Murdochb0fe1622011-05-05 13:52:32 +01006020bool JSFunction::NeedsArgumentsAdaption() {
6021 return shared()->formal_parameter_count() !=
6022 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
6023}
6024
6025
6026bool JSFunction::IsOptimized() {
6027 return code()->kind() == Code::OPTIMIZED_FUNCTION;
6028}
6029
6030
Ben Murdoch8b112d22011-06-08 16:22:53 +01006031bool JSFunction::IsOptimizable() {
6032 return code()->kind() == Code::FUNCTION && code()->optimizable();
6033}
6034
6035
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006036bool JSFunction::IsMarkedForOptimization() {
6037 return code() == GetIsolate()->builtins()->builtin(
6038 Builtins::kCompileOptimized);
6039}
6040
6041
6042bool JSFunction::IsMarkedForConcurrentOptimization() {
6043 return code() == GetIsolate()->builtins()->builtin(
6044 Builtins::kCompileOptimizedConcurrent);
6045}
6046
6047
6048bool JSFunction::IsInOptimizationQueue() {
6049 return code() == GetIsolate()->builtins()->builtin(
6050 Builtins::kInOptimizationQueue);
6051}
6052
6053
6054bool JSFunction::IsInobjectSlackTrackingInProgress() {
6055 return has_initial_map() &&
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006056 initial_map()->counter() >= Map::kSlackTrackingCounterEnd;
Ben Murdochb0fe1622011-05-05 13:52:32 +01006057}
6058
6059
Steve Blocka7e24c12009-10-30 11:49:00 +00006060Code* JSFunction::code() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006061 return Code::cast(
Steve Block791712a2010-08-27 10:21:07 +01006062 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006063}
6064
6065
6066void JSFunction::set_code(Code* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006067 DCHECK(!GetHeap()->InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01006068 Address entry = value->entry();
6069 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006070 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
6071 this,
6072 HeapObject::RawField(this, kCodeEntryOffset),
6073 value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006074}
6075
6076
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006077void JSFunction::set_code_no_write_barrier(Code* value) {
6078 DCHECK(!GetHeap()->InNewSpace(value));
6079 Address entry = value->entry();
6080 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
6081}
6082
6083
Ben Murdochb0fe1622011-05-05 13:52:32 +01006084void JSFunction::ReplaceCode(Code* code) {
6085 bool was_optimized = IsOptimized();
6086 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
6087
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006088 if (was_optimized && is_optimized) {
6089 shared()->EvictFromOptimizedCodeMap(this->code(),
6090 "Replacing with another optimized code");
6091 }
6092
Ben Murdochb0fe1622011-05-05 13:52:32 +01006093 set_code(code);
6094
6095 // Add/remove the function from the list of optimized functions for this
6096 // context based on the state change.
6097 if (!was_optimized && is_optimized) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006098 context()->native_context()->AddOptimizedFunction(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01006099 }
6100 if (was_optimized && !is_optimized) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006101 // TODO(titzer): linear in the number of optimized functions; fix!
6102 context()->native_context()->RemoveOptimizedFunction(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01006103 }
6104}
6105
6106
Steve Blocka7e24c12009-10-30 11:49:00 +00006107Context* JSFunction::context() {
6108 return Context::cast(READ_FIELD(this, kContextOffset));
6109}
6110
6111
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006112JSObject* JSFunction::global_proxy() {
6113 return context()->global_proxy();
Iain Merrick75681382010-08-19 15:07:18 +01006114}
6115
6116
Steve Blocka7e24c12009-10-30 11:49:00 +00006117void JSFunction::set_context(Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006118 DCHECK(value->IsUndefined() || value->IsContext());
Steve Blocka7e24c12009-10-30 11:49:00 +00006119 WRITE_FIELD(this, kContextOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006120 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006121}
6122
6123ACCESSORS(JSFunction, prototype_or_initial_map, Object,
6124 kPrototypeOrInitialMapOffset)
6125
6126
6127Map* JSFunction::initial_map() {
6128 return Map::cast(prototype_or_initial_map());
6129}
6130
6131
Steve Blocka7e24c12009-10-30 11:49:00 +00006132bool JSFunction::has_initial_map() {
6133 return prototype_or_initial_map()->IsMap();
6134}
6135
6136
6137bool JSFunction::has_instance_prototype() {
6138 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
6139}
6140
6141
6142bool JSFunction::has_prototype() {
6143 return map()->has_non_instance_prototype() || has_instance_prototype();
6144}
6145
6146
6147Object* JSFunction::instance_prototype() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006148 DCHECK(has_instance_prototype());
Steve Blocka7e24c12009-10-30 11:49:00 +00006149 if (has_initial_map()) return initial_map()->prototype();
6150 // When there is no initial map and the prototype is a JSObject, the
6151 // initial map field is used for the prototype field.
6152 return prototype_or_initial_map();
6153}
6154
6155
6156Object* JSFunction::prototype() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006157 DCHECK(has_prototype());
Steve Blocka7e24c12009-10-30 11:49:00 +00006158 // If the function's prototype property has been set to a non-JSObject
6159 // value, that value is stored in the constructor field of the map.
6160 if (map()->has_non_instance_prototype()) return map()->constructor();
6161 return instance_prototype();
6162}
6163
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006164
Steve Block6ded16b2010-05-10 14:33:55 +01006165bool JSFunction::should_have_prototype() {
6166 return map()->function_with_prototype();
6167}
6168
Steve Blocka7e24c12009-10-30 11:49:00 +00006169
6170bool JSFunction::is_compiled() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006171 return code() != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy);
Steve Blocka7e24c12009-10-30 11:49:00 +00006172}
6173
6174
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006175FixedArray* JSFunction::literals() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006176 DCHECK(!shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006177 return literals_or_bindings();
6178}
6179
6180
6181void JSFunction::set_literals(FixedArray* literals) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006182 DCHECK(!shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006183 set_literals_or_bindings(literals);
6184}
6185
6186
6187FixedArray* JSFunction::function_bindings() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006188 DCHECK(shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006189 return literals_or_bindings();
6190}
6191
6192
6193void JSFunction::set_function_bindings(FixedArray* bindings) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006194 DCHECK(shared()->bound());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006195 // Bound function literal may be initialized to the empty fixed array
6196 // before the bindings are set.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006197 DCHECK(bindings == GetHeap()->empty_fixed_array() ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006198 bindings->map() == GetHeap()->fixed_cow_array_map());
6199 set_literals_or_bindings(bindings);
6200}
6201
6202
Steve Blocka7e24c12009-10-30 11:49:00 +00006203int JSFunction::NumberOfLiterals() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006204 DCHECK(!shared()->bound());
Steve Blocka7e24c12009-10-30 11:49:00 +00006205 return literals()->length();
6206}
6207
6208
6209Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006210 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01006211 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00006212}
6213
6214
6215void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
6216 Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006217 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01006218 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006219 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
Steve Block6ded16b2010-05-10 14:33:55 +01006220}
6221
6222
6223Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006224 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01006225 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
6226}
6227
6228
6229void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
6230 Code* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006231 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01006232 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006233 DCHECK(!GetHeap()->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006234}
6235
6236
Ben Murdoch257744e2011-11-30 15:57:28 +00006237ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006238ACCESSORS(JSProxy, hash, Object, kHashOffset)
Ben Murdoch589d6972011-11-30 16:04:58 +00006239ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
6240ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
6241
6242
6243void JSProxy::InitializeBody(int object_size, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006244 DCHECK(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
Ben Murdoch589d6972011-11-30 16:04:58 +00006245 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
6246 WRITE_FIELD(this, offset, value);
6247 }
6248}
Ben Murdoch257744e2011-11-30 15:57:28 +00006249
6250
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006251ACCESSORS(JSCollection, table, Object, kTableOffset)
6252
6253
6254#define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \
6255 template<class Derived, class TableType> \
6256 type* OrderedHashTableIterator<Derived, TableType>::name() const { \
6257 return type::cast(READ_FIELD(this, offset)); \
6258 } \
6259 template<class Derived, class TableType> \
6260 void OrderedHashTableIterator<Derived, TableType>::set_##name( \
6261 type* value, WriteBarrierMode mode) { \
6262 WRITE_FIELD(this, offset, value); \
6263 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
6264 }
6265
6266ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset)
6267ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Object, kIndexOffset)
6268ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Object, kKindOffset)
6269
6270#undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS
6271
6272
6273ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
6274ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006275
6276
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006277Address Foreign::foreign_address() {
6278 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006279}
6280
6281
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006282void Foreign::set_foreign_address(Address value) {
6283 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006284}
6285
6286
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006287ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
6288ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
6289ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
6290SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
6291ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
6292SMI_ACCESSORS(JSGeneratorObject, stack_handler_index, kStackHandlerIndexOffset)
6293
6294bool JSGeneratorObject::is_suspended() {
6295 DCHECK_LT(kGeneratorExecuting, kGeneratorClosed);
6296 DCHECK_EQ(kGeneratorClosed, 0);
6297 return continuation() > 0;
6298}
6299
6300bool JSGeneratorObject::is_closed() {
6301 return continuation() == kGeneratorClosed;
6302}
6303
6304bool JSGeneratorObject::is_executing() {
6305 return continuation() == kGeneratorExecuting;
6306}
6307
6308ACCESSORS(JSModule, context, Object, kContextOffset)
6309ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset)
6310
6311
Steve Blocka7e24c12009-10-30 11:49:00 +00006312ACCESSORS(JSValue, value, Object, kValueOffset)
6313
6314
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006315HeapNumber* HeapNumber::cast(Object* object) {
6316 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
6317 return reinterpret_cast<HeapNumber*>(object);
6318}
6319
6320
6321const HeapNumber* HeapNumber::cast(const Object* object) {
6322 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
6323 return reinterpret_cast<const HeapNumber*>(object);
Steve Blocka7e24c12009-10-30 11:49:00 +00006324}
6325
6326
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006327ACCESSORS(JSDate, value, Object, kValueOffset)
6328ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
6329ACCESSORS(JSDate, year, Object, kYearOffset)
6330ACCESSORS(JSDate, month, Object, kMonthOffset)
6331ACCESSORS(JSDate, day, Object, kDayOffset)
6332ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
6333ACCESSORS(JSDate, hour, Object, kHourOffset)
6334ACCESSORS(JSDate, min, Object, kMinOffset)
6335ACCESSORS(JSDate, sec, Object, kSecOffset)
6336
6337
Steve Block1e0659c2011-05-24 12:43:12 +01006338ACCESSORS(JSMessageObject, type, String, kTypeOffset)
6339ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
6340ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
Steve Block1e0659c2011-05-24 12:43:12 +01006341ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
6342SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
6343SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
6344
6345
Steve Blocka7e24c12009-10-30 11:49:00 +00006346INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006347INT_ACCESSORS(Code, prologue_offset, kPrologueOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01006348ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006349ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01006350ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006351ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
6352ACCESSORS(Code, next_code_link, Object, kNextCodeLinkOffset)
6353
6354
6355void Code::WipeOutHeader() {
6356 WRITE_FIELD(this, kRelocationInfoOffset, NULL);
6357 WRITE_FIELD(this, kHandlerTableOffset, NULL);
6358 WRITE_FIELD(this, kDeoptimizationDataOffset, NULL);
6359 WRITE_FIELD(this, kConstantPoolOffset, NULL);
6360 // Do not wipe out major/minor keys on a code stub or IC
6361 if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) {
6362 WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL);
6363 }
6364}
6365
6366
6367Object* Code::type_feedback_info() {
6368 DCHECK(kind() == FUNCTION);
6369 return raw_type_feedback_info();
6370}
6371
6372
6373void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
6374 DCHECK(kind() == FUNCTION);
6375 set_raw_type_feedback_info(value, mode);
6376 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
6377 value, mode);
6378}
6379
6380
6381uint32_t Code::stub_key() {
6382 DCHECK(IsCodeStubOrIC());
6383 Smi* smi_key = Smi::cast(raw_type_feedback_info());
6384 return static_cast<uint32_t>(smi_key->value());
6385}
6386
6387
6388void Code::set_stub_key(uint32_t key) {
6389 DCHECK(IsCodeStubOrIC());
6390 set_raw_type_feedback_info(Smi::FromInt(key));
6391}
6392
6393
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006394ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
6395INT_ACCESSORS(Code, ic_age, kICAgeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00006396
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006397
Steve Blocka7e24c12009-10-30 11:49:00 +00006398byte* Code::instruction_start() {
6399 return FIELD_ADDR(this, kHeaderSize);
6400}
6401
6402
Leon Clarkeac952652010-07-15 11:15:24 +01006403byte* Code::instruction_end() {
6404 return instruction_start() + instruction_size();
6405}
6406
6407
Steve Blocka7e24c12009-10-30 11:49:00 +00006408int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01006409 return RoundUp(instruction_size(), kObjectAlignment);
6410}
6411
6412
6413ByteArray* Code::unchecked_relocation_info() {
6414 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00006415}
6416
6417
6418byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01006419 return unchecked_relocation_info()->GetDataStartAddress();
6420}
6421
6422
6423int Code::relocation_size() {
6424 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00006425}
6426
6427
6428byte* Code::entry() {
6429 return instruction_start();
6430}
6431
6432
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006433bool Code::contains(byte* inner_pointer) {
6434 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
Steve Blocka7e24c12009-10-30 11:49:00 +00006435}
6436
6437
Steve Blocka7e24c12009-10-30 11:49:00 +00006438ACCESSORS(JSArray, length, Object, kLengthOffset)
6439
6440
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006441void* JSArrayBuffer::backing_store() const {
6442 intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
6443 return reinterpret_cast<void*>(ptr);
6444}
6445
6446
6447void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
6448 intptr_t ptr = reinterpret_cast<intptr_t>(value);
6449 WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
6450}
6451
6452
6453ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
6454ACCESSORS_TO_SMI(JSArrayBuffer, flag, kFlagOffset)
6455
6456
6457bool JSArrayBuffer::is_external() {
6458 return BooleanBit::get(flag(), kIsExternalBit);
6459}
6460
6461
6462void JSArrayBuffer::set_is_external(bool value) {
6463 set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
6464}
6465
6466
6467bool JSArrayBuffer::should_be_freed() {
6468 return BooleanBit::get(flag(), kShouldBeFreed);
6469}
6470
6471
6472void JSArrayBuffer::set_should_be_freed(bool value) {
6473 set_flag(BooleanBit::set(flag(), kShouldBeFreed, value));
6474}
6475
6476
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006477bool JSArrayBuffer::is_neuterable() {
6478 return BooleanBit::get(flag(), kIsNeuterableBit);
6479}
6480
6481
6482void JSArrayBuffer::set_is_neuterable(bool value) {
6483 set_flag(BooleanBit::set(flag(), kIsNeuterableBit, value));
6484}
6485
6486
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006487ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
6488ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset)
6489
6490
6491ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
6492ACCESSORS(JSArrayBufferView, byte_offset, Object, kByteOffsetOffset)
6493ACCESSORS(JSArrayBufferView, byte_length, Object, kByteLengthOffset)
6494ACCESSORS(JSArrayBufferView, weak_next, Object, kWeakNextOffset)
6495ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
6496
Steve Blocka7e24c12009-10-30 11:49:00 +00006497ACCESSORS(JSRegExp, data, Object, kDataOffset)
6498
6499
6500JSRegExp::Type JSRegExp::TypeTag() {
6501 Object* data = this->data();
6502 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
6503 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
6504 return static_cast<JSRegExp::Type>(smi->value());
6505}
6506
6507
6508int JSRegExp::CaptureCount() {
6509 switch (TypeTag()) {
6510 case ATOM:
6511 return 0;
6512 case IRREGEXP:
6513 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
6514 default:
6515 UNREACHABLE();
6516 return -1;
6517 }
6518}
6519
6520
6521JSRegExp::Flags JSRegExp::GetFlags() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006522 DCHECK(this->data()->IsFixedArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00006523 Object* data = this->data();
6524 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
6525 return Flags(smi->value());
6526}
6527
6528
6529String* JSRegExp::Pattern() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006530 DCHECK(this->data()->IsFixedArray());
Steve Blocka7e24c12009-10-30 11:49:00 +00006531 Object* data = this->data();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006532 String* pattern = String::cast(FixedArray::cast(data)->get(kSourceIndex));
Steve Blocka7e24c12009-10-30 11:49:00 +00006533 return pattern;
6534}
6535
6536
6537Object* JSRegExp::DataAt(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006538 DCHECK(TypeTag() != NOT_COMPILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00006539 return FixedArray::cast(data())->get(index);
6540}
6541
6542
6543void JSRegExp::SetDataAt(int index, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006544 DCHECK(TypeTag() != NOT_COMPILED);
6545 DCHECK(index >= kDataIndex); // Only implementation data can be set this way.
Steve Blocka7e24c12009-10-30 11:49:00 +00006546 FixedArray::cast(data())->set(index, value);
6547}
6548
6549
Ben Murdoch589d6972011-11-30 16:04:58 +00006550ElementsKind JSObject::GetElementsKind() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006551 ElementsKind kind = map()->elements_kind();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006552#if VERIFY_HEAP && DEBUG
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006553 FixedArrayBase* fixed_array =
6554 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006555
6556 // If a GC was caused while constructing this object, the elements
6557 // pointer may point to a one pointer filler map.
6558 if (ElementsAreSafeToExamine()) {
6559 Map* map = fixed_array->map();
6560 DCHECK((IsFastSmiOrObjectElementsKind(kind) &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006561 (map == GetHeap()->fixed_array_map() ||
6562 map == GetHeap()->fixed_cow_array_map())) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006563 (IsFastDoubleElementsKind(kind) &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006564 (fixed_array->IsFixedDoubleArray() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006565 fixed_array == GetHeap()->empty_fixed_array())) ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006566 (kind == DICTIONARY_ELEMENTS &&
6567 fixed_array->IsFixedArray() &&
6568 fixed_array->IsDictionary()) ||
6569 (kind > DICTIONARY_ELEMENTS));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006570 DCHECK((kind != SLOPPY_ARGUMENTS_ELEMENTS) ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006571 (elements()->IsFixedArray() && elements()->length() >= 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006572 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006573#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006574 return kind;
Steve Blocka7e24c12009-10-30 11:49:00 +00006575}
6576
6577
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006578ElementsAccessor* JSObject::GetElementsAccessor() {
6579 return ElementsAccessor::ForKind(GetElementsKind());
6580}
6581
6582
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006583bool JSObject::HasFastObjectElements() {
6584 return IsFastObjectElementsKind(GetElementsKind());
Steve Blocka7e24c12009-10-30 11:49:00 +00006585}
6586
6587
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006588bool JSObject::HasFastSmiElements() {
6589 return IsFastSmiElementsKind(GetElementsKind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006590}
6591
6592
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006593bool JSObject::HasFastSmiOrObjectElements() {
6594 return IsFastSmiOrObjectElementsKind(GetElementsKind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006595}
6596
6597
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006598bool JSObject::HasFastDoubleElements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006599 return IsFastDoubleElementsKind(GetElementsKind());
6600}
6601
6602
6603bool JSObject::HasFastHoleyElements() {
6604 return IsFastHoleyElementsKind(GetElementsKind());
6605}
6606
6607
6608bool JSObject::HasFastElements() {
6609 return IsFastElementsKind(GetElementsKind());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006610}
6611
6612
Steve Blocka7e24c12009-10-30 11:49:00 +00006613bool JSObject::HasDictionaryElements() {
6614 return GetElementsKind() == DICTIONARY_ELEMENTS;
6615}
6616
6617
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006618bool JSObject::HasSloppyArgumentsElements() {
6619 return GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006620}
6621
6622
Steve Block3ce2e202009-11-05 08:53:23 +00006623bool JSObject::HasExternalArrayElements() {
Steve Block44f0eee2011-05-26 01:26:41 +01006624 HeapObject* array = elements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006625 DCHECK(array != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01006626 return array->IsExternalArray();
Steve Block3ce2e202009-11-05 08:53:23 +00006627}
6628
6629
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006630#define EXTERNAL_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \
6631bool JSObject::HasExternal##Type##Elements() { \
6632 HeapObject* array = elements(); \
6633 DCHECK(array != NULL); \
6634 if (!array->IsHeapObject()) \
6635 return false; \
6636 return array->map()->instance_type() == EXTERNAL_##TYPE##_ARRAY_TYPE; \
6637}
6638
6639TYPED_ARRAYS(EXTERNAL_ELEMENTS_CHECK)
6640
6641#undef EXTERNAL_ELEMENTS_CHECK
6642
6643
6644bool JSObject::HasFixedTypedArrayElements() {
6645 HeapObject* array = elements();
6646 DCHECK(array != NULL);
6647 return array->IsFixedTypedArrayBase();
Steve Block3ce2e202009-11-05 08:53:23 +00006648}
6649
6650
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006651#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \
6652bool JSObject::HasFixed##Type##Elements() { \
6653 HeapObject* array = elements(); \
6654 DCHECK(array != NULL); \
6655 if (!array->IsHeapObject()) \
6656 return false; \
6657 return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \
6658}
6659
6660TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)
6661
6662#undef FIXED_TYPED_ELEMENTS_CHECK
Steve Block3ce2e202009-11-05 08:53:23 +00006663
6664
Steve Blocka7e24c12009-10-30 11:49:00 +00006665bool JSObject::HasNamedInterceptor() {
6666 return map()->has_named_interceptor();
6667}
6668
6669
6670bool JSObject::HasIndexedInterceptor() {
6671 return map()->has_indexed_interceptor();
6672}
6673
6674
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006675NameDictionary* JSObject::property_dictionary() {
6676 DCHECK(!HasFastProperties());
6677 return NameDictionary::cast(properties());
Steve Blocka7e24c12009-10-30 11:49:00 +00006678}
6679
6680
Ben Murdochc7cc0282012-03-05 14:35:55 +00006681SeededNumberDictionary* JSObject::element_dictionary() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006682 DCHECK(HasDictionaryElements());
Ben Murdochc7cc0282012-03-05 14:35:55 +00006683 return SeededNumberDictionary::cast(elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00006684}
6685
6686
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006687bool Name::IsHashFieldComputed(uint32_t field) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006688 return (field & kHashNotComputedMask) == 0;
6689}
6690
6691
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006692bool Name::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006693 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00006694}
6695
6696
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006697uint32_t Name::Hash() {
Steve Blocka7e24c12009-10-30 11:49:00 +00006698 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00006699 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006700 if (IsHashFieldComputed(field)) return field >> kHashShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006701 // Slow case: compute hash code and set it. Has to be a string.
6702 return String::cast(this)->ComputeAndSetHash();
6703}
6704
6705bool Name::IsOwn() {
6706 return this->IsSymbol() && Symbol::cast(this)->is_own();
Steve Blocka7e24c12009-10-30 11:49:00 +00006707}
6708
6709
Ben Murdochc7cc0282012-03-05 14:35:55 +00006710StringHasher::StringHasher(int length, uint32_t seed)
Steve Blocka7e24c12009-10-30 11:49:00 +00006711 : length_(length),
Ben Murdochc7cc0282012-03-05 14:35:55 +00006712 raw_running_hash_(seed),
Steve Blocka7e24c12009-10-30 11:49:00 +00006713 array_index_(0),
6714 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006715 is_first_char_(true) {
6716 DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0);
Ben Murdochc7cc0282012-03-05 14:35:55 +00006717}
Steve Blocka7e24c12009-10-30 11:49:00 +00006718
6719
6720bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00006721 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00006722}
6723
6724
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006725uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
6726 running_hash += c;
6727 running_hash += (running_hash << 10);
6728 running_hash ^= (running_hash >> 6);
6729 return running_hash;
6730}
6731
6732
6733uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
6734 running_hash += (running_hash << 3);
6735 running_hash ^= (running_hash >> 11);
6736 running_hash += (running_hash << 15);
6737 if ((running_hash & String::kHashBitMask) == 0) {
6738 return kZeroHash;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006739 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006740 return running_hash;
6741}
6742
6743
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006744uint32_t StringHasher::ComputeRunningHash(uint32_t running_hash,
6745 const uc16* chars, int length) {
6746 DCHECK_NOT_NULL(chars);
6747 DCHECK(length >= 0);
6748 for (int i = 0; i < length; ++i) {
6749 running_hash = AddCharacterCore(running_hash, *chars++);
6750 }
6751 return running_hash;
6752}
6753
6754
6755uint32_t StringHasher::ComputeRunningHashOneByte(uint32_t running_hash,
6756 const char* chars,
6757 int length) {
6758 DCHECK_NOT_NULL(chars);
6759 DCHECK(length >= 0);
6760 for (int i = 0; i < length; ++i) {
6761 uint16_t c = static_cast<uint16_t>(*chars++);
6762 running_hash = AddCharacterCore(running_hash, c);
6763 }
6764 return running_hash;
6765}
6766
6767
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006768void StringHasher::AddCharacter(uint16_t c) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006769 // Use the Jenkins one-at-a-time hash function to update the hash
6770 // for the given character.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006771 raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
6772}
6773
6774
6775bool StringHasher::UpdateIndex(uint16_t c) {
6776 DCHECK(is_array_index_);
6777 if (c < '0' || c > '9') {
6778 is_array_index_ = false;
6779 return false;
6780 }
6781 int d = c - '0';
6782 if (is_first_char_) {
6783 is_first_char_ = false;
6784 if (c == '0' && length_ > 1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006785 is_array_index_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006786 return false;
6787 }
6788 }
6789 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
6790 is_array_index_ = false;
6791 return false;
6792 }
6793 array_index_ = array_index_ * 10 + d;
6794 return true;
6795}
6796
6797
6798template<typename Char>
6799inline void StringHasher::AddCharacters(const Char* chars, int length) {
6800 DCHECK(sizeof(Char) == 1 || sizeof(Char) == 2);
6801 int i = 0;
6802 if (is_array_index_) {
6803 for (; i < length; i++) {
6804 AddCharacter(chars[i]);
6805 if (!UpdateIndex(chars[i])) {
6806 i++;
6807 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00006808 }
6809 }
6810 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006811 for (; i < length; i++) {
6812 DCHECK(!is_array_index_);
6813 AddCharacter(chars[i]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006814 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006815}
6816
6817
Steve Block44f0eee2011-05-26 01:26:41 +01006818template <typename schar>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006819uint32_t StringHasher::HashSequentialString(const schar* chars,
6820 int length,
6821 uint32_t seed) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00006822 StringHasher hasher(length, seed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006823 if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
6824 return hasher.GetHashField();
6825}
6826
6827
6828uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) {
6829 IteratingStringHasher hasher(string->length(), seed);
6830 // Nothing to do.
6831 if (hasher.has_trivial_hash()) return hasher.GetHashField();
6832 ConsString* cons_string = String::VisitFlat(&hasher, string);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006833 if (cons_string == nullptr) return hasher.GetHashField();
6834 hasher.VisitConsString(cons_string);
Steve Block44f0eee2011-05-26 01:26:41 +01006835 return hasher.GetHashField();
6836}
6837
6838
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006839void IteratingStringHasher::VisitOneByteString(const uint8_t* chars,
6840 int length) {
6841 AddCharacters(chars, length);
6842}
6843
6844
6845void IteratingStringHasher::VisitTwoByteString(const uint16_t* chars,
6846 int length) {
6847 AddCharacters(chars, length);
6848}
6849
6850
6851bool Name::AsArrayIndex(uint32_t* index) {
6852 return IsString() && String::cast(this)->AsArrayIndex(index);
6853}
6854
6855
Steve Blocka7e24c12009-10-30 11:49:00 +00006856bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00006857 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006858 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
6859 return false;
6860 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006861 return SlowAsArrayIndex(index);
6862}
6863
6864
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006865void String::SetForwardedInternalizedString(String* canonical) {
6866 DCHECK(IsInternalizedString());
6867 DCHECK(HasHashCode());
6868 if (canonical == this) return; // No need to forward.
6869 DCHECK(SlowEquals(canonical));
6870 DCHECK(canonical->IsInternalizedString());
6871 DCHECK(canonical->HasHashCode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006872 WRITE_FIELD(this, kHashFieldSlot, canonical);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006873 // Setting the hash field to a tagged value sets the LSB, causing the hash
6874 // code to be interpreted as uninitialized. We use this fact to recognize
6875 // that we have a forwarded string.
6876 DCHECK(!HasHashCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00006877}
6878
6879
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006880String* String::GetForwardedInternalizedString() {
6881 DCHECK(IsInternalizedString());
6882 if (HasHashCode()) return this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006883 String* canonical = String::cast(READ_FIELD(this, kHashFieldSlot));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006884 DCHECK(canonical->IsInternalizedString());
6885 DCHECK(SlowEquals(canonical));
6886 DCHECK(canonical->HasHashCode());
6887 return canonical;
6888}
6889
6890
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006891Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
6892 Handle<Name> name) {
6893 if (object->IsJSProxy()) {
6894 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6895 return JSProxy::HasPropertyWithHandler(proxy, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006896 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006897 Maybe<PropertyAttributes> result = GetPropertyAttributes(object, name);
6898 if (!result.has_value) return Maybe<bool>();
6899 return maybe(result.value != ABSENT);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006900}
6901
6902
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006903Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
6904 Handle<Name> name) {
6905 if (object->IsJSProxy()) {
6906 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6907 return JSProxy::HasPropertyWithHandler(proxy, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006908 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006909 Maybe<PropertyAttributes> result = GetOwnPropertyAttributes(object, name);
6910 if (!result.has_value) return Maybe<bool>();
6911 return maybe(result.value != ABSENT);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006912}
6913
6914
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006915Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
6916 Handle<JSReceiver> object, Handle<Name> key) {
6917 uint32_t index;
6918 if (object->IsJSObject() && key->AsArrayIndex(&index)) {
6919 return GetElementAttribute(object, index);
Steve Blockd0582a62009-12-15 09:54:21 +00006920 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006921 LookupIterator it(object, key);
6922 return GetPropertyAttributes(&it);
Steve Blockd0582a62009-12-15 09:54:21 +00006923}
6924
6925
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006926Maybe<PropertyAttributes> JSReceiver::GetElementAttribute(
6927 Handle<JSReceiver> object, uint32_t index) {
6928 if (object->IsJSProxy()) {
6929 return JSProxy::GetElementAttributeWithHandler(
6930 Handle<JSProxy>::cast(object), object, index);
6931 }
6932 return JSObject::GetElementAttributeWithReceiver(
6933 Handle<JSObject>::cast(object), object, index, true);
6934}
6935
6936
6937bool JSGlobalObject::IsDetached() {
6938 return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this);
6939}
6940
6941
6942bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) const {
6943 const PrototypeIterator iter(this->GetIsolate(),
6944 const_cast<JSGlobalProxy*>(this));
6945 return iter.GetCurrent() != global;
6946}
6947
6948
6949Handle<Smi> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) {
6950 return object->IsJSProxy()
6951 ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object))
6952 : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object));
6953}
6954
6955
6956Object* JSReceiver::GetIdentityHash() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006957 return IsJSProxy()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006958 ? JSProxy::cast(this)->GetIdentityHash()
6959 : JSObject::cast(this)->GetIdentityHash();
Steve Blockd0582a62009-12-15 09:54:21 +00006960}
6961
6962
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006963Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
6964 if (object->IsJSProxy()) {
6965 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6966 return JSProxy::HasElementWithHandler(proxy, index);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006967 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006968 Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
6969 Handle<JSObject>::cast(object), object, index, true);
6970 if (!result.has_value) return Maybe<bool>();
6971 return maybe(result.value != ABSENT);
6972}
6973
6974
6975Maybe<bool> JSReceiver::HasOwnElement(Handle<JSReceiver> object,
6976 uint32_t index) {
6977 if (object->IsJSProxy()) {
6978 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6979 return JSProxy::HasElementWithHandler(proxy, index);
6980 }
6981 Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
6982 Handle<JSObject>::cast(object), object, index, false);
6983 if (!result.has_value) return Maybe<bool>();
6984 return maybe(result.value != ABSENT);
6985}
6986
6987
6988Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttribute(
6989 Handle<JSReceiver> object, uint32_t index) {
6990 if (object->IsJSProxy()) {
6991 return JSProxy::GetElementAttributeWithHandler(
6992 Handle<JSProxy>::cast(object), object, index);
6993 }
6994 return JSObject::GetElementAttributeWithReceiver(
6995 Handle<JSObject>::cast(object), object, index, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00006996}
6997
6998
6999bool AccessorInfo::all_can_read() {
7000 return BooleanBit::get(flag(), kAllCanReadBit);
7001}
7002
7003
7004void AccessorInfo::set_all_can_read(bool value) {
7005 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
7006}
7007
7008
7009bool AccessorInfo::all_can_write() {
7010 return BooleanBit::get(flag(), kAllCanWriteBit);
7011}
7012
7013
7014void AccessorInfo::set_all_can_write(bool value) {
7015 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
7016}
7017
7018
Steve Blocka7e24c12009-10-30 11:49:00 +00007019PropertyAttributes AccessorInfo::property_attributes() {
7020 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
7021}
7022
7023
7024void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
Ben Murdoch589d6972011-11-30 16:04:58 +00007025 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
Steve Blocka7e24c12009-10-30 11:49:00 +00007026}
7027
Ben Murdoch8b112d22011-06-08 16:22:53 +01007028
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007029bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
7030 if (!HasExpectedReceiverType()) return true;
7031 if (!receiver->IsJSObject()) return false;
7032 return FunctionTemplateInfo::cast(expected_receiver_type())
7033 ->IsTemplateFor(JSObject::cast(receiver)->map());
7034}
7035
7036
7037void ExecutableAccessorInfo::clear_setter() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007038 auto foreign = GetIsolate()->factory()->NewForeign(
7039 reinterpret_cast<v8::internal::Address>(
7040 reinterpret_cast<intptr_t>(nullptr)));
7041 set_setter(*foreign);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007042}
7043
7044
7045template<typename Derived, typename Shape, typename Key>
7046void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
7047 Handle<Object> key,
7048 Handle<Object> value) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01007049 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
7050}
7051
7052
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007053template<typename Derived, typename Shape, typename Key>
7054void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
7055 Handle<Object> key,
7056 Handle<Object> value,
7057 PropertyDetails details) {
7058 DCHECK(!key->IsName() ||
7059 details.IsDeleted() ||
7060 details.dictionary_index() > 0);
7061 int index = DerivedHashTable::EntryToIndex(entry);
7062 DisallowHeapAllocation no_gc;
Leon Clarke4515c472010-02-03 11:58:03 +00007063 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007064 FixedArray::set(index, *key, mode);
7065 FixedArray::set(index+1, *value, mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007066 FixedArray::set(index+2, details.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00007067}
7068
7069
Steve Block44f0eee2011-05-26 01:26:41 +01007070bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007071 DCHECK(other->IsNumber());
Steve Block44f0eee2011-05-26 01:26:41 +01007072 return key == static_cast<uint32_t>(other->Number());
7073}
7074
7075
Ben Murdochc7cc0282012-03-05 14:35:55 +00007076uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
7077 return ComputeIntegerHash(key, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01007078}
7079
7080
Ben Murdochc7cc0282012-03-05 14:35:55 +00007081uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
7082 Object* other) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007083 DCHECK(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00007084 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
Steve Block44f0eee2011-05-26 01:26:41 +01007085}
7086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007087
Ben Murdochc7cc0282012-03-05 14:35:55 +00007088uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
7089 return ComputeIntegerHash(key, seed);
7090}
7091
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007092
Ben Murdochc7cc0282012-03-05 14:35:55 +00007093uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
7094 uint32_t seed,
7095 Object* other) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007096 DCHECK(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00007097 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
7098}
Steve Block44f0eee2011-05-26 01:26:41 +01007099
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007100
7101Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) {
7102 return isolate->factory()->NewNumberFromUint(key);
Steve Block44f0eee2011-05-26 01:26:41 +01007103}
7104
7105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007106bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
Steve Block44f0eee2011-05-26 01:26:41 +01007107 // We know that all entries in a hash table had their hash keys created.
7108 // Use that knowledge to have fast failure.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007109 if (key->Hash() != Name::cast(other)->Hash()) return false;
7110 return key->Equals(Name::cast(other));
Steve Block44f0eee2011-05-26 01:26:41 +01007111}
7112
7113
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007114uint32_t NameDictionaryShape::Hash(Handle<Name> key) {
Steve Block44f0eee2011-05-26 01:26:41 +01007115 return key->Hash();
7116}
7117
7118
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007119uint32_t NameDictionaryShape::HashForObject(Handle<Name> key, Object* other) {
7120 return Name::cast(other)->Hash();
Steve Block44f0eee2011-05-26 01:26:41 +01007121}
7122
7123
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007124Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
7125 Handle<Name> key) {
7126 DCHECK(key->IsUniqueName());
Steve Block44f0eee2011-05-26 01:26:41 +01007127 return key;
7128}
7129
7130
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007131Handle<FixedArray> NameDictionary::DoGenerateNewEnumerationIndices(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007132 Handle<NameDictionary> dictionary) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007133 return DerivedDictionary::GenerateNewEnumerationIndices(dictionary);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007134}
7135
7136
7137bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) {
7138 return key->SameValue(other);
7139}
7140
7141
7142uint32_t ObjectHashTableShape::Hash(Handle<Object> key) {
7143 return Smi::cast(key->GetHash())->value();
7144}
7145
7146
7147uint32_t ObjectHashTableShape::HashForObject(Handle<Object> key,
7148 Object* other) {
7149 return Smi::cast(other->GetHash())->value();
7150}
7151
7152
7153Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate,
7154 Handle<Object> key) {
7155 return key;
7156}
7157
7158
7159Handle<ObjectHashTable> ObjectHashTable::Shrink(
7160 Handle<ObjectHashTable> table, Handle<Object> key) {
7161 return DerivedHashTable::Shrink(table, key);
7162}
7163
7164
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007165template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007166bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007167 return key->SameValue(other);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007168}
7169
7170
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007171template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007172uint32_t WeakHashTableShape<entrysize>::Hash(Handle<Object> key) {
7173 intptr_t hash = reinterpret_cast<intptr_t>(*key);
7174 return (uint32_t)(hash & 0xFFFFFFFF);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007175}
7176
7177
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007178template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007179uint32_t WeakHashTableShape<entrysize>::HashForObject(Handle<Object> key,
7180 Object* other) {
7181 intptr_t hash = reinterpret_cast<intptr_t>(other);
7182 return (uint32_t)(hash & 0xFFFFFFFF);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007183}
7184
7185
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007186template <int entrysize>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007187Handle<Object> WeakHashTableShape<entrysize>::AsHandle(Isolate* isolate,
7188 Handle<Object> key) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007189 return key;
7190}
7191
7192
Steve Block44f0eee2011-05-26 01:26:41 +01007193void Map::ClearCodeCache(Heap* heap) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007194 // No write barrier is needed since empty_fixed_array is not in new space.
7195 // Please note this function is used during marking:
7196 // - MarkCompactCollector::MarkUnmarkedObject
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007197 // - IncrementalMarking::Step
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007198 DCHECK(!heap->InNewSpace(heap->empty_fixed_array()));
7199 WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00007200}
7201
7202
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007203int Map::SlackForArraySize(int old_size, int size_limit) {
7204 const int max_slack = size_limit - old_size;
7205 CHECK(max_slack >= 0);
7206 if (old_size < 4) return Min(max_slack, 1);
7207 return Min(max_slack, old_size / 2);
7208}
7209
7210
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007211void JSArray::EnsureSize(Handle<JSArray> array, int required_size) {
7212 DCHECK(array->HasFastSmiOrObjectElements());
7213 Handle<FixedArray> elts = handle(FixedArray::cast(array->elements()));
Steve Blockd0582a62009-12-15 09:54:21 +00007214 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
7215 if (elts->length() < required_size) {
7216 // Doubling in size would be overkill, but leave some slack to avoid
7217 // constantly growing.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007218 Expand(array, required_size + (required_size >> 3));
Steve Blockd0582a62009-12-15 09:54:21 +00007219 // It's a performance benefit to keep a frequently used array in new-space.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007220 } else if (!array->GetHeap()->new_space()->Contains(*elts) &&
Steve Blockd0582a62009-12-15 09:54:21 +00007221 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
7222 // Expand will allocate a new backing store in new space even if the size
7223 // we asked for isn't larger than what we had before.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007224 Expand(array, required_size);
Steve Blockd0582a62009-12-15 09:54:21 +00007225 }
Steve Blocka7e24c12009-10-30 11:49:00 +00007226}
7227
7228
Leon Clarke4515c472010-02-03 11:58:03 +00007229void JSArray::set_length(Smi* length) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007230 // Don't need a write barrier for a Smi.
Leon Clarke4515c472010-02-03 11:58:03 +00007231 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
7232}
7233
7234
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007235bool JSArray::AllowsSetElementsLength() {
7236 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007237 DCHECK(result == !HasExternalArrayElements());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007238 return result;
7239}
7240
7241
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007242void JSArray::SetContent(Handle<JSArray> array,
7243 Handle<FixedArrayBase> storage) {
7244 EnsureCanContainElements(array, storage, storage->length(),
7245 ALLOW_COPIED_DOUBLE_ELEMENTS);
7246
7247 DCHECK((storage->map() == array->GetHeap()->fixed_double_array_map() &&
7248 IsFastDoubleElementsKind(array->GetElementsKind())) ||
7249 ((storage->map() != array->GetHeap()->fixed_double_array_map()) &&
7250 (IsFastObjectElementsKind(array->GetElementsKind()) ||
7251 (IsFastSmiElementsKind(array->GetElementsKind()) &&
7252 Handle<FixedArray>::cast(storage)->ContainsOnlySmisOrHoles()))));
7253 array->set_elements(*storage);
7254 array->set_length(Smi::FromInt(storage->length()));
Steve Blocka7e24c12009-10-30 11:49:00 +00007255}
7256
7257
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007258int TypeFeedbackInfo::ic_total_count() {
7259 int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7260 return ICTotalCountField::decode(current);
Steve Block44f0eee2011-05-26 01:26:41 +01007261}
7262
7263
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007264void TypeFeedbackInfo::set_ic_total_count(int count) {
7265 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7266 value = ICTotalCountField::update(value,
7267 ICTotalCountField::decode(count));
7268 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007269}
7270
7271
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007272int TypeFeedbackInfo::ic_with_type_info_count() {
7273 int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7274 return ICsWithTypeInfoCountField::decode(current);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007275}
7276
7277
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007278void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) {
7279 if (delta == 0) return;
7280 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7281 int new_count = ICsWithTypeInfoCountField::decode(value) + delta;
7282 // We can get negative count here when the type-feedback info is
7283 // shared between two code objects. The can only happen when
7284 // the debugger made a shallow copy of code object (see Heap::CopyCode).
7285 // Since we do not optimize when the debugger is active, we can skip
7286 // this counter update.
7287 if (new_count >= 0) {
7288 new_count &= ICsWithTypeInfoCountField::kMask;
7289 value = ICsWithTypeInfoCountField::update(value, new_count);
7290 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
7291 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007292}
7293
7294
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007295int TypeFeedbackInfo::ic_generic_count() {
7296 return Smi::cast(READ_FIELD(this, kStorage3Offset))->value();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007297}
7298
7299
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007300void TypeFeedbackInfo::change_ic_generic_count(int delta) {
7301 if (delta == 0) return;
7302 int new_count = ic_generic_count() + delta;
7303 if (new_count >= 0) {
7304 new_count &= ~Smi::kMinValue;
7305 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(new_count));
7306 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007307}
7308
7309
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007310void TypeFeedbackInfo::initialize_storage() {
7311 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0));
7312 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0));
7313 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(0));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007314}
7315
7316
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007317void TypeFeedbackInfo::change_own_type_change_checksum() {
7318 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7319 int checksum = OwnTypeChangeChecksum::decode(value);
7320 checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits);
7321 value = OwnTypeChangeChecksum::update(value, checksum);
7322 // Ensure packed bit field is in Smi range.
7323 if (value > Smi::kMaxValue) value |= Smi::kMinValue;
7324 if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
7325 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007326}
7327
7328
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007329void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) {
7330 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7331 int mask = (1 << kTypeChangeChecksumBits) - 1;
7332 value = InlinedTypeChangeChecksum::update(value, checksum & mask);
7333 // Ensure packed bit field is in Smi range.
7334 if (value > Smi::kMaxValue) value |= Smi::kMinValue;
7335 if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
7336 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007337}
7338
7339
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007340int TypeFeedbackInfo::own_type_change_checksum() {
7341 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7342 return OwnTypeChangeChecksum::decode(value);
7343}
7344
7345
7346bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
7347 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7348 int mask = (1 << kTypeChangeChecksumBits) - 1;
7349 return InlinedTypeChangeChecksum::decode(value) == (checksum & mask);
7350}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007351
7352
7353SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
7354
7355
Steve Block44f0eee2011-05-26 01:26:41 +01007356Relocatable::Relocatable(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01007357 isolate_ = isolate;
7358 prev_ = isolate->relocatable_top();
7359 isolate->set_relocatable_top(this);
7360}
7361
7362
7363Relocatable::~Relocatable() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007364 DCHECK_EQ(isolate_->relocatable_top(), this);
Steve Block44f0eee2011-05-26 01:26:41 +01007365 isolate_->set_relocatable_top(prev_);
Steve Blocka7e24c12009-10-30 11:49:00 +00007366}
7367
7368
Iain Merrick75681382010-08-19 15:07:18 +01007369int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
7370 return map->instance_size();
7371}
7372
7373
Ben Murdoch257744e2011-11-30 15:57:28 +00007374void Foreign::ForeignIterateBody(ObjectVisitor* v) {
Iain Merrick75681382010-08-19 15:07:18 +01007375 v->VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007376 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01007377}
7378
7379
7380template<typename StaticVisitor>
Ben Murdoch257744e2011-11-30 15:57:28 +00007381void Foreign::ForeignIterateBody() {
Iain Merrick75681382010-08-19 15:07:18 +01007382 StaticVisitor::VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007383 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01007384}
7385
7386
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007387void ExternalOneByteString::ExternalOneByteStringIterateBody(ObjectVisitor* v) {
7388 typedef v8::String::ExternalOneByteStringResource Resource;
7389 v->VisitExternalOneByteString(
Iain Merrick75681382010-08-19 15:07:18 +01007390 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7391}
7392
7393
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007394template <typename StaticVisitor>
7395void ExternalOneByteString::ExternalOneByteStringIterateBody() {
7396 typedef v8::String::ExternalOneByteStringResource Resource;
7397 StaticVisitor::VisitExternalOneByteString(
Iain Merrick75681382010-08-19 15:07:18 +01007398 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7399}
7400
7401
7402void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
7403 typedef v8::String::ExternalStringResource Resource;
7404 v->VisitExternalTwoByteString(
7405 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7406}
7407
7408
7409template<typename StaticVisitor>
7410void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
7411 typedef v8::String::ExternalStringResource Resource;
7412 StaticVisitor::VisitExternalTwoByteString(
7413 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7414}
7415
Iain Merrick75681382010-08-19 15:07:18 +01007416
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007417static inline void IterateBodyUsingLayoutDescriptor(HeapObject* object,
7418 int start_offset,
7419 int end_offset,
7420 ObjectVisitor* v) {
7421 DCHECK(FLAG_unbox_double_fields);
7422 DCHECK(IsAligned(start_offset, kPointerSize) &&
7423 IsAligned(end_offset, kPointerSize));
7424
7425 LayoutDescriptorHelper helper(object->map());
7426 DCHECK(!helper.all_fields_tagged());
7427
7428 for (int offset = start_offset; offset < end_offset; offset += kPointerSize) {
7429 // Visit all tagged fields.
7430 if (helper.IsTagged(offset)) {
7431 v->VisitPointer(HeapObject::RawField(object, offset));
7432 }
7433 }
7434}
7435
7436
Iain Merrick75681382010-08-19 15:07:18 +01007437template<int start_offset, int end_offset, int size>
7438void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
7439 HeapObject* obj,
7440 ObjectVisitor* v) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007441 if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007442 v->VisitPointers(HeapObject::RawField(obj, start_offset),
7443 HeapObject::RawField(obj, end_offset));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007444 } else {
7445 IterateBodyUsingLayoutDescriptor(obj, start_offset, end_offset, v);
7446 }
Iain Merrick75681382010-08-19 15:07:18 +01007447}
7448
7449
7450template<int start_offset>
7451void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
7452 int object_size,
7453 ObjectVisitor* v) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007454 if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
7455 v->VisitPointers(HeapObject::RawField(obj, start_offset),
7456 HeapObject::RawField(obj, object_size));
7457 } else {
7458 IterateBodyUsingLayoutDescriptor(obj, start_offset, object_size, v);
7459 }
Iain Merrick75681382010-08-19 15:07:18 +01007460}
7461
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007462
7463template<class Derived, class TableType>
7464Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
7465 TableType* table(TableType::cast(this->table()));
7466 int index = Smi::cast(this->index())->value();
7467 Object* key = table->KeyAt(index);
7468 DCHECK(!key->IsTheHole());
7469 return key;
7470}
7471
7472
7473void JSSetIterator::PopulateValueArray(FixedArray* array) {
7474 array->set(0, CurrentKey());
7475}
7476
7477
7478void JSMapIterator::PopulateValueArray(FixedArray* array) {
7479 array->set(0, CurrentKey());
7480 array->set(1, CurrentValue());
7481}
7482
7483
7484Object* JSMapIterator::CurrentValue() {
7485 OrderedHashMap* table(OrderedHashMap::cast(this->table()));
7486 int index = Smi::cast(this->index())->value();
7487 Object* value = table->ValueAt(index);
7488 DCHECK(!value->IsTheHole());
7489 return value;
7490}
7491
Iain Merrick75681382010-08-19 15:07:18 +01007492
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007493#undef TYPE_CHECKER
Steve Blocka7e24c12009-10-30 11:49:00 +00007494#undef CAST_ACCESSOR
7495#undef INT_ACCESSORS
Ben Murdoch85b71792012-04-11 18:30:58 +01007496#undef ACCESSORS
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007497#undef ACCESSORS_TO_SMI
7498#undef SMI_ACCESSORS
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007499#undef SYNCHRONIZED_SMI_ACCESSORS
7500#undef NOBARRIER_SMI_ACCESSORS
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007501#undef BOOL_GETTER
7502#undef BOOL_ACCESSORS
Steve Blocka7e24c12009-10-30 11:49:00 +00007503#undef FIELD_ADDR
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007504#undef FIELD_ADDR_CONST
Steve Blocka7e24c12009-10-30 11:49:00 +00007505#undef READ_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007506#undef NOBARRIER_READ_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007507#undef WRITE_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007508#undef NOBARRIER_WRITE_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007509#undef WRITE_BARRIER
7510#undef CONDITIONAL_WRITE_BARRIER
Steve Blocka7e24c12009-10-30 11:49:00 +00007511#undef READ_DOUBLE_FIELD
7512#undef WRITE_DOUBLE_FIELD
7513#undef READ_INT_FIELD
7514#undef WRITE_INT_FIELD
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007515#undef READ_INTPTR_FIELD
7516#undef WRITE_INTPTR_FIELD
7517#undef READ_UINT32_FIELD
7518#undef WRITE_UINT32_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007519#undef READ_SHORT_FIELD
7520#undef WRITE_SHORT_FIELD
7521#undef READ_BYTE_FIELD
7522#undef WRITE_BYTE_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007523#undef NOBARRIER_READ_BYTE_FIELD
7524#undef NOBARRIER_WRITE_BYTE_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00007525
7526} } // namespace v8::internal
7527
7528#endif // V8_OBJECTS_INL_H_