blob: 78578cc88427b36b08d8e1b2f97a237fa7178b55 [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 Murdoch3ef787d2012-04-12 10:51:47 +01001386 ASSERT(map()->has_fast_elements() || map()->has_fast_smi_only_elements());
Steve Block44f0eee2011-05-26 01:26:41 +01001387 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1388 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001389}
1390
1391
John Reck59135872010-11-02 12:39:01 -07001392MaybeObject* JSObject::ResetElements() {
1393 Object* obj;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001394 ElementsKind elements_kind = FLAG_smi_only_arrays
1395 ? FAST_SMI_ONLY_ELEMENTS
1396 : FAST_ELEMENTS;
1397 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
1398 elements_kind);
1399 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
Steve Block8defd9f2010-07-08 12:39:36 +01001400 set_map(Map::cast(obj));
1401 initialize_elements();
1402 return this;
1403}
1404
1405
Steve Blocka7e24c12009-10-30 11:49:00 +00001406ACCESSORS(Oddball, to_string, String, kToStringOffset)
1407ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1408
1409
Steve Block44f0eee2011-05-26 01:26:41 +01001410byte Oddball::kind() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001411 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
Steve Block44f0eee2011-05-26 01:26:41 +01001412}
1413
1414
1415void Oddball::set_kind(byte value) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001416 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
Steve Block44f0eee2011-05-26 01:26:41 +01001417}
1418
1419
Steve Blocka7e24c12009-10-30 11:49:00 +00001420Object* JSGlobalPropertyCell::value() {
1421 return READ_FIELD(this, kValueOffset);
1422}
1423
1424
1425void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1426 // The write barrier is not used for global property cells.
1427 ASSERT(!val->IsJSGlobalPropertyCell());
1428 WRITE_FIELD(this, kValueOffset, val);
1429}
1430
1431
1432int JSObject::GetHeaderSize() {
1433 InstanceType type = map()->instance_type();
1434 // Check for the most common kind of JavaScript object before
1435 // falling into the generic switch. This speeds up the internal
1436 // field operations considerably on average.
1437 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1438 switch (type) {
1439 case JS_GLOBAL_PROXY_TYPE:
1440 return JSGlobalProxy::kSize;
1441 case JS_GLOBAL_OBJECT_TYPE:
1442 return JSGlobalObject::kSize;
1443 case JS_BUILTINS_OBJECT_TYPE:
1444 return JSBuiltinsObject::kSize;
1445 case JS_FUNCTION_TYPE:
1446 return JSFunction::kSize;
1447 case JS_VALUE_TYPE:
1448 return JSValue::kSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001449 case JS_DATE_TYPE:
1450 return JSDate::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001451 case JS_ARRAY_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001452 return JSArray::kSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001453 case JS_WEAK_MAP_TYPE:
1454 return JSWeakMap::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001455 case JS_REGEXP_TYPE:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001456 return JSRegExp::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1458 return JSObject::kHeaderSize;
Steve Block1e0659c2011-05-24 12:43:12 +01001459 case JS_MESSAGE_OBJECT_TYPE:
1460 return JSMessageObject::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 default:
1462 UNREACHABLE();
1463 return 0;
1464 }
1465}
1466
1467
1468int JSObject::GetInternalFieldCount() {
1469 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1470 // Make sure to adjust for the number of in-object properties. These
1471 // properties do contribute to the size, but are not internal fields.
1472 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1473 map()->inobject_properties();
1474}
1475
1476
Steve Block44f0eee2011-05-26 01:26:41 +01001477int JSObject::GetInternalFieldOffset(int index) {
1478 ASSERT(index < GetInternalFieldCount() && index >= 0);
1479 return GetHeaderSize() + (kPointerSize * index);
1480}
1481
1482
Steve Blocka7e24c12009-10-30 11:49:00 +00001483Object* JSObject::GetInternalField(int index) {
1484 ASSERT(index < GetInternalFieldCount() && index >= 0);
1485 // Internal objects do follow immediately after the header, whereas in-object
1486 // properties are at the end of the object. Therefore there is no need
1487 // to adjust the index here.
1488 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1489}
1490
1491
1492void JSObject::SetInternalField(int index, Object* value) {
1493 ASSERT(index < GetInternalFieldCount() && index >= 0);
1494 // Internal objects do follow immediately after the header, whereas in-object
1495 // properties are at the end of the object. Therefore there is no need
1496 // to adjust the index here.
1497 int offset = GetHeaderSize() + (kPointerSize * index);
1498 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001499 WRITE_BARRIER(GetHeap(), this, offset, value);
1500}
1501
1502
1503void JSObject::SetInternalField(int index, Smi* value) {
1504 ASSERT(index < GetInternalFieldCount() && index >= 0);
1505 // Internal objects do follow immediately after the header, whereas in-object
1506 // properties are at the end of the object. Therefore there is no need
1507 // to adjust the index here.
1508 int offset = GetHeaderSize() + (kPointerSize * index);
1509 WRITE_FIELD(this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001510}
1511
1512
1513// Access fast-case object properties at index. The use of these routines
1514// is needed to correctly distinguish between properties stored in-object and
1515// properties stored in the properties array.
1516Object* JSObject::FastPropertyAt(int index) {
1517 // Adjust for the number of properties stored in the object.
1518 index -= map()->inobject_properties();
1519 if (index < 0) {
1520 int offset = map()->instance_size() + (index * kPointerSize);
1521 return READ_FIELD(this, offset);
1522 } else {
1523 ASSERT(index < properties()->length());
1524 return properties()->get(index);
1525 }
1526}
1527
1528
1529Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1530 // Adjust for the number of properties stored in the object.
1531 index -= map()->inobject_properties();
1532 if (index < 0) {
1533 int offset = map()->instance_size() + (index * kPointerSize);
1534 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001535 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 } else {
1537 ASSERT(index < properties()->length());
1538 properties()->set(index, value);
1539 }
1540 return value;
1541}
1542
1543
Steve Block44f0eee2011-05-26 01:26:41 +01001544int JSObject::GetInObjectPropertyOffset(int index) {
1545 // Adjust for the number of properties stored in the object.
1546 index -= map()->inobject_properties();
1547 ASSERT(index < 0);
1548 return map()->instance_size() + (index * kPointerSize);
1549}
1550
1551
Steve Blocka7e24c12009-10-30 11:49:00 +00001552Object* JSObject::InObjectPropertyAt(int index) {
1553 // Adjust for the number of properties stored in the object.
1554 index -= map()->inobject_properties();
1555 ASSERT(index < 0);
1556 int offset = map()->instance_size() + (index * kPointerSize);
1557 return READ_FIELD(this, offset);
1558}
1559
1560
1561Object* JSObject::InObjectPropertyAtPut(int index,
1562 Object* value,
1563 WriteBarrierMode mode) {
1564 // Adjust for the number of properties stored in the object.
1565 index -= map()->inobject_properties();
1566 ASSERT(index < 0);
1567 int offset = map()->instance_size() + (index * kPointerSize);
1568 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001569 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 return value;
1571}
1572
1573
1574
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001575void JSObject::InitializeBody(Map* map,
1576 Object* pre_allocated_value,
1577 Object* filler_value) {
1578 ASSERT(!filler_value->IsHeapObject() ||
1579 !GetHeap()->InNewSpace(filler_value));
1580 ASSERT(!pre_allocated_value->IsHeapObject() ||
1581 !GetHeap()->InNewSpace(pre_allocated_value));
1582 int size = map->instance_size();
1583 int offset = kHeaderSize;
1584 if (filler_value != pre_allocated_value) {
1585 int pre_allocated = map->pre_allocated_property_fields();
1586 ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1587 for (int i = 0; i < pre_allocated; i++) {
1588 WRITE_FIELD(this, offset, pre_allocated_value);
1589 offset += kPointerSize;
1590 }
1591 }
1592 while (offset < size) {
1593 WRITE_FIELD(this, offset, filler_value);
1594 offset += kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001595 }
1596}
1597
1598
Steve Block8defd9f2010-07-08 12:39:36 +01001599bool JSObject::HasFastProperties() {
1600 return !properties()->IsDictionary();
1601}
1602
1603
1604int JSObject::MaxFastProperties() {
1605 // Allow extra fast properties if the object has more than
1606 // kMaxFastProperties in-object properties. When this is the case,
1607 // it is very unlikely that the object is being used as a dictionary
1608 // and there is a good chance that allowing more map transitions
1609 // will be worth it.
1610 return Max(map()->inobject_properties(), kMaxFastProperties);
1611}
1612
1613
Steve Blocka7e24c12009-10-30 11:49:00 +00001614void Struct::InitializeBody(int object_size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001615 Object* value = GetHeap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001616 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1617 WRITE_FIELD(this, offset, value);
1618 }
1619}
1620
1621
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001622bool Object::ToArrayIndex(uint32_t* index) {
1623 if (IsSmi()) {
1624 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001625 if (value < 0) return false;
1626 *index = value;
1627 return true;
1628 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001629 if (IsHeapNumber()) {
1630 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001631 uint32_t uint_value = static_cast<uint32_t>(value);
1632 if (value == static_cast<double>(uint_value)) {
1633 *index = uint_value;
1634 return true;
1635 }
1636 }
1637 return false;
1638}
1639
1640
1641bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1642 if (!this->IsJSValue()) return false;
1643
1644 JSValue* js_value = JSValue::cast(this);
1645 if (!js_value->value()->IsString()) return false;
1646
1647 String* str = String::cast(js_value->value());
1648 if (index >= (uint32_t)str->length()) return false;
1649
1650 return true;
1651}
1652
1653
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001654FixedArrayBase* FixedArrayBase::cast(Object* object) {
1655 ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1656 return reinterpret_cast<FixedArrayBase*>(object);
1657}
1658
1659
Steve Blocka7e24c12009-10-30 11:49:00 +00001660Object* FixedArray::get(int index) {
1661 ASSERT(index >= 0 && index < this->length());
1662 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1663}
1664
1665
1666void FixedArray::set(int index, Smi* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001667 ASSERT(map() != HEAP->fixed_cow_array_map());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001668 ASSERT(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001669 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1670 int offset = kHeaderSize + index * kPointerSize;
1671 WRITE_FIELD(this, offset, value);
1672}
1673
1674
1675void FixedArray::set(int index, Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001676 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001677 ASSERT(index >= 0 && index < this->length());
1678 int offset = kHeaderSize + index * kPointerSize;
1679 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001680 WRITE_BARRIER(GetHeap(), this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001681}
1682
1683
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001684inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1685 return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1686}
1687
1688
1689inline double FixedDoubleArray::hole_nan_as_double() {
1690 return BitCast<double, uint64_t>(kHoleNanInt64);
1691}
1692
1693
1694inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1695 ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1696 ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1697 return OS::nan_value();
1698}
1699
1700
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001701double FixedDoubleArray::get_scalar(int index) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001702 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1703 map() != HEAP->fixed_array_map());
1704 ASSERT(index >= 0 && index < this->length());
1705 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1706 ASSERT(!is_the_hole_nan(result));
1707 return result;
1708}
1709
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001710int64_t FixedDoubleArray::get_representation(int index) {
1711 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1712 map() != HEAP->fixed_array_map());
1713 ASSERT(index >= 0 && index < this->length());
1714 return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
1715}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001716
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001717MaybeObject* FixedDoubleArray::get(int index) {
1718 if (is_the_hole(index)) {
1719 return GetHeap()->the_hole_value();
1720 } else {
1721 return GetHeap()->NumberFromDouble(get_scalar(index));
1722 }
1723}
1724
1725
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001726void FixedDoubleArray::set(int index, double value) {
1727 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1728 map() != HEAP->fixed_array_map());
1729 int offset = kHeaderSize + index * kDoubleSize;
1730 if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1731 WRITE_DOUBLE_FIELD(this, offset, value);
1732}
1733
1734
1735void FixedDoubleArray::set_the_hole(int index) {
1736 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1737 map() != HEAP->fixed_array_map());
1738 int offset = kHeaderSize + index * kDoubleSize;
1739 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1740}
1741
1742
1743bool FixedDoubleArray::is_the_hole(int index) {
1744 int offset = kHeaderSize + index * kDoubleSize;
1745 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1746}
1747
1748
Leon Clarke4515c472010-02-03 11:58:03 +00001749WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001750 Heap* heap = GetHeap();
1751 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1752 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
Steve Blocka7e24c12009-10-30 11:49:00 +00001753 return UPDATE_WRITE_BARRIER;
1754}
1755
1756
1757void FixedArray::set(int index,
1758 Object* value,
1759 WriteBarrierMode mode) {
Steve Block44f0eee2011-05-26 01:26:41 +01001760 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001761 ASSERT(index >= 0 && index < this->length());
1762 int offset = kHeaderSize + index * kPointerSize;
1763 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001764 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001765}
1766
1767
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001768void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
1769 int index,
1770 Object* value) {
1771 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1772 ASSERT(index >= 0 && index < array->length());
1773 int offset = kHeaderSize + index * kPointerSize;
1774 WRITE_FIELD(array, offset, value);
1775 Heap* heap = array->GetHeap();
1776 if (heap->InNewSpace(value)) {
1777 heap->RecordWrite(array->address(), offset);
1778 }
1779}
1780
1781
1782void FixedArray::NoWriteBarrierSet(FixedArray* array,
1783 int index,
1784 Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001785 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001786 ASSERT(index >= 0 && index < array->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001787 ASSERT(!HEAP->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001788 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1789}
1790
1791
1792void FixedArray::set_undefined(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001793 ASSERT(map() != HEAP->fixed_cow_array_map());
1794 set_undefined(GetHeap(), index);
1795}
1796
1797
1798void FixedArray::set_undefined(Heap* heap, int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001799 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001800 ASSERT(!heap->InNewSpace(heap->undefined_value()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001801 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
Steve Block44f0eee2011-05-26 01:26:41 +01001802 heap->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001803}
1804
1805
1806void FixedArray::set_null(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001807 set_null(GetHeap(), index);
1808}
1809
1810
1811void FixedArray::set_null(Heap* heap, int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001812 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001813 ASSERT(!heap->InNewSpace(heap->null_value()));
1814 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001815}
1816
1817
1818void FixedArray::set_the_hole(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001819 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001820 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001821 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1822 WRITE_FIELD(this,
1823 kHeaderSize + index * kPointerSize,
1824 GetHeap()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001825}
1826
1827
Iain Merrick75681382010-08-19 15:07:18 +01001828void FixedArray::set_unchecked(int index, Smi* value) {
1829 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1830 int offset = kHeaderSize + index * kPointerSize;
1831 WRITE_FIELD(this, offset, value);
1832}
1833
1834
Steve Block44f0eee2011-05-26 01:26:41 +01001835void FixedArray::set_unchecked(Heap* heap,
1836 int index,
Ben Murdochf87a2032010-10-22 12:50:53 +01001837 Object* value,
1838 WriteBarrierMode mode) {
1839 int offset = kHeaderSize + index * kPointerSize;
1840 WRITE_FIELD(this, offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001841 CONDITIONAL_WRITE_BARRIER(heap, this, offset, value, mode);
Ben Murdochf87a2032010-10-22 12:50:53 +01001842}
1843
1844
Steve Block44f0eee2011-05-26 01:26:41 +01001845void FixedArray::set_null_unchecked(Heap* heap, int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001846 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001847 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1848 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
Iain Merrick75681382010-08-19 15:07:18 +01001849}
1850
1851
Steve Block6ded16b2010-05-10 14:33:55 +01001852Object** FixedArray::data_start() {
1853 return HeapObject::RawField(this, kHeaderSize);
1854}
1855
1856
Steve Blocka7e24c12009-10-30 11:49:00 +00001857bool DescriptorArray::IsEmpty() {
Ben Murdoch257744e2011-11-30 15:57:28 +00001858 ASSERT(this->IsSmi() ||
1859 this->length() > kFirstIndex ||
Steve Block44f0eee2011-05-26 01:26:41 +01001860 this == HEAP->empty_descriptor_array());
Ben Murdoch257744e2011-11-30 15:57:28 +00001861 return this->IsSmi() || length() <= kFirstIndex;
1862}
1863
1864
1865int DescriptorArray::bit_field3_storage() {
1866 Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1867 return Smi::cast(storage)->value();
1868}
1869
1870void DescriptorArray::set_bit_field3_storage(int value) {
1871 ASSERT(!IsEmpty());
1872 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001873}
1874
1875
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001876void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
1877 int first,
1878 int second) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001879 Object* tmp = array->get(first);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001880 NoIncrementalWriteBarrierSet(array, first, array->get(second));
1881 NoIncrementalWriteBarrierSet(array, second, tmp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001882}
1883
1884
1885int DescriptorArray::Search(String* name) {
1886 SLOW_ASSERT(IsSortedNoDuplicates());
1887
1888 // Check for empty descriptor array.
1889 int nof = number_of_descriptors();
1890 if (nof == 0) return kNotFound;
1891
1892 // Fast case: do linear search for small arrays.
1893 const int kMaxElementsForLinearSearch = 8;
1894 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1895 return LinearSearch(name, nof);
1896 }
1897
1898 // Slow case: perform binary search.
1899 return BinarySearch(name, 0, nof - 1);
1900}
1901
1902
Iain Merrick75681382010-08-19 15:07:18 +01001903int DescriptorArray::SearchWithCache(String* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001904 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
Iain Merrick75681382010-08-19 15:07:18 +01001905 if (number == DescriptorLookupCache::kAbsent) {
1906 number = Search(name);
Steve Block44f0eee2011-05-26 01:26:41 +01001907 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
Iain Merrick75681382010-08-19 15:07:18 +01001908 }
1909 return number;
1910}
1911
1912
Steve Blocka7e24c12009-10-30 11:49:00 +00001913String* DescriptorArray::GetKey(int descriptor_number) {
1914 ASSERT(descriptor_number < number_of_descriptors());
1915 return String::cast(get(ToKeyIndex(descriptor_number)));
1916}
1917
1918
1919Object* DescriptorArray::GetValue(int descriptor_number) {
1920 ASSERT(descriptor_number < number_of_descriptors());
1921 return GetContentArray()->get(ToValueIndex(descriptor_number));
1922}
1923
1924
1925Smi* DescriptorArray::GetDetails(int descriptor_number) {
1926 ASSERT(descriptor_number < number_of_descriptors());
1927 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1928}
1929
1930
1931PropertyType DescriptorArray::GetType(int descriptor_number) {
1932 ASSERT(descriptor_number < number_of_descriptors());
1933 return PropertyDetails(GetDetails(descriptor_number)).type();
1934}
1935
1936
1937int DescriptorArray::GetFieldIndex(int descriptor_number) {
1938 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1939}
1940
1941
1942JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1943 return JSFunction::cast(GetValue(descriptor_number));
1944}
1945
1946
1947Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1948 ASSERT(GetType(descriptor_number) == CALLBACKS);
1949 return GetValue(descriptor_number);
1950}
1951
1952
1953AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1954 ASSERT(GetType(descriptor_number) == CALLBACKS);
Ben Murdoch257744e2011-11-30 15:57:28 +00001955 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001956 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001957}
1958
1959
1960bool DescriptorArray::IsProperty(int descriptor_number) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001961 Entry entry(this, descriptor_number);
1962 return IsPropertyDescriptor(&entry);
Steve Blocka7e24c12009-10-30 11:49:00 +00001963}
1964
1965
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001966bool DescriptorArray::IsTransitionOnly(int descriptor_number) {
1967 switch (GetType(descriptor_number)) {
1968 case MAP_TRANSITION:
1969 case CONSTANT_TRANSITION:
1970 case ELEMENTS_TRANSITION:
1971 return true;
1972 case CALLBACKS: {
1973 Object* value = GetValue(descriptor_number);
1974 if (!value->IsAccessorPair()) return false;
1975 AccessorPair* accessors = AccessorPair::cast(value);
1976 return accessors->getter()->IsMap() && accessors->setter()->IsMap();
1977 }
1978 case NORMAL:
1979 case FIELD:
1980 case CONSTANT_FUNCTION:
1981 case HANDLER:
1982 case INTERCEPTOR:
1983 case NULL_DESCRIPTOR:
1984 return false;
1985 }
1986 UNREACHABLE(); // Keep the compiler happy.
1987 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001988}
1989
1990
1991bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1992 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1993}
1994
1995
1996bool DescriptorArray::IsDontEnum(int descriptor_number) {
1997 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1998}
1999
2000
2001void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2002 desc->Init(GetKey(descriptor_number),
2003 GetValue(descriptor_number),
Ben Murdoch8b112d22011-06-08 16:22:53 +01002004 PropertyDetails(GetDetails(descriptor_number)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002005}
2006
2007
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002008void DescriptorArray::Set(int descriptor_number,
2009 Descriptor* desc,
2010 const WhitenessWitness&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002011 // Range check.
2012 ASSERT(descriptor_number < number_of_descriptors());
2013
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002014 NoIncrementalWriteBarrierSet(this,
2015 ToKeyIndex(descriptor_number),
2016 desc->GetKey());
Steve Blocka7e24c12009-10-30 11:49:00 +00002017 FixedArray* content_array = GetContentArray();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002018 NoIncrementalWriteBarrierSet(content_array,
2019 ToValueIndex(descriptor_number),
2020 desc->GetValue());
2021 NoIncrementalWriteBarrierSet(content_array,
2022 ToDetailsIndex(descriptor_number),
2023 desc->GetDetails().AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002024}
2025
2026
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002027void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
2028 int first, int second) {
2029 NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
2030 FixedArray* content_array = GetContentArray();
2031 NoIncrementalWriteBarrierSwap(content_array,
2032 ToValueIndex(first),
2033 ToValueIndex(second));
2034 NoIncrementalWriteBarrierSwap(content_array,
2035 ToDetailsIndex(first),
2036 ToDetailsIndex(second));
Ben Murdoch85b71792012-04-11 18:30:58 +01002037}
2038
2039
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002040DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
2041 : marking_(array->GetHeap()->incremental_marking()) {
2042 marking_->EnterNoMarkingScope();
2043 if (array->number_of_descriptors() > 0) {
2044 ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
2045 ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
2046 }
2047}
2048
2049
2050DescriptorArray::WhitenessWitness::~WhitenessWitness() {
2051 marking_->LeaveNoMarkingScope();
Steve Blocka7e24c12009-10-30 11:49:00 +00002052}
2053
2054
Steve Block44f0eee2011-05-26 01:26:41 +01002055template<typename Shape, typename Key>
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002056int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2057 const int kMinCapacity = 32;
2058 int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2059 if (capacity < kMinCapacity) {
2060 capacity = kMinCapacity; // Guarantee min capacity.
2061 }
2062 return capacity;
2063}
2064
2065
2066template<typename Shape, typename Key>
Steve Block44f0eee2011-05-26 01:26:41 +01002067int HashTable<Shape, Key>::FindEntry(Key key) {
2068 return FindEntry(GetIsolate(), key);
2069}
2070
2071
2072// Find entry for key otherwise return kNotFound.
2073template<typename Shape, typename Key>
2074int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2075 uint32_t capacity = Capacity();
Ben Murdochc7cc0282012-03-05 14:35:55 +00002076 uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
Steve Block44f0eee2011-05-26 01:26:41 +01002077 uint32_t count = 1;
2078 // EnsureCapacity will guarantee the hash table is never full.
2079 while (true) {
2080 Object* element = KeyAt(entry);
Ben Murdochc7cc0282012-03-05 14:35:55 +00002081 // Empty entry.
2082 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002083 if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
Steve Block44f0eee2011-05-26 01:26:41 +01002084 Shape::IsMatch(key, element)) return entry;
2085 entry = NextProbe(entry, count++, capacity);
2086 }
2087 return kNotFound;
2088}
2089
2090
Ben Murdochc7cc0282012-03-05 14:35:55 +00002091bool SeededNumberDictionary::requires_slow_elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002092 Object* max_index_object = get(kMaxNumberKeyIndex);
2093 if (!max_index_object->IsSmi()) return false;
2094 return 0 !=
2095 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2096}
2097
Ben Murdochc7cc0282012-03-05 14:35:55 +00002098uint32_t SeededNumberDictionary::max_number_key() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002099 ASSERT(!requires_slow_elements());
2100 Object* max_index_object = get(kMaxNumberKeyIndex);
2101 if (!max_index_object->IsSmi()) return 0;
2102 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2103 return value >> kRequiresSlowElementsTagSize;
2104}
2105
Ben Murdochc7cc0282012-03-05 14:35:55 +00002106void SeededNumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00002107 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00002108}
2109
2110
2111// ------------------------------------
2112// Cast operations
2113
2114
2115CAST_ACCESSOR(FixedArray)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002116CAST_ACCESSOR(FixedDoubleArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002117CAST_ACCESSOR(DescriptorArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002118CAST_ACCESSOR(DeoptimizationInputData)
2119CAST_ACCESSOR(DeoptimizationOutputData)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002120CAST_ACCESSOR(TypeFeedbackCells)
Steve Blocka7e24c12009-10-30 11:49:00 +00002121CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01002122CAST_ACCESSOR(JSFunctionResultCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002123CAST_ACCESSOR(NormalizedMapCache)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002124CAST_ACCESSOR(ScopeInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +00002125CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01002126CAST_ACCESSOR(CodeCacheHashTable)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002127CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00002128CAST_ACCESSOR(MapCache)
2129CAST_ACCESSOR(String)
2130CAST_ACCESSOR(SeqString)
2131CAST_ACCESSOR(SeqAsciiString)
2132CAST_ACCESSOR(SeqTwoByteString)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002133CAST_ACCESSOR(SlicedString)
Steve Blocka7e24c12009-10-30 11:49:00 +00002134CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00002135CAST_ACCESSOR(ExternalString)
2136CAST_ACCESSOR(ExternalAsciiString)
2137CAST_ACCESSOR(ExternalTwoByteString)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002138CAST_ACCESSOR(JSReceiver)
Steve Blocka7e24c12009-10-30 11:49:00 +00002139CAST_ACCESSOR(JSObject)
2140CAST_ACCESSOR(Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00002141CAST_ACCESSOR(HeapObject)
2142CAST_ACCESSOR(HeapNumber)
2143CAST_ACCESSOR(Oddball)
2144CAST_ACCESSOR(JSGlobalPropertyCell)
2145CAST_ACCESSOR(SharedFunctionInfo)
2146CAST_ACCESSOR(Map)
2147CAST_ACCESSOR(JSFunction)
2148CAST_ACCESSOR(GlobalObject)
2149CAST_ACCESSOR(JSGlobalProxy)
2150CAST_ACCESSOR(JSGlobalObject)
2151CAST_ACCESSOR(JSBuiltinsObject)
2152CAST_ACCESSOR(Code)
2153CAST_ACCESSOR(JSArray)
2154CAST_ACCESSOR(JSRegExp)
Ben Murdoch257744e2011-11-30 15:57:28 +00002155CAST_ACCESSOR(JSProxy)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002156CAST_ACCESSOR(JSFunctionProxy)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002157CAST_ACCESSOR(JSSet)
2158CAST_ACCESSOR(JSMap)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002159CAST_ACCESSOR(JSWeakMap)
Ben Murdoch257744e2011-11-30 15:57:28 +00002160CAST_ACCESSOR(Foreign)
Steve Blocka7e24c12009-10-30 11:49:00 +00002161CAST_ACCESSOR(ByteArray)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002162CAST_ACCESSOR(FreeSpace)
Steve Block3ce2e202009-11-05 08:53:23 +00002163CAST_ACCESSOR(ExternalArray)
2164CAST_ACCESSOR(ExternalByteArray)
2165CAST_ACCESSOR(ExternalUnsignedByteArray)
2166CAST_ACCESSOR(ExternalShortArray)
2167CAST_ACCESSOR(ExternalUnsignedShortArray)
2168CAST_ACCESSOR(ExternalIntArray)
2169CAST_ACCESSOR(ExternalUnsignedIntArray)
2170CAST_ACCESSOR(ExternalFloatArray)
Ben Murdoch257744e2011-11-30 15:57:28 +00002171CAST_ACCESSOR(ExternalDoubleArray)
Steve Block44f0eee2011-05-26 01:26:41 +01002172CAST_ACCESSOR(ExternalPixelArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002173CAST_ACCESSOR(Struct)
2174
2175
2176#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2177 STRUCT_LIST(MAKE_STRUCT_CAST)
2178#undef MAKE_STRUCT_CAST
2179
2180
2181template <typename Shape, typename Key>
2182HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2183 ASSERT(obj->IsHashTable());
2184 return reinterpret_cast<HashTable*>(obj);
2185}
2186
2187
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002188SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002189SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002190
Steve Block6ded16b2010-05-10 14:33:55 +01002191SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002192
2193
2194uint32_t String::hash_field() {
2195 return READ_UINT32_FIELD(this, kHashFieldOffset);
2196}
2197
2198
2199void String::set_hash_field(uint32_t value) {
2200 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002201#if V8_HOST_ARCH_64_BIT
2202 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2203#endif
Steve Blockd0582a62009-12-15 09:54:21 +00002204}
2205
2206
Steve Blocka7e24c12009-10-30 11:49:00 +00002207bool String::Equals(String* other) {
2208 if (other == this) return true;
2209 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2210 return false;
2211 }
2212 return SlowEquals(other);
2213}
2214
2215
John Reck59135872010-11-02 12:39:01 -07002216MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01002217 if (!StringShape(this).IsCons()) return this;
2218 ConsString* cons = ConsString::cast(this);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002219 if (cons->IsFlat()) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01002220 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00002221}
2222
2223
Leon Clarkef7060e22010-06-03 12:02:55 +01002224String* String::TryFlattenGetString(PretenureFlag pretenure) {
John Reck59135872010-11-02 12:39:01 -07002225 MaybeObject* flat = TryFlatten(pretenure);
2226 Object* successfully_flattened;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002227 if (!flat->ToObject(&successfully_flattened)) return this;
2228 return String::cast(successfully_flattened);
Leon Clarkef7060e22010-06-03 12:02:55 +01002229}
2230
2231
Steve Blocka7e24c12009-10-30 11:49:00 +00002232uint16_t String::Get(int index) {
2233 ASSERT(index >= 0 && index < length());
2234 switch (StringShape(this).full_representation_tag()) {
2235 case kSeqStringTag | kAsciiStringTag:
2236 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2237 case kSeqStringTag | kTwoByteStringTag:
2238 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2239 case kConsStringTag | kAsciiStringTag:
2240 case kConsStringTag | kTwoByteStringTag:
2241 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002242 case kExternalStringTag | kAsciiStringTag:
2243 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2244 case kExternalStringTag | kTwoByteStringTag:
2245 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002246 case kSlicedStringTag | kAsciiStringTag:
2247 case kSlicedStringTag | kTwoByteStringTag:
2248 return SlicedString::cast(this)->SlicedStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002249 default:
2250 break;
2251 }
2252
2253 UNREACHABLE();
2254 return 0;
2255}
2256
2257
2258void String::Set(int index, uint16_t value) {
2259 ASSERT(index >= 0 && index < length());
2260 ASSERT(StringShape(this).IsSequential());
2261
2262 return this->IsAsciiRepresentation()
2263 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2264 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2265}
2266
2267
2268bool String::IsFlat() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002269 if (!StringShape(this).IsCons()) return true;
2270 return ConsString::cast(this)->second()->length() == 0;
2271}
2272
2273
2274String* String::GetUnderlying() {
2275 // Giving direct access to underlying string only makes sense if the
2276 // wrapping string is already flattened.
2277 ASSERT(this->IsFlat());
2278 ASSERT(StringShape(this).IsIndirect());
2279 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2280 const int kUnderlyingOffset = SlicedString::kParentOffset;
2281 return String::cast(READ_FIELD(this, kUnderlyingOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002282}
2283
2284
2285uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2286 ASSERT(index >= 0 && index < length());
2287 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2288}
2289
2290
2291void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2292 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2293 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2294 static_cast<byte>(value));
2295}
2296
2297
2298Address SeqAsciiString::GetCharsAddress() {
2299 return FIELD_ADDR(this, kHeaderSize);
2300}
2301
2302
2303char* SeqAsciiString::GetChars() {
2304 return reinterpret_cast<char*>(GetCharsAddress());
2305}
2306
2307
2308Address SeqTwoByteString::GetCharsAddress() {
2309 return FIELD_ADDR(this, kHeaderSize);
2310}
2311
2312
2313uc16* SeqTwoByteString::GetChars() {
2314 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2315}
2316
2317
2318uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2319 ASSERT(index >= 0 && index < length());
2320 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2321}
2322
2323
2324void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2325 ASSERT(index >= 0 && index < length());
2326 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2327}
2328
2329
2330int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01002331 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002332}
2333
2334
2335int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01002336 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002337}
2338
2339
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002340String* SlicedString::parent() {
2341 return String::cast(READ_FIELD(this, kParentOffset));
2342}
2343
2344
2345void SlicedString::set_parent(String* parent) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002346 ASSERT(parent->IsSeqString() || parent->IsExternalString());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002347 WRITE_FIELD(this, kParentOffset, parent);
2348}
2349
2350
2351SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2352
2353
Steve Blocka7e24c12009-10-30 11:49:00 +00002354String* ConsString::first() {
2355 return String::cast(READ_FIELD(this, kFirstOffset));
2356}
2357
2358
2359Object* ConsString::unchecked_first() {
2360 return READ_FIELD(this, kFirstOffset);
2361}
2362
2363
2364void ConsString::set_first(String* value, WriteBarrierMode mode) {
2365 WRITE_FIELD(this, kFirstOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002366 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002367}
2368
2369
2370String* ConsString::second() {
2371 return String::cast(READ_FIELD(this, kSecondOffset));
2372}
2373
2374
2375Object* ConsString::unchecked_second() {
2376 return READ_FIELD(this, kSecondOffset);
2377}
2378
2379
2380void ConsString::set_second(String* value, WriteBarrierMode mode) {
2381 WRITE_FIELD(this, kSecondOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002382 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002383}
2384
2385
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002386bool ExternalString::is_short() {
2387 InstanceType type = map()->instance_type();
2388 return (type & kShortExternalStringMask) == kShortExternalStringTag;
2389}
2390
2391
2392const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002393 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2394}
2395
2396
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002397void ExternalAsciiString::update_data_cache() {
2398 if (is_short()) return;
2399 const char** data_field =
2400 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
2401 *data_field = resource()->data();
2402}
2403
2404
Steve Blocka7e24c12009-10-30 11:49:00 +00002405void ExternalAsciiString::set_resource(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002406 const ExternalAsciiString::Resource* resource) {
2407 *reinterpret_cast<const Resource**>(
2408 FIELD_ADDR(this, kResourceOffset)) = resource;
2409 if (resource != NULL) update_data_cache();
Steve Blocka7e24c12009-10-30 11:49:00 +00002410}
2411
2412
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002413const char* ExternalAsciiString::GetChars() {
2414 return resource()->data();
2415}
2416
2417
2418uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
2419 ASSERT(index >= 0 && index < length());
2420 return GetChars()[index];
2421}
2422
2423
2424const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002425 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2426}
2427
2428
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002429void ExternalTwoByteString::update_data_cache() {
2430 if (is_short()) return;
2431 const uint16_t** data_field =
2432 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
2433 *data_field = resource()->data();
2434}
2435
2436
Steve Blocka7e24c12009-10-30 11:49:00 +00002437void ExternalTwoByteString::set_resource(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002438 const ExternalTwoByteString::Resource* resource) {
2439 *reinterpret_cast<const Resource**>(
2440 FIELD_ADDR(this, kResourceOffset)) = resource;
2441 if (resource != NULL) update_data_cache();
2442}
2443
2444
2445const uint16_t* ExternalTwoByteString::GetChars() {
2446 return resource()->data();
2447}
2448
2449
2450uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
2451 ASSERT(index >= 0 && index < length());
2452 return GetChars()[index];
2453}
2454
2455
2456const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
2457 unsigned start) {
2458 return GetChars() + start;
Steve Blocka7e24c12009-10-30 11:49:00 +00002459}
2460
2461
Steve Block6ded16b2010-05-10 14:33:55 +01002462void JSFunctionResultCache::MakeZeroSize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002463 set_finger_index(kEntriesIndex);
2464 set_size(kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01002465}
2466
2467
2468void JSFunctionResultCache::Clear() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002469 int cache_size = size();
Steve Block6ded16b2010-05-10 14:33:55 +01002470 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002471 MemsetPointer(entries_start,
Steve Block44f0eee2011-05-26 01:26:41 +01002472 GetHeap()->the_hole_value(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002473 cache_size - kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01002474 MakeZeroSize();
2475}
2476
2477
Ben Murdochb8e0da22011-05-16 14:20:40 +01002478int JSFunctionResultCache::size() {
2479 return Smi::cast(get(kCacheSizeIndex))->value();
2480}
2481
2482
2483void JSFunctionResultCache::set_size(int size) {
2484 set(kCacheSizeIndex, Smi::FromInt(size));
2485}
2486
2487
2488int JSFunctionResultCache::finger_index() {
2489 return Smi::cast(get(kFingerIndex))->value();
2490}
2491
2492
2493void JSFunctionResultCache::set_finger_index(int finger_index) {
2494 set(kFingerIndex, Smi::FromInt(finger_index));
2495}
2496
2497
Steve Blocka7e24c12009-10-30 11:49:00 +00002498byte ByteArray::get(int index) {
2499 ASSERT(index >= 0 && index < this->length());
2500 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2501}
2502
2503
2504void ByteArray::set(int index, byte value) {
2505 ASSERT(index >= 0 && index < this->length());
2506 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2507}
2508
2509
2510int ByteArray::get_int(int index) {
2511 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2512 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2513}
2514
2515
2516ByteArray* ByteArray::FromDataStartAddress(Address address) {
2517 ASSERT_TAG_ALIGNED(address);
2518 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2519}
2520
2521
2522Address ByteArray::GetDataStartAddress() {
2523 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2524}
2525
2526
Steve Block44f0eee2011-05-26 01:26:41 +01002527uint8_t* ExternalPixelArray::external_pixel_pointer() {
2528 return reinterpret_cast<uint8_t*>(external_pointer());
Steve Blocka7e24c12009-10-30 11:49:00 +00002529}
2530
2531
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002532uint8_t ExternalPixelArray::get_scalar(int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002533 ASSERT((index >= 0) && (index < this->length()));
Steve Block44f0eee2011-05-26 01:26:41 +01002534 uint8_t* ptr = external_pixel_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00002535 return ptr[index];
2536}
2537
2538
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002539MaybeObject* ExternalPixelArray::get(int index) {
2540 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2541}
2542
2543
Steve Block44f0eee2011-05-26 01:26:41 +01002544void ExternalPixelArray::set(int index, uint8_t value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002545 ASSERT((index >= 0) && (index < this->length()));
Steve Block44f0eee2011-05-26 01:26:41 +01002546 uint8_t* ptr = external_pixel_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00002547 ptr[index] = value;
2548}
2549
2550
Steve Block3ce2e202009-11-05 08:53:23 +00002551void* ExternalArray::external_pointer() {
2552 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2553 return reinterpret_cast<void*>(ptr);
2554}
2555
2556
2557void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2558 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2559 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2560}
2561
2562
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002563int8_t ExternalByteArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002564 ASSERT((index >= 0) && (index < this->length()));
2565 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2566 return ptr[index];
2567}
2568
2569
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002570MaybeObject* ExternalByteArray::get(int index) {
2571 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2572}
2573
2574
Steve Block3ce2e202009-11-05 08:53:23 +00002575void ExternalByteArray::set(int index, int8_t value) {
2576 ASSERT((index >= 0) && (index < this->length()));
2577 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2578 ptr[index] = value;
2579}
2580
2581
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002582uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002583 ASSERT((index >= 0) && (index < this->length()));
2584 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2585 return ptr[index];
2586}
2587
2588
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002589MaybeObject* ExternalUnsignedByteArray::get(int index) {
2590 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2591}
2592
2593
Steve Block3ce2e202009-11-05 08:53:23 +00002594void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2595 ASSERT((index >= 0) && (index < this->length()));
2596 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2597 ptr[index] = value;
2598}
2599
2600
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002601int16_t ExternalShortArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002602 ASSERT((index >= 0) && (index < this->length()));
2603 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2604 return ptr[index];
2605}
2606
2607
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002608MaybeObject* ExternalShortArray::get(int index) {
2609 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2610}
2611
2612
Steve Block3ce2e202009-11-05 08:53:23 +00002613void ExternalShortArray::set(int index, int16_t value) {
2614 ASSERT((index >= 0) && (index < this->length()));
2615 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2616 ptr[index] = value;
2617}
2618
2619
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002620uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002621 ASSERT((index >= 0) && (index < this->length()));
2622 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2623 return ptr[index];
2624}
2625
2626
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002627MaybeObject* ExternalUnsignedShortArray::get(int index) {
2628 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2629}
2630
2631
Steve Block3ce2e202009-11-05 08:53:23 +00002632void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2633 ASSERT((index >= 0) && (index < this->length()));
2634 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2635 ptr[index] = value;
2636}
2637
2638
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002639int32_t ExternalIntArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002640 ASSERT((index >= 0) && (index < this->length()));
2641 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2642 return ptr[index];
2643}
2644
2645
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002646MaybeObject* ExternalIntArray::get(int index) {
2647 return GetHeap()->NumberFromInt32(get_scalar(index));
2648}
2649
2650
Steve Block3ce2e202009-11-05 08:53:23 +00002651void ExternalIntArray::set(int index, int32_t value) {
2652 ASSERT((index >= 0) && (index < this->length()));
2653 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2654 ptr[index] = value;
2655}
2656
2657
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002658uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002659 ASSERT((index >= 0) && (index < this->length()));
2660 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2661 return ptr[index];
2662}
2663
2664
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002665MaybeObject* ExternalUnsignedIntArray::get(int index) {
2666 return GetHeap()->NumberFromUint32(get_scalar(index));
2667}
2668
2669
Steve Block3ce2e202009-11-05 08:53:23 +00002670void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2671 ASSERT((index >= 0) && (index < this->length()));
2672 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2673 ptr[index] = value;
2674}
2675
2676
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002677float ExternalFloatArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002678 ASSERT((index >= 0) && (index < this->length()));
2679 float* ptr = static_cast<float*>(external_pointer());
2680 return ptr[index];
2681}
2682
2683
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002684MaybeObject* ExternalFloatArray::get(int index) {
2685 return GetHeap()->NumberFromDouble(get_scalar(index));
2686}
2687
2688
Steve Block3ce2e202009-11-05 08:53:23 +00002689void ExternalFloatArray::set(int index, float value) {
2690 ASSERT((index >= 0) && (index < this->length()));
2691 float* ptr = static_cast<float*>(external_pointer());
2692 ptr[index] = value;
2693}
2694
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002695
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002696double ExternalDoubleArray::get_scalar(int index) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002697 ASSERT((index >= 0) && (index < this->length()));
2698 double* ptr = static_cast<double*>(external_pointer());
2699 return ptr[index];
2700}
2701
2702
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002703MaybeObject* ExternalDoubleArray::get(int index) {
2704 return GetHeap()->NumberFromDouble(get_scalar(index));
2705}
2706
2707
Ben Murdoch257744e2011-11-30 15:57:28 +00002708void ExternalDoubleArray::set(int index, double value) {
2709 ASSERT((index >= 0) && (index < this->length()));
2710 double* ptr = static_cast<double*>(external_pointer());
2711 ptr[index] = value;
2712}
2713
2714
Iain Merrick9ac36c92010-09-13 15:29:50 +01002715int Map::visitor_id() {
2716 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2717}
2718
2719
2720void Map::set_visitor_id(int id) {
2721 ASSERT(0 <= id && id < 256);
2722 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2723}
2724
Steve Block3ce2e202009-11-05 08:53:23 +00002725
Steve Blocka7e24c12009-10-30 11:49:00 +00002726int Map::instance_size() {
2727 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2728}
2729
2730
2731int Map::inobject_properties() {
2732 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2733}
2734
2735
2736int Map::pre_allocated_property_fields() {
2737 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2738}
2739
2740
2741int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01002742 int instance_size = map->instance_size();
2743 if (instance_size != kVariableSizeSentinel) return instance_size;
2744 // We can ignore the "symbol" bit becase it is only set for symbols
2745 // and implies a string type.
2746 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002747 // Only inline the most frequent cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00002748 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002749 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002750 }
Steve Block791712a2010-08-27 10:21:07 +01002751 if (instance_type == ASCII_STRING_TYPE) {
2752 return SeqAsciiString::SizeFor(
2753 reinterpret_cast<SeqAsciiString*>(this)->length());
2754 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002755 if (instance_type == BYTE_ARRAY_TYPE) {
2756 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2757 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002758 if (instance_type == FREE_SPACE_TYPE) {
2759 return reinterpret_cast<FreeSpace*>(this)->size();
2760 }
Steve Block791712a2010-08-27 10:21:07 +01002761 if (instance_type == STRING_TYPE) {
2762 return SeqTwoByteString::SizeFor(
2763 reinterpret_cast<SeqTwoByteString*>(this)->length());
2764 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002765 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2766 return FixedDoubleArray::SizeFor(
2767 reinterpret_cast<FixedDoubleArray*>(this)->length());
2768 }
Steve Block791712a2010-08-27 10:21:07 +01002769 ASSERT(instance_type == CODE_TYPE);
2770 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00002771}
2772
2773
2774void Map::set_instance_size(int value) {
2775 ASSERT_EQ(0, value & (kPointerSize - 1));
2776 value >>= kPointerSizeLog2;
2777 ASSERT(0 <= value && value < 256);
2778 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2779}
2780
2781
2782void Map::set_inobject_properties(int value) {
2783 ASSERT(0 <= value && value < 256);
2784 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2785}
2786
2787
2788void Map::set_pre_allocated_property_fields(int value) {
2789 ASSERT(0 <= value && value < 256);
2790 WRITE_BYTE_FIELD(this,
2791 kPreAllocatedPropertyFieldsOffset,
2792 static_cast<byte>(value));
2793}
2794
2795
2796InstanceType Map::instance_type() {
2797 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2798}
2799
2800
2801void Map::set_instance_type(InstanceType value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002802 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2803}
2804
2805
2806int Map::unused_property_fields() {
2807 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2808}
2809
2810
2811void Map::set_unused_property_fields(int value) {
2812 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2813}
2814
2815
2816byte Map::bit_field() {
2817 return READ_BYTE_FIELD(this, kBitFieldOffset);
2818}
2819
2820
2821void Map::set_bit_field(byte value) {
2822 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2823}
2824
2825
2826byte Map::bit_field2() {
2827 return READ_BYTE_FIELD(this, kBitField2Offset);
2828}
2829
2830
2831void Map::set_bit_field2(byte value) {
2832 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2833}
2834
2835
2836void Map::set_non_instance_prototype(bool value) {
2837 if (value) {
2838 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2839 } else {
2840 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2841 }
2842}
2843
2844
2845bool Map::has_non_instance_prototype() {
2846 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2847}
2848
2849
Steve Block6ded16b2010-05-10 14:33:55 +01002850void Map::set_function_with_prototype(bool value) {
2851 if (value) {
2852 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2853 } else {
2854 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2855 }
2856}
2857
2858
2859bool Map::function_with_prototype() {
2860 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2861}
2862
2863
Steve Blocka7e24c12009-10-30 11:49:00 +00002864void Map::set_is_access_check_needed(bool access_check_needed) {
2865 if (access_check_needed) {
2866 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2867 } else {
2868 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2869 }
2870}
2871
2872
2873bool Map::is_access_check_needed() {
2874 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2875}
2876
2877
Steve Block8defd9f2010-07-08 12:39:36 +01002878void Map::set_is_extensible(bool value) {
2879 if (value) {
2880 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2881 } else {
2882 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2883 }
2884}
2885
2886bool Map::is_extensible() {
2887 return ((1 << kIsExtensible) & bit_field2()) != 0;
2888}
2889
2890
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002891void Map::set_attached_to_shared_function_info(bool value) {
2892 if (value) {
2893 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2894 } else {
2895 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2896 }
2897}
2898
2899bool Map::attached_to_shared_function_info() {
2900 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2901}
2902
2903
2904void Map::set_is_shared(bool value) {
2905 if (value) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002906 set_bit_field3(bit_field3() | (1 << kIsShared));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002907 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00002908 set_bit_field3(bit_field3() & ~(1 << kIsShared));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002909 }
2910}
2911
2912bool Map::is_shared() {
Ben Murdoch257744e2011-11-30 15:57:28 +00002913 return ((1 << kIsShared) & bit_field3()) != 0;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002914}
2915
2916
2917JSFunction* Map::unchecked_constructor() {
2918 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2919}
2920
Steve Block8defd9f2010-07-08 12:39:36 +01002921
Steve Blocka7e24c12009-10-30 11:49:00 +00002922Code::Flags Code::flags() {
2923 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2924}
2925
2926
2927void Code::set_flags(Code::Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00002928 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002929 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002930 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2931 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002932 ExtractArgumentsCountFromFlags(flags) >= 0);
2933 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2934}
2935
2936
2937Code::Kind Code::kind() {
2938 return ExtractKindFromFlags(flags());
2939}
2940
2941
Steve Blocka7e24c12009-10-30 11:49:00 +00002942InlineCacheState Code::ic_state() {
2943 InlineCacheState result = ExtractICStateFromFlags(flags());
2944 // Only allow uninitialized or debugger states for non-IC code
2945 // objects. This is used in the debugger to determine whether or not
2946 // a call to code object has been replaced with a debug break call.
2947 ASSERT(is_inline_cache_stub() ||
2948 result == UNINITIALIZED ||
2949 result == DEBUG_BREAK ||
2950 result == DEBUG_PREPARE_STEP_IN);
2951 return result;
2952}
2953
2954
Ben Murdochb8e0da22011-05-16 14:20:40 +01002955Code::ExtraICState Code::extra_ic_state() {
2956 ASSERT(is_inline_cache_stub());
2957 return ExtractExtraICStateFromFlags(flags());
2958}
2959
2960
Steve Blocka7e24c12009-10-30 11:49:00 +00002961PropertyType Code::type() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002962 return ExtractTypeFromFlags(flags());
2963}
2964
2965
2966int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002967 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002968 return ExtractArgumentsCountFromFlags(flags());
2969}
2970
2971
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002972int Code::major_key() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002973 ASSERT(kind() == STUB ||
Ben Murdoch257744e2011-11-30 15:57:28 +00002974 kind() == UNARY_OP_IC ||
2975 kind() == BINARY_OP_IC ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002976 kind() == COMPARE_IC ||
2977 kind() == TO_BOOLEAN_IC);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002978 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00002979}
2980
2981
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002982void Code::set_major_key(int major) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002983 ASSERT(kind() == STUB ||
Ben Murdoch257744e2011-11-30 15:57:28 +00002984 kind() == UNARY_OP_IC ||
2985 kind() == BINARY_OP_IC ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002986 kind() == COMPARE_IC ||
2987 kind() == TO_BOOLEAN_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002988 ASSERT(0 <= major && major < 256);
2989 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2990}
2991
2992
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002993bool Code::is_pregenerated() {
2994 return kind() == STUB && IsPregeneratedField::decode(flags());
2995}
2996
2997
2998void Code::set_is_pregenerated(bool value) {
2999 ASSERT(kind() == STUB);
3000 Flags f = flags();
3001 f = static_cast<Flags>(IsPregeneratedField::update(f, value));
3002 set_flags(f);
3003}
3004
3005
Ben Murdochb0fe1622011-05-05 13:52:32 +01003006bool Code::optimizable() {
3007 ASSERT(kind() == FUNCTION);
3008 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
3009}
3010
3011
3012void Code::set_optimizable(bool value) {
3013 ASSERT(kind() == FUNCTION);
3014 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
3015}
3016
3017
3018bool Code::has_deoptimization_support() {
3019 ASSERT(kind() == FUNCTION);
Ben Murdoch589d6972011-11-30 16:04:58 +00003020 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3021 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003022}
3023
3024
3025void Code::set_has_deoptimization_support(bool value) {
3026 ASSERT(kind() == FUNCTION);
Ben Murdoch589d6972011-11-30 16:04:58 +00003027 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3028 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
3029 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3030}
3031
3032
3033bool Code::has_debug_break_slots() {
3034 ASSERT(kind() == FUNCTION);
3035 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3036 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
3037}
3038
3039
3040void Code::set_has_debug_break_slots(bool value) {
3041 ASSERT(kind() == FUNCTION);
3042 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3043 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
3044 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003045}
3046
3047
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003048bool Code::is_compiled_optimizable() {
3049 ASSERT(kind() == FUNCTION);
3050 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3051 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
3052}
3053
3054
3055void Code::set_compiled_optimizable(bool value) {
3056 ASSERT(kind() == FUNCTION);
3057 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3058 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
3059 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3060}
3061
3062
3063bool Code::has_self_optimization_header() {
3064 ASSERT(kind() == FUNCTION);
3065 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3066 return FullCodeFlagsHasSelfOptimizationHeader::decode(flags);
3067}
3068
3069
3070void Code::set_self_optimization_header(bool value) {
3071 ASSERT(kind() == FUNCTION);
3072 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3073 flags = FullCodeFlagsHasSelfOptimizationHeader::update(flags, value);
3074 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3075}
3076
3077
Ben Murdochb0fe1622011-05-05 13:52:32 +01003078int Code::allow_osr_at_loop_nesting_level() {
3079 ASSERT(kind() == FUNCTION);
3080 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
3081}
3082
3083
3084void Code::set_allow_osr_at_loop_nesting_level(int level) {
3085 ASSERT(kind() == FUNCTION);
3086 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
3087 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
3088}
3089
3090
3091unsigned Code::stack_slots() {
3092 ASSERT(kind() == OPTIMIZED_FUNCTION);
3093 return READ_UINT32_FIELD(this, kStackSlotsOffset);
3094}
3095
3096
3097void Code::set_stack_slots(unsigned slots) {
3098 ASSERT(kind() == OPTIMIZED_FUNCTION);
3099 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
3100}
3101
3102
Steve Block1e0659c2011-05-24 12:43:12 +01003103unsigned Code::safepoint_table_offset() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003104 ASSERT(kind() == OPTIMIZED_FUNCTION);
Steve Block1e0659c2011-05-24 12:43:12 +01003105 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003106}
3107
3108
Steve Block1e0659c2011-05-24 12:43:12 +01003109void Code::set_safepoint_table_offset(unsigned offset) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003110 ASSERT(kind() == OPTIMIZED_FUNCTION);
3111 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
Steve Block1e0659c2011-05-24 12:43:12 +01003112 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003113}
3114
3115
Steve Block1e0659c2011-05-24 12:43:12 +01003116unsigned Code::stack_check_table_offset() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003117 ASSERT(kind() == FUNCTION);
Steve Block1e0659c2011-05-24 12:43:12 +01003118 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003119}
3120
3121
Steve Block1e0659c2011-05-24 12:43:12 +01003122void Code::set_stack_check_table_offset(unsigned offset) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003123 ASSERT(kind() == FUNCTION);
3124 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
Steve Block1e0659c2011-05-24 12:43:12 +01003125 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003126}
3127
3128
3129CheckType Code::check_type() {
3130 ASSERT(is_call_stub() || is_keyed_call_stub());
3131 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
3132 return static_cast<CheckType>(type);
3133}
3134
3135
3136void Code::set_check_type(CheckType value) {
3137 ASSERT(is_call_stub() || is_keyed_call_stub());
3138 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
3139}
3140
3141
Ben Murdoch257744e2011-11-30 15:57:28 +00003142byte Code::unary_op_type() {
3143 ASSERT(is_unary_op_stub());
3144 return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
3145}
3146
3147
3148void Code::set_unary_op_type(byte value) {
3149 ASSERT(is_unary_op_stub());
3150 WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
3151}
3152
3153
3154byte Code::binary_op_type() {
3155 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003156 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3157}
3158
3159
Ben Murdoch257744e2011-11-30 15:57:28 +00003160void Code::set_binary_op_type(byte value) {
3161 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003162 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3163}
3164
3165
Ben Murdoch257744e2011-11-30 15:57:28 +00003166byte Code::binary_op_result_type() {
3167 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003168 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3169}
3170
3171
Ben Murdoch257744e2011-11-30 15:57:28 +00003172void Code::set_binary_op_result_type(byte value) {
3173 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003174 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3175}
3176
3177
3178byte Code::compare_state() {
3179 ASSERT(is_compare_ic_stub());
3180 return READ_BYTE_FIELD(this, kCompareStateOffset);
3181}
3182
3183
3184void Code::set_compare_state(byte value) {
3185 ASSERT(is_compare_ic_stub());
3186 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3187}
3188
3189
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003190byte Code::to_boolean_state() {
3191 ASSERT(is_to_boolean_ic_stub());
3192 return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3193}
3194
3195
3196void Code::set_to_boolean_state(byte value) {
3197 ASSERT(is_to_boolean_ic_stub());
3198 WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3199}
3200
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003201
3202bool Code::has_function_cache() {
3203 ASSERT(kind() == STUB);
3204 return READ_BYTE_FIELD(this, kHasFunctionCacheOffset) != 0;
3205}
3206
3207
3208void Code::set_has_function_cache(bool flag) {
3209 ASSERT(kind() == STUB);
3210 WRITE_BYTE_FIELD(this, kHasFunctionCacheOffset, flag);
3211}
3212
3213
Steve Blocka7e24c12009-10-30 11:49:00 +00003214bool Code::is_inline_cache_stub() {
3215 Kind kind = this->kind();
3216 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3217}
3218
3219
3220Code::Flags Code::ComputeFlags(Kind kind,
Steve Blocka7e24c12009-10-30 11:49:00 +00003221 InlineCacheState ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003222 ExtraICState extra_ic_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00003223 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01003224 int argc,
3225 InlineCacheHolderFlag holder) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003226 // Extra IC state is only allowed for call IC stubs or for store IC
3227 // stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003228 ASSERT(extra_ic_state == kNoExtraICState ||
Ben Murdoch589d6972011-11-30 16:04:58 +00003229 kind == CALL_IC ||
3230 kind == STORE_IC ||
3231 kind == KEYED_STORE_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00003232 // Compute the bit mask.
Ben Murdoch589d6972011-11-30 16:04:58 +00003233 int bits = KindField::encode(kind)
3234 | ICStateField::encode(ic_state)
3235 | TypeField::encode(type)
3236 | ExtraICStateField::encode(extra_ic_state)
3237 | (argc << kArgumentsCountShift)
3238 | CacheHolderField::encode(holder);
3239 return static_cast<Flags>(bits);
Steve Blocka7e24c12009-10-30 11:49:00 +00003240}
3241
3242
3243Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3244 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003245 ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01003246 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00003247 int argc) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003248 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00003249}
3250
3251
3252Code::Kind Code::ExtractKindFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003253 return KindField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003254}
3255
3256
3257InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003258 return ICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003259}
3260
3261
Ben Murdochb8e0da22011-05-16 14:20:40 +01003262Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003263 return ExtraICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003264}
3265
3266
3267PropertyType Code::ExtractTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003268 return TypeField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003269}
3270
3271
3272int Code::ExtractArgumentsCountFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003273 return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003274}
3275
3276
Steve Block8defd9f2010-07-08 12:39:36 +01003277InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003278 return CacheHolderField::decode(flags);
Steve Block8defd9f2010-07-08 12:39:36 +01003279}
3280
3281
Steve Blocka7e24c12009-10-30 11:49:00 +00003282Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003283 int bits = flags & ~TypeField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00003284 return static_cast<Flags>(bits);
3285}
3286
3287
3288Code* Code::GetCodeFromTargetAddress(Address address) {
3289 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3290 // GetCodeFromTargetAddress might be called when marking objects during mark
3291 // sweep. reinterpret_cast is therefore used instead of the more appropriate
3292 // Code::cast. Code::cast does not work when the object's map is
3293 // marked.
3294 Code* result = reinterpret_cast<Code*>(code);
3295 return result;
3296}
3297
3298
Steve Block791712a2010-08-27 10:21:07 +01003299Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3300 return HeapObject::
3301 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3302}
3303
3304
Steve Blocka7e24c12009-10-30 11:49:00 +00003305Object* Map::prototype() {
3306 return READ_FIELD(this, kPrototypeOffset);
3307}
3308
3309
3310void Map::set_prototype(Object* value, WriteBarrierMode mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003311 ASSERT(value->IsNull() || value->IsJSReceiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003312 WRITE_FIELD(this, kPrototypeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003313 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
Steve Block1e0659c2011-05-24 12:43:12 +01003314}
3315
3316
Ben Murdoch257744e2011-11-30 15:57:28 +00003317DescriptorArray* Map::instance_descriptors() {
3318 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3319 if (object->IsSmi()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003320 return GetHeap()->empty_descriptor_array();
Ben Murdoch257744e2011-11-30 15:57:28 +00003321 } else {
3322 return DescriptorArray::cast(object);
3323 }
3324}
3325
3326
3327void Map::init_instance_descriptors() {
3328 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3329}
3330
3331
3332void Map::clear_instance_descriptors() {
3333 Object* object = READ_FIELD(this,
3334 kInstanceDescriptorsOrBitField3Offset);
3335 if (!object->IsSmi()) {
3336 WRITE_FIELD(
3337 this,
3338 kInstanceDescriptorsOrBitField3Offset,
3339 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3340 }
3341}
3342
3343
3344void Map::set_instance_descriptors(DescriptorArray* value,
3345 WriteBarrierMode mode) {
3346 Object* object = READ_FIELD(this,
3347 kInstanceDescriptorsOrBitField3Offset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003348 Heap* heap = GetHeap();
3349 if (value == heap->empty_descriptor_array()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003350 clear_instance_descriptors();
3351 return;
3352 } else {
3353 if (object->IsSmi()) {
3354 value->set_bit_field3_storage(Smi::cast(object)->value());
3355 } else {
3356 value->set_bit_field3_storage(
3357 DescriptorArray::cast(object)->bit_field3_storage());
3358 }
3359 }
3360 ASSERT(!is_shared());
3361 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003362 CONDITIONAL_WRITE_BARRIER(
3363 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00003364}
3365
3366
3367int Map::bit_field3() {
3368 Object* object = READ_FIELD(this,
3369 kInstanceDescriptorsOrBitField3Offset);
3370 if (object->IsSmi()) {
3371 return Smi::cast(object)->value();
3372 } else {
3373 return DescriptorArray::cast(object)->bit_field3_storage();
3374 }
3375}
3376
3377
3378void Map::set_bit_field3(int value) {
3379 ASSERT(Smi::IsValid(value));
3380 Object* object = READ_FIELD(this,
3381 kInstanceDescriptorsOrBitField3Offset);
3382 if (object->IsSmi()) {
3383 WRITE_FIELD(this,
3384 kInstanceDescriptorsOrBitField3Offset,
3385 Smi::FromInt(value));
3386 } else {
3387 DescriptorArray::cast(object)->set_bit_field3_storage(value);
3388 }
3389}
3390
3391
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003392FixedArray* Map::unchecked_prototype_transitions() {
3393 return reinterpret_cast<FixedArray*>(
3394 READ_FIELD(this, kPrototypeTransitionsOffset));
3395}
3396
3397
Steve Block6ded16b2010-05-10 14:33:55 +01003398ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Block053d10c2011-06-13 19:13:29 +01003399ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003400ACCESSORS(Map, constructor, Object, kConstructorOffset)
3401
3402ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003403ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
3404ACCESSORS(JSFunction,
3405 next_function_link,
3406 Object,
3407 kNextFunctionLinkOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003408
3409ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3410ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3411ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3412
3413ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3414
3415ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3416ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3417ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3418ACCESSORS(AccessorInfo, name, Object, kNameOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003419ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
3420
3421ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
3422ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
Ben Murdochc7cc0282012-03-05 14:35:55 +00003423
Steve Blocka7e24c12009-10-30 11:49:00 +00003424ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3425ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3426ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3427
3428ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3429ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3430ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3431ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3432ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3433ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3434
3435ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3436ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3437
3438ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3439ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3440
3441ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3442ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3443ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3444 kPropertyAccessorsOffset)
3445ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3446 kPrototypeTemplateOffset)
3447ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3448ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3449 kNamedPropertyHandlerOffset)
3450ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3451 kIndexedPropertyHandlerOffset)
3452ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3453 kInstanceTemplateOffset)
3454ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3455ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3456ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3457 kInstanceCallHandlerOffset)
3458ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3459 kAccessCheckInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003460ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003461
3462ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3463ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3464 kInternalFieldCountOffset)
3465
3466ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3467ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3468
3469ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3470
3471ACCESSORS(Script, source, Object, kSourceOffset)
3472ACCESSORS(Script, name, Object, kNameOffset)
3473ACCESSORS(Script, id, Object, kIdOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003474ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
3475ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003476ACCESSORS(Script, data, Object, kDataOffset)
3477ACCESSORS(Script, context_data, Object, kContextOffset)
Ben Murdoch257744e2011-11-30 15:57:28 +00003478ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003479ACCESSORS_TO_SMI(Script, type, kTypeOffset)
3480ACCESSORS_TO_SMI(Script, compilation_type, kCompilationTypeOffset)
3481ACCESSORS_TO_SMI(Script, compilation_state, kCompilationStateOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003482ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00003483ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003484ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
3485 kEvalFrominstructionsOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003486
3487#ifdef ENABLE_DEBUGGER_SUPPORT
3488ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3489ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3490ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3491ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3492
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003493ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
3494ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
3495ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00003496ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3497#endif
3498
Steve Blocka7e24c12009-10-30 11:49:00 +00003499ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003500ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3501ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003502ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3503 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01003504ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003505ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3506ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3507ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3508ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3509 kThisPropertyAssignmentsOffset)
3510
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003511SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
3512
Steve Blocka7e24c12009-10-30 11:49:00 +00003513BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3514 kHiddenPrototypeBit)
3515BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3516BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3517 kNeedsAccessCheckBit)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003518BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3519 kReadOnlyPrototypeBit)
Steve Blocka7e24c12009-10-30 11:49:00 +00003520BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3521 kIsExpressionBit)
3522BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3523 kIsTopLevelBit)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003524BOOL_GETTER(SharedFunctionInfo,
3525 compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00003526 has_only_simple_this_property_assignments,
3527 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00003528BOOL_ACCESSORS(SharedFunctionInfo,
3529 compiler_hints,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003530 allows_lazy_compilation,
3531 kAllowLazyCompilation)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003532BOOL_ACCESSORS(SharedFunctionInfo,
3533 compiler_hints,
3534 uses_arguments,
3535 kUsesArguments)
3536BOOL_ACCESSORS(SharedFunctionInfo,
3537 compiler_hints,
3538 has_duplicate_parameters,
3539 kHasDuplicateParameters)
Steve Blocka7e24c12009-10-30 11:49:00 +00003540
Iain Merrick75681382010-08-19 15:07:18 +01003541
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003542#if V8_HOST_ARCH_32_BIT
3543SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3544SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003545 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003546SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003547 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003548SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3549SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00003550 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003551SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3552SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00003553 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003554SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00003555 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003556SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003557 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003558SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003559SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3560SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003561#else
Steve Blocka7e24c12009-10-30 11:49:00 +00003562
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003563#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003564 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003565 int holder::name() { \
3566 int value = READ_INT_FIELD(this, offset); \
3567 ASSERT(kHeapObjectTag == 1); \
3568 ASSERT((value & kHeapObjectTag) == 0); \
3569 return value >> 1; \
3570 } \
3571 void holder::set_##name(int value) { \
3572 ASSERT(kHeapObjectTag == 1); \
3573 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3574 (value & 0xC0000000) == 0x000000000); \
3575 WRITE_INT_FIELD(this, \
3576 offset, \
3577 (value << 1) & ~kHeapObjectTag); \
3578 }
3579
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003580#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3581 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003582 INT_ACCESSORS(holder, name, offset)
3583
3584
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003585PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003586PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3587 formal_parameter_count,
3588 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003589
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003590PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3591 expected_nof_properties,
3592 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003593PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3594
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003595PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3596PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3597 start_position_and_type,
3598 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003599
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003600PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3601 function_token_position,
3602 kFunctionTokenPositionOffset)
3603PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3604 compiler_hints,
3605 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003606
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003607PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3608 this_property_assignments_count,
3609 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003610PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003611
3612PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3613PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003614#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003615
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003616
3617int SharedFunctionInfo::construction_count() {
3618 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3619}
3620
3621
3622void SharedFunctionInfo::set_construction_count(int value) {
3623 ASSERT(0 <= value && value < 256);
3624 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3625}
3626
3627
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003628BOOL_ACCESSORS(SharedFunctionInfo,
3629 compiler_hints,
3630 live_objects_may_exist,
3631 kLiveObjectsMayExist)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003632
3633
3634bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003635 return initial_map() != GetHeap()->undefined_value();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003636}
3637
3638
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003639BOOL_GETTER(SharedFunctionInfo,
3640 compiler_hints,
3641 optimization_disabled,
3642 kOptimizationDisabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003643
3644
3645void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3646 set_compiler_hints(BooleanBit::set(compiler_hints(),
3647 kOptimizationDisabled,
3648 disable));
3649 // If disabling optimizations we reflect that in the code object so
3650 // it will not be counted as optimizable code.
3651 if ((code()->kind() == Code::FUNCTION) && disable) {
3652 code()->set_optimizable(false);
3653 }
3654}
3655
3656
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003657LanguageMode SharedFunctionInfo::language_mode() {
3658 int hints = compiler_hints();
3659 if (BooleanBit::get(hints, kExtendedModeFunction)) {
3660 ASSERT(BooleanBit::get(hints, kStrictModeFunction));
3661 return EXTENDED_MODE;
3662 }
3663 return BooleanBit::get(hints, kStrictModeFunction)
3664 ? STRICT_MODE : CLASSIC_MODE;
3665}
3666
3667
3668void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
3669 // We only allow language mode transitions that go set the same language mode
3670 // again or go up in the chain:
3671 // CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
3672 ASSERT(this->language_mode() == CLASSIC_MODE ||
3673 this->language_mode() == language_mode ||
3674 language_mode == EXTENDED_MODE);
3675 int hints = compiler_hints();
3676 hints = BooleanBit::set(
3677 hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
3678 hints = BooleanBit::set(
3679 hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
3680 set_compiler_hints(hints);
3681}
3682
3683
3684bool SharedFunctionInfo::is_classic_mode() {
3685 return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
3686}
3687
3688BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
3689 kExtendedModeFunction)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003690BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3691BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3692 name_should_print_as_anonymous,
3693 kNameShouldPrintAsAnonymous)
3694BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3695BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003696BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
3697BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
3698 kDontOptimize)
3699BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
Ben Murdoch257744e2011-11-30 15:57:28 +00003700
Steve Block6ded16b2010-05-10 14:33:55 +01003701ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3702ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3703
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003704ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3705
Steve Block3ce2e202009-11-05 08:53:23 +00003706bool Script::HasValidSource() {
3707 Object* src = this->source();
3708 if (!src->IsString()) return true;
3709 String* src_str = String::cast(src);
3710 if (!StringShape(src_str).IsExternal()) return true;
3711 if (src_str->IsAsciiRepresentation()) {
3712 return ExternalAsciiString::cast(src)->resource() != NULL;
3713 } else if (src_str->IsTwoByteRepresentation()) {
3714 return ExternalTwoByteString::cast(src)->resource() != NULL;
3715 }
3716 return true;
3717}
3718
3719
Steve Blocka7e24c12009-10-30 11:49:00 +00003720void SharedFunctionInfo::DontAdaptArguments() {
3721 ASSERT(code()->kind() == Code::BUILTIN);
3722 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3723}
3724
3725
3726int SharedFunctionInfo::start_position() {
3727 return start_position_and_type() >> kStartPositionShift;
3728}
3729
3730
3731void SharedFunctionInfo::set_start_position(int start_position) {
3732 set_start_position_and_type((start_position << kStartPositionShift)
3733 | (start_position_and_type() & ~kStartPositionMask));
3734}
3735
3736
3737Code* SharedFunctionInfo::code() {
3738 return Code::cast(READ_FIELD(this, kCodeOffset));
3739}
3740
3741
Iain Merrick75681382010-08-19 15:07:18 +01003742Code* SharedFunctionInfo::unchecked_code() {
3743 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3744}
3745
3746
Steve Blocka7e24c12009-10-30 11:49:00 +00003747void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3748 WRITE_FIELD(this, kCodeOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003749 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003750}
3751
3752
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003753ScopeInfo* SharedFunctionInfo::scope_info() {
3754 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003755}
3756
3757
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003758void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003759 WriteBarrierMode mode) {
3760 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003761 CONDITIONAL_WRITE_BARRIER(GetHeap(),
3762 this,
3763 kScopeInfoOffset,
3764 reinterpret_cast<Object*>(value),
3765 mode);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003766}
3767
3768
Steve Blocka7e24c12009-10-30 11:49:00 +00003769bool SharedFunctionInfo::is_compiled() {
Steve Block44f0eee2011-05-26 01:26:41 +01003770 return code() !=
3771 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003772}
3773
3774
Steve Block6ded16b2010-05-10 14:33:55 +01003775bool SharedFunctionInfo::IsApiFunction() {
3776 return function_data()->IsFunctionTemplateInfo();
3777}
3778
3779
3780FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3781 ASSERT(IsApiFunction());
3782 return FunctionTemplateInfo::cast(function_data());
3783}
3784
3785
Ben Murdochb0fe1622011-05-05 13:52:32 +01003786bool SharedFunctionInfo::HasBuiltinFunctionId() {
Kristian Monsen25f61362010-05-21 11:50:48 +01003787 return function_data()->IsSmi();
3788}
3789
3790
Ben Murdochb0fe1622011-05-05 13:52:32 +01003791BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3792 ASSERT(HasBuiltinFunctionId());
3793 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003794}
3795
3796
Iain Merrick75681382010-08-19 15:07:18 +01003797int SharedFunctionInfo::code_age() {
3798 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3799}
3800
3801
3802void SharedFunctionInfo::set_code_age(int code_age) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003803 int hints = compiler_hints() & ~(kCodeAgeMask << kCodeAgeShift);
3804 set_compiler_hints(hints | ((code_age & kCodeAgeMask) << kCodeAgeShift));
Iain Merrick75681382010-08-19 15:07:18 +01003805}
3806
3807
Ben Murdochb0fe1622011-05-05 13:52:32 +01003808bool SharedFunctionInfo::has_deoptimization_support() {
3809 Code* code = this->code();
3810 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3811}
3812
3813
Steve Blocka7e24c12009-10-30 11:49:00 +00003814bool JSFunction::IsBuiltin() {
3815 return context()->global()->IsJSBuiltinsObject();
3816}
3817
3818
Ben Murdochb0fe1622011-05-05 13:52:32 +01003819bool JSFunction::NeedsArgumentsAdaption() {
3820 return shared()->formal_parameter_count() !=
3821 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3822}
3823
3824
3825bool JSFunction::IsOptimized() {
3826 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3827}
3828
3829
Ben Murdoch8b112d22011-06-08 16:22:53 +01003830bool JSFunction::IsOptimizable() {
3831 return code()->kind() == Code::FUNCTION && code()->optimizable();
3832}
3833
3834
Ben Murdochb0fe1622011-05-05 13:52:32 +01003835bool JSFunction::IsMarkedForLazyRecompilation() {
Steve Block44f0eee2011-05-26 01:26:41 +01003836 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003837}
3838
3839
Steve Blocka7e24c12009-10-30 11:49:00 +00003840Code* JSFunction::code() {
Steve Block791712a2010-08-27 10:21:07 +01003841 return Code::cast(unchecked_code());
Iain Merrick75681382010-08-19 15:07:18 +01003842}
3843
3844
3845Code* JSFunction::unchecked_code() {
Steve Block791712a2010-08-27 10:21:07 +01003846 return reinterpret_cast<Code*>(
3847 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003848}
3849
3850
3851void JSFunction::set_code(Code* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003852 ASSERT(!HEAP->InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01003853 Address entry = value->entry();
3854 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003855 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
3856 this,
3857 HeapObject::RawField(this, kCodeEntryOffset),
3858 value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003859}
3860
3861
Ben Murdochb0fe1622011-05-05 13:52:32 +01003862void JSFunction::ReplaceCode(Code* code) {
3863 bool was_optimized = IsOptimized();
3864 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3865
3866 set_code(code);
3867
3868 // Add/remove the function from the list of optimized functions for this
3869 // context based on the state change.
3870 if (!was_optimized && is_optimized) {
3871 context()->global_context()->AddOptimizedFunction(this);
3872 }
3873 if (was_optimized && !is_optimized) {
3874 context()->global_context()->RemoveOptimizedFunction(this);
3875 }
3876}
3877
3878
Steve Blocka7e24c12009-10-30 11:49:00 +00003879Context* JSFunction::context() {
3880 return Context::cast(READ_FIELD(this, kContextOffset));
3881}
3882
3883
3884Object* JSFunction::unchecked_context() {
3885 return READ_FIELD(this, kContextOffset);
3886}
3887
3888
Iain Merrick75681382010-08-19 15:07:18 +01003889SharedFunctionInfo* JSFunction::unchecked_shared() {
3890 return reinterpret_cast<SharedFunctionInfo*>(
3891 READ_FIELD(this, kSharedFunctionInfoOffset));
3892}
3893
3894
Steve Blocka7e24c12009-10-30 11:49:00 +00003895void JSFunction::set_context(Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003896 ASSERT(value->IsUndefined() || value->IsContext());
Steve Blocka7e24c12009-10-30 11:49:00 +00003897 WRITE_FIELD(this, kContextOffset, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003898 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003899}
3900
3901ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3902 kPrototypeOrInitialMapOffset)
3903
3904
3905Map* JSFunction::initial_map() {
3906 return Map::cast(prototype_or_initial_map());
3907}
3908
3909
3910void JSFunction::set_initial_map(Map* value) {
3911 set_prototype_or_initial_map(value);
3912}
3913
3914
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003915MaybeObject* JSFunction::set_initial_map_and_cache_transitions(
3916 Map* initial_map) {
3917 Context* global_context = context()->global_context();
3918 Object* array_function =
3919 global_context->get(Context::ARRAY_FUNCTION_INDEX);
3920 if (array_function->IsJSFunction() &&
3921 this == JSFunction::cast(array_function)) {
3922 ASSERT(initial_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
3923
3924 MaybeObject* maybe_map = initial_map->CopyDropTransitions();
3925 Map* new_double_map = NULL;
3926 if (!maybe_map->To<Map>(&new_double_map)) return maybe_map;
3927 new_double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
3928 maybe_map = initial_map->AddElementsTransition(FAST_DOUBLE_ELEMENTS,
3929 new_double_map);
3930 if (maybe_map->IsFailure()) return maybe_map;
3931
3932 maybe_map = new_double_map->CopyDropTransitions();
3933 Map* new_object_map = NULL;
3934 if (!maybe_map->To<Map>(&new_object_map)) return maybe_map;
3935 new_object_map->set_elements_kind(FAST_ELEMENTS);
3936 maybe_map = new_double_map->AddElementsTransition(FAST_ELEMENTS,
3937 new_object_map);
3938 if (maybe_map->IsFailure()) return maybe_map;
3939
3940 global_context->set_smi_js_array_map(initial_map);
3941 global_context->set_double_js_array_map(new_double_map);
3942 global_context->set_object_js_array_map(new_object_map);
3943 }
3944 set_initial_map(initial_map);
3945 return this;
3946}
3947
3948
Steve Blocka7e24c12009-10-30 11:49:00 +00003949bool JSFunction::has_initial_map() {
3950 return prototype_or_initial_map()->IsMap();
3951}
3952
3953
3954bool JSFunction::has_instance_prototype() {
3955 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3956}
3957
3958
3959bool JSFunction::has_prototype() {
3960 return map()->has_non_instance_prototype() || has_instance_prototype();
3961}
3962
3963
3964Object* JSFunction::instance_prototype() {
3965 ASSERT(has_instance_prototype());
3966 if (has_initial_map()) return initial_map()->prototype();
3967 // When there is no initial map and the prototype is a JSObject, the
3968 // initial map field is used for the prototype field.
3969 return prototype_or_initial_map();
3970}
3971
3972
3973Object* JSFunction::prototype() {
3974 ASSERT(has_prototype());
3975 // If the function's prototype property has been set to a non-JSObject
3976 // value, that value is stored in the constructor field of the map.
3977 if (map()->has_non_instance_prototype()) return map()->constructor();
3978 return instance_prototype();
3979}
3980
Steve Block6ded16b2010-05-10 14:33:55 +01003981bool JSFunction::should_have_prototype() {
3982 return map()->function_with_prototype();
3983}
3984
Steve Blocka7e24c12009-10-30 11:49:00 +00003985
3986bool JSFunction::is_compiled() {
Steve Block44f0eee2011-05-26 01:26:41 +01003987 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003988}
3989
3990
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003991FixedArray* JSFunction::literals() {
3992 ASSERT(!shared()->bound());
3993 return literals_or_bindings();
3994}
3995
3996
3997void JSFunction::set_literals(FixedArray* literals) {
3998 ASSERT(!shared()->bound());
3999 set_literals_or_bindings(literals);
4000}
4001
4002
4003FixedArray* JSFunction::function_bindings() {
4004 ASSERT(shared()->bound());
4005 return literals_or_bindings();
4006}
4007
4008
4009void JSFunction::set_function_bindings(FixedArray* bindings) {
4010 ASSERT(shared()->bound());
4011 // Bound function literal may be initialized to the empty fixed array
4012 // before the bindings are set.
4013 ASSERT(bindings == GetHeap()->empty_fixed_array() ||
4014 bindings->map() == GetHeap()->fixed_cow_array_map());
4015 set_literals_or_bindings(bindings);
4016}
4017
4018
Steve Blocka7e24c12009-10-30 11:49:00 +00004019int JSFunction::NumberOfLiterals() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004020 ASSERT(!shared()->bound());
Steve Blocka7e24c12009-10-30 11:49:00 +00004021 return literals()->length();
4022}
4023
4024
4025Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004026 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004027 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00004028}
4029
4030
4031void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
4032 Object* value) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004033 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004034 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004035 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
Steve Block6ded16b2010-05-10 14:33:55 +01004036}
4037
4038
4039Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004040 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004041 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
4042}
4043
4044
4045void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
4046 Code* value) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01004047 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01004048 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
Steve Block44f0eee2011-05-26 01:26:41 +01004049 ASSERT(!HEAP->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00004050}
4051
4052
Ben Murdoch257744e2011-11-30 15:57:28 +00004053ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004054ACCESSORS(JSProxy, hash, Object, kHashOffset)
Ben Murdoch589d6972011-11-30 16:04:58 +00004055ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
4056ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
4057
4058
4059void JSProxy::InitializeBody(int object_size, Object* value) {
4060 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
4061 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
4062 WRITE_FIELD(this, offset, value);
4063 }
4064}
Ben Murdoch257744e2011-11-30 15:57:28 +00004065
4066
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004067ACCESSORS(JSSet, table, Object, kTableOffset)
4068ACCESSORS(JSMap, table, Object, kTableOffset)
4069ACCESSORS(JSWeakMap, table, Object, kTableOffset)
4070ACCESSORS(JSWeakMap, next, Object, kNextOffset)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004071
4072
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004073Address Foreign::foreign_address() {
4074 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004075}
4076
4077
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004078void Foreign::set_foreign_address(Address value) {
4079 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00004080}
4081
4082
Steve Blocka7e24c12009-10-30 11:49:00 +00004083ACCESSORS(JSValue, value, Object, kValueOffset)
4084
4085
4086JSValue* JSValue::cast(Object* obj) {
4087 ASSERT(obj->IsJSValue());
4088 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
4089 return reinterpret_cast<JSValue*>(obj);
4090}
4091
4092
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004093ACCESSORS(JSDate, value, Object, kValueOffset)
4094ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
4095ACCESSORS(JSDate, year, Object, kYearOffset)
4096ACCESSORS(JSDate, month, Object, kMonthOffset)
4097ACCESSORS(JSDate, day, Object, kDayOffset)
4098ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
4099ACCESSORS(JSDate, hour, Object, kHourOffset)
4100ACCESSORS(JSDate, min, Object, kMinOffset)
4101ACCESSORS(JSDate, sec, Object, kSecOffset)
4102
4103
4104JSDate* JSDate::cast(Object* obj) {
4105 ASSERT(obj->IsJSDate());
4106 ASSERT(HeapObject::cast(obj)->Size() == JSDate::kSize);
4107 return reinterpret_cast<JSDate*>(obj);
4108}
4109
4110
Steve Block1e0659c2011-05-24 12:43:12 +01004111ACCESSORS(JSMessageObject, type, String, kTypeOffset)
4112ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
4113ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
4114ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
4115ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
4116SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
4117SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
4118
4119
4120JSMessageObject* JSMessageObject::cast(Object* obj) {
4121 ASSERT(obj->IsJSMessageObject());
4122 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
4123 return reinterpret_cast<JSMessageObject*>(obj);
4124}
4125
4126
Steve Blocka7e24c12009-10-30 11:49:00 +00004127INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01004128ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004129ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004130ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004131ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
4132ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
4133INT_ACCESSORS(Code, ic_age, kICAgeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00004134
4135byte* Code::instruction_start() {
4136 return FIELD_ADDR(this, kHeaderSize);
4137}
4138
4139
Leon Clarkeac952652010-07-15 11:15:24 +01004140byte* Code::instruction_end() {
4141 return instruction_start() + instruction_size();
4142}
4143
4144
Steve Blocka7e24c12009-10-30 11:49:00 +00004145int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01004146 return RoundUp(instruction_size(), kObjectAlignment);
4147}
4148
4149
Ben Murdochb0fe1622011-05-05 13:52:32 +01004150FixedArray* Code::unchecked_deoptimization_data() {
4151 return reinterpret_cast<FixedArray*>(
4152 READ_FIELD(this, kDeoptimizationDataOffset));
4153}
4154
4155
Leon Clarkeac952652010-07-15 11:15:24 +01004156ByteArray* Code::unchecked_relocation_info() {
4157 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00004158}
4159
4160
4161byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01004162 return unchecked_relocation_info()->GetDataStartAddress();
4163}
4164
4165
4166int Code::relocation_size() {
4167 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00004168}
4169
4170
4171byte* Code::entry() {
4172 return instruction_start();
4173}
4174
4175
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004176bool Code::contains(byte* inner_pointer) {
4177 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
Steve Blocka7e24c12009-10-30 11:49:00 +00004178}
4179
4180
Steve Blocka7e24c12009-10-30 11:49:00 +00004181ACCESSORS(JSArray, length, Object, kLengthOffset)
4182
4183
4184ACCESSORS(JSRegExp, data, Object, kDataOffset)
4185
4186
4187JSRegExp::Type JSRegExp::TypeTag() {
4188 Object* data = this->data();
4189 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
4190 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
4191 return static_cast<JSRegExp::Type>(smi->value());
4192}
4193
4194
Ben Murdoch257744e2011-11-30 15:57:28 +00004195JSRegExp::Type JSRegExp::TypeTagUnchecked() {
4196 Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
4197 return static_cast<JSRegExp::Type>(smi->value());
4198}
4199
4200
Steve Blocka7e24c12009-10-30 11:49:00 +00004201int JSRegExp::CaptureCount() {
4202 switch (TypeTag()) {
4203 case ATOM:
4204 return 0;
4205 case IRREGEXP:
4206 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
4207 default:
4208 UNREACHABLE();
4209 return -1;
4210 }
4211}
4212
4213
4214JSRegExp::Flags JSRegExp::GetFlags() {
4215 ASSERT(this->data()->IsFixedArray());
4216 Object* data = this->data();
4217 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
4218 return Flags(smi->value());
4219}
4220
4221
4222String* JSRegExp::Pattern() {
4223 ASSERT(this->data()->IsFixedArray());
4224 Object* data = this->data();
4225 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4226 return pattern;
4227}
4228
4229
4230Object* JSRegExp::DataAt(int index) {
4231 ASSERT(TypeTag() != NOT_COMPILED);
4232 return FixedArray::cast(data())->get(index);
4233}
4234
4235
Ben Murdoch257744e2011-11-30 15:57:28 +00004236Object* JSRegExp::DataAtUnchecked(int index) {
4237 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4238 int offset = FixedArray::kHeaderSize + index * kPointerSize;
4239 return READ_FIELD(fa, offset);
4240}
4241
4242
Steve Blocka7e24c12009-10-30 11:49:00 +00004243void JSRegExp::SetDataAt(int index, Object* value) {
4244 ASSERT(TypeTag() != NOT_COMPILED);
4245 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4246 FixedArray::cast(data())->set(index, value);
4247}
4248
4249
Ben Murdoch257744e2011-11-30 15:57:28 +00004250void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4251 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4252 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4253 if (value->IsSmi()) {
4254 fa->set_unchecked(index, Smi::cast(value));
4255 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004256 // We only do this during GC, so we don't need to notify the write barrier.
Ben Murdoch257744e2011-11-30 15:57:28 +00004257 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4258 }
4259}
4260
4261
Ben Murdoch589d6972011-11-30 16:04:58 +00004262ElementsKind JSObject::GetElementsKind() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004263 ElementsKind kind = map()->elements_kind();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004264#if DEBUG
4265 FixedArrayBase* fixed_array =
4266 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
4267 Map* map = fixed_array->map();
4268 ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) &&
4269 (map == GetHeap()->fixed_array_map() ||
4270 map == GetHeap()->fixed_cow_array_map())) ||
4271 (kind == FAST_DOUBLE_ELEMENTS &&
4272 (fixed_array->IsFixedDoubleArray() ||
4273 fixed_array == GetHeap()->empty_fixed_array())) ||
4274 (kind == DICTIONARY_ELEMENTS &&
4275 fixed_array->IsFixedArray() &&
4276 fixed_array->IsDictionary()) ||
4277 (kind > DICTIONARY_ELEMENTS));
4278 ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
4279 (elements()->IsFixedArray() && elements()->length() >= 2));
4280#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004281 return kind;
Steve Blocka7e24c12009-10-30 11:49:00 +00004282}
4283
4284
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004285ElementsAccessor* JSObject::GetElementsAccessor() {
4286 return ElementsAccessor::ForKind(GetElementsKind());
4287}
4288
4289
Steve Blocka7e24c12009-10-30 11:49:00 +00004290bool JSObject::HasFastElements() {
4291 return GetElementsKind() == FAST_ELEMENTS;
4292}
4293
4294
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004295bool JSObject::HasFastSmiOnlyElements() {
4296 return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS;
4297}
4298
4299
4300bool JSObject::HasFastTypeElements() {
4301 ElementsKind elements_kind = GetElementsKind();
4302 return elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4303 elements_kind == FAST_ELEMENTS;
4304}
4305
4306
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004307bool JSObject::HasFastDoubleElements() {
4308 return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4309}
4310
4311
Steve Blocka7e24c12009-10-30 11:49:00 +00004312bool JSObject::HasDictionaryElements() {
4313 return GetElementsKind() == DICTIONARY_ELEMENTS;
4314}
4315
4316
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004317bool JSObject::HasNonStrictArgumentsElements() {
4318 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4319}
4320
4321
Steve Block3ce2e202009-11-05 08:53:23 +00004322bool JSObject::HasExternalArrayElements() {
Steve Block44f0eee2011-05-26 01:26:41 +01004323 HeapObject* array = elements();
4324 ASSERT(array != NULL);
4325 return array->IsExternalArray();
Steve Block3ce2e202009-11-05 08:53:23 +00004326}
4327
4328
Steve Block44f0eee2011-05-26 01:26:41 +01004329#define EXTERNAL_ELEMENTS_CHECK(name, type) \
4330bool JSObject::HasExternal##name##Elements() { \
4331 HeapObject* array = elements(); \
4332 ASSERT(array != NULL); \
4333 if (!array->IsHeapObject()) \
4334 return false; \
4335 return array->map()->instance_type() == type; \
Steve Block3ce2e202009-11-05 08:53:23 +00004336}
4337
4338
Steve Block44f0eee2011-05-26 01:26:41 +01004339EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4340EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4341EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4342EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4343 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4344EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4345EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4346 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4347EXTERNAL_ELEMENTS_CHECK(Float,
4348 EXTERNAL_FLOAT_ARRAY_TYPE)
Ben Murdoch257744e2011-11-30 15:57:28 +00004349EXTERNAL_ELEMENTS_CHECK(Double,
4350 EXTERNAL_DOUBLE_ARRAY_TYPE)
Steve Block44f0eee2011-05-26 01:26:41 +01004351EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
Steve Block3ce2e202009-11-05 08:53:23 +00004352
4353
Steve Blocka7e24c12009-10-30 11:49:00 +00004354bool JSObject::HasNamedInterceptor() {
4355 return map()->has_named_interceptor();
4356}
4357
4358
4359bool JSObject::HasIndexedInterceptor() {
4360 return map()->has_indexed_interceptor();
4361}
4362
4363
John Reck59135872010-11-02 12:39:01 -07004364MaybeObject* JSObject::EnsureWritableFastElements() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004365 ASSERT(HasFastTypeElements());
Iain Merrick75681382010-08-19 15:07:18 +01004366 FixedArray* elems = FixedArray::cast(elements());
Steve Block44f0eee2011-05-26 01:26:41 +01004367 Isolate* isolate = GetIsolate();
4368 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
John Reck59135872010-11-02 12:39:01 -07004369 Object* writable_elems;
Steve Block44f0eee2011-05-26 01:26:41 +01004370 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4371 elems, isolate->heap()->fixed_array_map());
John Reck59135872010-11-02 12:39:01 -07004372 if (!maybe_writable_elems->ToObject(&writable_elems)) {
4373 return maybe_writable_elems;
4374 }
4375 }
Iain Merrick75681382010-08-19 15:07:18 +01004376 set_elements(FixedArray::cast(writable_elems));
Steve Block44f0eee2011-05-26 01:26:41 +01004377 isolate->counters()->cow_arrays_converted()->Increment();
Iain Merrick75681382010-08-19 15:07:18 +01004378 return writable_elems;
4379}
4380
4381
Steve Blocka7e24c12009-10-30 11:49:00 +00004382StringDictionary* JSObject::property_dictionary() {
4383 ASSERT(!HasFastProperties());
4384 return StringDictionary::cast(properties());
4385}
4386
4387
Ben Murdochc7cc0282012-03-05 14:35:55 +00004388SeededNumberDictionary* JSObject::element_dictionary() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004389 ASSERT(HasDictionaryElements());
Ben Murdochc7cc0282012-03-05 14:35:55 +00004390 return SeededNumberDictionary::cast(elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00004391}
4392
4393
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004394bool String::IsHashFieldComputed(uint32_t field) {
4395 return (field & kHashNotComputedMask) == 0;
4396}
4397
4398
Steve Blocka7e24c12009-10-30 11:49:00 +00004399bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004400 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00004401}
4402
4403
4404uint32_t String::Hash() {
4405 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00004406 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004407 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00004408 // Slow case: compute hash code and set it.
4409 return ComputeAndSetHash();
4410}
4411
4412
Ben Murdochc7cc0282012-03-05 14:35:55 +00004413StringHasher::StringHasher(int length, uint32_t seed)
Steve Blocka7e24c12009-10-30 11:49:00 +00004414 : length_(length),
Ben Murdochc7cc0282012-03-05 14:35:55 +00004415 raw_running_hash_(seed),
Steve Blocka7e24c12009-10-30 11:49:00 +00004416 array_index_(0),
4417 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4418 is_first_char_(true),
Ben Murdochc7cc0282012-03-05 14:35:55 +00004419 is_valid_(true) {
4420 ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
4421}
Steve Blocka7e24c12009-10-30 11:49:00 +00004422
4423
4424bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00004425 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00004426}
4427
4428
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004429void StringHasher::AddCharacter(uint32_t c) {
4430 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4431 AddSurrogatePair(c); // Not inlined.
4432 return;
4433 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004434 // Use the Jenkins one-at-a-time hash function to update the hash
4435 // for the given character.
4436 raw_running_hash_ += c;
4437 raw_running_hash_ += (raw_running_hash_ << 10);
4438 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4439 // Incremental array index computation.
4440 if (is_array_index_) {
4441 if (c < '0' || c > '9') {
4442 is_array_index_ = false;
4443 } else {
4444 int d = c - '0';
4445 if (is_first_char_) {
4446 is_first_char_ = false;
4447 if (c == '0' && length_ > 1) {
4448 is_array_index_ = false;
4449 return;
4450 }
4451 }
4452 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4453 is_array_index_ = false;
4454 } else {
4455 array_index_ = array_index_ * 10 + d;
4456 }
4457 }
4458 }
4459}
4460
4461
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004462void StringHasher::AddCharacterNoIndex(uint32_t c) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004463 ASSERT(!is_array_index());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004464 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4465 AddSurrogatePairNoIndex(c); // Not inlined.
4466 return;
4467 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004468 raw_running_hash_ += c;
4469 raw_running_hash_ += (raw_running_hash_ << 10);
4470 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4471}
4472
4473
4474uint32_t StringHasher::GetHash() {
4475 // Get the calculated raw hash value and do some more bit ops to distribute
4476 // the hash further. Ensure that we never return zero as the hash value.
4477 uint32_t result = raw_running_hash_;
4478 result += (result << 3);
4479 result ^= (result >> 11);
4480 result += (result << 15);
Ben Murdochc7cc0282012-03-05 14:35:55 +00004481 if ((result & String::kHashBitMask) == 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004482 result = 27;
4483 }
4484 return result;
4485}
4486
4487
Steve Block44f0eee2011-05-26 01:26:41 +01004488template <typename schar>
Ben Murdochc7cc0282012-03-05 14:35:55 +00004489uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) {
4490 StringHasher hasher(length, seed);
Steve Block44f0eee2011-05-26 01:26:41 +01004491 if (!hasher.has_trivial_hash()) {
4492 int i;
4493 for (i = 0; hasher.is_array_index() && (i < length); i++) {
4494 hasher.AddCharacter(chars[i]);
4495 }
4496 for (; i < length; i++) {
4497 hasher.AddCharacterNoIndex(chars[i]);
4498 }
4499 }
4500 return hasher.GetHashField();
4501}
4502
4503
Steve Blocka7e24c12009-10-30 11:49:00 +00004504bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00004505 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004506 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4507 return false;
4508 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004509 return SlowAsArrayIndex(index);
4510}
4511
4512
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004513Object* JSReceiver::GetPrototype() {
4514 return HeapObject::cast(this)->map()->prototype();
Steve Blocka7e24c12009-10-30 11:49:00 +00004515}
4516
4517
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004518bool JSReceiver::HasProperty(String* name) {
4519 if (IsJSProxy()) {
4520 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4521 }
4522 return GetPropertyAttribute(name) != ABSENT;
4523}
4524
4525
4526bool JSReceiver::HasLocalProperty(String* name) {
4527 if (IsJSProxy()) {
4528 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4529 }
4530 return GetLocalPropertyAttribute(name) != ABSENT;
4531}
4532
4533
4534PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004535 return GetPropertyAttributeWithReceiver(this, key);
4536}
4537
Steve Blockd0582a62009-12-15 09:54:21 +00004538// TODO(504): this may be useful in other places too where JSGlobalProxy
4539// is used.
4540Object* JSObject::BypassGlobalProxy() {
4541 if (IsJSGlobalProxy()) {
4542 Object* proto = GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01004543 if (proto->IsNull()) return GetHeap()->undefined_value();
Steve Blockd0582a62009-12-15 09:54:21 +00004544 ASSERT(proto->IsJSGlobalObject());
4545 return proto;
4546 }
4547 return this;
4548}
4549
4550
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004551MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
4552 return IsJSProxy()
4553 ? JSProxy::cast(this)->GetIdentityHash(flag)
4554 : JSObject::cast(this)->GetIdentityHash(flag);
Steve Blockd0582a62009-12-15 09:54:21 +00004555}
4556
4557
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004558bool JSReceiver::HasElement(uint32_t index) {
4559 if (IsJSProxy()) {
4560 return JSProxy::cast(this)->HasElementWithHandler(index);
4561 }
4562 return JSObject::cast(this)->HasElementWithReceiver(this, index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004563}
4564
4565
4566bool AccessorInfo::all_can_read() {
4567 return BooleanBit::get(flag(), kAllCanReadBit);
4568}
4569
4570
4571void AccessorInfo::set_all_can_read(bool value) {
4572 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4573}
4574
4575
4576bool AccessorInfo::all_can_write() {
4577 return BooleanBit::get(flag(), kAllCanWriteBit);
4578}
4579
4580
4581void AccessorInfo::set_all_can_write(bool value) {
4582 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4583}
4584
4585
4586bool AccessorInfo::prohibits_overwriting() {
4587 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4588}
4589
4590
4591void AccessorInfo::set_prohibits_overwriting(bool value) {
4592 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4593}
4594
4595
4596PropertyAttributes AccessorInfo::property_attributes() {
4597 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4598}
4599
4600
4601void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004602 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
Steve Blocka7e24c12009-10-30 11:49:00 +00004603}
4604
Ben Murdoch8b112d22011-06-08 16:22:53 +01004605
4606template<typename Shape, typename Key>
4607void Dictionary<Shape, Key>::SetEntry(int entry,
4608 Object* key,
4609 Object* value) {
4610 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4611}
4612
4613
Steve Blocka7e24c12009-10-30 11:49:00 +00004614template<typename Shape, typename Key>
4615void Dictionary<Shape, Key>::SetEntry(int entry,
4616 Object* key,
4617 Object* value,
4618 PropertyDetails details) {
4619 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4620 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00004621 AssertNoAllocation no_gc;
4622 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00004623 FixedArray::set(index, key, mode);
4624 FixedArray::set(index+1, value, mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004625 FixedArray::set(index+2, details.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00004626}
4627
4628
Steve Block44f0eee2011-05-26 01:26:41 +01004629bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4630 ASSERT(other->IsNumber());
4631 return key == static_cast<uint32_t>(other->Number());
4632}
4633
4634
Ben Murdochc7cc0282012-03-05 14:35:55 +00004635uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
4636 return ComputeIntegerHash(key, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01004637}
4638
4639
Ben Murdochc7cc0282012-03-05 14:35:55 +00004640uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
4641 Object* other) {
Steve Block44f0eee2011-05-26 01:26:41 +01004642 ASSERT(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00004643 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
Steve Block44f0eee2011-05-26 01:26:41 +01004644}
4645
Ben Murdochc7cc0282012-03-05 14:35:55 +00004646uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
4647 return ComputeIntegerHash(key, seed);
4648}
4649
4650uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
4651 uint32_t seed,
4652 Object* other) {
4653 ASSERT(other->IsNumber());
4654 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
4655}
Steve Block44f0eee2011-05-26 01:26:41 +01004656
4657MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4658 return Isolate::Current()->heap()->NumberFromUint32(key);
4659}
4660
4661
4662bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4663 // We know that all entries in a hash table had their hash keys created.
4664 // Use that knowledge to have fast failure.
4665 if (key->Hash() != String::cast(other)->Hash()) return false;
4666 return key->Equals(String::cast(other));
4667}
4668
4669
4670uint32_t StringDictionaryShape::Hash(String* key) {
4671 return key->Hash();
4672}
4673
4674
4675uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4676 return String::cast(other)->Hash();
4677}
4678
4679
4680MaybeObject* StringDictionaryShape::AsObject(String* key) {
4681 return key;
4682}
4683
4684
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004685template <int entrysize>
4686bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
4687 return key->SameValue(other);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004688}
4689
4690
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004691template <int entrysize>
4692uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
4693 MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
4694 return Smi::cast(maybe_hash->ToObjectChecked())->value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004695}
4696
4697
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004698template <int entrysize>
4699uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
4700 Object* other) {
4701 MaybeObject* maybe_hash = other->GetHash(OMIT_CREATION);
4702 return Smi::cast(maybe_hash->ToObjectChecked())->value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004703}
4704
4705
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004706template <int entrysize>
4707MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Object* key) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004708 return key;
4709}
4710
4711
Steve Block44f0eee2011-05-26 01:26:41 +01004712void Map::ClearCodeCache(Heap* heap) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004713 // No write barrier is needed since empty_fixed_array is not in new space.
4714 // Please note this function is used during marking:
4715 // - MarkCompactCollector::MarkUnmarkedObject
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004716 // - IncrementalMarking::Step
Steve Block44f0eee2011-05-26 01:26:41 +01004717 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4718 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00004719}
4720
4721
4722void JSArray::EnsureSize(int required_size) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004723 ASSERT(HasFastTypeElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004724 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00004725 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4726 if (elts->length() < required_size) {
4727 // Doubling in size would be overkill, but leave some slack to avoid
4728 // constantly growing.
4729 Expand(required_size + (required_size >> 3));
4730 // It's a performance benefit to keep a frequently used array in new-space.
Steve Block44f0eee2011-05-26 01:26:41 +01004731 } else if (!GetHeap()->new_space()->Contains(elts) &&
Steve Blockd0582a62009-12-15 09:54:21 +00004732 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4733 // Expand will allocate a new backing store in new space even if the size
4734 // we asked for isn't larger than what we had before.
4735 Expand(required_size);
4736 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004737}
4738
4739
Leon Clarke4515c472010-02-03 11:58:03 +00004740void JSArray::set_length(Smi* length) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004741 // Don't need a write barrier for a Smi.
Leon Clarke4515c472010-02-03 11:58:03 +00004742 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4743}
4744
4745
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004746bool JSArray::AllowsSetElementsLength() {
4747 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
4748 ASSERT(result == !HasExternalArrayElements());
4749 return result;
4750}
4751
4752
4753MaybeObject* JSArray::SetContent(FixedArrayBase* storage) {
4754 MaybeObject* maybe_result = EnsureCanContainElements(
4755 storage, ALLOW_COPIED_DOUBLE_ELEMENTS);
4756 if (maybe_result->IsFailure()) return maybe_result;
4757 ASSERT((storage->map() == GetHeap()->fixed_double_array_map() &&
4758 GetElementsKind() == FAST_DOUBLE_ELEMENTS) ||
4759 ((storage->map() != GetHeap()->fixed_double_array_map()) &&
4760 ((GetElementsKind() == FAST_ELEMENTS) ||
4761 (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS &&
4762 FixedArray::cast(storage)->ContainsOnlySmisOrHoles()))));
Ben Murdoch85b71792012-04-11 18:30:58 +01004763 set_elements(storage);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004764 set_length(Smi::FromInt(storage->length()));
4765 return this;
Steve Blocka7e24c12009-10-30 11:49:00 +00004766}
4767
4768
John Reck59135872010-11-02 12:39:01 -07004769MaybeObject* FixedArray::Copy() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004770 if (length() == 0) return this;
Steve Block44f0eee2011-05-26 01:26:41 +01004771 return GetHeap()->CopyFixedArray(this);
4772}
4773
4774
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004775MaybeObject* FixedDoubleArray::Copy() {
4776 if (length() == 0) return this;
4777 return GetHeap()->CopyFixedDoubleArray(this);
4778}
4779
4780
4781void TypeFeedbackCells::SetAstId(int index, Smi* id) {
4782 set(1 + index * 2, id);
4783}
4784
4785
4786Smi* TypeFeedbackCells::AstId(int index) {
4787 return Smi::cast(get(1 + index * 2));
4788}
4789
4790
4791void TypeFeedbackCells::SetCell(int index, JSGlobalPropertyCell* cell) {
4792 set(index * 2, cell);
4793}
4794
4795
4796JSGlobalPropertyCell* TypeFeedbackCells::Cell(int index) {
4797 return JSGlobalPropertyCell::cast(get(index * 2));
4798}
4799
4800
4801Handle<Object> TypeFeedbackCells::UninitializedSentinel(Isolate* isolate) {
4802 return isolate->factory()->the_hole_value();
4803}
4804
4805
4806Handle<Object> TypeFeedbackCells::MegamorphicSentinel(Isolate* isolate) {
4807 return isolate->factory()->undefined_value();
4808}
4809
4810
4811Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
4812 return heap->raw_unchecked_the_hole_value();
4813}
4814
4815
4816SMI_ACCESSORS(TypeFeedbackInfo, ic_total_count, kIcTotalCountOffset)
4817SMI_ACCESSORS(TypeFeedbackInfo, ic_with_typeinfo_count,
4818 kIcWithTypeinfoCountOffset)
4819ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
4820 kTypeFeedbackCellsOffset)
4821
4822
4823SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
4824
4825
Steve Block44f0eee2011-05-26 01:26:41 +01004826Relocatable::Relocatable(Isolate* isolate) {
4827 ASSERT(isolate == Isolate::Current());
4828 isolate_ = isolate;
4829 prev_ = isolate->relocatable_top();
4830 isolate->set_relocatable_top(this);
4831}
4832
4833
4834Relocatable::~Relocatable() {
4835 ASSERT(isolate_ == Isolate::Current());
4836 ASSERT_EQ(isolate_->relocatable_top(), this);
4837 isolate_->set_relocatable_top(prev_);
Steve Blocka7e24c12009-10-30 11:49:00 +00004838}
4839
4840
Iain Merrick75681382010-08-19 15:07:18 +01004841int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4842 return map->instance_size();
4843}
4844
4845
Ben Murdoch257744e2011-11-30 15:57:28 +00004846void Foreign::ForeignIterateBody(ObjectVisitor* v) {
Iain Merrick75681382010-08-19 15:07:18 +01004847 v->VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004848 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01004849}
4850
4851
4852template<typename StaticVisitor>
Ben Murdoch257744e2011-11-30 15:57:28 +00004853void Foreign::ForeignIterateBody() {
Iain Merrick75681382010-08-19 15:07:18 +01004854 StaticVisitor::VisitExternalReference(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004855 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01004856}
4857
4858
4859void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4860 typedef v8::String::ExternalAsciiStringResource Resource;
4861 v->VisitExternalAsciiString(
4862 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4863}
4864
4865
4866template<typename StaticVisitor>
4867void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4868 typedef v8::String::ExternalAsciiStringResource Resource;
4869 StaticVisitor::VisitExternalAsciiString(
4870 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4871}
4872
4873
4874void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4875 typedef v8::String::ExternalStringResource Resource;
4876 v->VisitExternalTwoByteString(
4877 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4878}
4879
4880
4881template<typename StaticVisitor>
4882void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4883 typedef v8::String::ExternalStringResource Resource;
4884 StaticVisitor::VisitExternalTwoByteString(
4885 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4886}
4887
4888#define SLOT_ADDR(obj, offset) \
4889 reinterpret_cast<Object**>((obj)->address() + offset)
4890
4891template<int start_offset, int end_offset, int size>
4892void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4893 HeapObject* obj,
4894 ObjectVisitor* v) {
4895 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4896}
4897
4898
4899template<int start_offset>
4900void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4901 int object_size,
4902 ObjectVisitor* v) {
4903 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4904}
4905
4906#undef SLOT_ADDR
4907
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004908#undef TYPE_CHECKER
Steve Blocka7e24c12009-10-30 11:49:00 +00004909#undef CAST_ACCESSOR
4910#undef INT_ACCESSORS
Ben Murdoch85b71792012-04-11 18:30:58 +01004911#undef ACCESSORS
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004912#undef ACCESSORS_TO_SMI
4913#undef SMI_ACCESSORS
4914#undef BOOL_GETTER
4915#undef BOOL_ACCESSORS
Steve Blocka7e24c12009-10-30 11:49:00 +00004916#undef FIELD_ADDR
4917#undef READ_FIELD
4918#undef WRITE_FIELD
4919#undef WRITE_BARRIER
4920#undef CONDITIONAL_WRITE_BARRIER
Steve Blocka7e24c12009-10-30 11:49:00 +00004921#undef READ_DOUBLE_FIELD
4922#undef WRITE_DOUBLE_FIELD
4923#undef READ_INT_FIELD
4924#undef WRITE_INT_FIELD
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004925#undef READ_INTPTR_FIELD
4926#undef WRITE_INTPTR_FIELD
4927#undef READ_UINT32_FIELD
4928#undef WRITE_UINT32_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00004929#undef READ_SHORT_FIELD
4930#undef WRITE_SHORT_FIELD
4931#undef READ_BYTE_FIELD
4932#undef WRITE_BYTE_FIELD
4933
4934
4935} } // namespace v8::internal
4936
4937#endif // V8_OBJECTS_INL_H_