blob: 68feda46b47ad35317b0d62d0e24ce49dc6e9815 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27//
28// Review notes:
29//
30// - The use of macros in these inline functions may seem superfluous
31// but it is absolutely needed to make sure gcc generates optimal
32// code. gcc is not happy when attempting to inline too deep.
33//
34
35#ifndef V8_OBJECTS_INL_H_
36#define V8_OBJECTS_INL_H_
37
Ben Murdoch69a99ed2011-11-30 16:03:39 +000038#include "elements.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010039#include "objects.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "contexts.h"
41#include "conversions-inl.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010042#include "heap.h"
Steve Block44f0eee2011-05-26 01:26:41 +010043#include "isolate.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000044#include "property.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010045#include "spaces.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +010046#include "store-buffer.h"
Steve Block44f0eee2011-05-26 01:26:41 +010047#include "v8memory.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +010048#include "factory.h"
49#include "incremental-marking.h"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000050
Steve Blocka7e24c12009-10-30 11:49:00 +000051namespace v8 {
52namespace internal {
53
54PropertyDetails::PropertyDetails(Smi* smi) {
55 value_ = smi->value();
56}
57
58
59Smi* PropertyDetails::AsSmi() {
60 return Smi::FromInt(value_);
61}
62
63
64PropertyDetails PropertyDetails::AsDeleted() {
Steve Block1e0659c2011-05-24 12:43:12 +010065 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000066 return PropertyDetails(smi);
67}
68
69
Ben Murdoch3ef787d2012-04-12 10:51:47 +010070#define TYPE_CHECKER(type, instancetype) \
71 bool Object::Is##type() { \
72 return Object::IsHeapObject() && \
73 HeapObject::cast(this)->map()->instance_type() == instancetype; \
74 }
75
76
Steve Blocka7e24c12009-10-30 11:49:00 +000077#define CAST_ACCESSOR(type) \
78 type* type::cast(Object* object) { \
79 ASSERT(object->Is##type()); \
80 return reinterpret_cast<type*>(object); \
81 }
82
83
84#define INT_ACCESSORS(holder, name, offset) \
85 int holder::name() { return READ_INT_FIELD(this, offset); } \
86 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
87
88
89#define ACCESSORS(holder, name, type, offset) \
90 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
91 void holder::set_##name(type* value, WriteBarrierMode mode) { \
92 WRITE_FIELD(this, offset, value); \
Ben Murdoch3ef787d2012-04-12 10:51:47 +010093 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
Steve Blocka7e24c12009-10-30 11:49:00 +000094 }
95
96
Ben Murdoch3ef787d2012-04-12 10:51:47 +010097// Getter that returns a tagged Smi and setter that writes a tagged Smi.
98#define ACCESSORS_TO_SMI(holder, name, offset) \
99 Smi* holder::name() { return Smi::cast(READ_FIELD(this, offset)); } \
100 void holder::set_##name(Smi* value, WriteBarrierMode mode) { \
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100101 WRITE_FIELD(this, offset, value); \
102 }
103
104
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100105// Getter that returns a Smi as an int and writes an int as a Smi.
Steve Blocka7e24c12009-10-30 11:49:00 +0000106#define SMI_ACCESSORS(holder, name, offset) \
107 int holder::name() { \
108 Object* value = READ_FIELD(this, offset); \
109 return Smi::cast(value)->value(); \
110 } \
111 void holder::set_##name(int value) { \
112 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
113 }
114
115
116#define BOOL_GETTER(holder, field, name, offset) \
117 bool holder::name() { \
118 return BooleanBit::get(field(), offset); \
119 } \
120
121
122#define BOOL_ACCESSORS(holder, field, name, offset) \
123 bool holder::name() { \
124 return BooleanBit::get(field(), offset); \
125 } \
126 void holder::set_##name(bool value) { \
127 set_##field(BooleanBit::set(field(), offset, value)); \
128 }
129
130
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100131bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
132 ElementsKind to_kind) {
133 if (to_kind == FAST_ELEMENTS) {
134 return from_kind == FAST_SMI_ONLY_ELEMENTS ||
135 from_kind == FAST_DOUBLE_ELEMENTS;
136 } else {
137 return to_kind == FAST_DOUBLE_ELEMENTS &&
138 from_kind == FAST_SMI_ONLY_ELEMENTS;
139 }
140}
141
142
143bool Object::IsFixedArrayBase() {
144 return IsFixedArray() || IsFixedDoubleArray();
145}
146
147
Steve Blocka7e24c12009-10-30 11:49:00 +0000148bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
149 // There is a constraint on the object; check.
150 if (!this->IsJSObject()) return false;
151 // Fetch the constructor function of the object.
152 Object* cons_obj = JSObject::cast(this)->map()->constructor();
153 if (!cons_obj->IsJSFunction()) return false;
154 JSFunction* fun = JSFunction::cast(cons_obj);
155 // Iterate through the chain of inheriting function templates to
156 // see if the required one occurs.
157 for (Object* type = fun->shared()->function_data();
158 type->IsFunctionTemplateInfo();
159 type = FunctionTemplateInfo::cast(type)->parent_template()) {
160 if (type == expected) return true;
161 }
162 // Didn't find the required type in the inheritance chain.
163 return false;
164}
165
166
167bool Object::IsSmi() {
168 return HAS_SMI_TAG(this);
169}
170
171
172bool Object::IsHeapObject() {
173 return Internals::HasHeapObjectTag(this);
174}
175
176
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100177bool Object::NonFailureIsHeapObject() {
178 ASSERT(!this->IsFailure());
179 return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000180}
181
182
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100183TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
184
185
Steve Blocka7e24c12009-10-30 11:49:00 +0000186bool Object::IsString() {
187 return Object::IsHeapObject()
188 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
189}
190
191
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000192bool Object::IsSpecObject() {
193 return Object::IsHeapObject()
194 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
195}
196
197
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100198bool Object::IsSpecFunction() {
199 if (!Object::IsHeapObject()) return false;
200 InstanceType type = HeapObject::cast(this)->map()->instance_type();
201 return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
202}
203
204
Steve Blocka7e24c12009-10-30 11:49:00 +0000205bool Object::IsSymbol() {
206 if (!this->IsHeapObject()) return false;
207 uint32_t type = HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000208 // Because the symbol tag is non-zero and no non-string types have the
209 // symbol bit set we can test for symbols with a very simple test
210 // operation.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000211 STATIC_ASSERT(kSymbolTag != 0);
Leon Clarkee46be812010-01-19 14:06:41 +0000212 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
213 return (type & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000214}
215
216
217bool Object::IsConsString() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000218 if (!IsString()) return false;
219 return StringShape(String::cast(this)).IsCons();
220}
221
222
223bool Object::IsSlicedString() {
224 if (!IsString()) return false;
225 return StringShape(String::cast(this)).IsSliced();
Steve Blocka7e24c12009-10-30 11:49:00 +0000226}
227
228
Steve Blocka7e24c12009-10-30 11:49:00 +0000229bool Object::IsSeqString() {
230 if (!IsString()) return false;
231 return StringShape(String::cast(this)).IsSequential();
232}
233
234
235bool Object::IsSeqAsciiString() {
236 if (!IsString()) return false;
237 return StringShape(String::cast(this)).IsSequential() &&
238 String::cast(this)->IsAsciiRepresentation();
239}
240
241
242bool Object::IsSeqTwoByteString() {
243 if (!IsString()) return false;
244 return StringShape(String::cast(this)).IsSequential() &&
245 String::cast(this)->IsTwoByteRepresentation();
246}
247
248
249bool Object::IsExternalString() {
250 if (!IsString()) return false;
251 return StringShape(String::cast(this)).IsExternal();
252}
253
254
255bool Object::IsExternalAsciiString() {
256 if (!IsString()) return false;
257 return StringShape(String::cast(this)).IsExternal() &&
258 String::cast(this)->IsAsciiRepresentation();
259}
260
261
262bool Object::IsExternalTwoByteString() {
263 if (!IsString()) return false;
264 return StringShape(String::cast(this)).IsExternal() &&
265 String::cast(this)->IsTwoByteRepresentation();
266}
267
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000268bool Object::HasValidElements() {
269 // Dictionary is covered under FixedArray.
270 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
271}
Steve Blocka7e24c12009-10-30 11:49:00 +0000272
Steve Blocka7e24c12009-10-30 11:49:00 +0000273StringShape::StringShape(String* str)
274 : type_(str->map()->instance_type()) {
275 set_valid();
276 ASSERT((type_ & kIsNotStringMask) == kStringTag);
277}
278
279
280StringShape::StringShape(Map* map)
281 : type_(map->instance_type()) {
282 set_valid();
283 ASSERT((type_ & kIsNotStringMask) == kStringTag);
284}
285
286
287StringShape::StringShape(InstanceType t)
288 : type_(static_cast<uint32_t>(t)) {
289 set_valid();
290 ASSERT((type_ & kIsNotStringMask) == kStringTag);
291}
292
293
294bool StringShape::IsSymbol() {
295 ASSERT(valid());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000296 STATIC_ASSERT(kSymbolTag != 0);
Leon Clarkee46be812010-01-19 14:06:41 +0000297 return (type_ & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000298}
299
300
301bool String::IsAsciiRepresentation() {
302 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 return (type & kStringEncodingMask) == kAsciiStringTag;
304}
305
306
307bool String::IsTwoByteRepresentation() {
308 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 return (type & kStringEncodingMask) == kTwoByteStringTag;
310}
311
312
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000313bool String::IsAsciiRepresentationUnderneath() {
314 uint32_t type = map()->instance_type();
315 STATIC_ASSERT(kIsIndirectStringTag != 0);
316 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
317 ASSERT(IsFlat());
318 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
319 case kAsciiStringTag:
320 return true;
321 case kTwoByteStringTag:
322 return false;
323 default: // Cons or sliced string. Need to go deeper.
324 return GetUnderlying()->IsAsciiRepresentation();
325 }
326}
327
328
329bool String::IsTwoByteRepresentationUnderneath() {
330 uint32_t type = map()->instance_type();
331 STATIC_ASSERT(kIsIndirectStringTag != 0);
332 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
333 ASSERT(IsFlat());
334 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
335 case kAsciiStringTag:
336 return false;
337 case kTwoByteStringTag:
338 return true;
339 default: // Cons or sliced string. Need to go deeper.
340 return GetUnderlying()->IsTwoByteRepresentation();
341 }
342}
343
344
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100345bool String::HasOnlyAsciiChars() {
346 uint32_t type = map()->instance_type();
347 return (type & kStringEncodingMask) == kAsciiStringTag ||
348 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
Steve Block6ded16b2010-05-10 14:33:55 +0100349}
350
351
Steve Blocka7e24c12009-10-30 11:49:00 +0000352bool StringShape::IsCons() {
353 return (type_ & kStringRepresentationMask) == kConsStringTag;
354}
355
356
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000357bool StringShape::IsSliced() {
358 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
359}
360
361
362bool StringShape::IsIndirect() {
363 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
364}
365
366
Steve Blocka7e24c12009-10-30 11:49:00 +0000367bool StringShape::IsExternal() {
368 return (type_ & kStringRepresentationMask) == kExternalStringTag;
369}
370
371
372bool StringShape::IsSequential() {
373 return (type_ & kStringRepresentationMask) == kSeqStringTag;
374}
375
376
377StringRepresentationTag StringShape::representation_tag() {
378 uint32_t tag = (type_ & kStringRepresentationMask);
379 return static_cast<StringRepresentationTag>(tag);
380}
381
382
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000383uint32_t StringShape::encoding_tag() {
384 return type_ & kStringEncodingMask;
385}
386
387
Steve Blocka7e24c12009-10-30 11:49:00 +0000388uint32_t StringShape::full_representation_tag() {
389 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
390}
391
392
393STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
394 Internals::kFullStringRepresentationMask);
395
396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397bool StringShape::IsSequentialAscii() {
398 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
399}
400
401
402bool StringShape::IsSequentialTwoByte() {
403 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
404}
405
406
407bool StringShape::IsExternalAscii() {
408 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
409}
410
411
412bool StringShape::IsExternalTwoByte() {
413 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
414}
415
416
417STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
418 Internals::kExternalTwoByteRepresentationTag);
419
420
421uc32 FlatStringReader::Get(int index) {
422 ASSERT(0 <= index && index <= length_);
423 if (is_ascii_) {
424 return static_cast<const byte*>(start_)[index];
425 } else {
426 return static_cast<const uc16*>(start_)[index];
427 }
428}
429
430
431bool Object::IsNumber() {
432 return IsSmi() || IsHeapNumber();
433}
434
435
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100436TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
437TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
438
439
440bool Object::IsFiller() {
441 if (!Object::IsHeapObject()) return false;
442 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
443 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000444}
445
446
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100447TYPE_CHECKER(ExternalPixelArray, EXTERNAL_PIXEL_ARRAY_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000448
449
Steve Block3ce2e202009-11-05 08:53:23 +0000450bool Object::IsExternalArray() {
451 if (!Object::IsHeapObject())
452 return false;
453 InstanceType instance_type =
454 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000455 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
456 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000457}
458
459
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100460TYPE_CHECKER(ExternalByteArray, EXTERNAL_BYTE_ARRAY_TYPE)
461TYPE_CHECKER(ExternalUnsignedByteArray, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
462TYPE_CHECKER(ExternalShortArray, EXTERNAL_SHORT_ARRAY_TYPE)
463TYPE_CHECKER(ExternalUnsignedShortArray, EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
464TYPE_CHECKER(ExternalIntArray, EXTERNAL_INT_ARRAY_TYPE)
465TYPE_CHECKER(ExternalUnsignedIntArray, EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
466TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
467TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
Ben Murdoch257744e2011-11-30 15:57:28 +0000468
469
John Reck59135872010-11-02 12:39:01 -0700470bool MaybeObject::IsFailure() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000471 return HAS_FAILURE_TAG(this);
472}
473
474
John Reck59135872010-11-02 12:39:01 -0700475bool MaybeObject::IsRetryAfterGC() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000476 return HAS_FAILURE_TAG(this)
477 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
478}
479
480
John Reck59135872010-11-02 12:39:01 -0700481bool MaybeObject::IsOutOfMemory() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 return HAS_FAILURE_TAG(this)
Steve Block1e0659c2011-05-24 12:43:12 +0100483 && Failure::cast(this)->IsOutOfMemoryException();
Steve Blocka7e24c12009-10-30 11:49:00 +0000484}
485
486
John Reck59135872010-11-02 12:39:01 -0700487bool MaybeObject::IsException() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 return this == Failure::Exception();
489}
490
491
John Reck59135872010-11-02 12:39:01 -0700492bool MaybeObject::IsTheHole() {
Steve Block44f0eee2011-05-26 01:26:41 +0100493 return !IsFailure() && ToObjectUnchecked()->IsTheHole();
John Reck59135872010-11-02 12:39:01 -0700494}
495
496
497Failure* Failure::cast(MaybeObject* obj) {
498 ASSERT(HAS_FAILURE_TAG(obj));
499 return reinterpret_cast<Failure*>(obj);
500}
501
502
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000503bool Object::IsJSReceiver() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100504 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000505 return IsHeapObject() &&
506 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
507}
508
509
Steve Blocka7e24c12009-10-30 11:49:00 +0000510bool Object::IsJSObject() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100511 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
512 return IsHeapObject() &&
513 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000514}
515
516
517bool Object::IsJSProxy() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100518 if (!Object::IsHeapObject()) return false;
519 InstanceType type = HeapObject::cast(this)->map()->instance_type();
520 return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000521}
522
523
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100524TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
525TYPE_CHECKER(JSSet, JS_SET_TYPE)
526TYPE_CHECKER(JSMap, JS_MAP_TYPE)
527TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
528TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
529TYPE_CHECKER(Map, MAP_TYPE)
530TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
531TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000532
533
Steve Blocka7e24c12009-10-30 11:49:00 +0000534bool Object::IsDescriptorArray() {
535 return IsFixedArray();
536}
537
538
Ben Murdochb0fe1622011-05-05 13:52:32 +0100539bool Object::IsDeoptimizationInputData() {
540 // Must be a fixed array.
541 if (!IsFixedArray()) return false;
542
543 // There's no sure way to detect the difference between a fixed array and
544 // a deoptimization data array. Since this is used for asserts we can
545 // check that the length is zero or else the fixed size plus a multiple of
546 // the entry size.
547 int length = FixedArray::cast(this)->length();
548 if (length == 0) return true;
549
550 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
551 return length >= 0 &&
552 length % DeoptimizationInputData::kDeoptEntrySize == 0;
553}
554
555
556bool Object::IsDeoptimizationOutputData() {
557 if (!IsFixedArray()) return false;
558 // There's actually no way to see the difference between a fixed array and
559 // a deoptimization data array. Since this is used for asserts we can check
560 // that the length is plausible though.
561 if (FixedArray::cast(this)->length() % 2 != 0) return false;
562 return true;
563}
564
565
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100566bool Object::IsTypeFeedbackCells() {
567 if (!IsFixedArray()) return false;
568 // There's actually no way to see the difference between a fixed array and
569 // a cache cells array. Since this is used for asserts we can check that
570 // the length is plausible though.
571 if (FixedArray::cast(this)->length() % 2 != 0) return false;
572 return true;
573}
574
575
Steve Blocka7e24c12009-10-30 11:49:00 +0000576bool Object::IsContext() {
Steve Block44f0eee2011-05-26 01:26:41 +0100577 if (Object::IsHeapObject()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000578 Map* map = HeapObject::cast(this)->map();
579 Heap* heap = map->GetHeap();
580 return (map == heap->function_context_map() ||
581 map == heap->catch_context_map() ||
582 map == heap->with_context_map() ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000583 map == heap->global_context_map() ||
584 map == heap->block_context_map());
Steve Block44f0eee2011-05-26 01:26:41 +0100585 }
586 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000587}
588
589
Steve Blocka7e24c12009-10-30 11:49:00 +0000590bool Object::IsGlobalContext() {
Steve Block44f0eee2011-05-26 01:26:41 +0100591 return Object::IsHeapObject() &&
592 HeapObject::cast(this)->map() ==
593 HeapObject::cast(this)->GetHeap()->global_context_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000594}
595
596
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100597bool Object::IsScopeInfo() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000598 return Object::IsHeapObject() &&
599 HeapObject::cast(this)->map() ==
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100600 HeapObject::cast(this)->GetHeap()->scope_info_map();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000601}
602
603
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100604TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000605
606
607template <> inline bool Is<JSFunction>(Object* obj) {
608 return obj->IsJSFunction();
609}
610
611
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100612TYPE_CHECKER(Code, CODE_TYPE)
613TYPE_CHECKER(Oddball, ODDBALL_TYPE)
614TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
615TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
616TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
617TYPE_CHECKER(JSDate, JS_DATE_TYPE)
618TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000619
620
621bool Object::IsStringWrapper() {
622 return IsJSValue() && JSValue::cast(this)->value()->IsString();
623}
624
625
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100626TYPE_CHECKER(Foreign, FOREIGN_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000627
628
629bool Object::IsBoolean() {
Steve Block44f0eee2011-05-26 01:26:41 +0100630 return IsOddball() &&
631 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000632}
633
634
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100635TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
636TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000637
638
639template <> inline bool Is<JSArray>(Object* obj) {
640 return obj->IsJSArray();
641}
642
643
644bool Object::IsHashTable() {
Steve Block44f0eee2011-05-26 01:26:41 +0100645 return Object::IsHeapObject() &&
646 HeapObject::cast(this)->map() ==
647 HeapObject::cast(this)->GetHeap()->hash_table_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000648}
649
650
651bool Object::IsDictionary() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000652 return IsHashTable() &&
653 this != HeapObject::cast(this)->GetHeap()->symbol_table();
Steve Blocka7e24c12009-10-30 11:49:00 +0000654}
655
656
657bool Object::IsSymbolTable() {
Steve Block44f0eee2011-05-26 01:26:41 +0100658 return IsHashTable() && this ==
659 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
Steve Blocka7e24c12009-10-30 11:49:00 +0000660}
661
662
Steve Block6ded16b2010-05-10 14:33:55 +0100663bool Object::IsJSFunctionResultCache() {
664 if (!IsFixedArray()) return false;
665 FixedArray* self = FixedArray::cast(this);
666 int length = self->length();
667 if (length < JSFunctionResultCache::kEntriesIndex) return false;
668 if ((length - JSFunctionResultCache::kEntriesIndex)
669 % JSFunctionResultCache::kEntrySize != 0) {
670 return false;
671 }
672#ifdef DEBUG
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100673 if (FLAG_verify_heap) {
674 reinterpret_cast<JSFunctionResultCache*>(this)->
675 JSFunctionResultCacheVerify();
676 }
Steve Block6ded16b2010-05-10 14:33:55 +0100677#endif
678 return true;
679}
680
681
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100682bool Object::IsNormalizedMapCache() {
683 if (!IsFixedArray()) return false;
684 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
685 return false;
686 }
687#ifdef DEBUG
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100688 if (FLAG_verify_heap) {
689 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
690 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100691#endif
692 return true;
693}
694
695
Steve Blocka7e24c12009-10-30 11:49:00 +0000696bool Object::IsCompilationCacheTable() {
697 return IsHashTable();
698}
699
700
Steve Block6ded16b2010-05-10 14:33:55 +0100701bool Object::IsCodeCacheHashTable() {
702 return IsHashTable();
703}
704
705
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000706bool Object::IsPolymorphicCodeCacheHashTable() {
707 return IsHashTable();
708}
709
710
Steve Blocka7e24c12009-10-30 11:49:00 +0000711bool Object::IsMapCache() {
712 return IsHashTable();
713}
714
715
716bool Object::IsPrimitive() {
717 return IsOddball() || IsNumber() || IsString();
718}
719
720
721bool Object::IsJSGlobalProxy() {
722 bool result = IsHeapObject() &&
723 (HeapObject::cast(this)->map()->instance_type() ==
724 JS_GLOBAL_PROXY_TYPE);
725 ASSERT(!result || IsAccessCheckNeeded());
726 return result;
727}
728
729
730bool Object::IsGlobalObject() {
731 if (!IsHeapObject()) return false;
732
733 InstanceType type = HeapObject::cast(this)->map()->instance_type();
734 return type == JS_GLOBAL_OBJECT_TYPE ||
735 type == JS_BUILTINS_OBJECT_TYPE;
736}
737
738
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100739TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
740TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000741
742
743bool Object::IsUndetectableObject() {
744 return IsHeapObject()
745 && HeapObject::cast(this)->map()->is_undetectable();
746}
747
748
749bool Object::IsAccessCheckNeeded() {
750 return IsHeapObject()
751 && HeapObject::cast(this)->map()->is_access_check_needed();
752}
753
754
755bool Object::IsStruct() {
756 if (!IsHeapObject()) return false;
757 switch (HeapObject::cast(this)->map()->instance_type()) {
758#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
759 STRUCT_LIST(MAKE_STRUCT_CASE)
760#undef MAKE_STRUCT_CASE
761 default: return false;
762 }
763}
764
765
766#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
767 bool Object::Is##Name() { \
768 return Object::IsHeapObject() \
769 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
770 }
771 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
772#undef MAKE_STRUCT_PREDICATE
773
774
775bool Object::IsUndefined() {
Steve Block44f0eee2011-05-26 01:26:41 +0100776 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
Steve Blocka7e24c12009-10-30 11:49:00 +0000777}
778
779
Steve Blocka7e24c12009-10-30 11:49:00 +0000780bool Object::IsNull() {
Steve Block44f0eee2011-05-26 01:26:41 +0100781 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
782}
783
784
785bool Object::IsTheHole() {
786 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
Steve Blocka7e24c12009-10-30 11:49:00 +0000787}
788
789
790bool Object::IsTrue() {
Steve Block44f0eee2011-05-26 01:26:41 +0100791 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
Steve Blocka7e24c12009-10-30 11:49:00 +0000792}
793
794
795bool Object::IsFalse() {
Steve Block44f0eee2011-05-26 01:26:41 +0100796 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
Steve Blocka7e24c12009-10-30 11:49:00 +0000797}
798
799
Ben Murdoch086aeea2011-05-13 15:57:08 +0100800bool Object::IsArgumentsMarker() {
Steve Block44f0eee2011-05-26 01:26:41 +0100801 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100802}
803
804
Steve Blocka7e24c12009-10-30 11:49:00 +0000805double Object::Number() {
806 ASSERT(IsNumber());
807 return IsSmi()
808 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
809 : reinterpret_cast<HeapNumber*>(this)->value();
810}
811
812
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100813bool Object::IsNaN() {
814 return this->IsHeapNumber() && isnan(HeapNumber::cast(this)->value());
815}
816
817
John Reck59135872010-11-02 12:39:01 -0700818MaybeObject* Object::ToSmi() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000819 if (IsSmi()) return this;
820 if (IsHeapNumber()) {
821 double value = HeapNumber::cast(this)->value();
822 int int_value = FastD2I(value);
823 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
824 return Smi::FromInt(int_value);
825 }
826 }
827 return Failure::Exception();
828}
829
830
831bool Object::HasSpecificClassOf(String* name) {
832 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
833}
834
835
John Reck59135872010-11-02 12:39:01 -0700836MaybeObject* Object::GetElement(uint32_t index) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100837 // GetElement can trigger a getter which can cause allocation.
838 // This was not always the case. This ASSERT is here to catch
839 // leftover incorrect uses.
Steve Block44f0eee2011-05-26 01:26:41 +0100840 ASSERT(HEAP->IsAllocationAllowed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000841 return GetElementWithReceiver(this, index);
842}
843
844
John Reck59135872010-11-02 12:39:01 -0700845Object* Object::GetElementNoExceptionThrown(uint32_t index) {
846 MaybeObject* maybe = GetElementWithReceiver(this, index);
847 ASSERT(!maybe->IsFailure());
848 Object* result = NULL; // Initialization to please compiler.
849 maybe->ToObject(&result);
850 return result;
851}
852
853
854MaybeObject* Object::GetProperty(String* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 PropertyAttributes attributes;
856 return GetPropertyWithReceiver(this, key, &attributes);
857}
858
859
John Reck59135872010-11-02 12:39:01 -0700860MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 return GetPropertyWithReceiver(this, key, attributes);
862}
863
864
865#define FIELD_ADDR(p, offset) \
866 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
867
868#define READ_FIELD(p, offset) \
869 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
870
871#define WRITE_FIELD(p, offset, value) \
872 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
873
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100874#define WRITE_BARRIER(heap, object, offset, value) \
875 heap->incremental_marking()->RecordWrite( \
876 object, HeapObject::RawField(object, offset), value); \
877 if (heap->InNewSpace(value)) { \
878 heap->RecordWrite(object->address(), offset); \
879 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000880
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100881#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
882 if (mode == UPDATE_WRITE_BARRIER) { \
883 heap->incremental_marking()->RecordWrite( \
884 object, HeapObject::RawField(object, offset), value); \
885 if (heap->InNewSpace(value)) { \
886 heap->RecordWrite(object->address(), offset); \
887 } \
Steve Blocka7e24c12009-10-30 11:49:00 +0000888 }
889
Steve Block44f0eee2011-05-26 01:26:41 +0100890#ifndef V8_TARGET_ARCH_MIPS
891 #define READ_DOUBLE_FIELD(p, offset) \
892 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
893#else // V8_TARGET_ARCH_MIPS
894 // Prevent gcc from using load-double (mips ldc1) on (possibly)
895 // non-64-bit aligned HeapNumber::value.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000896 static inline double read_double_field(void* p, int offset) {
Steve Block44f0eee2011-05-26 01:26:41 +0100897 union conversion {
898 double d;
899 uint32_t u[2];
900 } c;
901 c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
902 c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
903 return c.d;
904 }
905 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
906#endif // V8_TARGET_ARCH_MIPS
Steve Blocka7e24c12009-10-30 11:49:00 +0000907
Steve Block44f0eee2011-05-26 01:26:41 +0100908#ifndef V8_TARGET_ARCH_MIPS
909 #define WRITE_DOUBLE_FIELD(p, offset, value) \
910 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
911#else // V8_TARGET_ARCH_MIPS
912 // Prevent gcc from using store-double (mips sdc1) on (possibly)
913 // non-64-bit aligned HeapNumber::value.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000914 static inline void write_double_field(void* p, int offset,
Steve Block44f0eee2011-05-26 01:26:41 +0100915 double value) {
916 union conversion {
917 double d;
918 uint32_t u[2];
919 } c;
920 c.d = value;
921 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
922 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
923 }
924 #define WRITE_DOUBLE_FIELD(p, offset, value) \
925 write_double_field(p, offset, value)
926#endif // V8_TARGET_ARCH_MIPS
927
Steve Blocka7e24c12009-10-30 11:49:00 +0000928
929#define READ_INT_FIELD(p, offset) \
930 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
931
932#define WRITE_INT_FIELD(p, offset, value) \
933 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
934
935#define READ_INTPTR_FIELD(p, offset) \
936 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
937
938#define WRITE_INTPTR_FIELD(p, offset, value) \
939 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
940
941#define READ_UINT32_FIELD(p, offset) \
942 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
943
944#define WRITE_UINT32_FIELD(p, offset, value) \
945 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
946
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100947#define READ_INT64_FIELD(p, offset) \
948 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)))
949
950#define WRITE_INT64_FIELD(p, offset, value) \
951 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
952
Steve Blocka7e24c12009-10-30 11:49:00 +0000953#define READ_SHORT_FIELD(p, offset) \
954 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
955
956#define WRITE_SHORT_FIELD(p, offset, value) \
957 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
958
959#define READ_BYTE_FIELD(p, offset) \
960 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
961
962#define WRITE_BYTE_FIELD(p, offset, value) \
963 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
964
965
966Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
967 return &READ_FIELD(obj, byte_offset);
968}
969
970
971int Smi::value() {
972 return Internals::SmiValue(this);
973}
974
975
976Smi* Smi::FromInt(int value) {
977 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000978 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000979 intptr_t tagged_value =
Steve Block3ce2e202009-11-05 08:53:23 +0000980 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 return reinterpret_cast<Smi*>(tagged_value);
982}
983
984
985Smi* Smi::FromIntptr(intptr_t value) {
986 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000987 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
988 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000989}
990
991
992Failure::Type Failure::type() const {
993 return static_cast<Type>(value() & kFailureTypeTagMask);
994}
995
996
997bool Failure::IsInternalError() const {
998 return type() == INTERNAL_ERROR;
999}
1000
1001
1002bool Failure::IsOutOfMemoryException() const {
1003 return type() == OUT_OF_MEMORY_EXCEPTION;
1004}
1005
1006
Steve Blocka7e24c12009-10-30 11:49:00 +00001007AllocationSpace Failure::allocation_space() const {
1008 ASSERT_EQ(RETRY_AFTER_GC, type());
1009 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1010 & kSpaceTagMask);
1011}
1012
1013
1014Failure* Failure::InternalError() {
1015 return Construct(INTERNAL_ERROR);
1016}
1017
1018
1019Failure* Failure::Exception() {
1020 return Construct(EXCEPTION);
1021}
1022
1023
1024Failure* Failure::OutOfMemoryException() {
1025 return Construct(OUT_OF_MEMORY_EXCEPTION);
1026}
1027
1028
Steve Block3ce2e202009-11-05 08:53:23 +00001029intptr_t Failure::value() const {
Steve Block6ded16b2010-05-10 14:33:55 +01001030 return static_cast<intptr_t>(
1031 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00001032}
1033
1034
Ben Murdochf87a2032010-10-22 12:50:53 +01001035Failure* Failure::RetryAfterGC() {
1036 return RetryAfterGC(NEW_SPACE);
1037}
1038
1039
1040Failure* Failure::RetryAfterGC(AllocationSpace space) {
1041 ASSERT((space & ~kSpaceTagMask) == 0);
1042 return Construct(RETRY_AFTER_GC, space);
Steve Blocka7e24c12009-10-30 11:49:00 +00001043}
1044
1045
Steve Block3ce2e202009-11-05 08:53:23 +00001046Failure* Failure::Construct(Type type, intptr_t value) {
Steve Block6ded16b2010-05-10 14:33:55 +01001047 uintptr_t info =
1048 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
Steve Blocka7e24c12009-10-30 11:49:00 +00001049 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
Steve Block3ce2e202009-11-05 08:53:23 +00001050 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001051}
1052
1053
1054bool Smi::IsValid(intptr_t value) {
1055#ifdef DEBUG
1056 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1057#endif
Steve Block3ce2e202009-11-05 08:53:23 +00001058
1059#ifdef V8_TARGET_ARCH_X64
1060 // To be representable as a long smi, the value must be a 32-bit integer.
1061 bool result = (value == static_cast<int32_t>(value));
1062#else
Steve Blocka7e24c12009-10-30 11:49:00 +00001063 // To be representable as an tagged small integer, the two
1064 // most-significant bits of 'value' must be either 00 or 11 due to
1065 // sign-extension. To check this we add 01 to the two
1066 // most-significant bits, and check if the most-significant bit is 0
1067 //
1068 // CAUTION: The original code below:
1069 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1070 // may lead to incorrect results according to the C language spec, and
1071 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1072 // compiler may produce undefined results in case of signed integer
1073 // overflow. The computation must be done w/ unsigned ints.
Steve Block3ce2e202009-11-05 08:53:23 +00001074 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
Steve Blocka7e24c12009-10-30 11:49:00 +00001075#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 ASSERT(result == in_range);
1077 return result;
1078}
1079
1080
1081MapWord MapWord::FromMap(Map* map) {
1082 return MapWord(reinterpret_cast<uintptr_t>(map));
1083}
1084
1085
1086Map* MapWord::ToMap() {
1087 return reinterpret_cast<Map*>(value_);
1088}
1089
1090
1091bool MapWord::IsForwardingAddress() {
1092 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1093}
1094
1095
1096MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1097 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1098 return MapWord(reinterpret_cast<uintptr_t>(raw));
1099}
1100
1101
1102HeapObject* MapWord::ToForwardingAddress() {
1103 ASSERT(IsForwardingAddress());
1104 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1105}
1106
1107
Steve Blocka7e24c12009-10-30 11:49:00 +00001108#ifdef DEBUG
1109void HeapObject::VerifyObjectField(int offset) {
1110 VerifyPointer(READ_FIELD(this, offset));
1111}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001112
1113void HeapObject::VerifySmiField(int offset) {
1114 ASSERT(READ_FIELD(this, offset)->IsSmi());
1115}
Steve Blocka7e24c12009-10-30 11:49:00 +00001116#endif
1117
1118
Steve Block44f0eee2011-05-26 01:26:41 +01001119Heap* HeapObject::GetHeap() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001120 Heap* heap =
1121 MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1122 ASSERT(heap != NULL);
1123 ASSERT(heap->isolate() == Isolate::Current());
1124 return heap;
Steve Block44f0eee2011-05-26 01:26:41 +01001125}
1126
1127
1128Isolate* HeapObject::GetIsolate() {
1129 return GetHeap()->isolate();
1130}
1131
1132
Steve Blocka7e24c12009-10-30 11:49:00 +00001133Map* HeapObject::map() {
1134 return map_word().ToMap();
1135}
1136
1137
1138void HeapObject::set_map(Map* value) {
1139 set_map_word(MapWord::FromMap(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001140 if (value != NULL) {
1141 // TODO(1600) We are passing NULL as a slot because maps can never be on
1142 // evacuation candidate.
1143 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1144 }
1145}
1146
1147
1148// Unsafe accessor omitting write barrier.
1149void HeapObject::set_map_no_write_barrier(Map* value) {
1150 set_map_word(MapWord::FromMap(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001151}
1152
1153
1154MapWord HeapObject::map_word() {
1155 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1156}
1157
1158
1159void HeapObject::set_map_word(MapWord map_word) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001160 // WRITE_FIELD does not invoke write barrier, but there is no need
Steve Blocka7e24c12009-10-30 11:49:00 +00001161 // here.
1162 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1163}
1164
1165
1166HeapObject* HeapObject::FromAddress(Address address) {
1167 ASSERT_TAG_ALIGNED(address);
1168 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1169}
1170
1171
1172Address HeapObject::address() {
1173 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1174}
1175
1176
1177int HeapObject::Size() {
1178 return SizeFromMap(map());
1179}
1180
1181
1182void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1183 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1184 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1185}
1186
1187
1188void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1189 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1190}
1191
1192
Steve Blocka7e24c12009-10-30 11:49:00 +00001193double HeapNumber::value() {
1194 return READ_DOUBLE_FIELD(this, kValueOffset);
1195}
1196
1197
1198void HeapNumber::set_value(double value) {
1199 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1200}
1201
1202
Steve Block6ded16b2010-05-10 14:33:55 +01001203int HeapNumber::get_exponent() {
1204 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1205 kExponentShift) - kExponentBias;
1206}
1207
1208
1209int HeapNumber::get_sign() {
1210 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1211}
1212
1213
Steve Blocka7e24c12009-10-30 11:49:00 +00001214ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1215
1216
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001217Object** FixedArray::GetFirstElementAddress() {
1218 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1219}
1220
1221
1222bool FixedArray::ContainsOnlySmisOrHoles() {
1223 Object* the_hole = GetHeap()->the_hole_value();
1224 Object** current = GetFirstElementAddress();
1225 for (int i = 0; i < length(); ++i) {
1226 Object* candidate = *current++;
1227 if (!candidate->IsSmi() && candidate != the_hole) return false;
1228 }
1229 return true;
1230}
1231
1232
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001233FixedArrayBase* JSObject::elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 Object* array = READ_FIELD(this, kElementsOffset);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001235 return static_cast<FixedArrayBase*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001236}
1237
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001238void JSObject::ValidateSmiOnlyElements() {
1239#if DEBUG
1240 if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1241 Heap* heap = GetHeap();
1242 // Don't use elements, since integrity checks will fail if there
1243 // are filler pointers in the array.
1244 FixedArray* fixed_array =
1245 reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset));
1246 Map* map = fixed_array->map();
1247 // Arrays that have been shifted in place can't be verified.
1248 if (map != heap->raw_unchecked_one_pointer_filler_map() &&
1249 map != heap->raw_unchecked_two_pointer_filler_map() &&
1250 map != heap->free_space_map()) {
1251 for (int i = 0; i < fixed_array->length(); i++) {
1252 Object* current = fixed_array->get(i);
1253 ASSERT(current->IsSmi() || current->IsTheHole());
1254 }
1255 }
1256 }
1257#endif
1258}
1259
1260
1261MaybeObject* JSObject::EnsureCanContainHeapObjectElements() {
1262#if DEBUG
1263 ValidateSmiOnlyElements();
1264#endif
1265 if ((map()->elements_kind() != FAST_ELEMENTS)) {
1266 return TransitionElementsKind(FAST_ELEMENTS);
1267 }
1268 return this;
1269}
1270
1271
1272MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1273 uint32_t count,
1274 EnsureElementsMode mode) {
1275 ElementsKind current_kind = map()->elements_kind();
1276 ElementsKind target_kind = current_kind;
1277 ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1278 if (current_kind == FAST_ELEMENTS) return this;
1279
1280 Heap* heap = GetHeap();
1281 Object* the_hole = heap->the_hole_value();
1282 Object* heap_number_map = heap->heap_number_map();
1283 for (uint32_t i = 0; i < count; ++i) {
1284 Object* current = *objects++;
1285 if (!current->IsSmi() && current != the_hole) {
1286 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS &&
1287 HeapObject::cast(current)->map() == heap_number_map) {
1288 target_kind = FAST_DOUBLE_ELEMENTS;
1289 } else {
1290 target_kind = FAST_ELEMENTS;
1291 break;
1292 }
1293 }
1294 }
1295
1296 if (target_kind != current_kind) {
1297 return TransitionElementsKind(target_kind);
1298 }
1299 return this;
1300}
1301
1302
1303MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements,
1304 EnsureElementsMode mode) {
1305 if (elements->map() != GetHeap()->fixed_double_array_map()) {
1306 ASSERT(elements->map() == GetHeap()->fixed_array_map() ||
1307 elements->map() == GetHeap()->fixed_cow_array_map());
1308 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1309 mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1310 }
1311 Object** objects = FixedArray::cast(elements)->GetFirstElementAddress();
1312 return EnsureCanContainElements(objects, elements->length(), mode);
1313 }
1314
1315 ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1316 if (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) {
1317 return TransitionElementsKind(FAST_DOUBLE_ELEMENTS);
1318 }
1319
1320 return this;
1321}
1322
1323
1324MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate,
1325 ElementsKind to_kind) {
1326 Map* current_map = map();
1327 ElementsKind from_kind = current_map->elements_kind();
1328
1329 if (from_kind == to_kind) return current_map;
1330
1331 Context* global_context = isolate->context()->global_context();
1332 if (current_map == global_context->smi_js_array_map()) {
1333 if (to_kind == FAST_ELEMENTS) {
1334 return global_context->object_js_array_map();
1335 } else {
1336 if (to_kind == FAST_DOUBLE_ELEMENTS) {
1337 return global_context->double_js_array_map();
1338 } else {
1339 ASSERT(to_kind == DICTIONARY_ELEMENTS);
1340 }
1341 }
1342 }
1343 return GetElementsTransitionMapSlow(to_kind);
1344}
1345
1346
1347void JSObject::set_map_and_elements(Map* new_map,
1348 FixedArrayBase* value,
1349 WriteBarrierMode mode) {
1350 ASSERT(value->HasValidElements());
1351#ifdef DEBUG
1352 ValidateSmiOnlyElements();
1353#endif
1354 if (new_map != NULL) {
1355 if (mode == UPDATE_WRITE_BARRIER) {
1356 set_map(new_map);
1357 } else {
1358 ASSERT(mode == SKIP_WRITE_BARRIER);
1359 set_map_no_write_barrier(new_map);
1360 }
1361 }
1362 ASSERT((map()->has_fast_elements() ||
1363 map()->has_fast_smi_only_elements() ||
1364 (value == GetHeap()->empty_fixed_array())) ==
1365 (value->map() == GetHeap()->fixed_array_map() ||
1366 value->map() == GetHeap()->fixed_cow_array_map()));
1367 ASSERT((value == GetHeap()->empty_fixed_array()) ||
1368 (map()->has_fast_double_elements() == value->IsFixedDoubleArray()));
1369 WRITE_FIELD(this, kElementsOffset, value);
1370 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1371}
1372
Steve Blocka7e24c12009-10-30 11:49:00 +00001373
Ben Murdochc7cc0282012-03-05 14:35:55 +00001374void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001375 set_map_and_elements(NULL, value, mode);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001376}
1377
1378
Steve Blocka7e24c12009-10-30 11:49:00 +00001379void JSObject::initialize_properties() {
Steve Block44f0eee2011-05-26 01:26:41 +01001380 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1381 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001382}
1383
1384
1385void JSObject::initialize_elements() {
Ben Murdoch9413bcb2012-05-04 10:55:47 +01001386 ASSERT(map()->has_fast_elements() ||
1387 map()->has_fast_smi_only_elements() ||
1388 map()->has_fast_double_elements());
Steve Block44f0eee2011-05-26 01:26:41 +01001389 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1390 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001391}
1392
1393
John Reck59135872010-11-02 12:39:01 -07001394MaybeObject* JSObject::ResetElements() {
1395 Object* obj;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001396 ElementsKind elements_kind = FLAG_smi_only_arrays
1397 ? FAST_SMI_ONLY_ELEMENTS
1398 : FAST_ELEMENTS;
1399 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
1400 elements_kind);
1401 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
Steve Block8defd9f2010-07-08 12:39:36 +01001402 set_map(Map::cast(obj));
1403 initialize_elements();
1404 return this;
1405}
1406
1407
Steve Blocka7e24c12009-10-30 11:49:00 +00001408ACCESSORS(Oddball, to_string, String, kToStringOffset)
1409ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1410
1411
Steve Block44f0eee2011-05-26 01:26:41 +01001412byte Oddball::kind() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001413 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
Steve Block44f0eee2011-05-26 01:26:41 +01001414}
1415
1416
1417void Oddball::set_kind(byte value) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001418 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
Steve Block44f0eee2011-05-26 01:26:41 +01001419}
1420
1421
Steve Blocka7e24c12009-10-30 11:49:00 +00001422Object* JSGlobalPropertyCell::value() {
1423 return READ_FIELD(this, kValueOffset);
1424}
1425
1426
1427void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1428 // The write barrier is not used for global property cells.
1429 ASSERT(!val->IsJSGlobalPropertyCell());
1430 WRITE_FIELD(this, kValueOffset, val);
1431}
1432
1433
1434int JSObject::GetHeaderSize() {
1435 InstanceType type = map()->instance_type();
1436 // Check for the most common kind of JavaScript object before
1437 // falling into the generic switch. This speeds up the internal
1438 // field operations considerably on average.
1439 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1440 switch (type) {
1441 case JS_GLOBAL_PROXY_TYPE:
1442 return JSGlobalProxy::kSize;
1443 case JS_GLOBAL_OBJECT_TYPE:
1444 return JSGlobalObject::kSize;
1445 case JS_BUILTINS_OBJECT_TYPE:
1446 return JSBuiltinsObject::kSize;
1447 case JS_FUNCTION_TYPE:
1448 return JSFunction::kSize;
1449 case JS_VALUE_TYPE:
1450 return JSValue::kSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001451 case JS_DATE_TYPE:
1452 return JSDate::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 case JS_ARRAY_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001454 return JSArray::kSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001455 case JS_WEAK_MAP_TYPE:
1456 return JSWeakMap::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 case JS_REGEXP_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001458 return JSRegExp::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001459 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1460 return JSObject::kHeaderSize;
Steve Block1e0659c2011-05-24 12:43:12 +01001461 case JS_MESSAGE_OBJECT_TYPE:
1462 return JSMessageObject::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001463 default:
1464 UNREACHABLE();
1465 return 0;
1466 }
1467}
1468
1469
1470int JSObject::GetInternalFieldCount() {
1471 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1472 // Make sure to adjust for the number of in-object properties. These
1473 // properties do contribute to the size, but are not internal fields.
1474 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1475 map()->inobject_properties();
1476}
1477
1478
Steve Block44f0eee2011-05-26 01:26:41 +01001479int JSObject::GetInternalFieldOffset(int index) {
1480 ASSERT(index < GetInternalFieldCount() && index >= 0);
1481 return GetHeaderSize() + (kPointerSize * index);
1482}
1483
1484
Steve Blocka7e24c12009-10-30 11:49:00 +00001485Object* JSObject::GetInternalField(int index) {
1486 ASSERT(index < GetInternalFieldCount() && index >= 0);
1487 // Internal objects do follow immediately after the header, whereas in-object
1488 // properties are at the end of the object. Therefore there is no need
1489 // to adjust the index here.
1490 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1491}
1492
1493
1494void JSObject::SetInternalField(int index, Object* value) {
1495 ASSERT(index < GetInternalFieldCount() && index >= 0);
1496 // Internal objects do follow immediately after the header, whereas in-object
1497 // properties are at the end of the object. Therefore there is no need
1498 // to adjust the index here.
1499 int offset = GetHeaderSize() + (kPointerSize * index);
1500 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001501 WRITE_BARRIER(GetHeap(), this, offset, value);
1502}
1503
1504
1505void JSObject::SetInternalField(int index, Smi* value) {
1506 ASSERT(index < GetInternalFieldCount() && index >= 0);
1507 // Internal objects do follow immediately after the header, whereas in-object
1508 // properties are at the end of the object. Therefore there is no need
1509 // to adjust the index here.
1510 int offset = GetHeaderSize() + (kPointerSize * index);
1511 WRITE_FIELD(this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001512}
1513
1514
1515// Access fast-case object properties at index. The use of these routines
1516// is needed to correctly distinguish between properties stored in-object and
1517// properties stored in the properties array.
1518Object* JSObject::FastPropertyAt(int index) {
1519 // Adjust for the number of properties stored in the object.
1520 index -= map()->inobject_properties();
1521 if (index < 0) {
1522 int offset = map()->instance_size() + (index * kPointerSize);
1523 return READ_FIELD(this, offset);
1524 } else {
1525 ASSERT(index < properties()->length());
1526 return properties()->get(index);
1527 }
1528}
1529
1530
1531Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1532 // Adjust for the number of properties stored in the object.
1533 index -= map()->inobject_properties();
1534 if (index < 0) {
1535 int offset = map()->instance_size() + (index * kPointerSize);
1536 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001537 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 } else {
1539 ASSERT(index < properties()->length());
1540 properties()->set(index, value);
1541 }
1542 return value;
1543}
1544
1545
Steve Block44f0eee2011-05-26 01:26:41 +01001546int JSObject::GetInObjectPropertyOffset(int index) {
1547 // Adjust for the number of properties stored in the object.
1548 index -= map()->inobject_properties();
1549 ASSERT(index < 0);
1550 return map()->instance_size() + (index * kPointerSize);
1551}
1552
1553
Steve Blocka7e24c12009-10-30 11:49:00 +00001554Object* JSObject::InObjectPropertyAt(int index) {
1555 // Adjust for the number of properties stored in the object.
1556 index -= map()->inobject_properties();
1557 ASSERT(index < 0);
1558 int offset = map()->instance_size() + (index * kPointerSize);
1559 return READ_FIELD(this, offset);
1560}
1561
1562
1563Object* JSObject::InObjectPropertyAtPut(int index,
1564 Object* value,
1565 WriteBarrierMode mode) {
1566 // Adjust for the number of properties stored in the object.
1567 index -= map()->inobject_properties();
1568 ASSERT(index < 0);
1569 int offset = map()->instance_size() + (index * kPointerSize);
1570 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001571 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 return value;
1573}
1574
1575
1576
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001577void JSObject::InitializeBody(Map* map,
1578 Object* pre_allocated_value,
1579 Object* filler_value) {
1580 ASSERT(!filler_value->IsHeapObject() ||
1581 !GetHeap()->InNewSpace(filler_value));
1582 ASSERT(!pre_allocated_value->IsHeapObject() ||
1583 !GetHeap()->InNewSpace(pre_allocated_value));
1584 int size = map->instance_size();
1585 int offset = kHeaderSize;
1586 if (filler_value != pre_allocated_value) {
1587 int pre_allocated = map->pre_allocated_property_fields();
1588 ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1589 for (int i = 0; i < pre_allocated; i++) {
1590 WRITE_FIELD(this, offset, pre_allocated_value);
1591 offset += kPointerSize;
1592 }
1593 }
1594 while (offset < size) {
1595 WRITE_FIELD(this, offset, filler_value);
1596 offset += kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001597 }
1598}
1599
1600
Steve Block8defd9f2010-07-08 12:39:36 +01001601bool JSObject::HasFastProperties() {
1602 return !properties()->IsDictionary();
1603}
1604
1605
1606int JSObject::MaxFastProperties() {
1607 // Allow extra fast properties if the object has more than
1608 // kMaxFastProperties in-object properties. When this is the case,
1609 // it is very unlikely that the object is being used as a dictionary
1610 // and there is a good chance that allowing more map transitions
1611 // will be worth it.
1612 return Max(map()->inobject_properties(), kMaxFastProperties);
1613}
1614
1615
Steve Blocka7e24c12009-10-30 11:49:00 +00001616void Struct::InitializeBody(int object_size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001617 Object* value = GetHeap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001618 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1619 WRITE_FIELD(this, offset, value);
1620 }
1621}
1622
1623
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001624bool Object::ToArrayIndex(uint32_t* index) {
1625 if (IsSmi()) {
1626 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001627 if (value < 0) return false;
1628 *index = value;
1629 return true;
1630 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001631 if (IsHeapNumber()) {
1632 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001633 uint32_t uint_value = static_cast<uint32_t>(value);
1634 if (value == static_cast<double>(uint_value)) {
1635 *index = uint_value;
1636 return true;
1637 }
1638 }
1639 return false;
1640}
1641
1642
1643bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1644 if (!this->IsJSValue()) return false;
1645
1646 JSValue* js_value = JSValue::cast(this);
1647 if (!js_value->value()->IsString()) return false;
1648
1649 String* str = String::cast(js_value->value());
1650 if (index >= (uint32_t)str->length()) return false;
1651
1652 return true;
1653}
1654
1655
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001656FixedArrayBase* FixedArrayBase::cast(Object* object) {
1657 ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1658 return reinterpret_cast<FixedArrayBase*>(object);
1659}
1660
1661
Steve Blocka7e24c12009-10-30 11:49:00 +00001662Object* FixedArray::get(int index) {
1663 ASSERT(index >= 0 && index < this->length());
1664 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1665}
1666
1667
1668void FixedArray::set(int index, Smi* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001669 ASSERT(map() != HEAP->fixed_cow_array_map());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001670 ASSERT(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001671 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1672 int offset = kHeaderSize + index * kPointerSize;
1673 WRITE_FIELD(this, offset, value);
1674}
1675
1676
1677void FixedArray::set(int index, Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001678 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001679 ASSERT(index >= 0 && index < this->length());
1680 int offset = kHeaderSize + index * kPointerSize;
1681 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001682 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001683}
1684
1685
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001686inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1687 return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1688}
1689
1690
1691inline double FixedDoubleArray::hole_nan_as_double() {
1692 return BitCast<double, uint64_t>(kHoleNanInt64);
1693}
1694
1695
1696inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1697 ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1698 ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1699 return OS::nan_value();
1700}
1701
1702
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001703double FixedDoubleArray::get_scalar(int index) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001704 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1705 map() != HEAP->fixed_array_map());
1706 ASSERT(index >= 0 && index < this->length());
1707 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1708 ASSERT(!is_the_hole_nan(result));
1709 return result;
1710}
1711
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001712int64_t FixedDoubleArray::get_representation(int index) {
1713 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1714 map() != HEAP->fixed_array_map());
1715 ASSERT(index >= 0 && index < this->length());
1716 return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
1717}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001718
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001719MaybeObject* FixedDoubleArray::get(int index) {
1720 if (is_the_hole(index)) {
1721 return GetHeap()->the_hole_value();
1722 } else {
1723 return GetHeap()->NumberFromDouble(get_scalar(index));
1724 }
1725}
1726
1727
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001728void FixedDoubleArray::set(int index, double value) {
1729 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1730 map() != HEAP->fixed_array_map());
1731 int offset = kHeaderSize + index * kDoubleSize;
1732 if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1733 WRITE_DOUBLE_FIELD(this, offset, value);
1734}
1735
1736
1737void FixedDoubleArray::set_the_hole(int index) {
1738 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1739 map() != HEAP->fixed_array_map());
1740 int offset = kHeaderSize + index * kDoubleSize;
1741 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1742}
1743
1744
1745bool FixedDoubleArray::is_the_hole(int index) {
1746 int offset = kHeaderSize + index * kDoubleSize;
1747 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1748}
1749
1750
Leon Clarke4515c472010-02-03 11:58:03 +00001751WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001752 Heap* heap = GetHeap();
1753 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1754 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
Steve Blocka7e24c12009-10-30 11:49:00 +00001755 return UPDATE_WRITE_BARRIER;
1756}
1757
1758
1759void FixedArray::set(int index,
1760 Object* value,
1761 WriteBarrierMode mode) {
Steve Block44f0eee2011-05-26 01:26:41 +01001762 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001763 ASSERT(index >= 0 && index < this->length());
1764 int offset = kHeaderSize + index * kPointerSize;
1765 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001766 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001767}
1768
1769
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001770void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
1771 int index,
1772 Object* value) {
1773 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1774 ASSERT(index >= 0 && index < array->length());
1775 int offset = kHeaderSize + index * kPointerSize;
1776 WRITE_FIELD(array, offset, value);
1777 Heap* heap = array->GetHeap();
1778 if (heap->InNewSpace(value)) {
1779 heap->RecordWrite(array->address(), offset);
1780 }
1781}
1782
1783
1784void FixedArray::NoWriteBarrierSet(FixedArray* array,
1785 int index,
1786 Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001787 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001788 ASSERT(index >= 0 && index < array->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001789 ASSERT(!HEAP->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001790 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1791}
1792
1793
1794void FixedArray::set_undefined(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001795 ASSERT(map() != HEAP->fixed_cow_array_map());
1796 set_undefined(GetHeap(), index);
1797}
1798
1799
1800void FixedArray::set_undefined(Heap* heap, int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001801 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001802 ASSERT(!heap->InNewSpace(heap->undefined_value()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001803 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
Steve Block44f0eee2011-05-26 01:26:41 +01001804 heap->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001805}
1806
1807
1808void FixedArray::set_null(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001809 set_null(GetHeap(), index);
1810}
1811
1812
1813void FixedArray::set_null(Heap* heap, int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001814 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001815 ASSERT(!heap->InNewSpace(heap->null_value()));
1816 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001817}
1818
1819
1820void FixedArray::set_the_hole(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001821 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001822 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001823 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1824 WRITE_FIELD(this,
1825 kHeaderSize + index * kPointerSize,
1826 GetHeap()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001827}
1828
1829
Iain Merrick75681382010-08-19 15:07:18 +01001830void FixedArray::set_unchecked(int index, Smi* value) {
1831 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1832 int offset = kHeaderSize + index * kPointerSize;
1833 WRITE_FIELD(this, offset, value);
1834}
1835
1836
Steve Block44f0eee2011-05-26 01:26:41 +01001837void FixedArray::set_unchecked(Heap* heap,
1838 int index,
Ben Murdochf87a2032010-10-22 12:50:53 +01001839 Object* value,
1840 WriteBarrierMode mode) {
1841 int offset = kHeaderSize + index * kPointerSize;
1842 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001843 CONDITIONAL_WRITE_BARRIER(heap, this, offset, value, mode);
Ben Murdochf87a2032010-10-22 12:50:53 +01001844}
1845
1846
Steve Block44f0eee2011-05-26 01:26:41 +01001847void FixedArray::set_null_unchecked(Heap* heap, int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001848 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001849 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1850 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
Iain Merrick75681382010-08-19 15:07:18 +01001851}
1852
1853
Steve Block6ded16b2010-05-10 14:33:55 +01001854Object** FixedArray::data_start() {
1855 return HeapObject::RawField(this, kHeaderSize);
1856}
1857
1858
Steve Blocka7e24c12009-10-30 11:49:00 +00001859bool DescriptorArray::IsEmpty() {
Ben Murdoch257744e2011-11-30 15:57:28 +00001860 ASSERT(this->IsSmi() ||
1861 this->length() > kFirstIndex ||
Steve Block44f0eee2011-05-26 01:26:41 +01001862 this == HEAP->empty_descriptor_array());
Ben Murdoch257744e2011-11-30 15:57:28 +00001863 return this->IsSmi() || length() <= kFirstIndex;
1864}
1865
1866
1867int DescriptorArray::bit_field3_storage() {
1868 Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1869 return Smi::cast(storage)->value();
1870}
1871
1872void DescriptorArray::set_bit_field3_storage(int value) {
1873 ASSERT(!IsEmpty());
1874 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001875}
1876
1877
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001878void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
1879 int first,
1880 int second) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 Object* tmp = array->get(first);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001882 NoIncrementalWriteBarrierSet(array, first, array->get(second));
1883 NoIncrementalWriteBarrierSet(array, second, tmp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001884}
1885
1886
1887int DescriptorArray::Search(String* name) {
1888 SLOW_ASSERT(IsSortedNoDuplicates());
1889
1890 // Check for empty descriptor array.
1891 int nof = number_of_descriptors();
1892 if (nof == 0) return kNotFound;
1893
1894 // Fast case: do linear search for small arrays.
1895 const int kMaxElementsForLinearSearch = 8;
1896 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1897 return LinearSearch(name, nof);
1898 }
1899
1900 // Slow case: perform binary search.
1901 return BinarySearch(name, 0, nof - 1);
1902}
1903
1904
Iain Merrick75681382010-08-19 15:07:18 +01001905int DescriptorArray::SearchWithCache(String* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001906 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
Iain Merrick75681382010-08-19 15:07:18 +01001907 if (number == DescriptorLookupCache::kAbsent) {
1908 number = Search(name);
Steve Block44f0eee2011-05-26 01:26:41 +01001909 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
Iain Merrick75681382010-08-19 15:07:18 +01001910 }
1911 return number;
1912}
1913
1914
Steve Blocka7e24c12009-10-30 11:49:00 +00001915String* DescriptorArray::GetKey(int descriptor_number) {
1916 ASSERT(descriptor_number < number_of_descriptors());
1917 return String::cast(get(ToKeyIndex(descriptor_number)));
1918}
1919
1920
1921Object* DescriptorArray::GetValue(int descriptor_number) {
1922 ASSERT(descriptor_number < number_of_descriptors());
1923 return GetContentArray()->get(ToValueIndex(descriptor_number));
1924}
1925
1926
1927Smi* DescriptorArray::GetDetails(int descriptor_number) {
1928 ASSERT(descriptor_number < number_of_descriptors());
1929 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1930}
1931
1932
1933PropertyType DescriptorArray::GetType(int descriptor_number) {
1934 ASSERT(descriptor_number < number_of_descriptors());
1935 return PropertyDetails(GetDetails(descriptor_number)).type();
1936}
1937
1938
1939int DescriptorArray::GetFieldIndex(int descriptor_number) {
1940 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1941}
1942
1943
1944JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1945 return JSFunction::cast(GetValue(descriptor_number));
1946}
1947
1948
1949Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1950 ASSERT(GetType(descriptor_number) == CALLBACKS);
1951 return GetValue(descriptor_number);
1952}
1953
1954
1955AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1956 ASSERT(GetType(descriptor_number) == CALLBACKS);
Ben Murdoch257744e2011-11-30 15:57:28 +00001957 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001958 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001959}
1960
1961
1962bool DescriptorArray::IsProperty(int descriptor_number) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001963 Entry entry(this, descriptor_number);
1964 return IsPropertyDescriptor(&entry);
Steve Blocka7e24c12009-10-30 11:49:00 +00001965}
1966
1967
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001968bool DescriptorArray::IsTransitionOnly(int descriptor_number) {
1969 switch (GetType(descriptor_number)) {
1970 case MAP_TRANSITION:
1971 case CONSTANT_TRANSITION:
1972 case ELEMENTS_TRANSITION:
1973 return true;
1974 case CALLBACKS: {
1975 Object* value = GetValue(descriptor_number);
1976 if (!value->IsAccessorPair()) return false;
1977 AccessorPair* accessors = AccessorPair::cast(value);
1978 return accessors->getter()->IsMap() && accessors->setter()->IsMap();
1979 }
1980 case NORMAL:
1981 case FIELD:
1982 case CONSTANT_FUNCTION:
1983 case HANDLER:
1984 case INTERCEPTOR:
1985 case NULL_DESCRIPTOR:
1986 return false;
1987 }
1988 UNREACHABLE(); // Keep the compiler happy.
1989 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001990}
1991
1992
1993bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1994 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1995}
1996
1997
1998bool DescriptorArray::IsDontEnum(int descriptor_number) {
1999 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
2000}
2001
2002
2003void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2004 desc->Init(GetKey(descriptor_number),
2005 GetValue(descriptor_number),
Ben Murdoch8b112d22011-06-08 16:22:53 +01002006 PropertyDetails(GetDetails(descriptor_number)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002007}
2008
2009
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002010void DescriptorArray::Set(int descriptor_number,
2011 Descriptor* desc,
2012 const WhitenessWitness&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002013 // Range check.
2014 ASSERT(descriptor_number < number_of_descriptors());
2015
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002016 NoIncrementalWriteBarrierSet(this,
2017 ToKeyIndex(descriptor_number),
2018 desc->GetKey());
Steve Blocka7e24c12009-10-30 11:49:00 +00002019 FixedArray* content_array = GetContentArray();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002020 NoIncrementalWriteBarrierSet(content_array,
2021 ToValueIndex(descriptor_number),
2022 desc->GetValue());
2023 NoIncrementalWriteBarrierSet(content_array,
2024 ToDetailsIndex(descriptor_number),
2025 desc->GetDetails().AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002026}
2027
2028
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002029void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
2030 int first, int second) {
2031 NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
2032 FixedArray* content_array = GetContentArray();
2033 NoIncrementalWriteBarrierSwap(content_array,
2034 ToValueIndex(first),
2035 ToValueIndex(second));
2036 NoIncrementalWriteBarrierSwap(content_array,
2037 ToDetailsIndex(first),
2038 ToDetailsIndex(second));
Ben Murdoch85b71792012-04-11 18:30:58 +01002039}
2040
2041
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002042DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
2043 : marking_(array->GetHeap()->incremental_marking()) {
2044 marking_->EnterNoMarkingScope();
2045 if (array->number_of_descriptors() > 0) {
2046 ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
2047 ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
2048 }
2049}
2050
2051
2052DescriptorArray::WhitenessWitness::~WhitenessWitness() {
2053 marking_->LeaveNoMarkingScope();
Steve Blocka7e24c12009-10-30 11:49:00 +00002054}
2055
2056
Steve Block44f0eee2011-05-26 01:26:41 +01002057template<typename Shape, typename Key>
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002058int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2059 const int kMinCapacity = 32;
2060 int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2061 if (capacity < kMinCapacity) {
2062 capacity = kMinCapacity; // Guarantee min capacity.
2063 }
2064 return capacity;
2065}
2066
2067
2068template<typename Shape, typename Key>
Steve Block44f0eee2011-05-26 01:26:41 +01002069int HashTable<Shape, Key>::FindEntry(Key key) {
2070 return FindEntry(GetIsolate(), key);
2071}
2072
2073
2074// Find entry for key otherwise return kNotFound.
2075template<typename Shape, typename Key>
2076int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2077 uint32_t capacity = Capacity();
Ben Murdochc7cc0282012-03-05 14:35:55 +00002078 uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
Steve Block44f0eee2011-05-26 01:26:41 +01002079 uint32_t count = 1;
2080 // EnsureCapacity will guarantee the hash table is never full.
2081 while (true) {
2082 Object* element = KeyAt(entry);
Ben Murdochc7cc0282012-03-05 14:35:55 +00002083 // Empty entry.
2084 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002085 if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
Steve Block44f0eee2011-05-26 01:26:41 +01002086 Shape::IsMatch(key, element)) return entry;
2087 entry = NextProbe(entry, count++, capacity);
2088 }
2089 return kNotFound;
2090}
2091
2092
Ben Murdochc7cc0282012-03-05 14:35:55 +00002093bool SeededNumberDictionary::requires_slow_elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002094 Object* max_index_object = get(kMaxNumberKeyIndex);
2095 if (!max_index_object->IsSmi()) return false;
2096 return 0 !=
2097 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2098}
2099
Ben Murdochc7cc0282012-03-05 14:35:55 +00002100uint32_t SeededNumberDictionary::max_number_key() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002101 ASSERT(!requires_slow_elements());
2102 Object* max_index_object = get(kMaxNumberKeyIndex);
2103 if (!max_index_object->IsSmi()) return 0;
2104 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2105 return value >> kRequiresSlowElementsTagSize;
2106}
2107
Ben Murdochc7cc0282012-03-05 14:35:55 +00002108void SeededNumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00002109 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00002110}
2111
2112
2113// ------------------------------------
2114// Cast operations
2115
2116
2117CAST_ACCESSOR(FixedArray)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002118CAST_ACCESSOR(FixedDoubleArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002119CAST_ACCESSOR(DescriptorArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002120CAST_ACCESSOR(DeoptimizationInputData)
2121CAST_ACCESSOR(DeoptimizationOutputData)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002122CAST_ACCESSOR(TypeFeedbackCells)
Steve Blocka7e24c12009-10-30 11:49:00 +00002123CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01002124CAST_ACCESSOR(JSFunctionResultCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002125CAST_ACCESSOR(NormalizedMapCache)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002126CAST_ACCESSOR(ScopeInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +00002127CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01002128CAST_ACCESSOR(CodeCacheHashTable)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002129CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00002130CAST_ACCESSOR(MapCache)
2131CAST_ACCESSOR(String)
2132CAST_ACCESSOR(SeqString)
2133CAST_ACCESSOR(SeqAsciiString)
2134CAST_ACCESSOR(SeqTwoByteString)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002135CAST_ACCESSOR(SlicedString)
Steve Blocka7e24c12009-10-30 11:49:00 +00002136CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00002137CAST_ACCESSOR(ExternalString)
2138CAST_ACCESSOR(ExternalAsciiString)
2139CAST_ACCESSOR(ExternalTwoByteString)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002140CAST_ACCESSOR(JSReceiver)
Steve Blocka7e24c12009-10-30 11:49:00 +00002141CAST_ACCESSOR(JSObject)
2142CAST_ACCESSOR(Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00002143CAST_ACCESSOR(HeapObject)
2144CAST_ACCESSOR(HeapNumber)
2145CAST_ACCESSOR(Oddball)
2146CAST_ACCESSOR(JSGlobalPropertyCell)
2147CAST_ACCESSOR(SharedFunctionInfo)
2148CAST_ACCESSOR(Map)
2149CAST_ACCESSOR(JSFunction)
2150CAST_ACCESSOR(GlobalObject)
2151CAST_ACCESSOR(JSGlobalProxy)
2152CAST_ACCESSOR(JSGlobalObject)
2153CAST_ACCESSOR(JSBuiltinsObject)
2154CAST_ACCESSOR(Code)
2155CAST_ACCESSOR(JSArray)
2156CAST_ACCESSOR(JSRegExp)
Ben Murdoch257744e2011-11-30 15:57:28 +00002157CAST_ACCESSOR(JSProxy)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002158CAST_ACCESSOR(JSFunctionProxy)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002159CAST_ACCESSOR(JSSet)
2160CAST_ACCESSOR(JSMap)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002161CAST_ACCESSOR(JSWeakMap)
Ben Murdoch257744e2011-11-30 15:57:28 +00002162CAST_ACCESSOR(Foreign)
Steve Blocka7e24c12009-10-30 11:49:00 +00002163CAST_ACCESSOR(ByteArray)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002164CAST_ACCESSOR(FreeSpace)
Steve Block3ce2e202009-11-05 08:53:23 +00002165CAST_ACCESSOR(ExternalArray)
2166CAST_ACCESSOR(ExternalByteArray)
2167CAST_ACCESSOR(ExternalUnsignedByteArray)
2168CAST_ACCESSOR(ExternalShortArray)
2169CAST_ACCESSOR(ExternalUnsignedShortArray)
2170CAST_ACCESSOR(ExternalIntArray)
2171CAST_ACCESSOR(ExternalUnsignedIntArray)
2172CAST_ACCESSOR(ExternalFloatArray)
Ben Murdoch257744e2011-11-30 15:57:28 +00002173CAST_ACCESSOR(ExternalDoubleArray)
Steve Block44f0eee2011-05-26 01:26:41 +01002174CAST_ACCESSOR(ExternalPixelArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002175CAST_ACCESSOR(Struct)
2176
2177
2178#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2179 STRUCT_LIST(MAKE_STRUCT_CAST)
2180#undef MAKE_STRUCT_CAST
2181
2182
2183template <typename Shape, typename Key>
2184HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2185 ASSERT(obj->IsHashTable());
2186 return reinterpret_cast<HashTable*>(obj);
2187}
2188
2189
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002190SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002191SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002192
Steve Block6ded16b2010-05-10 14:33:55 +01002193SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002194
2195
2196uint32_t String::hash_field() {
2197 return READ_UINT32_FIELD(this, kHashFieldOffset);
2198}
2199
2200
2201void String::set_hash_field(uint32_t value) {
2202 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002203#if V8_HOST_ARCH_64_BIT
2204 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2205#endif
Steve Blockd0582a62009-12-15 09:54:21 +00002206}
2207
2208
Steve Blocka7e24c12009-10-30 11:49:00 +00002209bool String::Equals(String* other) {
2210 if (other == this) return true;
2211 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2212 return false;
2213 }
2214 return SlowEquals(other);
2215}
2216
2217
John Reck59135872010-11-02 12:39:01 -07002218MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01002219 if (!StringShape(this).IsCons()) return this;
2220 ConsString* cons = ConsString::cast(this);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002221 if (cons->IsFlat()) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01002222 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00002223}
2224
2225
Leon Clarkef7060e22010-06-03 12:02:55 +01002226String* String::TryFlattenGetString(PretenureFlag pretenure) {
John Reck59135872010-11-02 12:39:01 -07002227 MaybeObject* flat = TryFlatten(pretenure);
2228 Object* successfully_flattened;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002229 if (!flat->ToObject(&successfully_flattened)) return this;
2230 return String::cast(successfully_flattened);
Leon Clarkef7060e22010-06-03 12:02:55 +01002231}
2232
2233
Steve Blocka7e24c12009-10-30 11:49:00 +00002234uint16_t String::Get(int index) {
2235 ASSERT(index >= 0 && index < length());
2236 switch (StringShape(this).full_representation_tag()) {
2237 case kSeqStringTag | kAsciiStringTag:
2238 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2239 case kSeqStringTag | kTwoByteStringTag:
2240 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2241 case kConsStringTag | kAsciiStringTag:
2242 case kConsStringTag | kTwoByteStringTag:
2243 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002244 case kExternalStringTag | kAsciiStringTag:
2245 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2246 case kExternalStringTag | kTwoByteStringTag:
2247 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002248 case kSlicedStringTag | kAsciiStringTag:
2249 case kSlicedStringTag | kTwoByteStringTag:
2250 return SlicedString::cast(this)->SlicedStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002251 default:
2252 break;
2253 }
2254
2255 UNREACHABLE();
2256 return 0;
2257}
2258
2259
2260void String::Set(int index, uint16_t value) {
2261 ASSERT(index >= 0 && index < length());
2262 ASSERT(StringShape(this).IsSequential());
2263
2264 return this->IsAsciiRepresentation()
2265 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2266 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2267}
2268
2269
2270bool String::IsFlat() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002271 if (!StringShape(this).IsCons()) return true;
2272 return ConsString::cast(this)->second()->length() == 0;
2273}
2274
2275
2276String* String::GetUnderlying() {
2277 // Giving direct access to underlying string only makes sense if the
2278 // wrapping string is already flattened.
2279 ASSERT(this->IsFlat());
2280 ASSERT(StringShape(this).IsIndirect());
2281 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2282 const int kUnderlyingOffset = SlicedString::kParentOffset;
2283 return String::cast(READ_FIELD(this, kUnderlyingOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002284}
2285
2286
2287uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2288 ASSERT(index >= 0 && index < length());
2289 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2290}
2291
2292
2293void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2294 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2295 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2296 static_cast<byte>(value));
2297}
2298
2299
2300Address SeqAsciiString::GetCharsAddress() {
2301 return FIELD_ADDR(this, kHeaderSize);
2302}
2303
2304
2305char* SeqAsciiString::GetChars() {
2306 return reinterpret_cast<char*>(GetCharsAddress());
2307}
2308
2309
2310Address SeqTwoByteString::GetCharsAddress() {
2311 return FIELD_ADDR(this, kHeaderSize);
2312}
2313
2314
2315uc16* SeqTwoByteString::GetChars() {
2316 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2317}
2318
2319
2320uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2321 ASSERT(index >= 0 && index < length());
2322 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2323}
2324
2325
2326void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2327 ASSERT(index >= 0 && index < length());
2328 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2329}
2330
2331
2332int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01002333 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002334}
2335
2336
2337int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01002338 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002339}
2340
2341
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002342String* SlicedString::parent() {
2343 return String::cast(READ_FIELD(this, kParentOffset));
2344}
2345
2346
2347void SlicedString::set_parent(String* parent) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002348 ASSERT(parent->IsSeqString() || parent->IsExternalString());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002349 WRITE_FIELD(this, kParentOffset, parent);
2350}
2351
2352
2353SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2354
2355
Steve Blocka7e24c12009-10-30 11:49:00 +00002356String* ConsString::first() {
2357 return String::cast(READ_FIELD(this, kFirstOffset));
2358}
2359
2360
2361Object* ConsString::unchecked_first() {
2362 return READ_FIELD(this, kFirstOffset);
2363}
2364
2365
2366void ConsString::set_first(String* value, WriteBarrierMode mode) {
2367 WRITE_FIELD(this, kFirstOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002368 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002369}
2370
2371
2372String* ConsString::second() {
2373 return String::cast(READ_FIELD(this, kSecondOffset));
2374}
2375
2376
2377Object* ConsString::unchecked_second() {
2378 return READ_FIELD(this, kSecondOffset);
2379}
2380
2381
2382void ConsString::set_second(String* value, WriteBarrierMode mode) {
2383 WRITE_FIELD(this, kSecondOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002384 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002385}
2386
2387
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002388bool ExternalString::is_short() {
2389 InstanceType type = map()->instance_type();
2390 return (type & kShortExternalStringMask) == kShortExternalStringTag;
2391}
2392
2393
2394const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002395 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2396}
2397
2398
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002399void ExternalAsciiString::update_data_cache() {
2400 if (is_short()) return;
2401 const char** data_field =
2402 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
2403 *data_field = resource()->data();
2404}
2405
2406
Steve Blocka7e24c12009-10-30 11:49:00 +00002407void ExternalAsciiString::set_resource(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002408 const ExternalAsciiString::Resource* resource) {
2409 *reinterpret_cast<const Resource**>(
2410 FIELD_ADDR(this, kResourceOffset)) = resource;
2411 if (resource != NULL) update_data_cache();
Steve Blocka7e24c12009-10-30 11:49:00 +00002412}
2413
2414
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002415const char* ExternalAsciiString::GetChars() {
2416 return resource()->data();
2417}
2418
2419
2420uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
2421 ASSERT(index >= 0 && index < length());
2422 return GetChars()[index];
2423}
2424
2425
2426const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002427 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2428}
2429
2430
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002431void ExternalTwoByteString::update_data_cache() {
2432 if (is_short()) return;
2433 const uint16_t** data_field =
2434 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
2435 *data_field = resource()->data();
2436}
2437
2438
Steve Blocka7e24c12009-10-30 11:49:00 +00002439void ExternalTwoByteString::set_resource(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002440 const ExternalTwoByteString::Resource* resource) {
2441 *reinterpret_cast<const Resource**>(
2442 FIELD_ADDR(this, kResourceOffset)) = resource;
2443 if (resource != NULL) update_data_cache();
2444}
2445
2446
2447const uint16_t* ExternalTwoByteString::GetChars() {
2448 return resource()->data();
2449}
2450
2451
2452uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
2453 ASSERT(index >= 0 && index < length());
2454 return GetChars()[index];
2455}
2456
2457
2458const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
2459 unsigned start) {
2460 return GetChars() + start;
Steve Blocka7e24c12009-10-30 11:49:00 +00002461}
2462
2463
Steve Block6ded16b2010-05-10 14:33:55 +01002464void JSFunctionResultCache::MakeZeroSize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002465 set_finger_index(kEntriesIndex);
2466 set_size(kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01002467}
2468
2469
2470void JSFunctionResultCache::Clear() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002471 int cache_size = size();
Steve Block6ded16b2010-05-10 14:33:55 +01002472 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002473 MemsetPointer(entries_start,
Steve Block44f0eee2011-05-26 01:26:41 +01002474 GetHeap()->the_hole_value(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002475 cache_size - kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01002476 MakeZeroSize();
2477}
2478
2479
Ben Murdochb8e0da22011-05-16 14:20:40 +01002480int JSFunctionResultCache::size() {
2481 return Smi::cast(get(kCacheSizeIndex))->value();
2482}
2483
2484
2485void JSFunctionResultCache::set_size(int size) {
2486 set(kCacheSizeIndex, Smi::FromInt(size));
2487}
2488
2489
2490int JSFunctionResultCache::finger_index() {
2491 return Smi::cast(get(kFingerIndex))->value();
2492}
2493
2494
2495void JSFunctionResultCache::set_finger_index(int finger_index) {
2496 set(kFingerIndex, Smi::FromInt(finger_index));
2497}
2498
2499
Steve Blocka7e24c12009-10-30 11:49:00 +00002500byte ByteArray::get(int index) {
2501 ASSERT(index >= 0 && index < this->length());
2502 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2503}
2504
2505
2506void ByteArray::set(int index, byte value) {
2507 ASSERT(index >= 0 && index < this->length());
2508 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2509}
2510
2511
2512int ByteArray::get_int(int index) {
2513 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2514 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2515}
2516
2517
2518ByteArray* ByteArray::FromDataStartAddress(Address address) {
2519 ASSERT_TAG_ALIGNED(address);
2520 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2521}
2522
2523
2524Address ByteArray::GetDataStartAddress() {
2525 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2526}
2527
2528
Steve Block44f0eee2011-05-26 01:26:41 +01002529uint8_t* ExternalPixelArray::external_pixel_pointer() {
2530 return reinterpret_cast<uint8_t*>(external_pointer());
Steve Blocka7e24c12009-10-30 11:49:00 +00002531}
2532
2533
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002534uint8_t ExternalPixelArray::get_scalar(int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002535 ASSERT((index >= 0) && (index < this->length()));
Steve Block44f0eee2011-05-26 01:26:41 +01002536 uint8_t* ptr = external_pixel_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00002537 return ptr[index];
2538}
2539
2540
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002541MaybeObject* ExternalPixelArray::get(int index) {
2542 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2543}
2544
2545
Steve Block44f0eee2011-05-26 01:26:41 +01002546void ExternalPixelArray::set(int index, uint8_t value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002547 ASSERT((index >= 0) && (index < this->length()));
Steve Block44f0eee2011-05-26 01:26:41 +01002548 uint8_t* ptr = external_pixel_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00002549 ptr[index] = value;
2550}
2551
2552
Steve Block3ce2e202009-11-05 08:53:23 +00002553void* ExternalArray::external_pointer() {
2554 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2555 return reinterpret_cast<void*>(ptr);
2556}
2557
2558
2559void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2560 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2561 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2562}
2563
2564
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002565int8_t ExternalByteArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002566 ASSERT((index >= 0) && (index < this->length()));
2567 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2568 return ptr[index];
2569}
2570
2571
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002572MaybeObject* ExternalByteArray::get(int index) {
2573 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2574}
2575
2576
Steve Block3ce2e202009-11-05 08:53:23 +00002577void ExternalByteArray::set(int index, int8_t value) {
2578 ASSERT((index >= 0) && (index < this->length()));
2579 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2580 ptr[index] = value;
2581}
2582
2583
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002584uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002585 ASSERT((index >= 0) && (index < this->length()));
2586 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2587 return ptr[index];
2588}
2589
2590
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002591MaybeObject* ExternalUnsignedByteArray::get(int index) {
2592 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2593}
2594
2595
Steve Block3ce2e202009-11-05 08:53:23 +00002596void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2597 ASSERT((index >= 0) && (index < this->length()));
2598 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2599 ptr[index] = value;
2600}
2601
2602
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002603int16_t ExternalShortArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002604 ASSERT((index >= 0) && (index < this->length()));
2605 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2606 return ptr[index];
2607}
2608
2609
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002610MaybeObject* ExternalShortArray::get(int index) {
2611 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2612}
2613
2614
Steve Block3ce2e202009-11-05 08:53:23 +00002615void ExternalShortArray::set(int index, int16_t value) {
2616 ASSERT((index >= 0) && (index < this->length()));
2617 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2618 ptr[index] = value;
2619}
2620
2621
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002622uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002623 ASSERT((index >= 0) && (index < this->length()));
2624 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2625 return ptr[index];
2626}
2627
2628
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002629MaybeObject* ExternalUnsignedShortArray::get(int index) {
2630 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2631}
2632
2633
Steve Block3ce2e202009-11-05 08:53:23 +00002634void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2635 ASSERT((index >= 0) && (index < this->length()));
2636 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2637 ptr[index] = value;
2638}
2639
2640
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002641int32_t ExternalIntArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002642 ASSERT((index >= 0) && (index < this->length()));
2643 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2644 return ptr[index];
2645}
2646
2647
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002648MaybeObject* ExternalIntArray::get(int index) {
2649 return GetHeap()->NumberFromInt32(get_scalar(index));
2650}
2651
2652
Steve Block3ce2e202009-11-05 08:53:23 +00002653void ExternalIntArray::set(int index, int32_t value) {
2654 ASSERT((index >= 0) && (index < this->length()));
2655 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2656 ptr[index] = value;
2657}
2658
2659
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002660uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002661 ASSERT((index >= 0) && (index < this->length()));
2662 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2663 return ptr[index];
2664}
2665
2666
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002667MaybeObject* ExternalUnsignedIntArray::get(int index) {
2668 return GetHeap()->NumberFromUint32(get_scalar(index));
2669}
2670
2671
Steve Block3ce2e202009-11-05 08:53:23 +00002672void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2673 ASSERT((index >= 0) && (index < this->length()));
2674 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2675 ptr[index] = value;
2676}
2677
2678
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002679float ExternalFloatArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002680 ASSERT((index >= 0) && (index < this->length()));
2681 float* ptr = static_cast<float*>(external_pointer());
2682 return ptr[index];
2683}
2684
2685
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002686MaybeObject* ExternalFloatArray::get(int index) {
2687 return GetHeap()->NumberFromDouble(get_scalar(index));
2688}
2689
2690
Steve Block3ce2e202009-11-05 08:53:23 +00002691void ExternalFloatArray::set(int index, float value) {
2692 ASSERT((index >= 0) && (index < this->length()));
2693 float* ptr = static_cast<float*>(external_pointer());
2694 ptr[index] = value;
2695}
2696
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002697
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002698double ExternalDoubleArray::get_scalar(int index) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002699 ASSERT((index >= 0) && (index < this->length()));
2700 double* ptr = static_cast<double*>(external_pointer());
2701 return ptr[index];
2702}
2703
2704
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002705MaybeObject* ExternalDoubleArray::get(int index) {
2706 return GetHeap()->NumberFromDouble(get_scalar(index));
2707}
2708
2709
Ben Murdoch257744e2011-11-30 15:57:28 +00002710void ExternalDoubleArray::set(int index, double value) {
2711 ASSERT((index >= 0) && (index < this->length()));
2712 double* ptr = static_cast<double*>(external_pointer());
2713 ptr[index] = value;
2714}
2715
2716
Iain Merrick9ac36c92010-09-13 15:29:50 +01002717int Map::visitor_id() {
2718 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2719}
2720
2721
2722void Map::set_visitor_id(int id) {
2723 ASSERT(0 <= id && id < 256);
2724 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2725}
2726
Steve Block3ce2e202009-11-05 08:53:23 +00002727
Steve Blocka7e24c12009-10-30 11:49:00 +00002728int Map::instance_size() {
2729 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2730}
2731
2732
2733int Map::inobject_properties() {
2734 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2735}
2736
2737
2738int Map::pre_allocated_property_fields() {
2739 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2740}
2741
2742
2743int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01002744 int instance_size = map->instance_size();
2745 if (instance_size != kVariableSizeSentinel) return instance_size;
2746 // We can ignore the "symbol" bit becase it is only set for symbols
2747 // and implies a string type.
2748 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002749 // Only inline the most frequent cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00002750 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002751 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002752 }
Steve Block791712a2010-08-27 10:21:07 +01002753 if (instance_type == ASCII_STRING_TYPE) {
2754 return SeqAsciiString::SizeFor(
2755 reinterpret_cast<SeqAsciiString*>(this)->length());
2756 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002757 if (instance_type == BYTE_ARRAY_TYPE) {
2758 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2759 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002760 if (instance_type == FREE_SPACE_TYPE) {
2761 return reinterpret_cast<FreeSpace*>(this)->size();
2762 }
Steve Block791712a2010-08-27 10:21:07 +01002763 if (instance_type == STRING_TYPE) {
2764 return SeqTwoByteString::SizeFor(
2765 reinterpret_cast<SeqTwoByteString*>(this)->length());
2766 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002767 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2768 return FixedDoubleArray::SizeFor(
2769 reinterpret_cast<FixedDoubleArray*>(this)->length());
2770 }
Steve Block791712a2010-08-27 10:21:07 +01002771 ASSERT(instance_type == CODE_TYPE);
2772 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00002773}
2774
2775
2776void Map::set_instance_size(int value) {
2777 ASSERT_EQ(0, value & (kPointerSize - 1));
2778 value >>= kPointerSizeLog2;
2779 ASSERT(0 <= value && value < 256);
2780 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2781}
2782
2783
2784void Map::set_inobject_properties(int value) {
2785 ASSERT(0 <= value && value < 256);
2786 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2787}
2788
2789
2790void Map::set_pre_allocated_property_fields(int value) {
2791 ASSERT(0 <= value && value < 256);
2792 WRITE_BYTE_FIELD(this,
2793 kPreAllocatedPropertyFieldsOffset,
2794 static_cast<byte>(value));
2795}
2796
2797
2798InstanceType Map::instance_type() {
2799 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2800}
2801
2802
2803void Map::set_instance_type(InstanceType value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002804 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2805}
2806
2807
2808int Map::unused_property_fields() {
2809 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2810}
2811
2812
2813void Map::set_unused_property_fields(int value) {
2814 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2815}
2816
2817
2818byte Map::bit_field() {
2819 return READ_BYTE_FIELD(this, kBitFieldOffset);
2820}
2821
2822
2823void Map::set_bit_field(byte value) {
2824 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2825}
2826
2827
2828byte Map::bit_field2() {
2829 return READ_BYTE_FIELD(this, kBitField2Offset);
2830}
2831
2832
2833void Map::set_bit_field2(byte value) {
2834 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2835}
2836
2837
2838void Map::set_non_instance_prototype(bool value) {
2839 if (value) {
2840 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2841 } else {
2842 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2843 }
2844}
2845
2846
2847bool Map::has_non_instance_prototype() {
2848 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2849}
2850
2851
Steve Block6ded16b2010-05-10 14:33:55 +01002852void Map::set_function_with_prototype(bool value) {
2853 if (value) {
2854 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2855 } else {
2856 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2857 }
2858}
2859
2860
2861bool Map::function_with_prototype() {
2862 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2863}
2864
2865
Steve Blocka7e24c12009-10-30 11:49:00 +00002866void Map::set_is_access_check_needed(bool access_check_needed) {
2867 if (access_check_needed) {
2868 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2869 } else {
2870 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2871 }
2872}
2873
2874
2875bool Map::is_access_check_needed() {
2876 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2877}
2878
2879
Steve Block8defd9f2010-07-08 12:39:36 +01002880void Map::set_is_extensible(bool value) {
2881 if (value) {
2882 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2883 } else {
2884 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2885 }
2886}
2887
2888bool Map::is_extensible() {
2889 return ((1 << kIsExtensible) & bit_field2()) != 0;
2890}
2891
2892
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002893void Map::set_attached_to_shared_function_info(bool value) {
2894 if (value) {
2895 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2896 } else {
2897 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2898 }
2899}
2900
2901bool Map::attached_to_shared_function_info() {
2902 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2903}
2904
2905
2906void Map::set_is_shared(bool value) {
2907 if (value) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002908 set_bit_field3(bit_field3() | (1 << kIsShared));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002909 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00002910 set_bit_field3(bit_field3() & ~(1 << kIsShared));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002911 }
2912}
2913
2914bool Map::is_shared() {
Ben Murdoch257744e2011-11-30 15:57:28 +00002915 return ((1 << kIsShared) & bit_field3()) != 0;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002916}
2917
2918
2919JSFunction* Map::unchecked_constructor() {
2920 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2921}
2922
Steve Block8defd9f2010-07-08 12:39:36 +01002923
Steve Blocka7e24c12009-10-30 11:49:00 +00002924Code::Flags Code::flags() {
2925 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2926}
2927
2928
2929void Code::set_flags(Code::Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00002930 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002931 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002932 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2933 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002934 ExtractArgumentsCountFromFlags(flags) >= 0);
2935 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2936}
2937
2938
2939Code::Kind Code::kind() {
2940 return ExtractKindFromFlags(flags());
2941}
2942
2943
Steve Blocka7e24c12009-10-30 11:49:00 +00002944InlineCacheState Code::ic_state() {
2945 InlineCacheState result = ExtractICStateFromFlags(flags());
2946 // Only allow uninitialized or debugger states for non-IC code
2947 // objects. This is used in the debugger to determine whether or not
2948 // a call to code object has been replaced with a debug break call.
2949 ASSERT(is_inline_cache_stub() ||
2950 result == UNINITIALIZED ||
2951 result == DEBUG_BREAK ||
2952 result == DEBUG_PREPARE_STEP_IN);
2953 return result;
2954}
2955
2956
Ben Murdochb8e0da22011-05-16 14:20:40 +01002957Code::ExtraICState Code::extra_ic_state() {
2958 ASSERT(is_inline_cache_stub());
2959 return ExtractExtraICStateFromFlags(flags());
2960}
2961
2962
Steve Blocka7e24c12009-10-30 11:49:00 +00002963PropertyType Code::type() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002964 return ExtractTypeFromFlags(flags());
2965}
2966
2967
2968int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002969 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002970 return ExtractArgumentsCountFromFlags(flags());
2971}
2972
2973
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002974int Code::major_key() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002975 ASSERT(kind() == STUB ||
Ben Murdoch257744e2011-11-30 15:57:28 +00002976 kind() == UNARY_OP_IC ||
2977 kind() == BINARY_OP_IC ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002978 kind() == COMPARE_IC ||
2979 kind() == TO_BOOLEAN_IC);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002980 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00002981}
2982
2983
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002984void Code::set_major_key(int major) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002985 ASSERT(kind() == STUB ||
Ben Murdoch257744e2011-11-30 15:57:28 +00002986 kind() == UNARY_OP_IC ||
2987 kind() == BINARY_OP_IC ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002988 kind() == COMPARE_IC ||
2989 kind() == TO_BOOLEAN_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002990 ASSERT(0 <= major && major < 256);
2991 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2992}
2993
2994
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002995bool Code::is_pregenerated() {
2996 return kind() == STUB && IsPregeneratedField::decode(flags());
2997}
2998
2999
3000void Code::set_is_pregenerated(bool value) {
3001 ASSERT(kind() == STUB);
3002 Flags f = flags();
3003 f = static_cast<Flags>(IsPregeneratedField::update(f, value));
3004 set_flags(f);
3005}
3006
3007
Ben Murdochb0fe1622011-05-05 13:52:32 +01003008bool Code::optimizable() {
3009 ASSERT(kind() == FUNCTION);
3010 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
3011}
3012
3013
3014void Code::set_optimizable(bool value) {
3015 ASSERT(kind() == FUNCTION);
3016 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
3017}
3018
3019
3020bool Code::has_deoptimization_support() {
3021 ASSERT(kind() == FUNCTION);
Ben Murdoch589d6972011-11-30 16:04:58 +00003022 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3023 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003024}
3025
3026
3027void Code::set_has_deoptimization_support(bool value) {
3028 ASSERT(kind() == FUNCTION);
Ben Murdoch589d6972011-11-30 16:04:58 +00003029 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3030 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
3031 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3032}
3033
3034
3035bool Code::has_debug_break_slots() {
3036 ASSERT(kind() == FUNCTION);
3037 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3038 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
3039}
3040
3041
3042void Code::set_has_debug_break_slots(bool value) {
3043 ASSERT(kind() == FUNCTION);
3044 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3045 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
3046 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003047}
3048
3049
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003050bool Code::is_compiled_optimizable() {
3051 ASSERT(kind() == FUNCTION);
3052 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3053 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
3054}
3055
3056
3057void Code::set_compiled_optimizable(bool value) {
3058 ASSERT(kind() == FUNCTION);
3059 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3060 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
3061 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3062}
3063
3064
3065bool Code::has_self_optimization_header() {
3066 ASSERT(kind() == FUNCTION);
3067 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3068 return FullCodeFlagsHasSelfOptimizationHeader::decode(flags);
3069}
3070
3071
3072void Code::set_self_optimization_header(bool value) {
3073 ASSERT(kind() == FUNCTION);
3074 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3075 flags = FullCodeFlagsHasSelfOptimizationHeader::update(flags, value);
3076 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3077}
3078
3079
Ben Murdochb0fe1622011-05-05 13:52:32 +01003080int Code::allow_osr_at_loop_nesting_level() {
3081 ASSERT(kind() == FUNCTION);
3082 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
3083}
3084
3085
3086void Code::set_allow_osr_at_loop_nesting_level(int level) {
3087 ASSERT(kind() == FUNCTION);
3088 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
3089 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
3090}
3091
3092
Ben Murdoch8f9999f2012-04-23 10:39:17 +01003093int Code::profiler_ticks() {
3094 ASSERT(kind() == FUNCTION);
3095 return READ_BYTE_FIELD(this, kProfilerTicksOffset);
3096}
3097
3098
3099void Code::set_profiler_ticks(int ticks) {
3100 ASSERT(kind() == FUNCTION);
3101 ASSERT(ticks < 256);
3102 WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
3103}
3104
3105
Ben Murdochb0fe1622011-05-05 13:52:32 +01003106unsigned Code::stack_slots() {
3107 ASSERT(kind() == OPTIMIZED_FUNCTION);
3108 return READ_UINT32_FIELD(this, kStackSlotsOffset);
3109}
3110
3111
3112void Code::set_stack_slots(unsigned slots) {
3113 ASSERT(kind() == OPTIMIZED_FUNCTION);
3114 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
3115}
3116
3117
Steve Block1e0659c2011-05-24 12:43:12 +01003118unsigned Code::safepoint_table_offset() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003119 ASSERT(kind() == OPTIMIZED_FUNCTION);
Steve Block1e0659c2011-05-24 12:43:12 +01003120 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003121}
3122
3123
Steve Block1e0659c2011-05-24 12:43:12 +01003124void Code::set_safepoint_table_offset(unsigned offset) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003125 ASSERT(kind() == OPTIMIZED_FUNCTION);
3126 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
Steve Block1e0659c2011-05-24 12:43:12 +01003127 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003128}
3129
3130
Steve Block1e0659c2011-05-24 12:43:12 +01003131unsigned Code::stack_check_table_offset() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003132 ASSERT(kind() == FUNCTION);
Steve Block1e0659c2011-05-24 12:43:12 +01003133 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003134}
3135
3136
Steve Block1e0659c2011-05-24 12:43:12 +01003137void Code::set_stack_check_table_offset(unsigned offset) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003138 ASSERT(kind() == FUNCTION);
3139 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
Steve Block1e0659c2011-05-24 12:43:12 +01003140 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003141}
3142
3143
3144CheckType Code::check_type() {
3145 ASSERT(is_call_stub() || is_keyed_call_stub());
3146 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
3147 return static_cast<CheckType>(type);
3148}
3149
3150
3151void Code::set_check_type(CheckType value) {
3152 ASSERT(is_call_stub() || is_keyed_call_stub());
3153 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
3154}
3155
3156
Ben Murdoch257744e2011-11-30 15:57:28 +00003157byte Code::unary_op_type() {
3158 ASSERT(is_unary_op_stub());
3159 return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
3160}
3161
3162
3163void Code::set_unary_op_type(byte value) {
3164 ASSERT(is_unary_op_stub());
3165 WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
3166}
3167
3168
3169byte Code::binary_op_type() {
3170 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003171 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3172}
3173
3174
Ben Murdoch257744e2011-11-30 15:57:28 +00003175void Code::set_binary_op_type(byte value) {
3176 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003177 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3178}
3179
3180
Ben Murdoch257744e2011-11-30 15:57:28 +00003181byte Code::binary_op_result_type() {
3182 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003183 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3184}
3185
3186
Ben Murdoch257744e2011-11-30 15:57:28 +00003187void Code::set_binary_op_result_type(byte value) {
3188 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003189 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3190}
3191
3192
3193byte Code::compare_state() {
3194 ASSERT(is_compare_ic_stub());
3195 return READ_BYTE_FIELD(this, kCompareStateOffset);
3196}
3197
3198
3199void Code::set_compare_state(byte value) {
3200 ASSERT(is_compare_ic_stub());
3201 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3202}
3203
3204
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003205byte Code::to_boolean_state() {
3206 ASSERT(is_to_boolean_ic_stub());
3207 return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3208}
3209
3210
3211void Code::set_to_boolean_state(byte value) {
3212 ASSERT(is_to_boolean_ic_stub());
3213 WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3214}
3215
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003216
3217bool Code::has_function_cache() {
3218 ASSERT(kind() == STUB);
3219 return READ_BYTE_FIELD(this, kHasFunctionCacheOffset) != 0;
3220}
3221
3222
3223void Code::set_has_function_cache(bool flag) {
3224 ASSERT(kind() == STUB);
3225 WRITE_BYTE_FIELD(this, kHasFunctionCacheOffset, flag);
3226}
3227
3228
Steve Blocka7e24c12009-10-30 11:49:00 +00003229bool Code::is_inline_cache_stub() {
3230 Kind kind = this->kind();
3231 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3232}
3233
3234
3235Code::Flags Code::ComputeFlags(Kind kind,
Steve Blocka7e24c12009-10-30 11:49:00 +00003236 InlineCacheState ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003237 ExtraICState extra_ic_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00003238 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01003239 int argc,
3240 InlineCacheHolderFlag holder) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003241 // Extra IC state is only allowed for call IC stubs or for store IC
3242 // stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003243 ASSERT(extra_ic_state == kNoExtraICState ||
Ben Murdoch589d6972011-11-30 16:04:58 +00003244 kind == CALL_IC ||
3245 kind == STORE_IC ||
3246 kind == KEYED_STORE_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00003247 // Compute the bit mask.
Ben Murdoch589d6972011-11-30 16:04:58 +00003248 int bits = KindField::encode(kind)
3249 | ICStateField::encode(ic_state)
3250 | TypeField::encode(type)
3251 | ExtraICStateField::encode(extra_ic_state)
3252 | (argc << kArgumentsCountShift)
3253 | CacheHolderField::encode(holder);
3254 return static_cast<Flags>(bits);
Steve Blocka7e24c12009-10-30 11:49:00 +00003255}
3256
3257
3258Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3259 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003260 ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01003261 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00003262 int argc) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003263 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00003264}
3265
3266
3267Code::Kind Code::ExtractKindFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003268 return KindField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003269}
3270
3271
3272InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003273 return ICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003274}
3275
3276
Ben Murdochb8e0da22011-05-16 14:20:40 +01003277Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003278 return ExtraICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003279}
3280
3281
3282PropertyType Code::ExtractTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003283 return TypeField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003284}
3285
3286
3287int Code::ExtractArgumentsCountFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003288 return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003289}
3290
3291
Steve Block8defd9f2010-07-08 12:39:36 +01003292InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003293 return CacheHolderField::decode(flags);
Steve Block8defd9f2010-07-08 12:39:36 +01003294}
3295
3296
Steve Blocka7e24c12009-10-30 11:49:00 +00003297Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003298 int bits = flags & ~TypeField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00003299 return static_cast<Flags>(bits);
3300}
3301
3302
3303Code* Code::GetCodeFromTargetAddress(Address address) {
3304 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3305 // GetCodeFromTargetAddress might be called when marking objects during mark
3306 // sweep. reinterpret_cast is therefore used instead of the more appropriate
3307 // Code::cast. Code::cast does not work when the object's map is
3308 // marked.
3309 Code* result = reinterpret_cast<Code*>(code);
3310 return result;
3311}
3312
3313
Steve Block791712a2010-08-27 10:21:07 +01003314Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3315 return HeapObject::
3316 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3317}
3318
3319
Steve Blocka7e24c12009-10-30 11:49:00 +00003320Object* Map::prototype() {
3321 return READ_FIELD(this, kPrototypeOffset);
3322}
3323
3324
3325void Map::set_prototype(Object* value, WriteBarrierMode mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003326 ASSERT(value->IsNull() || value->IsJSReceiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003327 WRITE_FIELD(this, kPrototypeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003328 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
Steve Block1e0659c2011-05-24 12:43:12 +01003329}
3330
3331
Ben Murdoch257744e2011-11-30 15:57:28 +00003332DescriptorArray* Map::instance_descriptors() {
3333 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3334 if (object->IsSmi()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003335 return GetHeap()->empty_descriptor_array();
Ben Murdoch257744e2011-11-30 15:57:28 +00003336 } else {
3337 return DescriptorArray::cast(object);
3338 }
3339}
3340
3341
3342void Map::init_instance_descriptors() {
3343 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3344}
3345
3346
3347void Map::clear_instance_descriptors() {
3348 Object* object = READ_FIELD(this,
3349 kInstanceDescriptorsOrBitField3Offset);
3350 if (!object->IsSmi()) {
3351 WRITE_FIELD(
3352 this,
3353 kInstanceDescriptorsOrBitField3Offset,
3354 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3355 }
3356}
3357
3358
3359void Map::set_instance_descriptors(DescriptorArray* value,
3360 WriteBarrierMode mode) {
3361 Object* object = READ_FIELD(this,
3362 kInstanceDescriptorsOrBitField3Offset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003363 Heap* heap = GetHeap();
3364 if (value == heap->empty_descriptor_array()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003365 clear_instance_descriptors();
3366 return;
3367 } else {
3368 if (object->IsSmi()) {
3369 value->set_bit_field3_storage(Smi::cast(object)->value());
3370 } else {
3371 value->set_bit_field3_storage(
3372 DescriptorArray::cast(object)->bit_field3_storage());
3373 }
3374 }
3375 ASSERT(!is_shared());
3376 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003377 CONDITIONAL_WRITE_BARRIER(
3378 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00003379}
3380
3381
3382int Map::bit_field3() {
3383 Object* object = READ_FIELD(this,
3384 kInstanceDescriptorsOrBitField3Offset);
3385 if (object->IsSmi()) {
3386 return Smi::cast(object)->value();
3387 } else {
3388 return DescriptorArray::cast(object)->bit_field3_storage();
3389 }
3390}
3391
3392
3393void Map::set_bit_field3(int value) {
3394 ASSERT(Smi::IsValid(value));
3395 Object* object = READ_FIELD(this,
3396 kInstanceDescriptorsOrBitField3Offset);
3397 if (object->IsSmi()) {
3398 WRITE_FIELD(this,
3399 kInstanceDescriptorsOrBitField3Offset,
3400 Smi::FromInt(value));
3401 } else {
3402 DescriptorArray::cast(object)->set_bit_field3_storage(value);
3403 }
3404}
3405
3406
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003407FixedArray* Map::unchecked_prototype_transitions() {
3408 return reinterpret_cast<FixedArray*>(
3409 READ_FIELD(this, kPrototypeTransitionsOffset));
3410}
3411
3412
Steve Block6ded16b2010-05-10 14:33:55 +01003413ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Block053d10c2011-06-13 19:13:29 +01003414ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003415ACCESSORS(Map, constructor, Object, kConstructorOffset)
3416
3417ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003418ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
3419ACCESSORS(JSFunction,
3420 next_function_link,
3421 Object,
3422 kNextFunctionLinkOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003423
3424ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3425ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3426ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3427
3428ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3429
3430ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3431ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3432ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3433ACCESSORS(AccessorInfo, name, Object, kNameOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003434ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
3435
3436ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
3437ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
Ben Murdochc7cc0282012-03-05 14:35:55 +00003438
Steve Blocka7e24c12009-10-30 11:49:00 +00003439ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3440ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3441ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3442
3443ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3444ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3445ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3446ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3447ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3448ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3449
3450ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3451ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3452
3453ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3454ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3455
3456ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3457ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3458ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3459 kPropertyAccessorsOffset)
3460ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3461 kPrototypeTemplateOffset)
3462ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3463ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3464 kNamedPropertyHandlerOffset)
3465ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3466 kIndexedPropertyHandlerOffset)
3467ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3468 kInstanceTemplateOffset)
3469ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3470ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3471ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3472 kInstanceCallHandlerOffset)
3473ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3474 kAccessCheckInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003475ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003476
3477ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3478ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3479 kInternalFieldCountOffset)
3480
3481ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3482ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3483
3484ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3485
3486ACCESSORS(Script, source, Object, kSourceOffset)
3487ACCESSORS(Script, name, Object, kNameOffset)
3488ACCESSORS(Script, id, Object, kIdOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003489ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
3490ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003491ACCESSORS(Script, data, Object, kDataOffset)
3492ACCESSORS(Script, context_data, Object, kContextOffset)
Ben Murdoch257744e2011-11-30 15:57:28 +00003493ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003494ACCESSORS_TO_SMI(Script, type, kTypeOffset)
3495ACCESSORS_TO_SMI(Script, compilation_type, kCompilationTypeOffset)
3496ACCESSORS_TO_SMI(Script, compilation_state, kCompilationStateOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003497ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00003498ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003499ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
3500 kEvalFrominstructionsOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003501
3502#ifdef ENABLE_DEBUGGER_SUPPORT
3503ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3504ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3505ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3506ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3507
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003508ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
3509ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
3510ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00003511ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3512#endif
3513
Steve Blocka7e24c12009-10-30 11:49:00 +00003514ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003515ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3516ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003517ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3518 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01003519ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003520ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3521ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3522ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3523ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3524 kThisPropertyAssignmentsOffset)
Ben Murdoch8f9999f2012-04-23 10:39:17 +01003525SMI_ACCESSORS(SharedFunctionInfo, ic_age, kICAgeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003526
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003527
Steve Blocka7e24c12009-10-30 11:49:00 +00003528BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3529 kHiddenPrototypeBit)
3530BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3531BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3532 kNeedsAccessCheckBit)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003533BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3534 kReadOnlyPrototypeBit)
Steve Blocka7e24c12009-10-30 11:49:00 +00003535BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3536 kIsExpressionBit)
3537BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3538 kIsTopLevelBit)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003539BOOL_GETTER(SharedFunctionInfo,
3540 compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00003541 has_only_simple_this_property_assignments,
3542 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00003543BOOL_ACCESSORS(SharedFunctionInfo,
3544 compiler_hints,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003545 allows_lazy_compilation,
3546 kAllowLazyCompilation)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003547BOOL_ACCESSORS(SharedFunctionInfo,
3548 compiler_hints,
3549 uses_arguments,
3550 kUsesArguments)
3551BOOL_ACCESSORS(SharedFunctionInfo,
3552 compiler_hints,
3553 has_duplicate_parameters,
3554 kHasDuplicateParameters)
Steve Blocka7e24c12009-10-30 11:49:00 +00003555
Iain Merrick75681382010-08-19 15:07:18 +01003556
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003557#if V8_HOST_ARCH_32_BIT
3558SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3559SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003560 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003561SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003562 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003563SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3564SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00003565 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003566SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3567SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00003568 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003569SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00003570 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003571SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003572 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003573SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003574SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3575SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003576#else
Steve Blocka7e24c12009-10-30 11:49:00 +00003577
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003578#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003579 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003580 int holder::name() { \
3581 int value = READ_INT_FIELD(this, offset); \
3582 ASSERT(kHeapObjectTag == 1); \
3583 ASSERT((value & kHeapObjectTag) == 0); \
3584 return value >> 1; \
3585 } \
3586 void holder::set_##name(int value) { \
3587 ASSERT(kHeapObjectTag == 1); \
3588 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3589 (value & 0xC0000000) == 0x000000000); \
3590 WRITE_INT_FIELD(this, \
3591 offset, \
3592 (value << 1) & ~kHeapObjectTag); \
3593 }
3594
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003595#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3596 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003597 INT_ACCESSORS(holder, name, offset)
3598
3599
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003600PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003601PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3602 formal_parameter_count,
3603 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003604
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003605PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3606 expected_nof_properties,
3607 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003608PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3609
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003610PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3611PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3612 start_position_and_type,
3613 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003614
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003615PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3616 function_token_position,
3617 kFunctionTokenPositionOffset)
3618PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3619 compiler_hints,
3620 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003621
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003622PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3623 this_property_assignments_count,
3624 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003625PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003626
3627PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3628PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003629#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003630
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003631
3632int SharedFunctionInfo::construction_count() {
3633 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3634}
3635
3636
3637void SharedFunctionInfo::set_construction_count(int value) {
3638 ASSERT(0 <= value && value < 256);
3639 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3640}
3641
3642
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003643BOOL_ACCESSORS(SharedFunctionInfo,
3644 compiler_hints,
3645 live_objects_may_exist,
3646 kLiveObjectsMayExist)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003647
3648
3649bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003650 return initial_map() != GetHeap()->undefined_value();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003651}
3652
3653
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003654BOOL_GETTER(SharedFunctionInfo,
3655 compiler_hints,
3656 optimization_disabled,
3657 kOptimizationDisabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003658
3659
3660void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3661 set_compiler_hints(BooleanBit::set(compiler_hints(),
3662 kOptimizationDisabled,
3663 disable));
3664 // If disabling optimizations we reflect that in the code object so
3665 // it will not be counted as optimizable code.
3666 if ((code()->kind() == Code::FUNCTION) && disable) {
3667 code()->set_optimizable(false);
3668 }
3669}
3670
3671
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003672LanguageMode SharedFunctionInfo::language_mode() {
3673 int hints = compiler_hints();
3674 if (BooleanBit::get(hints, kExtendedModeFunction)) {
3675 ASSERT(BooleanBit::get(hints, kStrictModeFunction));
3676 return EXTENDED_MODE;
3677 }
3678 return BooleanBit::get(hints, kStrictModeFunction)
3679 ? STRICT_MODE : CLASSIC_MODE;
3680}
3681
3682
3683void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
3684 // We only allow language mode transitions that go set the same language mode
3685 // again or go up in the chain:
3686 // CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
3687 ASSERT(this->language_mode() == CLASSIC_MODE ||
3688 this->language_mode() == language_mode ||
3689 language_mode == EXTENDED_MODE);
3690 int hints = compiler_hints();
3691 hints = BooleanBit::set(
3692 hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
3693 hints = BooleanBit::set(
3694 hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
3695 set_compiler_hints(hints);
3696}
3697
3698
3699bool SharedFunctionInfo::is_classic_mode() {
3700 return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
3701}
3702
3703BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
3704 kExtendedModeFunction)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003705BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3706BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3707 name_should_print_as_anonymous,
3708 kNameShouldPrintAsAnonymous)
3709BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3710BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003711BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
3712BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
3713 kDontOptimize)
3714BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
Ben Murdoch257744e2011-11-30 15:57:28 +00003715
Steve Block6ded16b2010-05-10 14:33:55 +01003716ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3717ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3718
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003719ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3720
Steve Block3ce2e202009-11-05 08:53:23 +00003721bool Script::HasValidSource() {
3722 Object* src = this->source();
3723 if (!src->IsString()) return true;
3724 String* src_str = String::cast(src);
3725 if (!StringShape(src_str).IsExternal()) return true;
3726 if (src_str->IsAsciiRepresentation()) {
3727 return ExternalAsciiString::cast(src)->resource() != NULL;
3728 } else if (src_str->IsTwoByteRepresentation()) {
3729 return ExternalTwoByteString::cast(src)->resource() != NULL;
3730 }
3731 return true;
3732}
3733
3734
Steve Blocka7e24c12009-10-30 11:49:00 +00003735void SharedFunctionInfo::DontAdaptArguments() {
3736 ASSERT(code()->kind() == Code::BUILTIN);
3737 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3738}
3739
3740
3741int SharedFunctionInfo::start_position() {
3742 return start_position_and_type() >> kStartPositionShift;
3743}
3744
3745
3746void SharedFunctionInfo::set_start_position(int start_position) {
3747 set_start_position_and_type((start_position << kStartPositionShift)
3748 | (start_position_and_type() & ~kStartPositionMask));
3749}
3750
3751
3752Code* SharedFunctionInfo::code() {
3753 return Code::cast(READ_FIELD(this, kCodeOffset));
3754}
3755
3756
Iain Merrick75681382010-08-19 15:07:18 +01003757Code* SharedFunctionInfo::unchecked_code() {
3758 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3759}
3760
3761
Steve Blocka7e24c12009-10-30 11:49:00 +00003762void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3763 WRITE_FIELD(this, kCodeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003764 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003765}
3766
3767
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003768ScopeInfo* SharedFunctionInfo::scope_info() {
3769 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003770}
3771
3772
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003773void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003774 WriteBarrierMode mode) {
3775 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003776 CONDITIONAL_WRITE_BARRIER(GetHeap(),
3777 this,
3778 kScopeInfoOffset,
3779 reinterpret_cast<Object*>(value),
3780 mode);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003781}
3782
3783
Steve Blocka7e24c12009-10-30 11:49:00 +00003784bool SharedFunctionInfo::is_compiled() {
Steve Block44f0eee2011-05-26 01:26:41 +01003785 return code() !=
3786 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003787}
3788
3789
Steve Block6ded16b2010-05-10 14:33:55 +01003790bool SharedFunctionInfo::IsApiFunction() {
3791 return function_data()->IsFunctionTemplateInfo();
3792}
3793
3794
3795FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3796 ASSERT(IsApiFunction());
3797 return FunctionTemplateInfo::cast(function_data());
3798}
3799
3800
Ben Murdochb0fe1622011-05-05 13:52:32 +01003801bool SharedFunctionInfo::HasBuiltinFunctionId() {
Kristian Monsen25f61362010-05-21 11:50:48 +01003802 return function_data()->IsSmi();
3803}
3804
3805
Ben Murdochb0fe1622011-05-05 13:52:32 +01003806BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3807 ASSERT(HasBuiltinFunctionId());
3808 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003809}
3810
3811
Iain Merrick75681382010-08-19 15:07:18 +01003812int SharedFunctionInfo::code_age() {
3813 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3814}
3815
3816
3817void SharedFunctionInfo::set_code_age(int code_age) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003818 int hints = compiler_hints() & ~(kCodeAgeMask << kCodeAgeShift);
3819 set_compiler_hints(hints | ((code_age & kCodeAgeMask) << kCodeAgeShift));
Iain Merrick75681382010-08-19 15:07:18 +01003820}
3821
3822
Ben Murdochb0fe1622011-05-05 13:52:32 +01003823bool SharedFunctionInfo::has_deoptimization_support() {
3824 Code* code = this->code();
3825 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3826}
3827
3828
Steve Blocka7e24c12009-10-30 11:49:00 +00003829bool JSFunction::IsBuiltin() {
3830 return context()->global()->IsJSBuiltinsObject();
3831}
3832
3833
Ben Murdochb0fe1622011-05-05 13:52:32 +01003834bool JSFunction::NeedsArgumentsAdaption() {
3835 return shared()->formal_parameter_count() !=
3836 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3837}
3838
3839
3840bool JSFunction::IsOptimized() {
3841 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3842}
3843
3844
Ben Murdoch8b112d22011-06-08 16:22:53 +01003845bool JSFunction::IsOptimizable() {
3846 return code()->kind() == Code::FUNCTION && code()->optimizable();
3847}
3848
3849
Ben Murdochb0fe1622011-05-05 13:52:32 +01003850bool JSFunction::IsMarkedForLazyRecompilation() {
Steve Block44f0eee2011-05-26 01:26:41 +01003851 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003852}
3853
3854
Steve Blocka7e24c12009-10-30 11:49:00 +00003855Code* JSFunction::code() {
Steve Block791712a2010-08-27 10:21:07 +01003856 return Code::cast(unchecked_code());
Iain Merrick75681382010-08-19 15:07:18 +01003857}
3858
3859
3860Code* JSFunction::unchecked_code() {
Steve Block791712a2010-08-27 10:21:07 +01003861 return reinterpret_cast<Code*>(
3862 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003863}
3864
3865
3866void JSFunction::set_code(Code* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003867 ASSERT(!HEAP->InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01003868 Address entry = value->entry();
3869 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003870 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
3871 this,
3872 HeapObject::RawField(this, kCodeEntryOffset),
3873 value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003874}
3875
3876
Ben Murdochb0fe1622011-05-05 13:52:32 +01003877void JSFunction::ReplaceCode(Code* code) {
3878 bool was_optimized = IsOptimized();
3879 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3880
3881 set_code(code);
3882
3883 // Add/remove the function from the list of optimized functions for this
3884 // context based on the state change.
3885 if (!was_optimized && is_optimized) {
3886 context()->global_context()->AddOptimizedFunction(this);
3887 }
3888 if (was_optimized && !is_optimized) {
3889 context()->global_context()->RemoveOptimizedFunction(this);
3890 }
3891}
3892
3893
Steve Blocka7e24c12009-10-30 11:49:00 +00003894Context* JSFunction::context() {
3895 return Context::cast(READ_FIELD(this, kContextOffset));
3896}
3897
3898
3899Object* JSFunction::unchecked_context() {
3900 return READ_FIELD(this, kContextOffset);
3901}
3902
3903
Iain Merrick75681382010-08-19 15:07:18 +01003904SharedFunctionInfo* JSFunction::unchecked_shared() {
3905 return reinterpret_cast<SharedFunctionInfo*>(
3906 READ_FIELD(this, kSharedFunctionInfoOffset));
3907}
3908
3909
Steve Blocka7e24c12009-10-30 11:49:00 +00003910void JSFunction::set_context(Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003911 ASSERT(value->IsUndefined() || value->IsContext());
Steve Blocka7e24c12009-10-30 11:49:00 +00003912 WRITE_FIELD(this, kContextOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003913 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003914}
3915
3916ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3917 kPrototypeOrInitialMapOffset)
3918
3919
3920Map* JSFunction::initial_map() {
3921 return Map::cast(prototype_or_initial_map());
3922}
3923
3924
3925void JSFunction::set_initial_map(Map* value) {
3926 set_prototype_or_initial_map(value);
3927}
3928
3929
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003930MaybeObject* JSFunction::set_initial_map_and_cache_transitions(
3931 Map* initial_map) {
3932 Context* global_context = context()->global_context();
3933 Object* array_function =
3934 global_context->get(Context::ARRAY_FUNCTION_INDEX);
3935 if (array_function->IsJSFunction() &&
3936 this == JSFunction::cast(array_function)) {
3937 ASSERT(initial_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
3938
3939 MaybeObject* maybe_map = initial_map->CopyDropTransitions();
3940 Map* new_double_map = NULL;
3941 if (!maybe_map->To<Map>(&new_double_map)) return maybe_map;
3942 new_double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
3943 maybe_map = initial_map->AddElementsTransition(FAST_DOUBLE_ELEMENTS,
3944 new_double_map);
3945 if (maybe_map->IsFailure()) return maybe_map;
3946
3947 maybe_map = new_double_map->CopyDropTransitions();
3948 Map* new_object_map = NULL;
3949 if (!maybe_map->To<Map>(&new_object_map)) return maybe_map;
3950 new_object_map->set_elements_kind(FAST_ELEMENTS);
3951 maybe_map = new_double_map->AddElementsTransition(FAST_ELEMENTS,
3952 new_object_map);
3953 if (maybe_map->IsFailure()) return maybe_map;
3954
3955 global_context->set_smi_js_array_map(initial_map);
3956 global_context->set_double_js_array_map(new_double_map);
3957 global_context->set_object_js_array_map(new_object_map);
3958 }
3959 set_initial_map(initial_map);
3960 return this;
3961}
3962
3963
Steve Blocka7e24c12009-10-30 11:49:00 +00003964bool JSFunction::has_initial_map() {
3965 return prototype_or_initial_map()->IsMap();
3966}
3967
3968
3969bool JSFunction::has_instance_prototype() {
3970 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3971}
3972
3973
3974bool JSFunction::has_prototype() {
3975 return map()->has_non_instance_prototype() || has_instance_prototype();
3976}
3977
3978
3979Object* JSFunction::instance_prototype() {
3980 ASSERT(has_instance_prototype());
3981 if (has_initial_map()) return initial_map()->prototype();
3982 // When there is no initial map and the prototype is a JSObject, the
3983 // initial map field is used for the prototype field.
3984 return prototype_or_initial_map();
3985}
3986
3987
3988Object* JSFunction::prototype() {
3989 ASSERT(has_prototype());
3990 // If the function's prototype property has been set to a non-JSObject
3991 // value, that value is stored in the constructor field of the map.
3992 if (map()->has_non_instance_prototype()) return map()->constructor();
3993 return instance_prototype();
3994}
3995
Steve Block6ded16b2010-05-10 14:33:55 +01003996bool JSFunction::should_have_prototype() {
3997 return map()->function_with_prototype();
3998}
3999
Steve Blocka7e24c12009-10-30 11:49:00 +00004000
4001bool JSFunction::is_compiled() {
Steve Block44f0eee2011-05-26 01:26:41 +01004002 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00004003}
4004
4005
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004006FixedArray* JSFunction::literals() {
4007 ASSERT(!shared()->bound());
4008 return literals_or_bindings();
4009}
4010
4011
4012void JSFunction::set_literals(FixedArray* literals) {
4013 ASSERT(!shared()->bound());
4014 set_literals_or_bindings(literals);
4015}
4016
4017
4018FixedArray* JSFunction::function_bindings() {
4019 ASSERT(shared()->bound());
4020 return literals_or_bindings();
4021}
4022
4023
4024void JSFunction::set_function_bindings(FixedArray* bindings) {
4025 ASSERT(shared()->bound());
4026 // Bound function literal may be initialized to the empty fixed array
4027 // before the bindings are set.
4028 ASSERT(bindings == GetHeap()->empty_fixed_array() ||
4029 bindings->map() == GetHeap()->fixed_cow_array_map());
4030 set_literals_or_bindings(bindings);
4031}
4032
4033
Steve Blocka7e24c12009-10-30 11:49:00 +00004034int JSFunction::NumberOfLiterals() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004035 ASSERT(!shared()->bound());
Steve Blocka7e24c12009-10-30 11:49:00 +00004036 return literals()->length();
4037}
4038
4039
4040Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004041 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004042 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00004043}
4044
4045
4046void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
4047 Object* value) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004048 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004049 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004050 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
Steve Block6ded16b2010-05-10 14:33:55 +01004051}
4052
4053
4054Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004055 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004056 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
4057}
4058
4059
4060void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
4061 Code* value) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004062 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004063 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
Steve Block44f0eee2011-05-26 01:26:41 +01004064 ASSERT(!HEAP->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00004065}
4066
4067
Ben Murdoch257744e2011-11-30 15:57:28 +00004068ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004069ACCESSORS(JSProxy, hash, Object, kHashOffset)
Ben Murdoch589d6972011-11-30 16:04:58 +00004070ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
4071ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
4072
4073
4074void JSProxy::InitializeBody(int object_size, Object* value) {
4075 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
4076 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
4077 WRITE_FIELD(this, offset, value);
4078 }
4079}
Ben Murdoch257744e2011-11-30 15:57:28 +00004080
4081
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004082ACCESSORS(JSSet, table, Object, kTableOffset)
4083ACCESSORS(JSMap, table, Object, kTableOffset)
4084ACCESSORS(JSWeakMap, table, Object, kTableOffset)
4085ACCESSORS(JSWeakMap, next, Object, kNextOffset)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004086
4087
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004088Address Foreign::foreign_address() {
4089 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004090}
4091
4092
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004093void Foreign::set_foreign_address(Address value) {
4094 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00004095}
4096
4097
Steve Blocka7e24c12009-10-30 11:49:00 +00004098ACCESSORS(JSValue, value, Object, kValueOffset)
4099
4100
4101JSValue* JSValue::cast(Object* obj) {
4102 ASSERT(obj->IsJSValue());
4103 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
4104 return reinterpret_cast<JSValue*>(obj);
4105}
4106
4107
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004108ACCESSORS(JSDate, value, Object, kValueOffset)
4109ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
4110ACCESSORS(JSDate, year, Object, kYearOffset)
4111ACCESSORS(JSDate, month, Object, kMonthOffset)
4112ACCESSORS(JSDate, day, Object, kDayOffset)
4113ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
4114ACCESSORS(JSDate, hour, Object, kHourOffset)
4115ACCESSORS(JSDate, min, Object, kMinOffset)
4116ACCESSORS(JSDate, sec, Object, kSecOffset)
4117
4118
4119JSDate* JSDate::cast(Object* obj) {
4120 ASSERT(obj->IsJSDate());
4121 ASSERT(HeapObject::cast(obj)->Size() == JSDate::kSize);
4122 return reinterpret_cast<JSDate*>(obj);
4123}
4124
4125
Steve Block1e0659c2011-05-24 12:43:12 +01004126ACCESSORS(JSMessageObject, type, String, kTypeOffset)
4127ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
4128ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
4129ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
4130ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
4131SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
4132SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
4133
4134
4135JSMessageObject* JSMessageObject::cast(Object* obj) {
4136 ASSERT(obj->IsJSMessageObject());
4137 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
4138 return reinterpret_cast<JSMessageObject*>(obj);
4139}
4140
4141
Steve Blocka7e24c12009-10-30 11:49:00 +00004142INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01004143ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004144ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004145ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004146ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
4147ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
4148INT_ACCESSORS(Code, ic_age, kICAgeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00004149
4150byte* Code::instruction_start() {
4151 return FIELD_ADDR(this, kHeaderSize);
4152}
4153
4154
Leon Clarkeac952652010-07-15 11:15:24 +01004155byte* Code::instruction_end() {
4156 return instruction_start() + instruction_size();
4157}
4158
4159
Steve Blocka7e24c12009-10-30 11:49:00 +00004160int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01004161 return RoundUp(instruction_size(), kObjectAlignment);
4162}
4163
4164
Ben Murdochb0fe1622011-05-05 13:52:32 +01004165FixedArray* Code::unchecked_deoptimization_data() {
4166 return reinterpret_cast<FixedArray*>(
4167 READ_FIELD(this, kDeoptimizationDataOffset));
4168}
4169
4170
Leon Clarkeac952652010-07-15 11:15:24 +01004171ByteArray* Code::unchecked_relocation_info() {
4172 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00004173}
4174
4175
4176byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01004177 return unchecked_relocation_info()->GetDataStartAddress();
4178}
4179
4180
4181int Code::relocation_size() {
4182 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00004183}
4184
4185
4186byte* Code::entry() {
4187 return instruction_start();
4188}
4189
4190
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004191bool Code::contains(byte* inner_pointer) {
4192 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
Steve Blocka7e24c12009-10-30 11:49:00 +00004193}
4194
4195
Steve Blocka7e24c12009-10-30 11:49:00 +00004196ACCESSORS(JSArray, length, Object, kLengthOffset)
4197
4198
4199ACCESSORS(JSRegExp, data, Object, kDataOffset)
4200
4201
4202JSRegExp::Type JSRegExp::TypeTag() {
4203 Object* data = this->data();
4204 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
4205 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
4206 return static_cast<JSRegExp::Type>(smi->value());
4207}
4208
4209
Ben Murdoch257744e2011-11-30 15:57:28 +00004210JSRegExp::Type JSRegExp::TypeTagUnchecked() {
4211 Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
4212 return static_cast<JSRegExp::Type>(smi->value());
4213}
4214
4215
Steve Blocka7e24c12009-10-30 11:49:00 +00004216int JSRegExp::CaptureCount() {
4217 switch (TypeTag()) {
4218 case ATOM:
4219 return 0;
4220 case IRREGEXP:
4221 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
4222 default:
4223 UNREACHABLE();
4224 return -1;
4225 }
4226}
4227
4228
4229JSRegExp::Flags JSRegExp::GetFlags() {
4230 ASSERT(this->data()->IsFixedArray());
4231 Object* data = this->data();
4232 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
4233 return Flags(smi->value());
4234}
4235
4236
4237String* JSRegExp::Pattern() {
4238 ASSERT(this->data()->IsFixedArray());
4239 Object* data = this->data();
4240 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4241 return pattern;
4242}
4243
4244
4245Object* JSRegExp::DataAt(int index) {
4246 ASSERT(TypeTag() != NOT_COMPILED);
4247 return FixedArray::cast(data())->get(index);
4248}
4249
4250
Ben Murdoch257744e2011-11-30 15:57:28 +00004251Object* JSRegExp::DataAtUnchecked(int index) {
4252 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4253 int offset = FixedArray::kHeaderSize + index * kPointerSize;
4254 return READ_FIELD(fa, offset);
4255}
4256
4257
Steve Blocka7e24c12009-10-30 11:49:00 +00004258void JSRegExp::SetDataAt(int index, Object* value) {
4259 ASSERT(TypeTag() != NOT_COMPILED);
4260 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4261 FixedArray::cast(data())->set(index, value);
4262}
4263
4264
Ben Murdoch257744e2011-11-30 15:57:28 +00004265void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4266 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4267 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4268 if (value->IsSmi()) {
4269 fa->set_unchecked(index, Smi::cast(value));
4270 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004271 // We only do this during GC, so we don't need to notify the write barrier.
Ben Murdoch257744e2011-11-30 15:57:28 +00004272 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4273 }
4274}
4275
4276
Ben Murdoch589d6972011-11-30 16:04:58 +00004277ElementsKind JSObject::GetElementsKind() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004278 ElementsKind kind = map()->elements_kind();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004279#if DEBUG
4280 FixedArrayBase* fixed_array =
4281 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
4282 Map* map = fixed_array->map();
4283 ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) &&
4284 (map == GetHeap()->fixed_array_map() ||
4285 map == GetHeap()->fixed_cow_array_map())) ||
4286 (kind == FAST_DOUBLE_ELEMENTS &&
4287 (fixed_array->IsFixedDoubleArray() ||
4288 fixed_array == GetHeap()->empty_fixed_array())) ||
4289 (kind == DICTIONARY_ELEMENTS &&
4290 fixed_array->IsFixedArray() &&
4291 fixed_array->IsDictionary()) ||
4292 (kind > DICTIONARY_ELEMENTS));
4293 ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
4294 (elements()->IsFixedArray() && elements()->length() >= 2));
4295#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004296 return kind;
Steve Blocka7e24c12009-10-30 11:49:00 +00004297}
4298
4299
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004300ElementsAccessor* JSObject::GetElementsAccessor() {
4301 return ElementsAccessor::ForKind(GetElementsKind());
4302}
4303
4304
Steve Blocka7e24c12009-10-30 11:49:00 +00004305bool JSObject::HasFastElements() {
4306 return GetElementsKind() == FAST_ELEMENTS;
4307}
4308
4309
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004310bool JSObject::HasFastSmiOnlyElements() {
4311 return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS;
4312}
4313
4314
4315bool JSObject::HasFastTypeElements() {
4316 ElementsKind elements_kind = GetElementsKind();
4317 return elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4318 elements_kind == FAST_ELEMENTS;
4319}
4320
4321
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004322bool JSObject::HasFastDoubleElements() {
4323 return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4324}
4325
4326
Steve Blocka7e24c12009-10-30 11:49:00 +00004327bool JSObject::HasDictionaryElements() {
4328 return GetElementsKind() == DICTIONARY_ELEMENTS;
4329}
4330
4331
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004332bool JSObject::HasNonStrictArgumentsElements() {
4333 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4334}
4335
4336
Steve Block3ce2e202009-11-05 08:53:23 +00004337bool JSObject::HasExternalArrayElements() {
Steve Block44f0eee2011-05-26 01:26:41 +01004338 HeapObject* array = elements();
4339 ASSERT(array != NULL);
4340 return array->IsExternalArray();
Steve Block3ce2e202009-11-05 08:53:23 +00004341}
4342
4343
Steve Block44f0eee2011-05-26 01:26:41 +01004344#define EXTERNAL_ELEMENTS_CHECK(name, type) \
4345bool JSObject::HasExternal##name##Elements() { \
4346 HeapObject* array = elements(); \
4347 ASSERT(array != NULL); \
4348 if (!array->IsHeapObject()) \
4349 return false; \
4350 return array->map()->instance_type() == type; \
Steve Block3ce2e202009-11-05 08:53:23 +00004351}
4352
4353
Steve Block44f0eee2011-05-26 01:26:41 +01004354EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4355EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4356EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4357EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4358 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4359EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4360EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4361 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4362EXTERNAL_ELEMENTS_CHECK(Float,
4363 EXTERNAL_FLOAT_ARRAY_TYPE)
Ben Murdoch257744e2011-11-30 15:57:28 +00004364EXTERNAL_ELEMENTS_CHECK(Double,
4365 EXTERNAL_DOUBLE_ARRAY_TYPE)
Steve Block44f0eee2011-05-26 01:26:41 +01004366EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
Steve Block3ce2e202009-11-05 08:53:23 +00004367
4368
Steve Blocka7e24c12009-10-30 11:49:00 +00004369bool JSObject::HasNamedInterceptor() {
4370 return map()->has_named_interceptor();
4371}
4372
4373
4374bool JSObject::HasIndexedInterceptor() {
4375 return map()->has_indexed_interceptor();
4376}
4377
4378
John Reck59135872010-11-02 12:39:01 -07004379MaybeObject* JSObject::EnsureWritableFastElements() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004380 ASSERT(HasFastTypeElements());
Iain Merrick75681382010-08-19 15:07:18 +01004381 FixedArray* elems = FixedArray::cast(elements());
Steve Block44f0eee2011-05-26 01:26:41 +01004382 Isolate* isolate = GetIsolate();
4383 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
John Reck59135872010-11-02 12:39:01 -07004384 Object* writable_elems;
Steve Block44f0eee2011-05-26 01:26:41 +01004385 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4386 elems, isolate->heap()->fixed_array_map());
John Reck59135872010-11-02 12:39:01 -07004387 if (!maybe_writable_elems->ToObject(&writable_elems)) {
4388 return maybe_writable_elems;
4389 }
4390 }
Iain Merrick75681382010-08-19 15:07:18 +01004391 set_elements(FixedArray::cast(writable_elems));
Steve Block44f0eee2011-05-26 01:26:41 +01004392 isolate->counters()->cow_arrays_converted()->Increment();
Iain Merrick75681382010-08-19 15:07:18 +01004393 return writable_elems;
4394}
4395
4396
Steve Blocka7e24c12009-10-30 11:49:00 +00004397StringDictionary* JSObject::property_dictionary() {
4398 ASSERT(!HasFastProperties());
4399 return StringDictionary::cast(properties());
4400}
4401
4402
Ben Murdochc7cc0282012-03-05 14:35:55 +00004403SeededNumberDictionary* JSObject::element_dictionary() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004404 ASSERT(HasDictionaryElements());
Ben Murdochc7cc0282012-03-05 14:35:55 +00004405 return SeededNumberDictionary::cast(elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00004406}
4407
4408
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004409bool String::IsHashFieldComputed(uint32_t field) {
4410 return (field & kHashNotComputedMask) == 0;
4411}
4412
4413
Steve Blocka7e24c12009-10-30 11:49:00 +00004414bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004415 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00004416}
4417
4418
4419uint32_t String::Hash() {
4420 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00004421 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004422 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00004423 // Slow case: compute hash code and set it.
4424 return ComputeAndSetHash();
4425}
4426
4427
Ben Murdochc7cc0282012-03-05 14:35:55 +00004428StringHasher::StringHasher(int length, uint32_t seed)
Steve Blocka7e24c12009-10-30 11:49:00 +00004429 : length_(length),
Ben Murdochc7cc0282012-03-05 14:35:55 +00004430 raw_running_hash_(seed),
Steve Blocka7e24c12009-10-30 11:49:00 +00004431 array_index_(0),
4432 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4433 is_first_char_(true),
Ben Murdochc7cc0282012-03-05 14:35:55 +00004434 is_valid_(true) {
4435 ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
4436}
Steve Blocka7e24c12009-10-30 11:49:00 +00004437
4438
4439bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00004440 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00004441}
4442
4443
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004444void StringHasher::AddCharacter(uint32_t c) {
4445 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4446 AddSurrogatePair(c); // Not inlined.
4447 return;
4448 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004449 // Use the Jenkins one-at-a-time hash function to update the hash
4450 // for the given character.
4451 raw_running_hash_ += c;
4452 raw_running_hash_ += (raw_running_hash_ << 10);
4453 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4454 // Incremental array index computation.
4455 if (is_array_index_) {
4456 if (c < '0' || c > '9') {
4457 is_array_index_ = false;
4458 } else {
4459 int d = c - '0';
4460 if (is_first_char_) {
4461 is_first_char_ = false;
4462 if (c == '0' && length_ > 1) {
4463 is_array_index_ = false;
4464 return;
4465 }
4466 }
4467 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4468 is_array_index_ = false;
4469 } else {
4470 array_index_ = array_index_ * 10 + d;
4471 }
4472 }
4473 }
4474}
4475
4476
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004477void StringHasher::AddCharacterNoIndex(uint32_t c) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004478 ASSERT(!is_array_index());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004479 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4480 AddSurrogatePairNoIndex(c); // Not inlined.
4481 return;
4482 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004483 raw_running_hash_ += c;
4484 raw_running_hash_ += (raw_running_hash_ << 10);
4485 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4486}
4487
4488
4489uint32_t StringHasher::GetHash() {
4490 // Get the calculated raw hash value and do some more bit ops to distribute
4491 // the hash further. Ensure that we never return zero as the hash value.
4492 uint32_t result = raw_running_hash_;
4493 result += (result << 3);
4494 result ^= (result >> 11);
4495 result += (result << 15);
Ben Murdochc7cc0282012-03-05 14:35:55 +00004496 if ((result & String::kHashBitMask) == 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004497 result = 27;
4498 }
4499 return result;
4500}
4501
4502
Steve Block44f0eee2011-05-26 01:26:41 +01004503template <typename schar>
Ben Murdochc7cc0282012-03-05 14:35:55 +00004504uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) {
4505 StringHasher hasher(length, seed);
Steve Block44f0eee2011-05-26 01:26:41 +01004506 if (!hasher.has_trivial_hash()) {
4507 int i;
4508 for (i = 0; hasher.is_array_index() && (i < length); i++) {
4509 hasher.AddCharacter(chars[i]);
4510 }
4511 for (; i < length; i++) {
4512 hasher.AddCharacterNoIndex(chars[i]);
4513 }
4514 }
4515 return hasher.GetHashField();
4516}
4517
4518
Steve Blocka7e24c12009-10-30 11:49:00 +00004519bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00004520 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004521 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4522 return false;
4523 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004524 return SlowAsArrayIndex(index);
4525}
4526
4527
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004528Object* JSReceiver::GetPrototype() {
4529 return HeapObject::cast(this)->map()->prototype();
Steve Blocka7e24c12009-10-30 11:49:00 +00004530}
4531
4532
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004533bool JSReceiver::HasProperty(String* name) {
4534 if (IsJSProxy()) {
4535 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4536 }
4537 return GetPropertyAttribute(name) != ABSENT;
4538}
4539
4540
4541bool JSReceiver::HasLocalProperty(String* name) {
4542 if (IsJSProxy()) {
4543 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4544 }
4545 return GetLocalPropertyAttribute(name) != ABSENT;
4546}
4547
4548
4549PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004550 return GetPropertyAttributeWithReceiver(this, key);
4551}
4552
Steve Blockd0582a62009-12-15 09:54:21 +00004553// TODO(504): this may be useful in other places too where JSGlobalProxy
4554// is used.
4555Object* JSObject::BypassGlobalProxy() {
4556 if (IsJSGlobalProxy()) {
4557 Object* proto = GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01004558 if (proto->IsNull()) return GetHeap()->undefined_value();
Steve Blockd0582a62009-12-15 09:54:21 +00004559 ASSERT(proto->IsJSGlobalObject());
4560 return proto;
4561 }
4562 return this;
4563}
4564
4565
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004566MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
4567 return IsJSProxy()
4568 ? JSProxy::cast(this)->GetIdentityHash(flag)
4569 : JSObject::cast(this)->GetIdentityHash(flag);
Steve Blockd0582a62009-12-15 09:54:21 +00004570}
4571
4572
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004573bool JSReceiver::HasElement(uint32_t index) {
4574 if (IsJSProxy()) {
4575 return JSProxy::cast(this)->HasElementWithHandler(index);
4576 }
4577 return JSObject::cast(this)->HasElementWithReceiver(this, index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004578}
4579
4580
4581bool AccessorInfo::all_can_read() {
4582 return BooleanBit::get(flag(), kAllCanReadBit);
4583}
4584
4585
4586void AccessorInfo::set_all_can_read(bool value) {
4587 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4588}
4589
4590
4591bool AccessorInfo::all_can_write() {
4592 return BooleanBit::get(flag(), kAllCanWriteBit);
4593}
4594
4595
4596void AccessorInfo::set_all_can_write(bool value) {
4597 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4598}
4599
4600
4601bool AccessorInfo::prohibits_overwriting() {
4602 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4603}
4604
4605
4606void AccessorInfo::set_prohibits_overwriting(bool value) {
4607 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4608}
4609
4610
4611PropertyAttributes AccessorInfo::property_attributes() {
4612 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4613}
4614
4615
4616void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004617 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
Steve Blocka7e24c12009-10-30 11:49:00 +00004618}
4619
Ben Murdoch8b112d22011-06-08 16:22:53 +01004620
4621template<typename Shape, typename Key>
4622void Dictionary<Shape, Key>::SetEntry(int entry,
4623 Object* key,
4624 Object* value) {
4625 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4626}
4627
4628
Steve Blocka7e24c12009-10-30 11:49:00 +00004629template<typename Shape, typename Key>
4630void Dictionary<Shape, Key>::SetEntry(int entry,
4631 Object* key,
4632 Object* value,
4633 PropertyDetails details) {
4634 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4635 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00004636 AssertNoAllocation no_gc;
4637 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00004638 FixedArray::set(index, key, mode);
4639 FixedArray::set(index+1, value, mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004640 FixedArray::set(index+2, details.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00004641}
4642
4643
Steve Block44f0eee2011-05-26 01:26:41 +01004644bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4645 ASSERT(other->IsNumber());
4646 return key == static_cast<uint32_t>(other->Number());
4647}
4648
4649
Ben Murdochc7cc0282012-03-05 14:35:55 +00004650uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
4651 return ComputeIntegerHash(key, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01004652}
4653
4654
Ben Murdochc7cc0282012-03-05 14:35:55 +00004655uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
4656 Object* other) {
Steve Block44f0eee2011-05-26 01:26:41 +01004657 ASSERT(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00004658 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
Steve Block44f0eee2011-05-26 01:26:41 +01004659}
4660
Ben Murdochc7cc0282012-03-05 14:35:55 +00004661uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
4662 return ComputeIntegerHash(key, seed);
4663}
4664
4665uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
4666 uint32_t seed,
4667 Object* other) {
4668 ASSERT(other->IsNumber());
4669 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
4670}
Steve Block44f0eee2011-05-26 01:26:41 +01004671
4672MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4673 return Isolate::Current()->heap()->NumberFromUint32(key);
4674}
4675
4676
4677bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4678 // We know that all entries in a hash table had their hash keys created.
4679 // Use that knowledge to have fast failure.
4680 if (key->Hash() != String::cast(other)->Hash()) return false;
4681 return key->Equals(String::cast(other));
4682}
4683
4684
4685uint32_t StringDictionaryShape::Hash(String* key) {
4686 return key->Hash();
4687}
4688
4689
4690uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4691 return String::cast(other)->Hash();
4692}
4693
4694
4695MaybeObject* StringDictionaryShape::AsObject(String* key) {
4696 return key;
4697}
4698
4699
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004700template <int entrysize>
4701bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
4702 return key->SameValue(other);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004703}
4704
4705
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004706template <int entrysize>
4707uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
4708 MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
4709 return Smi::cast(maybe_hash->ToObjectChecked())->value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004710}
4711
4712
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004713template <int entrysize>
4714uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
4715 Object* other) {
4716 MaybeObject* maybe_hash = other->GetHash(OMIT_CREATION);
4717 return Smi::cast(maybe_hash->ToObjectChecked())->value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004718}
4719
4720
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004721template <int entrysize>
4722MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Object* key) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004723 return key;
4724}
4725
4726
Steve Block44f0eee2011-05-26 01:26:41 +01004727void Map::ClearCodeCache(Heap* heap) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004728 // No write barrier is needed since empty_fixed_array is not in new space.
4729 // Please note this function is used during marking:
4730 // - MarkCompactCollector::MarkUnmarkedObject
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004731 // - IncrementalMarking::Step
Steve Block44f0eee2011-05-26 01:26:41 +01004732 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4733 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00004734}
4735
4736
4737void JSArray::EnsureSize(int required_size) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004738 ASSERT(HasFastTypeElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004739 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00004740 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4741 if (elts->length() < required_size) {
4742 // Doubling in size would be overkill, but leave some slack to avoid
4743 // constantly growing.
4744 Expand(required_size + (required_size >> 3));
4745 // It's a performance benefit to keep a frequently used array in new-space.
Steve Block44f0eee2011-05-26 01:26:41 +01004746 } else if (!GetHeap()->new_space()->Contains(elts) &&
Steve Blockd0582a62009-12-15 09:54:21 +00004747 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4748 // Expand will allocate a new backing store in new space even if the size
4749 // we asked for isn't larger than what we had before.
4750 Expand(required_size);
4751 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004752}
4753
4754
Leon Clarke4515c472010-02-03 11:58:03 +00004755void JSArray::set_length(Smi* length) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004756 // Don't need a write barrier for a Smi.
Leon Clarke4515c472010-02-03 11:58:03 +00004757 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4758}
4759
4760
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004761bool JSArray::AllowsSetElementsLength() {
4762 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
4763 ASSERT(result == !HasExternalArrayElements());
4764 return result;
4765}
4766
4767
4768MaybeObject* JSArray::SetContent(FixedArrayBase* storage) {
4769 MaybeObject* maybe_result = EnsureCanContainElements(
4770 storage, ALLOW_COPIED_DOUBLE_ELEMENTS);
4771 if (maybe_result->IsFailure()) return maybe_result;
4772 ASSERT((storage->map() == GetHeap()->fixed_double_array_map() &&
4773 GetElementsKind() == FAST_DOUBLE_ELEMENTS) ||
4774 ((storage->map() != GetHeap()->fixed_double_array_map()) &&
4775 ((GetElementsKind() == FAST_ELEMENTS) ||
4776 (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS &&
4777 FixedArray::cast(storage)->ContainsOnlySmisOrHoles()))));
Ben Murdoch85b71792012-04-11 18:30:58 +01004778 set_elements(storage);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004779 set_length(Smi::FromInt(storage->length()));
4780 return this;
Steve Blocka7e24c12009-10-30 11:49:00 +00004781}
4782
4783
John Reck59135872010-11-02 12:39:01 -07004784MaybeObject* FixedArray::Copy() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004785 if (length() == 0) return this;
Steve Block44f0eee2011-05-26 01:26:41 +01004786 return GetHeap()->CopyFixedArray(this);
4787}
4788
4789
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004790MaybeObject* FixedDoubleArray::Copy() {
4791 if (length() == 0) return this;
4792 return GetHeap()->CopyFixedDoubleArray(this);
4793}
4794
4795
4796void TypeFeedbackCells::SetAstId(int index, Smi* id) {
4797 set(1 + index * 2, id);
4798}
4799
4800
4801Smi* TypeFeedbackCells::AstId(int index) {
4802 return Smi::cast(get(1 + index * 2));
4803}
4804
4805
4806void TypeFeedbackCells::SetCell(int index, JSGlobalPropertyCell* cell) {
4807 set(index * 2, cell);
4808}
4809
4810
4811JSGlobalPropertyCell* TypeFeedbackCells::Cell(int index) {
4812 return JSGlobalPropertyCell::cast(get(index * 2));
4813}
4814
4815
4816Handle<Object> TypeFeedbackCells::UninitializedSentinel(Isolate* isolate) {
4817 return isolate->factory()->the_hole_value();
4818}
4819
4820
4821Handle<Object> TypeFeedbackCells::MegamorphicSentinel(Isolate* isolate) {
4822 return isolate->factory()->undefined_value();
4823}
4824
4825
4826Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
4827 return heap->raw_unchecked_the_hole_value();
4828}
4829
4830
4831SMI_ACCESSORS(TypeFeedbackInfo, ic_total_count, kIcTotalCountOffset)
Ben Murdoch8f9999f2012-04-23 10:39:17 +01004832SMI_ACCESSORS(TypeFeedbackInfo, ic_with_type_info_count,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004833 kIcWithTypeinfoCountOffset)
4834ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
4835 kTypeFeedbackCellsOffset)
4836
4837
4838SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
4839
4840
Steve Block44f0eee2011-05-26 01:26:41 +01004841Relocatable::Relocatable(Isolate* isolate) {
4842 ASSERT(isolate == Isolate::Current());
4843 isolate_ = isolate;
4844 prev_ = isolate->relocatable_top();
4845 isolate->set_relocatable_top(this);
4846}
4847
4848
4849Relocatable::~Relocatable() {
4850 ASSERT(isolate_ == Isolate::Current());
4851 ASSERT_EQ(isolate_->relocatable_top(), this);
4852 isolate_->set_relocatable_top(prev_);
Steve Blocka7e24c12009-10-30 11:49:00 +00004853}
4854
4855
Iain Merrick75681382010-08-19 15:07:18 +01004856int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4857 return map->instance_size();
4858}
4859
4860
Ben Murdoch257744e2011-11-30 15:57:28 +00004861void Foreign::ForeignIterateBody(ObjectVisitor* v) {
Iain Merrick75681382010-08-19 15:07:18 +01004862 v->VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004863 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01004864}
4865
4866
4867template<typename StaticVisitor>
Ben Murdoch257744e2011-11-30 15:57:28 +00004868void Foreign::ForeignIterateBody() {
Iain Merrick75681382010-08-19 15:07:18 +01004869 StaticVisitor::VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004870 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01004871}
4872
4873
4874void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4875 typedef v8::String::ExternalAsciiStringResource Resource;
4876 v->VisitExternalAsciiString(
4877 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4878}
4879
4880
4881template<typename StaticVisitor>
4882void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4883 typedef v8::String::ExternalAsciiStringResource Resource;
4884 StaticVisitor::VisitExternalAsciiString(
4885 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4886}
4887
4888
4889void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4890 typedef v8::String::ExternalStringResource Resource;
4891 v->VisitExternalTwoByteString(
4892 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4893}
4894
4895
4896template<typename StaticVisitor>
4897void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4898 typedef v8::String::ExternalStringResource Resource;
4899 StaticVisitor::VisitExternalTwoByteString(
4900 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4901}
4902
4903#define SLOT_ADDR(obj, offset) \
4904 reinterpret_cast<Object**>((obj)->address() + offset)
4905
4906template<int start_offset, int end_offset, int size>
4907void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4908 HeapObject* obj,
4909 ObjectVisitor* v) {
4910 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4911}
4912
4913
4914template<int start_offset>
4915void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4916 int object_size,
4917 ObjectVisitor* v) {
4918 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4919}
4920
4921#undef SLOT_ADDR
4922
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004923#undef TYPE_CHECKER
Steve Blocka7e24c12009-10-30 11:49:00 +00004924#undef CAST_ACCESSOR
4925#undef INT_ACCESSORS
Ben Murdoch85b71792012-04-11 18:30:58 +01004926#undef ACCESSORS
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004927#undef ACCESSORS_TO_SMI
4928#undef SMI_ACCESSORS
4929#undef BOOL_GETTER
4930#undef BOOL_ACCESSORS
Steve Blocka7e24c12009-10-30 11:49:00 +00004931#undef FIELD_ADDR
4932#undef READ_FIELD
4933#undef WRITE_FIELD
4934#undef WRITE_BARRIER
4935#undef CONDITIONAL_WRITE_BARRIER
Steve Blocka7e24c12009-10-30 11:49:00 +00004936#undef READ_DOUBLE_FIELD
4937#undef WRITE_DOUBLE_FIELD
4938#undef READ_INT_FIELD
4939#undef WRITE_INT_FIELD
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004940#undef READ_INTPTR_FIELD
4941#undef WRITE_INTPTR_FIELD
4942#undef READ_UINT32_FIELD
4943#undef WRITE_UINT32_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00004944#undef READ_SHORT_FIELD
4945#undef WRITE_SHORT_FIELD
4946#undef READ_BYTE_FIELD
4947#undef WRITE_BYTE_FIELD
4948
4949
4950} } // namespace v8::internal
4951
4952#endif // V8_OBJECTS_INL_H_