blob: e7b6a34296f721c81245dcbf773bb5822b36989c [file] [log] [blame]
Ben Murdoch85b71792012-04-11 18:30:58 +01001// Copyright 2011 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"
Steve Block44f0eee2011-05-26 01:26:41 +010046#include "v8memory.h"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000047
Steve Blocka7e24c12009-10-30 11:49:00 +000048namespace v8 {
49namespace internal {
50
51PropertyDetails::PropertyDetails(Smi* smi) {
52 value_ = smi->value();
53}
54
55
56Smi* PropertyDetails::AsSmi() {
57 return Smi::FromInt(value_);
58}
59
60
61PropertyDetails PropertyDetails::AsDeleted() {
Steve Block1e0659c2011-05-24 12:43:12 +010062 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000063 return PropertyDetails(smi);
64}
65
66
67#define CAST_ACCESSOR(type) \
68 type* type::cast(Object* object) { \
69 ASSERT(object->Is##type()); \
70 return reinterpret_cast<type*>(object); \
71 }
72
73
74#define INT_ACCESSORS(holder, name, offset) \
75 int holder::name() { return READ_INT_FIELD(this, offset); } \
76 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
77
78
79#define ACCESSORS(holder, name, type, offset) \
80 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
81 void holder::set_##name(type* value, WriteBarrierMode mode) { \
82 WRITE_FIELD(this, offset, value); \
Ben Murdoch85b71792012-04-11 18:30:58 +010083 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); \
Steve Blocka7e24c12009-10-30 11:49:00 +000084 }
85
86
Ben Murdoch85b71792012-04-11 18:30:58 +010087// GC-safe accessors do not use HeapObject::GetHeap(), but access TLS instead.
88#define ACCESSORS_GCSAFE(holder, name, type, offset) \
89 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
90 void holder::set_##name(type* value, WriteBarrierMode mode) { \
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +010091 WRITE_FIELD(this, offset, value); \
Ben Murdoch85b71792012-04-11 18:30:58 +010092 CONDITIONAL_WRITE_BARRIER(HEAP, this, offset, mode); \
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +010093 }
94
95
Steve Blocka7e24c12009-10-30 11:49:00 +000096#define SMI_ACCESSORS(holder, name, offset) \
97 int holder::name() { \
98 Object* value = READ_FIELD(this, offset); \
99 return Smi::cast(value)->value(); \
100 } \
101 void holder::set_##name(int value) { \
102 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
103 }
104
105
106#define BOOL_GETTER(holder, field, name, offset) \
107 bool holder::name() { \
108 return BooleanBit::get(field(), offset); \
109 } \
110
111
112#define BOOL_ACCESSORS(holder, field, name, offset) \
113 bool holder::name() { \
114 return BooleanBit::get(field(), offset); \
115 } \
116 void holder::set_##name(bool value) { \
117 set_##field(BooleanBit::set(field(), offset, value)); \
118 }
119
120
121bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
122 // There is a constraint on the object; check.
123 if (!this->IsJSObject()) return false;
124 // Fetch the constructor function of the object.
125 Object* cons_obj = JSObject::cast(this)->map()->constructor();
126 if (!cons_obj->IsJSFunction()) return false;
127 JSFunction* fun = JSFunction::cast(cons_obj);
128 // Iterate through the chain of inheriting function templates to
129 // see if the required one occurs.
130 for (Object* type = fun->shared()->function_data();
131 type->IsFunctionTemplateInfo();
132 type = FunctionTemplateInfo::cast(type)->parent_template()) {
133 if (type == expected) return true;
134 }
135 // Didn't find the required type in the inheritance chain.
136 return false;
137}
138
139
140bool Object::IsSmi() {
141 return HAS_SMI_TAG(this);
142}
143
144
145bool Object::IsHeapObject() {
146 return Internals::HasHeapObjectTag(this);
147}
148
149
Ben Murdoch85b71792012-04-11 18:30:58 +0100150bool Object::IsHeapNumber() {
151 return Object::IsHeapObject()
152 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000153}
154
155
156bool Object::IsString() {
157 return Object::IsHeapObject()
158 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
159}
160
161
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000162bool Object::IsSpecObject() {
163 return Object::IsHeapObject()
164 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
165}
166
167
Steve Blocka7e24c12009-10-30 11:49:00 +0000168bool Object::IsSymbol() {
169 if (!this->IsHeapObject()) return false;
170 uint32_t type = HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000171 // Because the symbol tag is non-zero and no non-string types have the
172 // symbol bit set we can test for symbols with a very simple test
173 // operation.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000174 STATIC_ASSERT(kSymbolTag != 0);
Leon Clarkee46be812010-01-19 14:06:41 +0000175 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
176 return (type & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000177}
178
179
180bool Object::IsConsString() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000181 if (!IsString()) return false;
182 return StringShape(String::cast(this)).IsCons();
183}
184
185
186bool Object::IsSlicedString() {
187 if (!IsString()) return false;
188 return StringShape(String::cast(this)).IsSliced();
Steve Blocka7e24c12009-10-30 11:49:00 +0000189}
190
191
Steve Blocka7e24c12009-10-30 11:49:00 +0000192bool Object::IsSeqString() {
193 if (!IsString()) return false;
194 return StringShape(String::cast(this)).IsSequential();
195}
196
197
198bool Object::IsSeqAsciiString() {
199 if (!IsString()) return false;
200 return StringShape(String::cast(this)).IsSequential() &&
201 String::cast(this)->IsAsciiRepresentation();
202}
203
204
205bool Object::IsSeqTwoByteString() {
206 if (!IsString()) return false;
207 return StringShape(String::cast(this)).IsSequential() &&
208 String::cast(this)->IsTwoByteRepresentation();
209}
210
211
212bool Object::IsExternalString() {
213 if (!IsString()) return false;
214 return StringShape(String::cast(this)).IsExternal();
215}
216
217
218bool Object::IsExternalAsciiString() {
219 if (!IsString()) return false;
220 return StringShape(String::cast(this)).IsExternal() &&
221 String::cast(this)->IsAsciiRepresentation();
222}
223
224
225bool Object::IsExternalTwoByteString() {
226 if (!IsString()) return false;
227 return StringShape(String::cast(this)).IsExternal() &&
228 String::cast(this)->IsTwoByteRepresentation();
229}
230
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000231bool Object::HasValidElements() {
232 // Dictionary is covered under FixedArray.
233 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
234}
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
Steve Blocka7e24c12009-10-30 11:49:00 +0000236StringShape::StringShape(String* str)
237 : type_(str->map()->instance_type()) {
238 set_valid();
239 ASSERT((type_ & kIsNotStringMask) == kStringTag);
240}
241
242
243StringShape::StringShape(Map* map)
244 : type_(map->instance_type()) {
245 set_valid();
246 ASSERT((type_ & kIsNotStringMask) == kStringTag);
247}
248
249
250StringShape::StringShape(InstanceType t)
251 : type_(static_cast<uint32_t>(t)) {
252 set_valid();
253 ASSERT((type_ & kIsNotStringMask) == kStringTag);
254}
255
256
257bool StringShape::IsSymbol() {
258 ASSERT(valid());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000259 STATIC_ASSERT(kSymbolTag != 0);
Leon Clarkee46be812010-01-19 14:06:41 +0000260 return (type_ & kIsSymbolMask) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000261}
262
263
264bool String::IsAsciiRepresentation() {
265 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 return (type & kStringEncodingMask) == kAsciiStringTag;
267}
268
269
270bool String::IsTwoByteRepresentation() {
271 uint32_t type = map()->instance_type();
Steve Blocka7e24c12009-10-30 11:49:00 +0000272 return (type & kStringEncodingMask) == kTwoByteStringTag;
273}
274
275
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000276bool String::IsAsciiRepresentationUnderneath() {
277 uint32_t type = map()->instance_type();
278 STATIC_ASSERT(kIsIndirectStringTag != 0);
279 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
280 ASSERT(IsFlat());
281 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
282 case kAsciiStringTag:
283 return true;
284 case kTwoByteStringTag:
285 return false;
286 default: // Cons or sliced string. Need to go deeper.
287 return GetUnderlying()->IsAsciiRepresentation();
288 }
289}
290
291
292bool String::IsTwoByteRepresentationUnderneath() {
293 uint32_t type = map()->instance_type();
294 STATIC_ASSERT(kIsIndirectStringTag != 0);
295 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
296 ASSERT(IsFlat());
297 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
298 case kAsciiStringTag:
299 return false;
300 case kTwoByteStringTag:
301 return true;
302 default: // Cons or sliced string. Need to go deeper.
303 return GetUnderlying()->IsTwoByteRepresentation();
304 }
305}
306
307
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100308bool String::HasOnlyAsciiChars() {
309 uint32_t type = map()->instance_type();
310 return (type & kStringEncodingMask) == kAsciiStringTag ||
311 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
Steve Block6ded16b2010-05-10 14:33:55 +0100312}
313
314
Steve Blocka7e24c12009-10-30 11:49:00 +0000315bool StringShape::IsCons() {
316 return (type_ & kStringRepresentationMask) == kConsStringTag;
317}
318
319
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000320bool StringShape::IsSliced() {
321 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
322}
323
324
325bool StringShape::IsIndirect() {
326 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
327}
328
329
Steve Blocka7e24c12009-10-30 11:49:00 +0000330bool StringShape::IsExternal() {
331 return (type_ & kStringRepresentationMask) == kExternalStringTag;
332}
333
334
335bool StringShape::IsSequential() {
336 return (type_ & kStringRepresentationMask) == kSeqStringTag;
337}
338
339
340StringRepresentationTag StringShape::representation_tag() {
341 uint32_t tag = (type_ & kStringRepresentationMask);
342 return static_cast<StringRepresentationTag>(tag);
343}
344
345
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000346uint32_t StringShape::encoding_tag() {
347 return type_ & kStringEncodingMask;
348}
349
350
Steve Blocka7e24c12009-10-30 11:49:00 +0000351uint32_t StringShape::full_representation_tag() {
352 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
353}
354
355
356STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
357 Internals::kFullStringRepresentationMask);
358
359
Steve Blocka7e24c12009-10-30 11:49:00 +0000360bool StringShape::IsSequentialAscii() {
361 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
362}
363
364
365bool StringShape::IsSequentialTwoByte() {
366 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
367}
368
369
370bool StringShape::IsExternalAscii() {
371 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
372}
373
374
375bool StringShape::IsExternalTwoByte() {
376 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
377}
378
379
380STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
381 Internals::kExternalTwoByteRepresentationTag);
382
383
384uc32 FlatStringReader::Get(int index) {
385 ASSERT(0 <= index && index <= length_);
386 if (is_ascii_) {
387 return static_cast<const byte*>(start_)[index];
388 } else {
389 return static_cast<const uc16*>(start_)[index];
390 }
391}
392
393
394bool Object::IsNumber() {
395 return IsSmi() || IsHeapNumber();
396}
397
398
Ben Murdoch85b71792012-04-11 18:30:58 +0100399bool Object::IsByteArray() {
400 return Object::IsHeapObject()
401 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000402}
403
404
Ben Murdoch85b71792012-04-11 18:30:58 +0100405bool Object::IsExternalPixelArray() {
406 return Object::IsHeapObject() &&
407 HeapObject::cast(this)->map()->instance_type() ==
408 EXTERNAL_PIXEL_ARRAY_TYPE;
409}
Steve Blocka7e24c12009-10-30 11:49:00 +0000410
411
Steve Block3ce2e202009-11-05 08:53:23 +0000412bool Object::IsExternalArray() {
413 if (!Object::IsHeapObject())
414 return false;
415 InstanceType instance_type =
416 HeapObject::cast(this)->map()->instance_type();
Leon Clarkee46be812010-01-19 14:06:41 +0000417 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
418 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
Steve Block3ce2e202009-11-05 08:53:23 +0000419}
420
421
Ben Murdoch85b71792012-04-11 18:30:58 +0100422bool Object::IsExternalByteArray() {
423 return Object::IsHeapObject() &&
424 HeapObject::cast(this)->map()->instance_type() ==
425 EXTERNAL_BYTE_ARRAY_TYPE;
426}
427
428
429bool Object::IsExternalUnsignedByteArray() {
430 return Object::IsHeapObject() &&
431 HeapObject::cast(this)->map()->instance_type() ==
432 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
433}
434
435
436bool Object::IsExternalShortArray() {
437 return Object::IsHeapObject() &&
438 HeapObject::cast(this)->map()->instance_type() ==
439 EXTERNAL_SHORT_ARRAY_TYPE;
440}
441
442
443bool Object::IsExternalUnsignedShortArray() {
444 return Object::IsHeapObject() &&
445 HeapObject::cast(this)->map()->instance_type() ==
446 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
447}
448
449
450bool Object::IsExternalIntArray() {
451 return Object::IsHeapObject() &&
452 HeapObject::cast(this)->map()->instance_type() ==
453 EXTERNAL_INT_ARRAY_TYPE;
454}
455
456
457bool Object::IsExternalUnsignedIntArray() {
458 return Object::IsHeapObject() &&
459 HeapObject::cast(this)->map()->instance_type() ==
460 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
461}
462
463
464bool Object::IsExternalFloatArray() {
465 return Object::IsHeapObject() &&
466 HeapObject::cast(this)->map()->instance_type() ==
467 EXTERNAL_FLOAT_ARRAY_TYPE;
468}
469
470
471bool Object::IsExternalDoubleArray() {
472 return Object::IsHeapObject() &&
473 HeapObject::cast(this)->map()->instance_type() ==
474 EXTERNAL_DOUBLE_ARRAY_TYPE;
475}
Ben Murdoch257744e2011-11-30 15:57:28 +0000476
477
John Reck59135872010-11-02 12:39:01 -0700478bool MaybeObject::IsFailure() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000479 return HAS_FAILURE_TAG(this);
480}
481
482
John Reck59135872010-11-02 12:39:01 -0700483bool MaybeObject::IsRetryAfterGC() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000484 return HAS_FAILURE_TAG(this)
485 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
486}
487
488
John Reck59135872010-11-02 12:39:01 -0700489bool MaybeObject::IsOutOfMemory() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 return HAS_FAILURE_TAG(this)
Steve Block1e0659c2011-05-24 12:43:12 +0100491 && Failure::cast(this)->IsOutOfMemoryException();
Steve Blocka7e24c12009-10-30 11:49:00 +0000492}
493
494
John Reck59135872010-11-02 12:39:01 -0700495bool MaybeObject::IsException() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000496 return this == Failure::Exception();
497}
498
499
John Reck59135872010-11-02 12:39:01 -0700500bool MaybeObject::IsTheHole() {
Steve Block44f0eee2011-05-26 01:26:41 +0100501 return !IsFailure() && ToObjectUnchecked()->IsTheHole();
John Reck59135872010-11-02 12:39:01 -0700502}
503
504
505Failure* Failure::cast(MaybeObject* obj) {
506 ASSERT(HAS_FAILURE_TAG(obj));
507 return reinterpret_cast<Failure*>(obj);
508}
509
510
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000511bool Object::IsJSReceiver() {
512 return IsHeapObject() &&
513 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
514}
515
516
Steve Blocka7e24c12009-10-30 11:49:00 +0000517bool Object::IsJSObject() {
Ben Murdoch85b71792012-04-11 18:30:58 +0100518 return IsJSReceiver() && !IsJSProxy();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000519}
520
521
522bool Object::IsJSProxy() {
Ben Murdoch85b71792012-04-11 18:30:58 +0100523 return Object::IsHeapObject() &&
524 (HeapObject::cast(this)->map()->instance_type() == JS_PROXY_TYPE ||
525 HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_PROXY_TYPE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000526}
527
528
Ben Murdoch85b71792012-04-11 18:30:58 +0100529bool Object::IsJSFunctionProxy() {
530 return Object::IsHeapObject() &&
531 HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_PROXY_TYPE;
532}
533
534
535bool Object::IsJSWeakMap() {
536 return Object::IsJSObject() &&
537 HeapObject::cast(this)->map()->instance_type() == JS_WEAK_MAP_TYPE;
538}
539
540
541bool Object::IsJSContextExtensionObject() {
542 return IsHeapObject()
543 && (HeapObject::cast(this)->map()->instance_type() ==
544 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
545}
546
547
548bool Object::IsMap() {
549 return Object::IsHeapObject()
550 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
551}
552
553
554bool Object::IsFixedArray() {
555 return Object::IsHeapObject()
556 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
557}
558
559
560bool Object::IsFixedDoubleArray() {
561 return Object::IsHeapObject()
562 && HeapObject::cast(this)->map()->instance_type() ==
563 FIXED_DOUBLE_ARRAY_TYPE;
564}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000565
566
Steve Blocka7e24c12009-10-30 11:49:00 +0000567bool Object::IsDescriptorArray() {
568 return IsFixedArray();
569}
570
571
Ben Murdochb0fe1622011-05-05 13:52:32 +0100572bool Object::IsDeoptimizationInputData() {
573 // Must be a fixed array.
574 if (!IsFixedArray()) return false;
575
576 // There's no sure way to detect the difference between a fixed array and
577 // a deoptimization data array. Since this is used for asserts we can
578 // check that the length is zero or else the fixed size plus a multiple of
579 // the entry size.
580 int length = FixedArray::cast(this)->length();
581 if (length == 0) return true;
582
583 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
584 return length >= 0 &&
585 length % DeoptimizationInputData::kDeoptEntrySize == 0;
586}
587
588
589bool Object::IsDeoptimizationOutputData() {
590 if (!IsFixedArray()) return false;
591 // There's actually no way to see the difference between a fixed array and
592 // a deoptimization data array. Since this is used for asserts we can check
593 // that the length is plausible though.
594 if (FixedArray::cast(this)->length() % 2 != 0) return false;
595 return true;
596}
597
598
Steve Blocka7e24c12009-10-30 11:49:00 +0000599bool Object::IsContext() {
Steve Block44f0eee2011-05-26 01:26:41 +0100600 if (Object::IsHeapObject()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000601 Map* map = HeapObject::cast(this)->map();
602 Heap* heap = map->GetHeap();
603 return (map == heap->function_context_map() ||
604 map == heap->catch_context_map() ||
605 map == heap->with_context_map() ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000606 map == heap->global_context_map() ||
607 map == heap->block_context_map());
Steve Block44f0eee2011-05-26 01:26:41 +0100608 }
609 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000610}
611
612
Steve Blocka7e24c12009-10-30 11:49:00 +0000613bool Object::IsGlobalContext() {
Steve Block44f0eee2011-05-26 01:26:41 +0100614 return Object::IsHeapObject() &&
615 HeapObject::cast(this)->map() ==
616 HeapObject::cast(this)->GetHeap()->global_context_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000617}
618
619
Ben Murdoch85b71792012-04-11 18:30:58 +0100620bool Object::IsSerializedScopeInfo() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000621 return Object::IsHeapObject() &&
622 HeapObject::cast(this)->map() ==
Ben Murdoch85b71792012-04-11 18:30:58 +0100623 HeapObject::cast(this)->GetHeap()->serialized_scope_info_map();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000624}
625
626
Ben Murdoch85b71792012-04-11 18:30:58 +0100627bool Object::IsJSFunction() {
628 return Object::IsHeapObject()
629 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
630}
Steve Blocka7e24c12009-10-30 11:49:00 +0000631
632
633template <> inline bool Is<JSFunction>(Object* obj) {
634 return obj->IsJSFunction();
635}
636
637
Ben Murdoch85b71792012-04-11 18:30:58 +0100638bool Object::IsCode() {
639 return Object::IsHeapObject()
640 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
641}
642
643
644bool Object::IsOddball() {
645 ASSERT(HEAP->is_safe_to_read_maps());
646 return Object::IsHeapObject()
647 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
648}
649
650
651bool Object::IsJSGlobalPropertyCell() {
652 return Object::IsHeapObject()
653 && HeapObject::cast(this)->map()->instance_type()
654 == JS_GLOBAL_PROPERTY_CELL_TYPE;
655}
656
657
658bool Object::IsSharedFunctionInfo() {
659 return Object::IsHeapObject() &&
660 (HeapObject::cast(this)->map()->instance_type() ==
661 SHARED_FUNCTION_INFO_TYPE);
662}
663
664
665bool Object::IsJSValue() {
666 return Object::IsHeapObject()
667 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
668}
669
670
671bool Object::IsJSMessageObject() {
672 return Object::IsHeapObject()
673 && (HeapObject::cast(this)->map()->instance_type() ==
674 JS_MESSAGE_OBJECT_TYPE);
675}
Steve Blocka7e24c12009-10-30 11:49:00 +0000676
677
678bool Object::IsStringWrapper() {
679 return IsJSValue() && JSValue::cast(this)->value()->IsString();
680}
681
682
Ben Murdoch85b71792012-04-11 18:30:58 +0100683bool Object::IsForeign() {
684 return Object::IsHeapObject()
685 && HeapObject::cast(this)->map()->instance_type() == FOREIGN_TYPE;
686}
Steve Blocka7e24c12009-10-30 11:49:00 +0000687
688
689bool Object::IsBoolean() {
Steve Block44f0eee2011-05-26 01:26:41 +0100690 return IsOddball() &&
691 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000692}
693
694
Ben Murdoch85b71792012-04-11 18:30:58 +0100695bool Object::IsJSArray() {
696 return Object::IsHeapObject()
697 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
698}
699
700
701bool Object::IsJSRegExp() {
702 return Object::IsHeapObject()
703 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
704}
Steve Blocka7e24c12009-10-30 11:49:00 +0000705
706
707template <> inline bool Is<JSArray>(Object* obj) {
708 return obj->IsJSArray();
709}
710
711
712bool Object::IsHashTable() {
Steve Block44f0eee2011-05-26 01:26:41 +0100713 return Object::IsHeapObject() &&
714 HeapObject::cast(this)->map() ==
715 HeapObject::cast(this)->GetHeap()->hash_table_map();
Steve Blocka7e24c12009-10-30 11:49:00 +0000716}
717
718
719bool Object::IsDictionary() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000720 return IsHashTable() &&
721 this != HeapObject::cast(this)->GetHeap()->symbol_table();
Steve Blocka7e24c12009-10-30 11:49:00 +0000722}
723
724
725bool Object::IsSymbolTable() {
Steve Block44f0eee2011-05-26 01:26:41 +0100726 return IsHashTable() && this ==
727 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
Steve Blocka7e24c12009-10-30 11:49:00 +0000728}
729
730
Steve Block6ded16b2010-05-10 14:33:55 +0100731bool Object::IsJSFunctionResultCache() {
732 if (!IsFixedArray()) return false;
733 FixedArray* self = FixedArray::cast(this);
734 int length = self->length();
735 if (length < JSFunctionResultCache::kEntriesIndex) return false;
736 if ((length - JSFunctionResultCache::kEntriesIndex)
737 % JSFunctionResultCache::kEntrySize != 0) {
738 return false;
739 }
740#ifdef DEBUG
Ben Murdoch85b71792012-04-11 18:30:58 +0100741 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
Steve Block6ded16b2010-05-10 14:33:55 +0100742#endif
743 return true;
744}
745
746
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100747bool Object::IsNormalizedMapCache() {
748 if (!IsFixedArray()) return false;
749 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
750 return false;
751 }
752#ifdef DEBUG
Ben Murdoch85b71792012-04-11 18:30:58 +0100753 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100754#endif
755 return true;
756}
757
758
Steve Blocka7e24c12009-10-30 11:49:00 +0000759bool Object::IsCompilationCacheTable() {
760 return IsHashTable();
761}
762
763
Steve Block6ded16b2010-05-10 14:33:55 +0100764bool Object::IsCodeCacheHashTable() {
765 return IsHashTable();
766}
767
768
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000769bool Object::IsPolymorphicCodeCacheHashTable() {
770 return IsHashTable();
771}
772
773
Steve Blocka7e24c12009-10-30 11:49:00 +0000774bool Object::IsMapCache() {
775 return IsHashTable();
776}
777
778
779bool Object::IsPrimitive() {
780 return IsOddball() || IsNumber() || IsString();
781}
782
783
784bool Object::IsJSGlobalProxy() {
785 bool result = IsHeapObject() &&
786 (HeapObject::cast(this)->map()->instance_type() ==
787 JS_GLOBAL_PROXY_TYPE);
788 ASSERT(!result || IsAccessCheckNeeded());
789 return result;
790}
791
792
793bool Object::IsGlobalObject() {
794 if (!IsHeapObject()) return false;
795
796 InstanceType type = HeapObject::cast(this)->map()->instance_type();
797 return type == JS_GLOBAL_OBJECT_TYPE ||
798 type == JS_BUILTINS_OBJECT_TYPE;
799}
800
801
Ben Murdoch85b71792012-04-11 18:30:58 +0100802bool Object::IsJSGlobalObject() {
803 return IsHeapObject() &&
804 (HeapObject::cast(this)->map()->instance_type() ==
805 JS_GLOBAL_OBJECT_TYPE);
806}
807
808
809bool Object::IsJSBuiltinsObject() {
810 return IsHeapObject() &&
811 (HeapObject::cast(this)->map()->instance_type() ==
812 JS_BUILTINS_OBJECT_TYPE);
813}
Steve Blocka7e24c12009-10-30 11:49:00 +0000814
815
816bool Object::IsUndetectableObject() {
817 return IsHeapObject()
818 && HeapObject::cast(this)->map()->is_undetectable();
819}
820
821
822bool Object::IsAccessCheckNeeded() {
823 return IsHeapObject()
824 && HeapObject::cast(this)->map()->is_access_check_needed();
825}
826
827
828bool Object::IsStruct() {
829 if (!IsHeapObject()) return false;
830 switch (HeapObject::cast(this)->map()->instance_type()) {
831#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
832 STRUCT_LIST(MAKE_STRUCT_CASE)
833#undef MAKE_STRUCT_CASE
834 default: return false;
835 }
836}
837
838
839#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
840 bool Object::Is##Name() { \
841 return Object::IsHeapObject() \
842 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
843 }
844 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
845#undef MAKE_STRUCT_PREDICATE
846
847
848bool Object::IsUndefined() {
Steve Block44f0eee2011-05-26 01:26:41 +0100849 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
Steve Blocka7e24c12009-10-30 11:49:00 +0000850}
851
852
Steve Blocka7e24c12009-10-30 11:49:00 +0000853bool Object::IsNull() {
Steve Block44f0eee2011-05-26 01:26:41 +0100854 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
855}
856
857
858bool Object::IsTheHole() {
859 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
Steve Blocka7e24c12009-10-30 11:49:00 +0000860}
861
862
863bool Object::IsTrue() {
Steve Block44f0eee2011-05-26 01:26:41 +0100864 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
Steve Blocka7e24c12009-10-30 11:49:00 +0000865}
866
867
868bool Object::IsFalse() {
Steve Block44f0eee2011-05-26 01:26:41 +0100869 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
Steve Blocka7e24c12009-10-30 11:49:00 +0000870}
871
872
Ben Murdoch086aeea2011-05-13 15:57:08 +0100873bool Object::IsArgumentsMarker() {
Steve Block44f0eee2011-05-26 01:26:41 +0100874 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100875}
876
877
Steve Blocka7e24c12009-10-30 11:49:00 +0000878double Object::Number() {
879 ASSERT(IsNumber());
880 return IsSmi()
881 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
882 : reinterpret_cast<HeapNumber*>(this)->value();
883}
884
885
John Reck59135872010-11-02 12:39:01 -0700886MaybeObject* Object::ToSmi() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000887 if (IsSmi()) return this;
888 if (IsHeapNumber()) {
889 double value = HeapNumber::cast(this)->value();
890 int int_value = FastD2I(value);
891 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
892 return Smi::FromInt(int_value);
893 }
894 }
895 return Failure::Exception();
896}
897
898
899bool Object::HasSpecificClassOf(String* name) {
900 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
901}
902
903
John Reck59135872010-11-02 12:39:01 -0700904MaybeObject* Object::GetElement(uint32_t index) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100905 // GetElement can trigger a getter which can cause allocation.
906 // This was not always the case. This ASSERT is here to catch
907 // leftover incorrect uses.
Steve Block44f0eee2011-05-26 01:26:41 +0100908 ASSERT(HEAP->IsAllocationAllowed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000909 return GetElementWithReceiver(this, index);
910}
911
912
John Reck59135872010-11-02 12:39:01 -0700913Object* Object::GetElementNoExceptionThrown(uint32_t index) {
914 MaybeObject* maybe = GetElementWithReceiver(this, index);
915 ASSERT(!maybe->IsFailure());
916 Object* result = NULL; // Initialization to please compiler.
917 maybe->ToObject(&result);
918 return result;
919}
920
921
922MaybeObject* Object::GetProperty(String* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 PropertyAttributes attributes;
924 return GetPropertyWithReceiver(this, key, &attributes);
925}
926
927
John Reck59135872010-11-02 12:39:01 -0700928MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 return GetPropertyWithReceiver(this, key, attributes);
930}
931
932
933#define FIELD_ADDR(p, offset) \
934 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
935
936#define READ_FIELD(p, offset) \
937 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
938
939#define WRITE_FIELD(p, offset, value) \
940 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
941
Ben Murdoch85b71792012-04-11 18:30:58 +0100942// TODO(isolates): Pass heap in to these macros.
943#define WRITE_BARRIER(object, offset) \
944 object->GetHeap()->RecordWrite(object->address(), offset);
Steve Blocka7e24c12009-10-30 11:49:00 +0000945
Ben Murdoch85b71792012-04-11 18:30:58 +0100946// CONDITIONAL_WRITE_BARRIER must be issued after the actual
947// write due to the assert validating the written value.
948#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, mode) \
949 if (mode == UPDATE_WRITE_BARRIER) { \
950 heap->RecordWrite(object->address(), offset); \
951 } else { \
952 ASSERT(mode == SKIP_WRITE_BARRIER); \
953 ASSERT(heap->InNewSpace(object) || \
954 !heap->InNewSpace(READ_FIELD(object, offset)) || \
955 Page::FromAddress(object->address())-> \
956 IsRegionDirty(object->address() + offset)); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 }
958
Steve Block44f0eee2011-05-26 01:26:41 +0100959#ifndef V8_TARGET_ARCH_MIPS
960 #define READ_DOUBLE_FIELD(p, offset) \
961 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
962#else // V8_TARGET_ARCH_MIPS
963 // Prevent gcc from using load-double (mips ldc1) on (possibly)
964 // non-64-bit aligned HeapNumber::value.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000965 static inline double read_double_field(void* p, int offset) {
Steve Block44f0eee2011-05-26 01:26:41 +0100966 union conversion {
967 double d;
968 uint32_t u[2];
969 } c;
970 c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
971 c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
972 return c.d;
973 }
974 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
975#endif // V8_TARGET_ARCH_MIPS
Steve Blocka7e24c12009-10-30 11:49:00 +0000976
Ben Murdoch85b71792012-04-11 18:30:58 +0100977
Steve Block44f0eee2011-05-26 01:26:41 +0100978#ifndef V8_TARGET_ARCH_MIPS
979 #define WRITE_DOUBLE_FIELD(p, offset, value) \
980 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
981#else // V8_TARGET_ARCH_MIPS
982 // Prevent gcc from using store-double (mips sdc1) on (possibly)
983 // non-64-bit aligned HeapNumber::value.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000984 static inline void write_double_field(void* p, int offset,
Steve Block44f0eee2011-05-26 01:26:41 +0100985 double value) {
986 union conversion {
987 double d;
988 uint32_t u[2];
989 } c;
990 c.d = value;
991 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
992 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
993 }
994 #define WRITE_DOUBLE_FIELD(p, offset, value) \
995 write_double_field(p, offset, value)
996#endif // V8_TARGET_ARCH_MIPS
997
Steve Blocka7e24c12009-10-30 11:49:00 +0000998
999#define READ_INT_FIELD(p, offset) \
1000 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
1001
1002#define WRITE_INT_FIELD(p, offset, value) \
1003 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
1004
1005#define READ_INTPTR_FIELD(p, offset) \
1006 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
1007
1008#define WRITE_INTPTR_FIELD(p, offset, value) \
1009 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
1010
1011#define READ_UINT32_FIELD(p, offset) \
1012 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
1013
1014#define WRITE_UINT32_FIELD(p, offset, value) \
1015 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
1016
1017#define READ_SHORT_FIELD(p, offset) \
1018 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
1019
1020#define WRITE_SHORT_FIELD(p, offset, value) \
1021 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
1022
1023#define READ_BYTE_FIELD(p, offset) \
1024 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
1025
1026#define WRITE_BYTE_FIELD(p, offset, value) \
1027 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
1028
1029
1030Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
1031 return &READ_FIELD(obj, byte_offset);
1032}
1033
1034
1035int Smi::value() {
1036 return Internals::SmiValue(this);
1037}
1038
1039
1040Smi* Smi::FromInt(int value) {
1041 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +00001042 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001043 intptr_t tagged_value =
Steve Block3ce2e202009-11-05 08:53:23 +00001044 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 return reinterpret_cast<Smi*>(tagged_value);
1046}
1047
1048
1049Smi* Smi::FromIntptr(intptr_t value) {
1050 ASSERT(Smi::IsValid(value));
Steve Block3ce2e202009-11-05 08:53:23 +00001051 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
1052 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001053}
1054
1055
1056Failure::Type Failure::type() const {
1057 return static_cast<Type>(value() & kFailureTypeTagMask);
1058}
1059
1060
1061bool Failure::IsInternalError() const {
1062 return type() == INTERNAL_ERROR;
1063}
1064
1065
1066bool Failure::IsOutOfMemoryException() const {
1067 return type() == OUT_OF_MEMORY_EXCEPTION;
1068}
1069
1070
Steve Blocka7e24c12009-10-30 11:49:00 +00001071AllocationSpace Failure::allocation_space() const {
1072 ASSERT_EQ(RETRY_AFTER_GC, type());
1073 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1074 & kSpaceTagMask);
1075}
1076
1077
1078Failure* Failure::InternalError() {
1079 return Construct(INTERNAL_ERROR);
1080}
1081
1082
1083Failure* Failure::Exception() {
1084 return Construct(EXCEPTION);
1085}
1086
1087
1088Failure* Failure::OutOfMemoryException() {
1089 return Construct(OUT_OF_MEMORY_EXCEPTION);
1090}
1091
1092
Steve Block3ce2e202009-11-05 08:53:23 +00001093intptr_t Failure::value() const {
Steve Block6ded16b2010-05-10 14:33:55 +01001094 return static_cast<intptr_t>(
1095 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00001096}
1097
1098
Ben Murdochf87a2032010-10-22 12:50:53 +01001099Failure* Failure::RetryAfterGC() {
1100 return RetryAfterGC(NEW_SPACE);
1101}
1102
1103
1104Failure* Failure::RetryAfterGC(AllocationSpace space) {
1105 ASSERT((space & ~kSpaceTagMask) == 0);
1106 return Construct(RETRY_AFTER_GC, space);
Steve Blocka7e24c12009-10-30 11:49:00 +00001107}
1108
1109
Steve Block3ce2e202009-11-05 08:53:23 +00001110Failure* Failure::Construct(Type type, intptr_t value) {
Steve Block6ded16b2010-05-10 14:33:55 +01001111 uintptr_t info =
1112 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
Steve Blocka7e24c12009-10-30 11:49:00 +00001113 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
Steve Block3ce2e202009-11-05 08:53:23 +00001114 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001115}
1116
1117
1118bool Smi::IsValid(intptr_t value) {
1119#ifdef DEBUG
1120 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1121#endif
Steve Block3ce2e202009-11-05 08:53:23 +00001122
1123#ifdef V8_TARGET_ARCH_X64
1124 // To be representable as a long smi, the value must be a 32-bit integer.
1125 bool result = (value == static_cast<int32_t>(value));
1126#else
Steve Blocka7e24c12009-10-30 11:49:00 +00001127 // To be representable as an tagged small integer, the two
1128 // most-significant bits of 'value' must be either 00 or 11 due to
1129 // sign-extension. To check this we add 01 to the two
1130 // most-significant bits, and check if the most-significant bit is 0
1131 //
1132 // CAUTION: The original code below:
1133 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1134 // may lead to incorrect results according to the C language spec, and
1135 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1136 // compiler may produce undefined results in case of signed integer
1137 // overflow. The computation must be done w/ unsigned ints.
Steve Block3ce2e202009-11-05 08:53:23 +00001138 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
Steve Blocka7e24c12009-10-30 11:49:00 +00001139#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001140 ASSERT(result == in_range);
1141 return result;
1142}
1143
1144
1145MapWord MapWord::FromMap(Map* map) {
1146 return MapWord(reinterpret_cast<uintptr_t>(map));
1147}
1148
1149
1150Map* MapWord::ToMap() {
1151 return reinterpret_cast<Map*>(value_);
1152}
1153
1154
1155bool MapWord::IsForwardingAddress() {
1156 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1157}
1158
1159
1160MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1161 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1162 return MapWord(reinterpret_cast<uintptr_t>(raw));
1163}
1164
1165
1166HeapObject* MapWord::ToForwardingAddress() {
1167 ASSERT(IsForwardingAddress());
1168 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1169}
1170
1171
Ben Murdoch85b71792012-04-11 18:30:58 +01001172bool MapWord::IsMarked() {
1173 return (value_ & kMarkingMask) == 0;
1174}
1175
1176
1177void MapWord::SetMark() {
1178 value_ &= ~kMarkingMask;
1179}
1180
1181
1182void MapWord::ClearMark() {
1183 value_ |= kMarkingMask;
1184}
1185
1186
1187bool MapWord::IsOverflowed() {
1188 return (value_ & kOverflowMask) != 0;
1189}
1190
1191
1192void MapWord::SetOverflow() {
1193 value_ |= kOverflowMask;
1194}
1195
1196
1197void MapWord::ClearOverflow() {
1198 value_ &= ~kOverflowMask;
1199}
1200
1201
1202MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1203 // Offset is the distance in live bytes from the first live object in the
1204 // same page. The offset between two objects in the same page should not
1205 // exceed the object area size of a page.
1206 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1207
1208 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
1209 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1210
1211 Page* map_page = Page::FromAddress(map_address);
1212 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1213
1214 uintptr_t map_page_offset =
1215 map_page->Offset(map_address) >> kMapAlignmentBits;
1216
1217 uintptr_t encoding =
1218 (compact_offset << kForwardingOffsetShift) |
1219 (map_page_offset << kMapPageOffsetShift) |
1220 (map_page->mc_page_index << kMapPageIndexShift);
1221 return MapWord(encoding);
1222}
1223
1224
1225Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1226 int map_page_index =
1227 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1228 ASSERT_MAP_PAGE_INDEX(map_page_index);
1229
1230 int map_page_offset = static_cast<int>(
1231 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1232 kMapAlignmentBits);
1233
1234 return (map_space->PageAddress(map_page_index) + map_page_offset);
1235}
1236
1237
1238int MapWord::DecodeOffset() {
1239 // The offset field is represented in the kForwardingOffsetBits
1240 // most-significant bits.
1241 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1242 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1243 return static_cast<int>(offset);
1244}
1245
1246
1247MapWord MapWord::FromEncodedAddress(Address address) {
1248 return MapWord(reinterpret_cast<uintptr_t>(address));
1249}
1250
1251
1252Address MapWord::ToEncodedAddress() {
1253 return reinterpret_cast<Address>(value_);
1254}
1255
1256
Steve Blocka7e24c12009-10-30 11:49:00 +00001257#ifdef DEBUG
1258void HeapObject::VerifyObjectField(int offset) {
1259 VerifyPointer(READ_FIELD(this, offset));
1260}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001261
1262void HeapObject::VerifySmiField(int offset) {
1263 ASSERT(READ_FIELD(this, offset)->IsSmi());
1264}
Steve Blocka7e24c12009-10-30 11:49:00 +00001265#endif
1266
1267
Steve Block44f0eee2011-05-26 01:26:41 +01001268Heap* HeapObject::GetHeap() {
Ben Murdoch85b71792012-04-11 18:30:58 +01001269 // During GC, the map pointer in HeapObject is used in various ways that
1270 // prevent us from retrieving Heap from the map.
1271 // Assert that we are not in GC, implement GC code in a way that it doesn't
1272 // pull heap from the map.
1273 ASSERT(HEAP->is_safe_to_read_maps());
1274 return map()->heap();
Steve Block44f0eee2011-05-26 01:26:41 +01001275}
1276
1277
1278Isolate* HeapObject::GetIsolate() {
1279 return GetHeap()->isolate();
1280}
1281
1282
Steve Blocka7e24c12009-10-30 11:49:00 +00001283Map* HeapObject::map() {
1284 return map_word().ToMap();
1285}
1286
1287
1288void HeapObject::set_map(Map* value) {
1289 set_map_word(MapWord::FromMap(value));
1290}
1291
1292
1293MapWord HeapObject::map_word() {
1294 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1295}
1296
1297
1298void HeapObject::set_map_word(MapWord map_word) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001299 // WRITE_FIELD does not invoke write barrier, but there is no need
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 // here.
1301 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1302}
1303
1304
1305HeapObject* HeapObject::FromAddress(Address address) {
1306 ASSERT_TAG_ALIGNED(address);
1307 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1308}
1309
1310
1311Address HeapObject::address() {
1312 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1313}
1314
1315
1316int HeapObject::Size() {
1317 return SizeFromMap(map());
1318}
1319
1320
1321void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1322 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1323 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1324}
1325
1326
1327void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1328 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1329}
1330
1331
Ben Murdoch85b71792012-04-11 18:30:58 +01001332bool HeapObject::IsMarked() {
1333 return map_word().IsMarked();
1334}
1335
1336
1337void HeapObject::SetMark() {
1338 ASSERT(!IsMarked());
1339 MapWord first_word = map_word();
1340 first_word.SetMark();
1341 set_map_word(first_word);
1342}
1343
1344
1345void HeapObject::ClearMark() {
1346 ASSERT(IsMarked());
1347 MapWord first_word = map_word();
1348 first_word.ClearMark();
1349 set_map_word(first_word);
1350}
1351
1352
1353bool HeapObject::IsOverflowed() {
1354 return map_word().IsOverflowed();
1355}
1356
1357
1358void HeapObject::SetOverflow() {
1359 MapWord first_word = map_word();
1360 first_word.SetOverflow();
1361 set_map_word(first_word);
1362}
1363
1364
1365void HeapObject::ClearOverflow() {
1366 ASSERT(IsOverflowed());
1367 MapWord first_word = map_word();
1368 first_word.ClearOverflow();
1369 set_map_word(first_word);
1370}
1371
1372
Steve Blocka7e24c12009-10-30 11:49:00 +00001373double HeapNumber::value() {
1374 return READ_DOUBLE_FIELD(this, kValueOffset);
1375}
1376
1377
1378void HeapNumber::set_value(double value) {
1379 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1380}
1381
1382
Steve Block6ded16b2010-05-10 14:33:55 +01001383int HeapNumber::get_exponent() {
1384 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1385 kExponentShift) - kExponentBias;
1386}
1387
1388
1389int HeapNumber::get_sign() {
1390 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1391}
1392
1393
Steve Blocka7e24c12009-10-30 11:49:00 +00001394ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1395
1396
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001397FixedArrayBase* JSObject::elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001398 Object* array = READ_FIELD(this, kElementsOffset);
Ben Murdoch85b71792012-04-11 18:30:58 +01001399 ASSERT(array->HasValidElements());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001400 return static_cast<FixedArrayBase*>(array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001401}
1402
Steve Blocka7e24c12009-10-30 11:49:00 +00001403
Ben Murdochc7cc0282012-03-05 14:35:55 +00001404void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001405 ASSERT(map()->has_fast_elements() ==
1406 (value->map() == GetHeap()->fixed_array_map() ||
1407 value->map() == GetHeap()->fixed_cow_array_map()));
1408 ASSERT(map()->has_fast_double_elements() ==
1409 value->IsFixedDoubleArray());
1410 ASSERT(value->HasValidElements());
1411 WRITE_FIELD(this, kElementsOffset, value);
1412 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, mode);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001413}
1414
1415
Steve Blocka7e24c12009-10-30 11:49:00 +00001416void JSObject::initialize_properties() {
Steve Block44f0eee2011-05-26 01:26:41 +01001417 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1418 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001419}
1420
1421
1422void JSObject::initialize_elements() {
Ben Murdoch85b71792012-04-11 18:30:58 +01001423 ASSERT(map()->has_fast_elements());
Steve Block44f0eee2011-05-26 01:26:41 +01001424 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1425 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00001426}
1427
1428
John Reck59135872010-11-02 12:39:01 -07001429MaybeObject* JSObject::ResetElements() {
1430 Object* obj;
Ben Murdoch85b71792012-04-11 18:30:58 +01001431 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1432 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1433 }
Steve Block8defd9f2010-07-08 12:39:36 +01001434 set_map(Map::cast(obj));
1435 initialize_elements();
1436 return this;
1437}
1438
1439
Steve Blocka7e24c12009-10-30 11:49:00 +00001440ACCESSORS(Oddball, to_string, String, kToStringOffset)
1441ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1442
1443
Steve Block44f0eee2011-05-26 01:26:41 +01001444byte Oddball::kind() {
Ben Murdoch85b71792012-04-11 18:30:58 +01001445 return READ_BYTE_FIELD(this, kKindOffset);
Steve Block44f0eee2011-05-26 01:26:41 +01001446}
1447
1448
1449void Oddball::set_kind(byte value) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001450 WRITE_BYTE_FIELD(this, kKindOffset, value);
Steve Block44f0eee2011-05-26 01:26:41 +01001451}
1452
1453
Steve Blocka7e24c12009-10-30 11:49:00 +00001454Object* JSGlobalPropertyCell::value() {
1455 return READ_FIELD(this, kValueOffset);
1456}
1457
1458
1459void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1460 // The write barrier is not used for global property cells.
1461 ASSERT(!val->IsJSGlobalPropertyCell());
1462 WRITE_FIELD(this, kValueOffset, val);
1463}
1464
1465
1466int JSObject::GetHeaderSize() {
1467 InstanceType type = map()->instance_type();
1468 // Check for the most common kind of JavaScript object before
1469 // falling into the generic switch. This speeds up the internal
1470 // field operations considerably on average.
1471 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1472 switch (type) {
1473 case JS_GLOBAL_PROXY_TYPE:
1474 return JSGlobalProxy::kSize;
1475 case JS_GLOBAL_OBJECT_TYPE:
1476 return JSGlobalObject::kSize;
1477 case JS_BUILTINS_OBJECT_TYPE:
1478 return JSBuiltinsObject::kSize;
1479 case JS_FUNCTION_TYPE:
1480 return JSFunction::kSize;
1481 case JS_VALUE_TYPE:
1482 return JSValue::kSize;
1483 case JS_ARRAY_TYPE:
Ben Murdoch85b71792012-04-11 18:30:58 +01001484 return JSValue::kSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001485 case JS_WEAK_MAP_TYPE:
1486 return JSWeakMap::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001487 case JS_REGEXP_TYPE:
Ben Murdoch85b71792012-04-11 18:30:58 +01001488 return JSValue::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1490 return JSObject::kHeaderSize;
Steve Block1e0659c2011-05-24 12:43:12 +01001491 case JS_MESSAGE_OBJECT_TYPE:
1492 return JSMessageObject::kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001493 default:
1494 UNREACHABLE();
1495 return 0;
1496 }
1497}
1498
1499
1500int JSObject::GetInternalFieldCount() {
1501 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1502 // Make sure to adjust for the number of in-object properties. These
1503 // properties do contribute to the size, but are not internal fields.
1504 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1505 map()->inobject_properties();
1506}
1507
1508
Steve Block44f0eee2011-05-26 01:26:41 +01001509int JSObject::GetInternalFieldOffset(int index) {
1510 ASSERT(index < GetInternalFieldCount() && index >= 0);
1511 return GetHeaderSize() + (kPointerSize * index);
1512}
1513
1514
Steve Blocka7e24c12009-10-30 11:49:00 +00001515Object* JSObject::GetInternalField(int index) {
1516 ASSERT(index < GetInternalFieldCount() && index >= 0);
1517 // Internal objects do follow immediately after the header, whereas in-object
1518 // properties are at the end of the object. Therefore there is no need
1519 // to adjust the index here.
1520 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1521}
1522
1523
1524void JSObject::SetInternalField(int index, Object* value) {
1525 ASSERT(index < GetInternalFieldCount() && index >= 0);
1526 // Internal objects do follow immediately after the header, whereas in-object
1527 // properties are at the end of the object. Therefore there is no need
1528 // to adjust the index here.
1529 int offset = GetHeaderSize() + (kPointerSize * index);
1530 WRITE_FIELD(this, offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01001531 WRITE_BARRIER(this, offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001532}
1533
1534
1535// Access fast-case object properties at index. The use of these routines
1536// is needed to correctly distinguish between properties stored in-object and
1537// properties stored in the properties array.
1538Object* JSObject::FastPropertyAt(int index) {
1539 // Adjust for the number of properties stored in the object.
1540 index -= map()->inobject_properties();
1541 if (index < 0) {
1542 int offset = map()->instance_size() + (index * kPointerSize);
1543 return READ_FIELD(this, offset);
1544 } else {
1545 ASSERT(index < properties()->length());
1546 return properties()->get(index);
1547 }
1548}
1549
1550
1551Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1552 // Adjust for the number of properties stored in the object.
1553 index -= map()->inobject_properties();
1554 if (index < 0) {
1555 int offset = map()->instance_size() + (index * kPointerSize);
1556 WRITE_FIELD(this, offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01001557 WRITE_BARRIER(this, offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001558 } else {
1559 ASSERT(index < properties()->length());
1560 properties()->set(index, value);
1561 }
1562 return value;
1563}
1564
1565
Steve Block44f0eee2011-05-26 01:26:41 +01001566int JSObject::GetInObjectPropertyOffset(int index) {
1567 // Adjust for the number of properties stored in the object.
1568 index -= map()->inobject_properties();
1569 ASSERT(index < 0);
1570 return map()->instance_size() + (index * kPointerSize);
1571}
1572
1573
Steve Blocka7e24c12009-10-30 11:49:00 +00001574Object* JSObject::InObjectPropertyAt(int index) {
1575 // Adjust for the number of properties stored in the object.
1576 index -= map()->inobject_properties();
1577 ASSERT(index < 0);
1578 int offset = map()->instance_size() + (index * kPointerSize);
1579 return READ_FIELD(this, offset);
1580}
1581
1582
1583Object* JSObject::InObjectPropertyAtPut(int index,
1584 Object* value,
1585 WriteBarrierMode mode) {
1586 // Adjust for the number of properties stored in the object.
1587 index -= map()->inobject_properties();
1588 ASSERT(index < 0);
1589 int offset = map()->instance_size() + (index * kPointerSize);
1590 WRITE_FIELD(this, offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01001591 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001592 return value;
1593}
1594
1595
1596
Ben Murdoch85b71792012-04-11 18:30:58 +01001597void JSObject::InitializeBody(int object_size, Object* value) {
1598 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
1599 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1600 WRITE_FIELD(this, offset, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001601 }
1602}
1603
1604
Steve Block8defd9f2010-07-08 12:39:36 +01001605bool JSObject::HasFastProperties() {
1606 return !properties()->IsDictionary();
1607}
1608
1609
1610int JSObject::MaxFastProperties() {
1611 // Allow extra fast properties if the object has more than
1612 // kMaxFastProperties in-object properties. When this is the case,
1613 // it is very unlikely that the object is being used as a dictionary
1614 // and there is a good chance that allowing more map transitions
1615 // will be worth it.
1616 return Max(map()->inobject_properties(), kMaxFastProperties);
1617}
1618
1619
Steve Blocka7e24c12009-10-30 11:49:00 +00001620void Struct::InitializeBody(int object_size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001621 Object* value = GetHeap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001622 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1623 WRITE_FIELD(this, offset, value);
1624 }
1625}
1626
1627
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001628bool Object::ToArrayIndex(uint32_t* index) {
1629 if (IsSmi()) {
1630 int value = Smi::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001631 if (value < 0) return false;
1632 *index = value;
1633 return true;
1634 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001635 if (IsHeapNumber()) {
1636 double value = HeapNumber::cast(this)->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 uint32_t uint_value = static_cast<uint32_t>(value);
1638 if (value == static_cast<double>(uint_value)) {
1639 *index = uint_value;
1640 return true;
1641 }
1642 }
1643 return false;
1644}
1645
1646
1647bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1648 if (!this->IsJSValue()) return false;
1649
1650 JSValue* js_value = JSValue::cast(this);
1651 if (!js_value->value()->IsString()) return false;
1652
1653 String* str = String::cast(js_value->value());
1654 if (index >= (uint32_t)str->length()) return false;
1655
1656 return true;
1657}
1658
1659
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001660FixedArrayBase* FixedArrayBase::cast(Object* object) {
1661 ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1662 return reinterpret_cast<FixedArrayBase*>(object);
1663}
1664
1665
Steve Blocka7e24c12009-10-30 11:49:00 +00001666Object* FixedArray::get(int index) {
1667 ASSERT(index >= 0 && index < this->length());
1668 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1669}
1670
1671
1672void FixedArray::set(int index, Smi* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001673 ASSERT(map() != HEAP->fixed_cow_array_map());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001674 ASSERT(index >= 0 && index < this->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001675 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1676 int offset = kHeaderSize + index * kPointerSize;
1677 WRITE_FIELD(this, offset, value);
1678}
1679
1680
1681void FixedArray::set(int index, Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001682 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 ASSERT(index >= 0 && index < this->length());
1684 int offset = kHeaderSize + index * kPointerSize;
1685 WRITE_FIELD(this, offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01001686 WRITE_BARRIER(this, offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001687}
1688
1689
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001690inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1691 return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1692}
1693
1694
1695inline double FixedDoubleArray::hole_nan_as_double() {
1696 return BitCast<double, uint64_t>(kHoleNanInt64);
1697}
1698
1699
1700inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1701 ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1702 ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1703 return OS::nan_value();
1704}
1705
1706
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001707double FixedDoubleArray::get_scalar(int index) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001708 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1709 map() != HEAP->fixed_array_map());
1710 ASSERT(index >= 0 && index < this->length());
1711 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1712 ASSERT(!is_the_hole_nan(result));
1713 return result;
1714}
1715
1716
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
Ben Murdoch85b71792012-04-11 18:30:58 +01001749void FixedDoubleArray::Initialize(FixedDoubleArray* from) {
1750 int old_length = from->length();
1751 ASSERT(old_length < length());
1752 if (old_length * kDoubleSize >= OS::kMinComplexMemCopy) {
1753 OS::MemCopy(FIELD_ADDR(this, kHeaderSize),
1754 FIELD_ADDR(from, kHeaderSize),
1755 old_length * kDoubleSize);
1756 } else {
1757 for (int i = 0; i < old_length; ++i) {
1758 if (from->is_the_hole(i)) {
1759 set_the_hole(i);
1760 } else {
1761 set(i, from->get_scalar(i));
1762 }
1763 }
1764 }
1765 int offset = kHeaderSize + old_length * kDoubleSize;
1766 for (int current = from->length(); current < length(); ++current) {
1767 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1768 offset += kDoubleSize;
1769 }
1770}
1771
1772
1773void FixedDoubleArray::Initialize(FixedArray* from) {
1774 int old_length = from->length();
1775 ASSERT(old_length < length());
1776 for (int i = 0; i < old_length; i++) {
1777 Object* hole_or_object = from->get(i);
1778 if (hole_or_object->IsTheHole()) {
1779 set_the_hole(i);
1780 } else {
1781 set(i, hole_or_object->Number());
1782 }
1783 }
1784 int offset = kHeaderSize + old_length * kDoubleSize;
1785 for (int current = from->length(); current < length(); ++current) {
1786 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1787 offset += kDoubleSize;
1788 }
1789}
1790
1791
1792void FixedDoubleArray::Initialize(SeededNumberDictionary* from) {
1793 int offset = kHeaderSize;
1794 for (int current = 0; current < length(); ++current) {
1795 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1796 offset += kDoubleSize;
1797 }
1798 for (int i = 0; i < from->Capacity(); i++) {
1799 Object* key = from->KeyAt(i);
1800 if (key->IsNumber()) {
1801 uint32_t entry = static_cast<uint32_t>(key->Number());
1802 set(entry, from->ValueAt(i)->Number());
1803 }
1804 }
1805}
1806
1807
Leon Clarke4515c472010-02-03 11:58:03 +00001808WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001809 if (GetHeap()->InNewSpace(this)) return SKIP_WRITE_BARRIER;
Steve Blocka7e24c12009-10-30 11:49:00 +00001810 return UPDATE_WRITE_BARRIER;
1811}
1812
1813
1814void FixedArray::set(int index,
1815 Object* value,
1816 WriteBarrierMode mode) {
Steve Block44f0eee2011-05-26 01:26:41 +01001817 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001818 ASSERT(index >= 0 && index < this->length());
1819 int offset = kHeaderSize + index * kPointerSize;
1820 WRITE_FIELD(this, offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01001821 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001822}
1823
1824
Ben Murdoch85b71792012-04-11 18:30:58 +01001825void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01001826 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001827 ASSERT(index >= 0 && index < array->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001828 ASSERT(!HEAP->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001829 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1830}
1831
1832
1833void FixedArray::set_undefined(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001834 ASSERT(map() != HEAP->fixed_cow_array_map());
1835 set_undefined(GetHeap(), index);
1836}
1837
1838
1839void FixedArray::set_undefined(Heap* heap, int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001840 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001841 ASSERT(!heap->InNewSpace(heap->undefined_value()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001842 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
Steve Block44f0eee2011-05-26 01:26:41 +01001843 heap->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001844}
1845
1846
1847void FixedArray::set_null(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001848 set_null(GetHeap(), index);
1849}
1850
1851
1852void FixedArray::set_null(Heap* heap, int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001853 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001854 ASSERT(!heap->InNewSpace(heap->null_value()));
1855 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001856}
1857
1858
1859void FixedArray::set_the_hole(int index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001860 ASSERT(map() != HEAP->fixed_cow_array_map());
Steve Blocka7e24c12009-10-30 11:49:00 +00001861 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001862 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1863 WRITE_FIELD(this,
1864 kHeaderSize + index * kPointerSize,
1865 GetHeap()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001866}
1867
1868
Iain Merrick75681382010-08-19 15:07:18 +01001869void FixedArray::set_unchecked(int index, Smi* value) {
1870 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1871 int offset = kHeaderSize + index * kPointerSize;
1872 WRITE_FIELD(this, offset, value);
1873}
1874
1875
Steve Block44f0eee2011-05-26 01:26:41 +01001876void FixedArray::set_unchecked(Heap* heap,
1877 int index,
Ben Murdochf87a2032010-10-22 12:50:53 +01001878 Object* value,
1879 WriteBarrierMode mode) {
1880 int offset = kHeaderSize + index * kPointerSize;
1881 WRITE_FIELD(this, offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01001882 CONDITIONAL_WRITE_BARRIER(heap, this, offset, mode);
Ben Murdochf87a2032010-10-22 12:50:53 +01001883}
1884
1885
Steve Block44f0eee2011-05-26 01:26:41 +01001886void FixedArray::set_null_unchecked(Heap* heap, int index) {
Iain Merrick75681382010-08-19 15:07:18 +01001887 ASSERT(index >= 0 && index < this->length());
Steve Block44f0eee2011-05-26 01:26:41 +01001888 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1889 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
Iain Merrick75681382010-08-19 15:07:18 +01001890}
1891
1892
Steve Block6ded16b2010-05-10 14:33:55 +01001893Object** FixedArray::data_start() {
1894 return HeapObject::RawField(this, kHeaderSize);
1895}
1896
1897
Steve Blocka7e24c12009-10-30 11:49:00 +00001898bool DescriptorArray::IsEmpty() {
Ben Murdoch257744e2011-11-30 15:57:28 +00001899 ASSERT(this->IsSmi() ||
1900 this->length() > kFirstIndex ||
Steve Block44f0eee2011-05-26 01:26:41 +01001901 this == HEAP->empty_descriptor_array());
Ben Murdoch257744e2011-11-30 15:57:28 +00001902 return this->IsSmi() || length() <= kFirstIndex;
1903}
1904
1905
1906int DescriptorArray::bit_field3_storage() {
1907 Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1908 return Smi::cast(storage)->value();
1909}
1910
1911void DescriptorArray::set_bit_field3_storage(int value) {
1912 ASSERT(!IsEmpty());
1913 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001914}
1915
1916
Ben Murdoch85b71792012-04-11 18:30:58 +01001917void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001918 Object* tmp = array->get(first);
Ben Murdoch85b71792012-04-11 18:30:58 +01001919 fast_set(array, first, array->get(second));
1920 fast_set(array, second, tmp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001921}
1922
1923
1924int DescriptorArray::Search(String* name) {
1925 SLOW_ASSERT(IsSortedNoDuplicates());
1926
1927 // Check for empty descriptor array.
1928 int nof = number_of_descriptors();
1929 if (nof == 0) return kNotFound;
1930
1931 // Fast case: do linear search for small arrays.
1932 const int kMaxElementsForLinearSearch = 8;
1933 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1934 return LinearSearch(name, nof);
1935 }
1936
1937 // Slow case: perform binary search.
1938 return BinarySearch(name, 0, nof - 1);
1939}
1940
1941
Iain Merrick75681382010-08-19 15:07:18 +01001942int DescriptorArray::SearchWithCache(String* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001943 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
Iain Merrick75681382010-08-19 15:07:18 +01001944 if (number == DescriptorLookupCache::kAbsent) {
1945 number = Search(name);
Steve Block44f0eee2011-05-26 01:26:41 +01001946 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
Iain Merrick75681382010-08-19 15:07:18 +01001947 }
1948 return number;
1949}
1950
1951
Steve Blocka7e24c12009-10-30 11:49:00 +00001952String* DescriptorArray::GetKey(int descriptor_number) {
1953 ASSERT(descriptor_number < number_of_descriptors());
1954 return String::cast(get(ToKeyIndex(descriptor_number)));
1955}
1956
1957
1958Object* DescriptorArray::GetValue(int descriptor_number) {
1959 ASSERT(descriptor_number < number_of_descriptors());
1960 return GetContentArray()->get(ToValueIndex(descriptor_number));
1961}
1962
1963
1964Smi* DescriptorArray::GetDetails(int descriptor_number) {
1965 ASSERT(descriptor_number < number_of_descriptors());
1966 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1967}
1968
1969
1970PropertyType DescriptorArray::GetType(int descriptor_number) {
1971 ASSERT(descriptor_number < number_of_descriptors());
1972 return PropertyDetails(GetDetails(descriptor_number)).type();
1973}
1974
1975
1976int DescriptorArray::GetFieldIndex(int descriptor_number) {
1977 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1978}
1979
1980
1981JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1982 return JSFunction::cast(GetValue(descriptor_number));
1983}
1984
1985
1986Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1987 ASSERT(GetType(descriptor_number) == CALLBACKS);
1988 return GetValue(descriptor_number);
1989}
1990
1991
1992AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1993 ASSERT(GetType(descriptor_number) == CALLBACKS);
Ben Murdoch257744e2011-11-30 15:57:28 +00001994 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
Ben Murdoch85b71792012-04-11 18:30:58 +01001995 return reinterpret_cast<AccessorDescriptor*>(p->address());
Steve Blocka7e24c12009-10-30 11:49:00 +00001996}
1997
1998
1999bool DescriptorArray::IsProperty(int descriptor_number) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002000 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
Steve Blocka7e24c12009-10-30 11:49:00 +00002001}
2002
2003
Ben Murdoch85b71792012-04-11 18:30:58 +01002004bool DescriptorArray::IsTransition(int descriptor_number) {
2005 PropertyType t = GetType(descriptor_number);
2006 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
2007 t == ELEMENTS_TRANSITION;
Steve Blocka7e24c12009-10-30 11:49:00 +00002008}
2009
2010
2011bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
2012 return GetType(descriptor_number) == NULL_DESCRIPTOR;
2013}
2014
2015
2016bool DescriptorArray::IsDontEnum(int descriptor_number) {
2017 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
2018}
2019
2020
2021void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2022 desc->Init(GetKey(descriptor_number),
2023 GetValue(descriptor_number),
Ben Murdoch8b112d22011-06-08 16:22:53 +01002024 PropertyDetails(GetDetails(descriptor_number)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002025}
2026
2027
Ben Murdoch85b71792012-04-11 18:30:58 +01002028void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002029 // Range check.
2030 ASSERT(descriptor_number < number_of_descriptors());
2031
Ben Murdoch85b71792012-04-11 18:30:58 +01002032 // Make sure none of the elements in desc are in new space.
2033 ASSERT(!HEAP->InNewSpace(desc->GetKey()));
2034 ASSERT(!HEAP->InNewSpace(desc->GetValue()));
2035
2036 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
Steve Blocka7e24c12009-10-30 11:49:00 +00002037 FixedArray* content_array = GetContentArray();
Ben Murdoch85b71792012-04-11 18:30:58 +01002038 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
2039 fast_set(content_array, ToDetailsIndex(descriptor_number),
2040 desc->GetDetails().AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002041}
2042
2043
Ben Murdoch85b71792012-04-11 18:30:58 +01002044void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
2045 Descriptor desc;
2046 src->Get(src_index, &desc);
2047 Set(index, &desc);
2048}
2049
2050
2051void DescriptorArray::Swap(int first, int second) {
2052 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
Steve Blocka7e24c12009-10-30 11:49:00 +00002053 FixedArray* content_array = GetContentArray();
Ben Murdoch85b71792012-04-11 18:30:58 +01002054 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
2055 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
Steve Blocka7e24c12009-10-30 11:49:00 +00002056}
2057
2058
Steve Block44f0eee2011-05-26 01:26:41 +01002059template<typename Shape, typename Key>
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002060int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2061 const int kMinCapacity = 32;
2062 int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2063 if (capacity < kMinCapacity) {
2064 capacity = kMinCapacity; // Guarantee min capacity.
2065 }
2066 return capacity;
2067}
2068
2069
2070template<typename Shape, typename Key>
Steve Block44f0eee2011-05-26 01:26:41 +01002071int HashTable<Shape, Key>::FindEntry(Key key) {
2072 return FindEntry(GetIsolate(), key);
2073}
2074
2075
2076// Find entry for key otherwise return kNotFound.
2077template<typename Shape, typename Key>
2078int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2079 uint32_t capacity = Capacity();
Ben Murdochc7cc0282012-03-05 14:35:55 +00002080 uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
Steve Block44f0eee2011-05-26 01:26:41 +01002081 uint32_t count = 1;
2082 // EnsureCapacity will guarantee the hash table is never full.
2083 while (true) {
2084 Object* element = KeyAt(entry);
Ben Murdochc7cc0282012-03-05 14:35:55 +00002085 // Empty entry.
2086 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
Ben Murdoch85b71792012-04-11 18:30:58 +01002087 if (element != isolate->heap()->raw_unchecked_null_value() &&
Steve Block44f0eee2011-05-26 01:26:41 +01002088 Shape::IsMatch(key, element)) return entry;
2089 entry = NextProbe(entry, count++, capacity);
2090 }
2091 return kNotFound;
2092}
2093
2094
Ben Murdochc7cc0282012-03-05 14:35:55 +00002095bool SeededNumberDictionary::requires_slow_elements() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002096 Object* max_index_object = get(kMaxNumberKeyIndex);
2097 if (!max_index_object->IsSmi()) return false;
2098 return 0 !=
2099 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2100}
2101
Ben Murdochc7cc0282012-03-05 14:35:55 +00002102uint32_t SeededNumberDictionary::max_number_key() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002103 ASSERT(!requires_slow_elements());
2104 Object* max_index_object = get(kMaxNumberKeyIndex);
2105 if (!max_index_object->IsSmi()) return 0;
2106 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2107 return value >> kRequiresSlowElementsTagSize;
2108}
2109
Ben Murdochc7cc0282012-03-05 14:35:55 +00002110void SeededNumberDictionary::set_requires_slow_elements() {
Leon Clarke4515c472010-02-03 11:58:03 +00002111 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +00002112}
2113
2114
2115// ------------------------------------
2116// Cast operations
2117
2118
2119CAST_ACCESSOR(FixedArray)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002120CAST_ACCESSOR(FixedDoubleArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002121CAST_ACCESSOR(DescriptorArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002122CAST_ACCESSOR(DeoptimizationInputData)
2123CAST_ACCESSOR(DeoptimizationOutputData)
Steve Blocka7e24c12009-10-30 11:49:00 +00002124CAST_ACCESSOR(SymbolTable)
Steve Block6ded16b2010-05-10 14:33:55 +01002125CAST_ACCESSOR(JSFunctionResultCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002126CAST_ACCESSOR(NormalizedMapCache)
Steve Blocka7e24c12009-10-30 11:49:00 +00002127CAST_ACCESSOR(CompilationCacheTable)
Steve Block6ded16b2010-05-10 14:33:55 +01002128CAST_ACCESSOR(CodeCacheHashTable)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002129CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00002130CAST_ACCESSOR(MapCache)
2131CAST_ACCESSOR(String)
2132CAST_ACCESSOR(SeqString)
2133CAST_ACCESSOR(SeqAsciiString)
2134CAST_ACCESSOR(SeqTwoByteString)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002135CAST_ACCESSOR(SlicedString)
Steve Blocka7e24c12009-10-30 11:49:00 +00002136CAST_ACCESSOR(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00002137CAST_ACCESSOR(ExternalString)
2138CAST_ACCESSOR(ExternalAsciiString)
2139CAST_ACCESSOR(ExternalTwoByteString)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002140CAST_ACCESSOR(JSReceiver)
Steve Blocka7e24c12009-10-30 11:49:00 +00002141CAST_ACCESSOR(JSObject)
2142CAST_ACCESSOR(Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00002143CAST_ACCESSOR(HeapObject)
2144CAST_ACCESSOR(HeapNumber)
2145CAST_ACCESSOR(Oddball)
2146CAST_ACCESSOR(JSGlobalPropertyCell)
2147CAST_ACCESSOR(SharedFunctionInfo)
2148CAST_ACCESSOR(Map)
2149CAST_ACCESSOR(JSFunction)
2150CAST_ACCESSOR(GlobalObject)
2151CAST_ACCESSOR(JSGlobalProxy)
2152CAST_ACCESSOR(JSGlobalObject)
2153CAST_ACCESSOR(JSBuiltinsObject)
2154CAST_ACCESSOR(Code)
2155CAST_ACCESSOR(JSArray)
2156CAST_ACCESSOR(JSRegExp)
Ben Murdoch257744e2011-11-30 15:57:28 +00002157CAST_ACCESSOR(JSProxy)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002158CAST_ACCESSOR(JSFunctionProxy)
Ben 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)
Steve Block3ce2e202009-11-05 08:53:23 +00002162CAST_ACCESSOR(ExternalArray)
2163CAST_ACCESSOR(ExternalByteArray)
2164CAST_ACCESSOR(ExternalUnsignedByteArray)
2165CAST_ACCESSOR(ExternalShortArray)
2166CAST_ACCESSOR(ExternalUnsignedShortArray)
2167CAST_ACCESSOR(ExternalIntArray)
2168CAST_ACCESSOR(ExternalUnsignedIntArray)
2169CAST_ACCESSOR(ExternalFloatArray)
Ben Murdoch257744e2011-11-30 15:57:28 +00002170CAST_ACCESSOR(ExternalDoubleArray)
Steve Block44f0eee2011-05-26 01:26:41 +01002171CAST_ACCESSOR(ExternalPixelArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002172CAST_ACCESSOR(Struct)
2173
2174
2175#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2176 STRUCT_LIST(MAKE_STRUCT_CAST)
2177#undef MAKE_STRUCT_CAST
2178
2179
2180template <typename Shape, typename Key>
2181HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2182 ASSERT(obj->IsHashTable());
2183 return reinterpret_cast<HashTable*>(obj);
2184}
2185
2186
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002187SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00002188
Steve Block6ded16b2010-05-10 14:33:55 +01002189SMI_ACCESSORS(String, length, kLengthOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00002190
2191
2192uint32_t String::hash_field() {
2193 return READ_UINT32_FIELD(this, kHashFieldOffset);
2194}
2195
2196
2197void String::set_hash_field(uint32_t value) {
2198 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002199#if V8_HOST_ARCH_64_BIT
2200 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2201#endif
Steve Blockd0582a62009-12-15 09:54:21 +00002202}
2203
2204
Steve Blocka7e24c12009-10-30 11:49:00 +00002205bool String::Equals(String* other) {
2206 if (other == this) return true;
2207 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2208 return false;
2209 }
2210 return SlowEquals(other);
2211}
2212
2213
John Reck59135872010-11-02 12:39:01 -07002214MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
Leon Clarkef7060e22010-06-03 12:02:55 +01002215 if (!StringShape(this).IsCons()) return this;
2216 ConsString* cons = ConsString::cast(this);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002217 if (cons->IsFlat()) return cons->first();
Steve Block6ded16b2010-05-10 14:33:55 +01002218 return SlowTryFlatten(pretenure);
Steve Blocka7e24c12009-10-30 11:49:00 +00002219}
2220
2221
Leon Clarkef7060e22010-06-03 12:02:55 +01002222String* String::TryFlattenGetString(PretenureFlag pretenure) {
John Reck59135872010-11-02 12:39:01 -07002223 MaybeObject* flat = TryFlatten(pretenure);
2224 Object* successfully_flattened;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002225 if (!flat->ToObject(&successfully_flattened)) return this;
2226 return String::cast(successfully_flattened);
Leon Clarkef7060e22010-06-03 12:02:55 +01002227}
2228
2229
Steve Blocka7e24c12009-10-30 11:49:00 +00002230uint16_t String::Get(int index) {
2231 ASSERT(index >= 0 && index < length());
2232 switch (StringShape(this).full_representation_tag()) {
2233 case kSeqStringTag | kAsciiStringTag:
2234 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2235 case kSeqStringTag | kTwoByteStringTag:
2236 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2237 case kConsStringTag | kAsciiStringTag:
2238 case kConsStringTag | kTwoByteStringTag:
2239 return ConsString::cast(this)->ConsStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002240 case kExternalStringTag | kAsciiStringTag:
2241 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2242 case kExternalStringTag | kTwoByteStringTag:
2243 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002244 case kSlicedStringTag | kAsciiStringTag:
2245 case kSlicedStringTag | kTwoByteStringTag:
2246 return SlicedString::cast(this)->SlicedStringGet(index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002247 default:
2248 break;
2249 }
2250
2251 UNREACHABLE();
2252 return 0;
2253}
2254
2255
2256void String::Set(int index, uint16_t value) {
2257 ASSERT(index >= 0 && index < length());
2258 ASSERT(StringShape(this).IsSequential());
2259
2260 return this->IsAsciiRepresentation()
2261 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2262 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2263}
2264
2265
2266bool String::IsFlat() {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002267 if (!StringShape(this).IsCons()) return true;
2268 return ConsString::cast(this)->second()->length() == 0;
2269}
2270
2271
2272String* String::GetUnderlying() {
2273 // Giving direct access to underlying string only makes sense if the
2274 // wrapping string is already flattened.
2275 ASSERT(this->IsFlat());
2276 ASSERT(StringShape(this).IsIndirect());
2277 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2278 const int kUnderlyingOffset = SlicedString::kParentOffset;
2279 return String::cast(READ_FIELD(this, kUnderlyingOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002280}
2281
2282
2283uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2284 ASSERT(index >= 0 && index < length());
2285 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2286}
2287
2288
2289void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2290 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2291 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2292 static_cast<byte>(value));
2293}
2294
2295
2296Address SeqAsciiString::GetCharsAddress() {
2297 return FIELD_ADDR(this, kHeaderSize);
2298}
2299
2300
2301char* SeqAsciiString::GetChars() {
2302 return reinterpret_cast<char*>(GetCharsAddress());
2303}
2304
2305
2306Address SeqTwoByteString::GetCharsAddress() {
2307 return FIELD_ADDR(this, kHeaderSize);
2308}
2309
2310
2311uc16* SeqTwoByteString::GetChars() {
2312 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2313}
2314
2315
2316uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2317 ASSERT(index >= 0 && index < length());
2318 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2319}
2320
2321
2322void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2323 ASSERT(index >= 0 && index < length());
2324 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2325}
2326
2327
2328int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01002329 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002330}
2331
2332
2333int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
Steve Block6ded16b2010-05-10 14:33:55 +01002334 return SizeFor(length());
Steve Blocka7e24c12009-10-30 11:49:00 +00002335}
2336
2337
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002338String* SlicedString::parent() {
2339 return String::cast(READ_FIELD(this, kParentOffset));
2340}
2341
2342
2343void SlicedString::set_parent(String* parent) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002344 ASSERT(parent->IsSeqString());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002345 WRITE_FIELD(this, kParentOffset, parent);
2346}
2347
2348
2349SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2350
2351
Steve Blocka7e24c12009-10-30 11:49:00 +00002352String* ConsString::first() {
2353 return String::cast(READ_FIELD(this, kFirstOffset));
2354}
2355
2356
2357Object* ConsString::unchecked_first() {
2358 return READ_FIELD(this, kFirstOffset);
2359}
2360
2361
2362void ConsString::set_first(String* value, WriteBarrierMode mode) {
2363 WRITE_FIELD(this, kFirstOffset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01002364 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002365}
2366
2367
2368String* ConsString::second() {
2369 return String::cast(READ_FIELD(this, kSecondOffset));
2370}
2371
2372
2373Object* ConsString::unchecked_second() {
2374 return READ_FIELD(this, kSecondOffset);
2375}
2376
2377
2378void ConsString::set_second(String* value, WriteBarrierMode mode) {
2379 WRITE_FIELD(this, kSecondOffset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01002380 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002381}
2382
2383
Ben Murdoch85b71792012-04-11 18:30:58 +01002384ExternalAsciiString::Resource* ExternalAsciiString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002385 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2386}
2387
2388
2389void ExternalAsciiString::set_resource(
Ben Murdoch85b71792012-04-11 18:30:58 +01002390 ExternalAsciiString::Resource* resource) {
2391 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
Steve Blocka7e24c12009-10-30 11:49:00 +00002392}
2393
2394
Ben Murdoch85b71792012-04-11 18:30:58 +01002395ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002396 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2397}
2398
2399
2400void ExternalTwoByteString::set_resource(
Ben Murdoch85b71792012-04-11 18:30:58 +01002401 ExternalTwoByteString::Resource* resource) {
2402 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
Steve Blocka7e24c12009-10-30 11:49:00 +00002403}
2404
2405
Steve Block6ded16b2010-05-10 14:33:55 +01002406void JSFunctionResultCache::MakeZeroSize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002407 set_finger_index(kEntriesIndex);
2408 set_size(kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01002409}
2410
2411
2412void JSFunctionResultCache::Clear() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002413 int cache_size = size();
Steve Block6ded16b2010-05-10 14:33:55 +01002414 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002415 MemsetPointer(entries_start,
Steve Block44f0eee2011-05-26 01:26:41 +01002416 GetHeap()->the_hole_value(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002417 cache_size - kEntriesIndex);
Steve Block6ded16b2010-05-10 14:33:55 +01002418 MakeZeroSize();
2419}
2420
2421
Ben Murdochb8e0da22011-05-16 14:20:40 +01002422int JSFunctionResultCache::size() {
2423 return Smi::cast(get(kCacheSizeIndex))->value();
2424}
2425
2426
2427void JSFunctionResultCache::set_size(int size) {
2428 set(kCacheSizeIndex, Smi::FromInt(size));
2429}
2430
2431
2432int JSFunctionResultCache::finger_index() {
2433 return Smi::cast(get(kFingerIndex))->value();
2434}
2435
2436
2437void JSFunctionResultCache::set_finger_index(int finger_index) {
2438 set(kFingerIndex, Smi::FromInt(finger_index));
2439}
2440
2441
Steve Blocka7e24c12009-10-30 11:49:00 +00002442byte ByteArray::get(int index) {
2443 ASSERT(index >= 0 && index < this->length());
2444 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2445}
2446
2447
2448void ByteArray::set(int index, byte value) {
2449 ASSERT(index >= 0 && index < this->length());
2450 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2451}
2452
2453
2454int ByteArray::get_int(int index) {
2455 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2456 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2457}
2458
2459
2460ByteArray* ByteArray::FromDataStartAddress(Address address) {
2461 ASSERT_TAG_ALIGNED(address);
2462 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2463}
2464
2465
2466Address ByteArray::GetDataStartAddress() {
2467 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2468}
2469
2470
Steve Block44f0eee2011-05-26 01:26:41 +01002471uint8_t* ExternalPixelArray::external_pixel_pointer() {
2472 return reinterpret_cast<uint8_t*>(external_pointer());
Steve Blocka7e24c12009-10-30 11:49:00 +00002473}
2474
2475
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002476uint8_t ExternalPixelArray::get_scalar(int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002477 ASSERT((index >= 0) && (index < this->length()));
Steve Block44f0eee2011-05-26 01:26:41 +01002478 uint8_t* ptr = external_pixel_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00002479 return ptr[index];
2480}
2481
2482
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002483MaybeObject* ExternalPixelArray::get(int index) {
2484 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2485}
2486
2487
Steve Block44f0eee2011-05-26 01:26:41 +01002488void ExternalPixelArray::set(int index, uint8_t value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002489 ASSERT((index >= 0) && (index < this->length()));
Steve Block44f0eee2011-05-26 01:26:41 +01002490 uint8_t* ptr = external_pixel_pointer();
Steve Blocka7e24c12009-10-30 11:49:00 +00002491 ptr[index] = value;
2492}
2493
2494
Steve Block3ce2e202009-11-05 08:53:23 +00002495void* ExternalArray::external_pointer() {
2496 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2497 return reinterpret_cast<void*>(ptr);
2498}
2499
2500
2501void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2502 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2503 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2504}
2505
2506
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002507int8_t ExternalByteArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002508 ASSERT((index >= 0) && (index < this->length()));
2509 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2510 return ptr[index];
2511}
2512
2513
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002514MaybeObject* ExternalByteArray::get(int index) {
2515 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2516}
2517
2518
Steve Block3ce2e202009-11-05 08:53:23 +00002519void ExternalByteArray::set(int index, int8_t value) {
2520 ASSERT((index >= 0) && (index < this->length()));
2521 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2522 ptr[index] = value;
2523}
2524
2525
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002526uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002527 ASSERT((index >= 0) && (index < this->length()));
2528 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2529 return ptr[index];
2530}
2531
2532
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002533MaybeObject* ExternalUnsignedByteArray::get(int index) {
2534 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2535}
2536
2537
Steve Block3ce2e202009-11-05 08:53:23 +00002538void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2539 ASSERT((index >= 0) && (index < this->length()));
2540 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2541 ptr[index] = value;
2542}
2543
2544
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002545int16_t ExternalShortArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002546 ASSERT((index >= 0) && (index < this->length()));
2547 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2548 return ptr[index];
2549}
2550
2551
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002552MaybeObject* ExternalShortArray::get(int index) {
2553 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2554}
2555
2556
Steve Block3ce2e202009-11-05 08:53:23 +00002557void ExternalShortArray::set(int index, int16_t value) {
2558 ASSERT((index >= 0) && (index < this->length()));
2559 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2560 ptr[index] = value;
2561}
2562
2563
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002564uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002565 ASSERT((index >= 0) && (index < this->length()));
2566 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2567 return ptr[index];
2568}
2569
2570
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002571MaybeObject* ExternalUnsignedShortArray::get(int index) {
2572 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2573}
2574
2575
Steve Block3ce2e202009-11-05 08:53:23 +00002576void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2577 ASSERT((index >= 0) && (index < this->length()));
2578 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2579 ptr[index] = value;
2580}
2581
2582
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002583int32_t ExternalIntArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002584 ASSERT((index >= 0) && (index < this->length()));
2585 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2586 return ptr[index];
2587}
2588
2589
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002590MaybeObject* ExternalIntArray::get(int index) {
2591 return GetHeap()->NumberFromInt32(get_scalar(index));
2592}
2593
2594
Steve Block3ce2e202009-11-05 08:53:23 +00002595void ExternalIntArray::set(int index, int32_t value) {
2596 ASSERT((index >= 0) && (index < this->length()));
2597 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2598 ptr[index] = value;
2599}
2600
2601
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002602uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002603 ASSERT((index >= 0) && (index < this->length()));
2604 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2605 return ptr[index];
2606}
2607
2608
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002609MaybeObject* ExternalUnsignedIntArray::get(int index) {
2610 return GetHeap()->NumberFromUint32(get_scalar(index));
2611}
2612
2613
Steve Block3ce2e202009-11-05 08:53:23 +00002614void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2615 ASSERT((index >= 0) && (index < this->length()));
2616 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2617 ptr[index] = value;
2618}
2619
2620
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002621float ExternalFloatArray::get_scalar(int index) {
Steve Block3ce2e202009-11-05 08:53:23 +00002622 ASSERT((index >= 0) && (index < this->length()));
2623 float* ptr = static_cast<float*>(external_pointer());
2624 return ptr[index];
2625}
2626
2627
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002628MaybeObject* ExternalFloatArray::get(int index) {
2629 return GetHeap()->NumberFromDouble(get_scalar(index));
2630}
2631
2632
Steve Block3ce2e202009-11-05 08:53:23 +00002633void ExternalFloatArray::set(int index, float value) {
2634 ASSERT((index >= 0) && (index < this->length()));
2635 float* ptr = static_cast<float*>(external_pointer());
2636 ptr[index] = value;
2637}
2638
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002639
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002640double ExternalDoubleArray::get_scalar(int index) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002641 ASSERT((index >= 0) && (index < this->length()));
2642 double* ptr = static_cast<double*>(external_pointer());
2643 return ptr[index];
2644}
2645
2646
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002647MaybeObject* ExternalDoubleArray::get(int index) {
2648 return GetHeap()->NumberFromDouble(get_scalar(index));
2649}
2650
2651
Ben Murdoch257744e2011-11-30 15:57:28 +00002652void ExternalDoubleArray::set(int index, double value) {
2653 ASSERT((index >= 0) && (index < this->length()));
2654 double* ptr = static_cast<double*>(external_pointer());
2655 ptr[index] = value;
2656}
2657
2658
Iain Merrick9ac36c92010-09-13 15:29:50 +01002659int Map::visitor_id() {
2660 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2661}
2662
2663
2664void Map::set_visitor_id(int id) {
2665 ASSERT(0 <= id && id < 256);
2666 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2667}
2668
Steve Block3ce2e202009-11-05 08:53:23 +00002669
Steve Blocka7e24c12009-10-30 11:49:00 +00002670int Map::instance_size() {
2671 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2672}
2673
2674
2675int Map::inobject_properties() {
2676 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2677}
2678
2679
2680int Map::pre_allocated_property_fields() {
2681 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2682}
2683
2684
2685int HeapObject::SizeFromMap(Map* map) {
Steve Block791712a2010-08-27 10:21:07 +01002686 int instance_size = map->instance_size();
2687 if (instance_size != kVariableSizeSentinel) return instance_size;
2688 // We can ignore the "symbol" bit becase it is only set for symbols
2689 // and implies a string type.
2690 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00002691 // Only inline the most frequent cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00002692 if (instance_type == FIXED_ARRAY_TYPE) {
Iain Merrick75681382010-08-19 15:07:18 +01002693 return FixedArray::BodyDescriptor::SizeOf(map, this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002694 }
Steve Block791712a2010-08-27 10:21:07 +01002695 if (instance_type == ASCII_STRING_TYPE) {
2696 return SeqAsciiString::SizeFor(
2697 reinterpret_cast<SeqAsciiString*>(this)->length());
2698 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002699 if (instance_type == BYTE_ARRAY_TYPE) {
2700 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2701 }
Steve Block791712a2010-08-27 10:21:07 +01002702 if (instance_type == STRING_TYPE) {
2703 return SeqTwoByteString::SizeFor(
2704 reinterpret_cast<SeqTwoByteString*>(this)->length());
2705 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002706 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2707 return FixedDoubleArray::SizeFor(
2708 reinterpret_cast<FixedDoubleArray*>(this)->length());
2709 }
Steve Block791712a2010-08-27 10:21:07 +01002710 ASSERT(instance_type == CODE_TYPE);
2711 return reinterpret_cast<Code*>(this)->CodeSize();
Steve Blocka7e24c12009-10-30 11:49:00 +00002712}
2713
2714
2715void Map::set_instance_size(int value) {
2716 ASSERT_EQ(0, value & (kPointerSize - 1));
2717 value >>= kPointerSizeLog2;
2718 ASSERT(0 <= value && value < 256);
2719 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2720}
2721
2722
2723void Map::set_inobject_properties(int value) {
2724 ASSERT(0 <= value && value < 256);
2725 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2726}
2727
2728
2729void Map::set_pre_allocated_property_fields(int value) {
2730 ASSERT(0 <= value && value < 256);
2731 WRITE_BYTE_FIELD(this,
2732 kPreAllocatedPropertyFieldsOffset,
2733 static_cast<byte>(value));
2734}
2735
2736
2737InstanceType Map::instance_type() {
2738 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2739}
2740
2741
2742void Map::set_instance_type(InstanceType value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002743 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2744}
2745
2746
2747int Map::unused_property_fields() {
2748 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2749}
2750
2751
2752void Map::set_unused_property_fields(int value) {
2753 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2754}
2755
2756
2757byte Map::bit_field() {
2758 return READ_BYTE_FIELD(this, kBitFieldOffset);
2759}
2760
2761
2762void Map::set_bit_field(byte value) {
2763 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2764}
2765
2766
2767byte Map::bit_field2() {
2768 return READ_BYTE_FIELD(this, kBitField2Offset);
2769}
2770
2771
2772void Map::set_bit_field2(byte value) {
2773 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2774}
2775
2776
2777void Map::set_non_instance_prototype(bool value) {
2778 if (value) {
2779 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2780 } else {
2781 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2782 }
2783}
2784
2785
2786bool Map::has_non_instance_prototype() {
2787 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2788}
2789
2790
Steve Block6ded16b2010-05-10 14:33:55 +01002791void Map::set_function_with_prototype(bool value) {
2792 if (value) {
2793 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2794 } else {
2795 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2796 }
2797}
2798
2799
2800bool Map::function_with_prototype() {
2801 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2802}
2803
2804
Steve Blocka7e24c12009-10-30 11:49:00 +00002805void Map::set_is_access_check_needed(bool access_check_needed) {
2806 if (access_check_needed) {
2807 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2808 } else {
2809 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2810 }
2811}
2812
2813
2814bool Map::is_access_check_needed() {
2815 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2816}
2817
2818
Steve Block8defd9f2010-07-08 12:39:36 +01002819void Map::set_is_extensible(bool value) {
2820 if (value) {
2821 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2822 } else {
2823 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2824 }
2825}
2826
2827bool Map::is_extensible() {
2828 return ((1 << kIsExtensible) & bit_field2()) != 0;
2829}
2830
2831
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002832void Map::set_attached_to_shared_function_info(bool value) {
2833 if (value) {
2834 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2835 } else {
2836 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2837 }
2838}
2839
2840bool Map::attached_to_shared_function_info() {
2841 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2842}
2843
2844
2845void Map::set_is_shared(bool value) {
2846 if (value) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002847 set_bit_field3(bit_field3() | (1 << kIsShared));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002848 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00002849 set_bit_field3(bit_field3() & ~(1 << kIsShared));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002850 }
2851}
2852
2853bool Map::is_shared() {
Ben Murdoch257744e2011-11-30 15:57:28 +00002854 return ((1 << kIsShared) & bit_field3()) != 0;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002855}
2856
2857
2858JSFunction* Map::unchecked_constructor() {
2859 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2860}
2861
Steve Block8defd9f2010-07-08 12:39:36 +01002862
Ben Murdoch85b71792012-04-11 18:30:58 +01002863FixedArray* Map::unchecked_prototype_transitions() {
2864 return reinterpret_cast<FixedArray*>(
2865 READ_FIELD(this, kPrototypeTransitionsOffset));
2866}
2867
2868
Steve Blocka7e24c12009-10-30 11:49:00 +00002869Code::Flags Code::flags() {
2870 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2871}
2872
2873
2874void Code::set_flags(Code::Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00002875 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002876 // Make sure that all call stubs have an arguments count.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002877 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2878 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002879 ExtractArgumentsCountFromFlags(flags) >= 0);
2880 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2881}
2882
2883
2884Code::Kind Code::kind() {
2885 return ExtractKindFromFlags(flags());
2886}
2887
2888
Steve Blocka7e24c12009-10-30 11:49:00 +00002889InlineCacheState Code::ic_state() {
2890 InlineCacheState result = ExtractICStateFromFlags(flags());
2891 // Only allow uninitialized or debugger states for non-IC code
2892 // objects. This is used in the debugger to determine whether or not
2893 // a call to code object has been replaced with a debug break call.
2894 ASSERT(is_inline_cache_stub() ||
2895 result == UNINITIALIZED ||
2896 result == DEBUG_BREAK ||
2897 result == DEBUG_PREPARE_STEP_IN);
2898 return result;
2899}
2900
2901
Ben Murdochb8e0da22011-05-16 14:20:40 +01002902Code::ExtraICState Code::extra_ic_state() {
2903 ASSERT(is_inline_cache_stub());
2904 return ExtractExtraICStateFromFlags(flags());
2905}
2906
2907
Steve Blocka7e24c12009-10-30 11:49:00 +00002908PropertyType Code::type() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002909 return ExtractTypeFromFlags(flags());
2910}
2911
2912
2913int Code::arguments_count() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002914 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
Steve Blocka7e24c12009-10-30 11:49:00 +00002915 return ExtractArgumentsCountFromFlags(flags());
2916}
2917
2918
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002919int Code::major_key() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002920 ASSERT(kind() == STUB ||
Ben Murdoch257744e2011-11-30 15:57:28 +00002921 kind() == UNARY_OP_IC ||
2922 kind() == BINARY_OP_IC ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002923 kind() == COMPARE_IC ||
2924 kind() == TO_BOOLEAN_IC);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002925 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00002926}
2927
2928
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002929void Code::set_major_key(int major) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002930 ASSERT(kind() == STUB ||
Ben Murdoch257744e2011-11-30 15:57:28 +00002931 kind() == UNARY_OP_IC ||
2932 kind() == BINARY_OP_IC ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002933 kind() == COMPARE_IC ||
2934 kind() == TO_BOOLEAN_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00002935 ASSERT(0 <= major && major < 256);
2936 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2937}
2938
2939
Ben Murdochb0fe1622011-05-05 13:52:32 +01002940bool Code::optimizable() {
2941 ASSERT(kind() == FUNCTION);
2942 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2943}
2944
2945
2946void Code::set_optimizable(bool value) {
2947 ASSERT(kind() == FUNCTION);
2948 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2949}
2950
2951
2952bool Code::has_deoptimization_support() {
2953 ASSERT(kind() == FUNCTION);
Ben Murdoch589d6972011-11-30 16:04:58 +00002954 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2955 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002956}
2957
2958
2959void Code::set_has_deoptimization_support(bool value) {
2960 ASSERT(kind() == FUNCTION);
Ben Murdoch589d6972011-11-30 16:04:58 +00002961 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2962 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
2963 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2964}
2965
2966
2967bool Code::has_debug_break_slots() {
2968 ASSERT(kind() == FUNCTION);
2969 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2970 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
2971}
2972
2973
2974void Code::set_has_debug_break_slots(bool value) {
2975 ASSERT(kind() == FUNCTION);
2976 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2977 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
2978 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002979}
2980
2981
2982int Code::allow_osr_at_loop_nesting_level() {
2983 ASSERT(kind() == FUNCTION);
2984 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2985}
2986
2987
2988void Code::set_allow_osr_at_loop_nesting_level(int level) {
2989 ASSERT(kind() == FUNCTION);
2990 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2991 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2992}
2993
2994
2995unsigned Code::stack_slots() {
2996 ASSERT(kind() == OPTIMIZED_FUNCTION);
2997 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2998}
2999
3000
3001void Code::set_stack_slots(unsigned slots) {
3002 ASSERT(kind() == OPTIMIZED_FUNCTION);
3003 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
3004}
3005
3006
Steve Block1e0659c2011-05-24 12:43:12 +01003007unsigned Code::safepoint_table_offset() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003008 ASSERT(kind() == OPTIMIZED_FUNCTION);
Steve Block1e0659c2011-05-24 12:43:12 +01003009 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003010}
3011
3012
Steve Block1e0659c2011-05-24 12:43:12 +01003013void Code::set_safepoint_table_offset(unsigned offset) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003014 ASSERT(kind() == OPTIMIZED_FUNCTION);
3015 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
Steve Block1e0659c2011-05-24 12:43:12 +01003016 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003017}
3018
3019
Steve Block1e0659c2011-05-24 12:43:12 +01003020unsigned Code::stack_check_table_offset() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003021 ASSERT(kind() == FUNCTION);
Steve Block1e0659c2011-05-24 12:43:12 +01003022 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003023}
3024
3025
Steve Block1e0659c2011-05-24 12:43:12 +01003026void Code::set_stack_check_table_offset(unsigned offset) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003027 ASSERT(kind() == FUNCTION);
3028 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
Steve Block1e0659c2011-05-24 12:43:12 +01003029 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003030}
3031
3032
3033CheckType Code::check_type() {
3034 ASSERT(is_call_stub() || is_keyed_call_stub());
3035 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
3036 return static_cast<CheckType>(type);
3037}
3038
3039
3040void Code::set_check_type(CheckType value) {
3041 ASSERT(is_call_stub() || is_keyed_call_stub());
3042 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
3043}
3044
3045
Ben Murdoch257744e2011-11-30 15:57:28 +00003046byte Code::unary_op_type() {
3047 ASSERT(is_unary_op_stub());
3048 return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
3049}
3050
3051
3052void Code::set_unary_op_type(byte value) {
3053 ASSERT(is_unary_op_stub());
3054 WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
3055}
3056
3057
3058byte Code::binary_op_type() {
3059 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003060 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3061}
3062
3063
Ben Murdoch257744e2011-11-30 15:57:28 +00003064void Code::set_binary_op_type(byte value) {
3065 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003066 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3067}
3068
3069
Ben Murdoch257744e2011-11-30 15:57:28 +00003070byte Code::binary_op_result_type() {
3071 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003072 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3073}
3074
3075
Ben Murdoch257744e2011-11-30 15:57:28 +00003076void Code::set_binary_op_result_type(byte value) {
3077 ASSERT(is_binary_op_stub());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003078 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3079}
3080
3081
3082byte Code::compare_state() {
3083 ASSERT(is_compare_ic_stub());
3084 return READ_BYTE_FIELD(this, kCompareStateOffset);
3085}
3086
3087
3088void Code::set_compare_state(byte value) {
3089 ASSERT(is_compare_ic_stub());
3090 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3091}
3092
3093
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003094byte Code::to_boolean_state() {
3095 ASSERT(is_to_boolean_ic_stub());
3096 return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3097}
3098
3099
3100void Code::set_to_boolean_state(byte value) {
3101 ASSERT(is_to_boolean_ic_stub());
3102 WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3103}
3104
Steve Blocka7e24c12009-10-30 11:49:00 +00003105bool Code::is_inline_cache_stub() {
3106 Kind kind = this->kind();
3107 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3108}
3109
3110
3111Code::Flags Code::ComputeFlags(Kind kind,
Steve Blocka7e24c12009-10-30 11:49:00 +00003112 InlineCacheState ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003113 ExtraICState extra_ic_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00003114 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01003115 int argc,
3116 InlineCacheHolderFlag holder) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003117 // Extra IC state is only allowed for call IC stubs or for store IC
3118 // stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003119 ASSERT(extra_ic_state == kNoExtraICState ||
Ben Murdoch589d6972011-11-30 16:04:58 +00003120 kind == CALL_IC ||
3121 kind == STORE_IC ||
3122 kind == KEYED_STORE_IC);
Steve Blocka7e24c12009-10-30 11:49:00 +00003123 // Compute the bit mask.
Ben Murdoch589d6972011-11-30 16:04:58 +00003124 int bits = KindField::encode(kind)
3125 | ICStateField::encode(ic_state)
3126 | TypeField::encode(type)
3127 | ExtraICStateField::encode(extra_ic_state)
3128 | (argc << kArgumentsCountShift)
3129 | CacheHolderField::encode(holder);
3130 return static_cast<Flags>(bits);
Steve Blocka7e24c12009-10-30 11:49:00 +00003131}
3132
3133
3134Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3135 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003136 ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01003137 InlineCacheHolderFlag holder,
Steve Blocka7e24c12009-10-30 11:49:00 +00003138 int argc) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003139 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00003140}
3141
3142
3143Code::Kind Code::ExtractKindFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003144 return KindField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003145}
3146
3147
3148InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003149 return ICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003150}
3151
3152
Ben Murdochb8e0da22011-05-16 14:20:40 +01003153Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003154 return ExtraICStateField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003155}
3156
3157
3158PropertyType Code::ExtractTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003159 return TypeField::decode(flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003160}
3161
3162
3163int Code::ExtractArgumentsCountFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003164 return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00003165}
3166
3167
Steve Block8defd9f2010-07-08 12:39:36 +01003168InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003169 return CacheHolderField::decode(flags);
Steve Block8defd9f2010-07-08 12:39:36 +01003170}
3171
3172
Steve Blocka7e24c12009-10-30 11:49:00 +00003173Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003174 int bits = flags & ~TypeField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00003175 return static_cast<Flags>(bits);
3176}
3177
3178
3179Code* Code::GetCodeFromTargetAddress(Address address) {
3180 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3181 // GetCodeFromTargetAddress might be called when marking objects during mark
3182 // sweep. reinterpret_cast is therefore used instead of the more appropriate
3183 // Code::cast. Code::cast does not work when the object's map is
3184 // marked.
3185 Code* result = reinterpret_cast<Code*>(code);
3186 return result;
3187}
3188
3189
Ben Murdoch85b71792012-04-11 18:30:58 +01003190Isolate* Map::isolate() {
3191 return heap()->isolate();
3192}
3193
3194
3195Heap* Map::heap() {
3196 // NOTE: address() helper is not used to save one instruction.
3197 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
3198 ASSERT(heap != NULL);
3199 ASSERT(heap->isolate() == Isolate::Current());
3200 return heap;
3201}
3202
3203
3204Heap* Code::heap() {
3205 // NOTE: address() helper is not used to save one instruction.
3206 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
3207 ASSERT(heap != NULL);
3208 ASSERT(heap->isolate() == Isolate::Current());
3209 return heap;
3210}
3211
3212
3213Isolate* Code::isolate() {
3214 return heap()->isolate();
3215}
3216
3217
3218Heap* JSGlobalPropertyCell::heap() {
3219 // NOTE: address() helper is not used to save one instruction.
3220 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
3221 ASSERT(heap != NULL);
3222 ASSERT(heap->isolate() == Isolate::Current());
3223 return heap;
3224}
3225
3226
3227Isolate* JSGlobalPropertyCell::isolate() {
3228 return heap()->isolate();
3229}
3230
3231
Steve Block791712a2010-08-27 10:21:07 +01003232Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3233 return HeapObject::
3234 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3235}
3236
3237
Steve Blocka7e24c12009-10-30 11:49:00 +00003238Object* Map::prototype() {
3239 return READ_FIELD(this, kPrototypeOffset);
3240}
3241
3242
3243void Map::set_prototype(Object* value, WriteBarrierMode mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003244 ASSERT(value->IsNull() || value->IsJSReceiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003245 WRITE_FIELD(this, kPrototypeOffset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01003246 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode);
3247}
3248
3249
3250MaybeObject* Map::GetFastElementsMap() {
3251 if (has_fast_elements()) return this;
3252 Object* obj;
3253 { MaybeObject* maybe_obj = CopyDropTransitions();
3254 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3255 }
3256 Map* new_map = Map::cast(obj);
3257 new_map->set_elements_kind(FAST_ELEMENTS);
3258 isolate()->counters()->map_to_fast_elements()->Increment();
3259 return new_map;
3260}
3261
3262
3263MaybeObject* Map::GetFastDoubleElementsMap() {
3264 if (has_fast_double_elements()) return this;
3265 Object* obj;
3266 { MaybeObject* maybe_obj = CopyDropTransitions();
3267 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3268 }
3269 Map* new_map = Map::cast(obj);
3270 new_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
3271 isolate()->counters()->map_to_fast_double_elements()->Increment();
3272 return new_map;
3273}
3274
3275
3276MaybeObject* Map::GetSlowElementsMap() {
3277 if (!has_fast_elements() && !has_fast_double_elements()) return this;
3278 Object* obj;
3279 { MaybeObject* maybe_obj = CopyDropTransitions();
3280 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3281 }
3282 Map* new_map = Map::cast(obj);
3283 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
3284 isolate()->counters()->map_to_slow_elements()->Increment();
3285 return new_map;
Steve Block1e0659c2011-05-24 12:43:12 +01003286}
3287
3288
Ben Murdoch257744e2011-11-30 15:57:28 +00003289DescriptorArray* Map::instance_descriptors() {
3290 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3291 if (object->IsSmi()) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003292 return HEAP->empty_descriptor_array();
Ben Murdoch257744e2011-11-30 15:57:28 +00003293 } else {
3294 return DescriptorArray::cast(object);
3295 }
3296}
3297
3298
3299void Map::init_instance_descriptors() {
3300 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3301}
3302
3303
3304void Map::clear_instance_descriptors() {
3305 Object* object = READ_FIELD(this,
3306 kInstanceDescriptorsOrBitField3Offset);
3307 if (!object->IsSmi()) {
3308 WRITE_FIELD(
3309 this,
3310 kInstanceDescriptorsOrBitField3Offset,
3311 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3312 }
3313}
3314
3315
3316void Map::set_instance_descriptors(DescriptorArray* value,
3317 WriteBarrierMode mode) {
3318 Object* object = READ_FIELD(this,
3319 kInstanceDescriptorsOrBitField3Offset);
Ben Murdoch85b71792012-04-11 18:30:58 +01003320 if (value == isolate()->heap()->empty_descriptor_array()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003321 clear_instance_descriptors();
3322 return;
3323 } else {
3324 if (object->IsSmi()) {
3325 value->set_bit_field3_storage(Smi::cast(object)->value());
3326 } else {
3327 value->set_bit_field3_storage(
3328 DescriptorArray::cast(object)->bit_field3_storage());
3329 }
3330 }
3331 ASSERT(!is_shared());
3332 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01003333 CONDITIONAL_WRITE_BARRIER(GetHeap(),
3334 this,
3335 kInstanceDescriptorsOrBitField3Offset,
3336 mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00003337}
3338
3339
3340int Map::bit_field3() {
3341 Object* object = READ_FIELD(this,
3342 kInstanceDescriptorsOrBitField3Offset);
3343 if (object->IsSmi()) {
3344 return Smi::cast(object)->value();
3345 } else {
3346 return DescriptorArray::cast(object)->bit_field3_storage();
3347 }
3348}
3349
3350
3351void Map::set_bit_field3(int value) {
3352 ASSERT(Smi::IsValid(value));
3353 Object* object = READ_FIELD(this,
3354 kInstanceDescriptorsOrBitField3Offset);
3355 if (object->IsSmi()) {
3356 WRITE_FIELD(this,
3357 kInstanceDescriptorsOrBitField3Offset,
3358 Smi::FromInt(value));
3359 } else {
3360 DescriptorArray::cast(object)->set_bit_field3_storage(value);
3361 }
3362}
3363
3364
Steve Block6ded16b2010-05-10 14:33:55 +01003365ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
Steve Block053d10c2011-06-13 19:13:29 +01003366ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003367ACCESSORS(Map, constructor, Object, kConstructorOffset)
3368
3369ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003370ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
3371ACCESSORS_GCSAFE(JSFunction, next_function_link, Object,
3372 kNextFunctionLinkOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003373
3374ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3375ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3376ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3377
3378ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3379
3380ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3381ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3382ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3383ACCESSORS(AccessorInfo, name, Object, kNameOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003384ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
Ben Murdochc7cc0282012-03-05 14:35:55 +00003385
Steve Blocka7e24c12009-10-30 11:49:00 +00003386ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3387ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3388ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3389
3390ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3391ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3392ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3393ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3394ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3395ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3396
3397ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3398ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3399
3400ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3401ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3402
3403ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3404ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3405ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3406 kPropertyAccessorsOffset)
3407ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3408 kPrototypeTemplateOffset)
3409ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3410ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3411 kNamedPropertyHandlerOffset)
3412ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3413 kIndexedPropertyHandlerOffset)
3414ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3415 kInstanceTemplateOffset)
3416ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3417ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3418ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3419 kInstanceCallHandlerOffset)
3420ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3421 kAccessCheckInfoOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003422ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003423
3424ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3425ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3426 kInternalFieldCountOffset)
3427
3428ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3429ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3430
3431ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3432
3433ACCESSORS(Script, source, Object, kSourceOffset)
3434ACCESSORS(Script, name, Object, kNameOffset)
3435ACCESSORS(Script, id, Object, kIdOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003436ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
3437ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003438ACCESSORS(Script, data, Object, kDataOffset)
3439ACCESSORS(Script, context_data, Object, kContextOffset)
Ben Murdoch257744e2011-11-30 15:57:28 +00003440ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003441ACCESSORS(Script, type, Smi, kTypeOffset)
3442ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003443ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
Steve Blockd0582a62009-12-15 09:54:21 +00003444ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003445ACCESSORS(Script, eval_from_instructions_offset, Smi,
3446 kEvalFrominstructionsOffsetOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003447
3448#ifdef ENABLE_DEBUGGER_SUPPORT
3449ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3450ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3451ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3452ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3453
Ben Murdoch85b71792012-04-11 18:30:58 +01003454ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
3455ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
3456ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
Steve Blocka7e24c12009-10-30 11:49:00 +00003457ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3458#endif
3459
Steve Blocka7e24c12009-10-30 11:49:00 +00003460ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003461ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3462ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003463ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3464 kInstanceClassNameOffset)
Steve Block6ded16b2010-05-10 14:33:55 +01003465ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
Steve Blocka7e24c12009-10-30 11:49:00 +00003466ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3467ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3468ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3469ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3470 kThisPropertyAssignmentsOffset)
3471
3472BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3473 kHiddenPrototypeBit)
3474BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3475BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3476 kNeedsAccessCheckBit)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003477BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3478 kReadOnlyPrototypeBit)
Steve Blocka7e24c12009-10-30 11:49:00 +00003479BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3480 kIsExpressionBit)
3481BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3482 kIsTopLevelBit)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003483BOOL_GETTER(SharedFunctionInfo,
3484 compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00003485 has_only_simple_this_property_assignments,
3486 kHasOnlySimpleThisPropertyAssignments)
Steve Blockd0582a62009-12-15 09:54:21 +00003487BOOL_ACCESSORS(SharedFunctionInfo,
3488 compiler_hints,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003489 allows_lazy_compilation,
3490 kAllowLazyCompilation)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003491BOOL_ACCESSORS(SharedFunctionInfo,
3492 compiler_hints,
3493 uses_arguments,
3494 kUsesArguments)
3495BOOL_ACCESSORS(SharedFunctionInfo,
3496 compiler_hints,
3497 has_duplicate_parameters,
3498 kHasDuplicateParameters)
Steve Blocka7e24c12009-10-30 11:49:00 +00003499
Iain Merrick75681382010-08-19 15:07:18 +01003500
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003501#if V8_HOST_ARCH_32_BIT
3502SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3503SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003504 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003505SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003506 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003507SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3508SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
Steve Blocka7e24c12009-10-30 11:49:00 +00003509 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003510SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3511SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
Steve Blocka7e24c12009-10-30 11:49:00 +00003512 kFunctionTokenPositionOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003513SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
Steve Blocka7e24c12009-10-30 11:49:00 +00003514 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003515SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003516 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003517SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003518#else
Steve Blocka7e24c12009-10-30 11:49:00 +00003519
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003520#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003521 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003522 int holder::name() { \
3523 int value = READ_INT_FIELD(this, offset); \
3524 ASSERT(kHeapObjectTag == 1); \
3525 ASSERT((value & kHeapObjectTag) == 0); \
3526 return value >> 1; \
3527 } \
3528 void holder::set_##name(int value) { \
3529 ASSERT(kHeapObjectTag == 1); \
3530 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3531 (value & 0xC0000000) == 0x000000000); \
3532 WRITE_INT_FIELD(this, \
3533 offset, \
3534 (value << 1) & ~kHeapObjectTag); \
3535 }
3536
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003537#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3538 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003539 INT_ACCESSORS(holder, name, offset)
3540
3541
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003542PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003543PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3544 formal_parameter_count,
3545 kFormalParameterCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003546
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003547PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3548 expected_nof_properties,
3549 kExpectedNofPropertiesOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003550PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3551
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003552PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3553PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3554 start_position_and_type,
3555 kStartPositionAndTypeOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003556
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003557PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3558 function_token_position,
3559 kFunctionTokenPositionOffset)
3560PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3561 compiler_hints,
3562 kCompilerHintsOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003563
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003564PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3565 this_property_assignments_count,
3566 kThisPropertyAssignmentsCountOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003567PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003568#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003569
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003570
3571int SharedFunctionInfo::construction_count() {
3572 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3573}
3574
3575
3576void SharedFunctionInfo::set_construction_count(int value) {
3577 ASSERT(0 <= value && value < 256);
3578 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3579}
3580
3581
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003582BOOL_ACCESSORS(SharedFunctionInfo,
3583 compiler_hints,
3584 live_objects_may_exist,
3585 kLiveObjectsMayExist)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003586
3587
3588bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
Ben Murdoch85b71792012-04-11 18:30:58 +01003589 return initial_map() != HEAP->undefined_value();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003590}
3591
3592
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003593BOOL_GETTER(SharedFunctionInfo,
3594 compiler_hints,
3595 optimization_disabled,
3596 kOptimizationDisabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003597
3598
3599void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3600 set_compiler_hints(BooleanBit::set(compiler_hints(),
3601 kOptimizationDisabled,
3602 disable));
3603 // If disabling optimizations we reflect that in the code object so
3604 // it will not be counted as optimizable code.
3605 if ((code()->kind() == Code::FUNCTION) && disable) {
3606 code()->set_optimizable(false);
3607 }
3608}
3609
3610
Ben Murdoch85b71792012-04-11 18:30:58 +01003611BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, strict_mode,
3612 kStrictModeFunction)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003613BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3614BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3615 name_should_print_as_anonymous,
3616 kNameShouldPrintAsAnonymous)
3617BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3618BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
Ben Murdoch257744e2011-11-30 15:57:28 +00003619
Steve Block6ded16b2010-05-10 14:33:55 +01003620ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3621ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3622
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003623ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3624
Steve Block3ce2e202009-11-05 08:53:23 +00003625bool Script::HasValidSource() {
3626 Object* src = this->source();
3627 if (!src->IsString()) return true;
3628 String* src_str = String::cast(src);
3629 if (!StringShape(src_str).IsExternal()) return true;
3630 if (src_str->IsAsciiRepresentation()) {
3631 return ExternalAsciiString::cast(src)->resource() != NULL;
3632 } else if (src_str->IsTwoByteRepresentation()) {
3633 return ExternalTwoByteString::cast(src)->resource() != NULL;
3634 }
3635 return true;
3636}
3637
3638
Steve Blocka7e24c12009-10-30 11:49:00 +00003639void SharedFunctionInfo::DontAdaptArguments() {
3640 ASSERT(code()->kind() == Code::BUILTIN);
3641 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3642}
3643
3644
3645int SharedFunctionInfo::start_position() {
3646 return start_position_and_type() >> kStartPositionShift;
3647}
3648
3649
3650void SharedFunctionInfo::set_start_position(int start_position) {
3651 set_start_position_and_type((start_position << kStartPositionShift)
3652 | (start_position_and_type() & ~kStartPositionMask));
3653}
3654
3655
3656Code* SharedFunctionInfo::code() {
3657 return Code::cast(READ_FIELD(this, kCodeOffset));
3658}
3659
3660
Iain Merrick75681382010-08-19 15:07:18 +01003661Code* SharedFunctionInfo::unchecked_code() {
3662 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3663}
3664
3665
Steve Blocka7e24c12009-10-30 11:49:00 +00003666void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3667 WRITE_FIELD(this, kCodeOffset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01003668 ASSERT(!Isolate::Current()->heap()->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00003669}
3670
3671
Ben Murdoch85b71792012-04-11 18:30:58 +01003672SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3673 return reinterpret_cast<SerializedScopeInfo*>(
3674 READ_FIELD(this, kScopeInfoOffset));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003675}
3676
3677
Ben Murdoch85b71792012-04-11 18:30:58 +01003678void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003679 WriteBarrierMode mode) {
3680 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
Ben Murdoch85b71792012-04-11 18:30:58 +01003681 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode);
3682}
3683
3684
3685Smi* SharedFunctionInfo::deopt_counter() {
3686 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3687}
3688
3689
3690void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3691 WRITE_FIELD(this, kDeoptCounterOffset, value);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003692}
3693
3694
Steve Blocka7e24c12009-10-30 11:49:00 +00003695bool SharedFunctionInfo::is_compiled() {
Steve Block44f0eee2011-05-26 01:26:41 +01003696 return code() !=
3697 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003698}
3699
3700
Steve Block6ded16b2010-05-10 14:33:55 +01003701bool SharedFunctionInfo::IsApiFunction() {
3702 return function_data()->IsFunctionTemplateInfo();
3703}
3704
3705
3706FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3707 ASSERT(IsApiFunction());
3708 return FunctionTemplateInfo::cast(function_data());
3709}
3710
3711
Ben Murdochb0fe1622011-05-05 13:52:32 +01003712bool SharedFunctionInfo::HasBuiltinFunctionId() {
Kristian Monsen25f61362010-05-21 11:50:48 +01003713 return function_data()->IsSmi();
3714}
3715
3716
Ben Murdochb0fe1622011-05-05 13:52:32 +01003717BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3718 ASSERT(HasBuiltinFunctionId());
3719 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003720}
3721
3722
Iain Merrick75681382010-08-19 15:07:18 +01003723int SharedFunctionInfo::code_age() {
3724 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3725}
3726
3727
3728void SharedFunctionInfo::set_code_age(int code_age) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003729 set_compiler_hints(compiler_hints() |
3730 ((code_age & kCodeAgeMask) << kCodeAgeShift));
Iain Merrick75681382010-08-19 15:07:18 +01003731}
3732
3733
Ben Murdochb0fe1622011-05-05 13:52:32 +01003734bool SharedFunctionInfo::has_deoptimization_support() {
3735 Code* code = this->code();
3736 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3737}
3738
3739
Steve Blocka7e24c12009-10-30 11:49:00 +00003740bool JSFunction::IsBuiltin() {
3741 return context()->global()->IsJSBuiltinsObject();
3742}
3743
3744
Ben Murdochb0fe1622011-05-05 13:52:32 +01003745bool JSFunction::NeedsArgumentsAdaption() {
3746 return shared()->formal_parameter_count() !=
3747 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3748}
3749
3750
3751bool JSFunction::IsOptimized() {
3752 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3753}
3754
3755
Ben Murdoch8b112d22011-06-08 16:22:53 +01003756bool JSFunction::IsOptimizable() {
3757 return code()->kind() == Code::FUNCTION && code()->optimizable();
3758}
3759
3760
Ben Murdochb0fe1622011-05-05 13:52:32 +01003761bool JSFunction::IsMarkedForLazyRecompilation() {
Steve Block44f0eee2011-05-26 01:26:41 +01003762 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003763}
3764
3765
Steve Blocka7e24c12009-10-30 11:49:00 +00003766Code* JSFunction::code() {
Steve Block791712a2010-08-27 10:21:07 +01003767 return Code::cast(unchecked_code());
Iain Merrick75681382010-08-19 15:07:18 +01003768}
3769
3770
3771Code* JSFunction::unchecked_code() {
Steve Block791712a2010-08-27 10:21:07 +01003772 return reinterpret_cast<Code*>(
3773 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003774}
3775
3776
3777void JSFunction::set_code(Code* value) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003778 // Skip the write barrier because code is never in new space.
Steve Block44f0eee2011-05-26 01:26:41 +01003779 ASSERT(!HEAP->InNewSpace(value));
Steve Block791712a2010-08-27 10:21:07 +01003780 Address entry = value->entry();
3781 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
Steve Blocka7e24c12009-10-30 11:49:00 +00003782}
3783
3784
Ben Murdochb0fe1622011-05-05 13:52:32 +01003785void JSFunction::ReplaceCode(Code* code) {
3786 bool was_optimized = IsOptimized();
3787 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3788
3789 set_code(code);
3790
3791 // Add/remove the function from the list of optimized functions for this
3792 // context based on the state change.
3793 if (!was_optimized && is_optimized) {
3794 context()->global_context()->AddOptimizedFunction(this);
3795 }
3796 if (was_optimized && !is_optimized) {
3797 context()->global_context()->RemoveOptimizedFunction(this);
3798 }
3799}
3800
3801
Steve Blocka7e24c12009-10-30 11:49:00 +00003802Context* JSFunction::context() {
3803 return Context::cast(READ_FIELD(this, kContextOffset));
3804}
3805
3806
3807Object* JSFunction::unchecked_context() {
3808 return READ_FIELD(this, kContextOffset);
3809}
3810
3811
Iain Merrick75681382010-08-19 15:07:18 +01003812SharedFunctionInfo* JSFunction::unchecked_shared() {
3813 return reinterpret_cast<SharedFunctionInfo*>(
3814 READ_FIELD(this, kSharedFunctionInfoOffset));
3815}
3816
3817
Steve Blocka7e24c12009-10-30 11:49:00 +00003818void JSFunction::set_context(Object* value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003819 ASSERT(value->IsUndefined() || value->IsContext());
Steve Blocka7e24c12009-10-30 11:49:00 +00003820 WRITE_FIELD(this, kContextOffset, value);
Ben Murdoch85b71792012-04-11 18:30:58 +01003821 WRITE_BARRIER(this, kContextOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00003822}
3823
3824ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3825 kPrototypeOrInitialMapOffset)
3826
3827
3828Map* JSFunction::initial_map() {
3829 return Map::cast(prototype_or_initial_map());
3830}
3831
3832
3833void JSFunction::set_initial_map(Map* value) {
3834 set_prototype_or_initial_map(value);
3835}
3836
3837
3838bool JSFunction::has_initial_map() {
3839 return prototype_or_initial_map()->IsMap();
3840}
3841
3842
3843bool JSFunction::has_instance_prototype() {
3844 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3845}
3846
3847
3848bool JSFunction::has_prototype() {
3849 return map()->has_non_instance_prototype() || has_instance_prototype();
3850}
3851
3852
3853Object* JSFunction::instance_prototype() {
3854 ASSERT(has_instance_prototype());
3855 if (has_initial_map()) return initial_map()->prototype();
3856 // When there is no initial map and the prototype is a JSObject, the
3857 // initial map field is used for the prototype field.
3858 return prototype_or_initial_map();
3859}
3860
3861
3862Object* JSFunction::prototype() {
3863 ASSERT(has_prototype());
3864 // If the function's prototype property has been set to a non-JSObject
3865 // value, that value is stored in the constructor field of the map.
3866 if (map()->has_non_instance_prototype()) return map()->constructor();
3867 return instance_prototype();
3868}
3869
Steve Block6ded16b2010-05-10 14:33:55 +01003870bool JSFunction::should_have_prototype() {
3871 return map()->function_with_prototype();
3872}
3873
Steve Blocka7e24c12009-10-30 11:49:00 +00003874
3875bool JSFunction::is_compiled() {
Steve Block44f0eee2011-05-26 01:26:41 +01003876 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
Steve Blocka7e24c12009-10-30 11:49:00 +00003877}
3878
3879
3880int JSFunction::NumberOfLiterals() {
3881 return literals()->length();
3882}
3883
3884
3885Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003886 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01003887 return READ_FIELD(this, OffsetOfFunctionWithId(id));
Steve Blocka7e24c12009-10-30 11:49:00 +00003888}
3889
3890
3891void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3892 Object* value) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003893 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01003894 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
Ben Murdoch85b71792012-04-11 18:30:58 +01003895 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
Steve Block6ded16b2010-05-10 14:33:55 +01003896}
3897
3898
3899Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003900 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01003901 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3902}
3903
3904
3905void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3906 Code* value) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003907 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01003908 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
Steve Block44f0eee2011-05-26 01:26:41 +01003909 ASSERT(!HEAP->InNewSpace(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00003910}
3911
3912
Ben Murdoch257744e2011-11-30 15:57:28 +00003913ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
Ben Murdoch589d6972011-11-30 16:04:58 +00003914ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
3915ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
3916
3917
3918void JSProxy::InitializeBody(int object_size, Object* value) {
3919 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
3920 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
3921 WRITE_FIELD(this, offset, value);
3922 }
3923}
Ben Murdoch257744e2011-11-30 15:57:28 +00003924
3925
Ben Murdoch85b71792012-04-11 18:30:58 +01003926ACCESSORS(JSWeakMap, table, ObjectHashTable, kTableOffset)
3927ACCESSORS_GCSAFE(JSWeakMap, next, Object, kNextOffset)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003928
3929
Ben Murdoch85b71792012-04-11 18:30:58 +01003930ObjectHashTable* JSWeakMap::unchecked_table() {
3931 return reinterpret_cast<ObjectHashTable*>(READ_FIELD(this, kTableOffset));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003932}
3933
3934
Ben Murdoch85b71792012-04-11 18:30:58 +01003935Address Foreign::address() {
3936 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kAddressOffset));
3937}
3938
3939
3940void Foreign::set_address(Address value) {
3941 WRITE_INTPTR_FIELD(this, kAddressOffset, OffsetFrom(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00003942}
3943
3944
Steve Blocka7e24c12009-10-30 11:49:00 +00003945ACCESSORS(JSValue, value, Object, kValueOffset)
3946
3947
3948JSValue* JSValue::cast(Object* obj) {
3949 ASSERT(obj->IsJSValue());
3950 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3951 return reinterpret_cast<JSValue*>(obj);
3952}
3953
3954
Steve Block1e0659c2011-05-24 12:43:12 +01003955ACCESSORS(JSMessageObject, type, String, kTypeOffset)
3956ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
3957ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
3958ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
3959ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
3960SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
3961SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
3962
3963
3964JSMessageObject* JSMessageObject::cast(Object* obj) {
3965 ASSERT(obj->IsJSMessageObject());
3966 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
3967 return reinterpret_cast<JSMessageObject*>(obj);
3968}
3969
3970
Steve Blocka7e24c12009-10-30 11:49:00 +00003971INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
Leon Clarkeac952652010-07-15 11:15:24 +01003972ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003973ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
Ben Murdoch85b71792012-04-11 18:30:58 +01003974ACCESSORS(Code, next_code_flushing_candidate,
3975 Object, kNextCodeFlushingCandidateOffset)
3976
Steve Blocka7e24c12009-10-30 11:49:00 +00003977
3978byte* Code::instruction_start() {
3979 return FIELD_ADDR(this, kHeaderSize);
3980}
3981
3982
Leon Clarkeac952652010-07-15 11:15:24 +01003983byte* Code::instruction_end() {
3984 return instruction_start() + instruction_size();
3985}
3986
3987
Steve Blocka7e24c12009-10-30 11:49:00 +00003988int Code::body_size() {
Leon Clarkeac952652010-07-15 11:15:24 +01003989 return RoundUp(instruction_size(), kObjectAlignment);
3990}
3991
3992
Ben Murdochb0fe1622011-05-05 13:52:32 +01003993FixedArray* Code::unchecked_deoptimization_data() {
3994 return reinterpret_cast<FixedArray*>(
3995 READ_FIELD(this, kDeoptimizationDataOffset));
3996}
3997
3998
Leon Clarkeac952652010-07-15 11:15:24 +01003999ByteArray* Code::unchecked_relocation_info() {
4000 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +00004001}
4002
4003
4004byte* Code::relocation_start() {
Leon Clarkeac952652010-07-15 11:15:24 +01004005 return unchecked_relocation_info()->GetDataStartAddress();
4006}
4007
4008
4009int Code::relocation_size() {
4010 return unchecked_relocation_info()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00004011}
4012
4013
4014byte* Code::entry() {
4015 return instruction_start();
4016}
4017
4018
Ben Murdoch85b71792012-04-11 18:30:58 +01004019bool Code::contains(byte* pc) {
4020 return (instruction_start() <= pc) &&
4021 (pc <= instruction_start() + instruction_size());
Steve Blocka7e24c12009-10-30 11:49:00 +00004022}
4023
4024
Steve Blocka7e24c12009-10-30 11:49:00 +00004025ACCESSORS(JSArray, length, Object, kLengthOffset)
4026
4027
4028ACCESSORS(JSRegExp, data, Object, kDataOffset)
4029
4030
4031JSRegExp::Type JSRegExp::TypeTag() {
4032 Object* data = this->data();
4033 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
4034 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
4035 return static_cast<JSRegExp::Type>(smi->value());
4036}
4037
4038
Ben Murdoch257744e2011-11-30 15:57:28 +00004039JSRegExp::Type JSRegExp::TypeTagUnchecked() {
4040 Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
4041 return static_cast<JSRegExp::Type>(smi->value());
4042}
4043
4044
Steve Blocka7e24c12009-10-30 11:49:00 +00004045int JSRegExp::CaptureCount() {
4046 switch (TypeTag()) {
4047 case ATOM:
4048 return 0;
4049 case IRREGEXP:
4050 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
4051 default:
4052 UNREACHABLE();
4053 return -1;
4054 }
4055}
4056
4057
4058JSRegExp::Flags JSRegExp::GetFlags() {
4059 ASSERT(this->data()->IsFixedArray());
4060 Object* data = this->data();
4061 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
4062 return Flags(smi->value());
4063}
4064
4065
4066String* JSRegExp::Pattern() {
4067 ASSERT(this->data()->IsFixedArray());
4068 Object* data = this->data();
4069 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4070 return pattern;
4071}
4072
4073
4074Object* JSRegExp::DataAt(int index) {
4075 ASSERT(TypeTag() != NOT_COMPILED);
4076 return FixedArray::cast(data())->get(index);
4077}
4078
4079
Ben Murdoch257744e2011-11-30 15:57:28 +00004080Object* JSRegExp::DataAtUnchecked(int index) {
4081 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4082 int offset = FixedArray::kHeaderSize + index * kPointerSize;
4083 return READ_FIELD(fa, offset);
4084}
4085
4086
Steve Blocka7e24c12009-10-30 11:49:00 +00004087void JSRegExp::SetDataAt(int index, Object* value) {
4088 ASSERT(TypeTag() != NOT_COMPILED);
4089 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4090 FixedArray::cast(data())->set(index, value);
4091}
4092
4093
Ben Murdoch257744e2011-11-30 15:57:28 +00004094void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4095 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4096 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4097 if (value->IsSmi()) {
4098 fa->set_unchecked(index, Smi::cast(value));
4099 } else {
4100 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4101 }
4102}
4103
4104
Ben Murdoch589d6972011-11-30 16:04:58 +00004105ElementsKind JSObject::GetElementsKind() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004106 ElementsKind kind = map()->elements_kind();
Ben Murdoch85b71792012-04-11 18:30:58 +01004107 ASSERT((kind == FAST_ELEMENTS &&
4108 (elements()->map() == GetHeap()->fixed_array_map() ||
4109 elements()->map() == GetHeap()->fixed_cow_array_map())) ||
4110 (kind == FAST_DOUBLE_ELEMENTS &&
4111 elements()->IsFixedDoubleArray()) ||
4112 (kind == DICTIONARY_ELEMENTS &&
4113 elements()->IsFixedArray() &&
4114 elements()->IsDictionary()) ||
4115 (kind > DICTIONARY_ELEMENTS));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004116 return kind;
Steve Blocka7e24c12009-10-30 11:49:00 +00004117}
4118
4119
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004120ElementsAccessor* JSObject::GetElementsAccessor() {
4121 return ElementsAccessor::ForKind(GetElementsKind());
4122}
4123
4124
Steve Blocka7e24c12009-10-30 11:49:00 +00004125bool JSObject::HasFastElements() {
4126 return GetElementsKind() == FAST_ELEMENTS;
4127}
4128
4129
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004130bool JSObject::HasFastDoubleElements() {
4131 return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4132}
4133
4134
Steve Blocka7e24c12009-10-30 11:49:00 +00004135bool JSObject::HasDictionaryElements() {
4136 return GetElementsKind() == DICTIONARY_ELEMENTS;
4137}
4138
4139
Steve Block3ce2e202009-11-05 08:53:23 +00004140bool JSObject::HasExternalArrayElements() {
Steve Block44f0eee2011-05-26 01:26:41 +01004141 HeapObject* array = elements();
4142 ASSERT(array != NULL);
4143 return array->IsExternalArray();
Steve Block3ce2e202009-11-05 08:53:23 +00004144}
4145
4146
Steve Block44f0eee2011-05-26 01:26:41 +01004147#define EXTERNAL_ELEMENTS_CHECK(name, type) \
4148bool JSObject::HasExternal##name##Elements() { \
4149 HeapObject* array = elements(); \
4150 ASSERT(array != NULL); \
4151 if (!array->IsHeapObject()) \
4152 return false; \
4153 return array->map()->instance_type() == type; \
Steve Block3ce2e202009-11-05 08:53:23 +00004154}
4155
4156
Steve Block44f0eee2011-05-26 01:26:41 +01004157EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4158EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4159EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4160EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4161 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4162EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4163EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4164 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4165EXTERNAL_ELEMENTS_CHECK(Float,
4166 EXTERNAL_FLOAT_ARRAY_TYPE)
Ben Murdoch257744e2011-11-30 15:57:28 +00004167EXTERNAL_ELEMENTS_CHECK(Double,
4168 EXTERNAL_DOUBLE_ARRAY_TYPE)
Steve Block44f0eee2011-05-26 01:26:41 +01004169EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
Steve Block3ce2e202009-11-05 08:53:23 +00004170
4171
Steve Blocka7e24c12009-10-30 11:49:00 +00004172bool JSObject::HasNamedInterceptor() {
4173 return map()->has_named_interceptor();
4174}
4175
4176
4177bool JSObject::HasIndexedInterceptor() {
4178 return map()->has_indexed_interceptor();
4179}
4180
4181
Ben Murdoch85b71792012-04-11 18:30:58 +01004182bool JSObject::AllowsSetElementsLength() {
4183 bool result = elements()->IsFixedArray() ||
4184 elements()->IsFixedDoubleArray();
4185 ASSERT(result == !HasExternalArrayElements());
4186 return result;
4187}
4188
4189
John Reck59135872010-11-02 12:39:01 -07004190MaybeObject* JSObject::EnsureWritableFastElements() {
Ben Murdoch85b71792012-04-11 18:30:58 +01004191 ASSERT(HasFastElements());
Iain Merrick75681382010-08-19 15:07:18 +01004192 FixedArray* elems = FixedArray::cast(elements());
Steve Block44f0eee2011-05-26 01:26:41 +01004193 Isolate* isolate = GetIsolate();
4194 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
John Reck59135872010-11-02 12:39:01 -07004195 Object* writable_elems;
Steve Block44f0eee2011-05-26 01:26:41 +01004196 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4197 elems, isolate->heap()->fixed_array_map());
John Reck59135872010-11-02 12:39:01 -07004198 if (!maybe_writable_elems->ToObject(&writable_elems)) {
4199 return maybe_writable_elems;
4200 }
4201 }
Iain Merrick75681382010-08-19 15:07:18 +01004202 set_elements(FixedArray::cast(writable_elems));
Steve Block44f0eee2011-05-26 01:26:41 +01004203 isolate->counters()->cow_arrays_converted()->Increment();
Iain Merrick75681382010-08-19 15:07:18 +01004204 return writable_elems;
4205}
4206
4207
Steve Blocka7e24c12009-10-30 11:49:00 +00004208StringDictionary* JSObject::property_dictionary() {
4209 ASSERT(!HasFastProperties());
4210 return StringDictionary::cast(properties());
4211}
4212
4213
Ben Murdochc7cc0282012-03-05 14:35:55 +00004214SeededNumberDictionary* JSObject::element_dictionary() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004215 ASSERT(HasDictionaryElements());
Ben Murdochc7cc0282012-03-05 14:35:55 +00004216 return SeededNumberDictionary::cast(elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00004217}
4218
4219
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004220bool String::IsHashFieldComputed(uint32_t field) {
4221 return (field & kHashNotComputedMask) == 0;
4222}
4223
4224
Steve Blocka7e24c12009-10-30 11:49:00 +00004225bool String::HasHashCode() {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004226 return IsHashFieldComputed(hash_field());
Steve Blocka7e24c12009-10-30 11:49:00 +00004227}
4228
4229
4230uint32_t String::Hash() {
4231 // Fast case: has hash code already been computed?
Steve Blockd0582a62009-12-15 09:54:21 +00004232 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004233 if (IsHashFieldComputed(field)) return field >> kHashShift;
Steve Blocka7e24c12009-10-30 11:49:00 +00004234 // Slow case: compute hash code and set it.
4235 return ComputeAndSetHash();
4236}
4237
4238
Ben Murdochc7cc0282012-03-05 14:35:55 +00004239StringHasher::StringHasher(int length, uint32_t seed)
Steve Blocka7e24c12009-10-30 11:49:00 +00004240 : length_(length),
Ben Murdochc7cc0282012-03-05 14:35:55 +00004241 raw_running_hash_(seed),
Steve Blocka7e24c12009-10-30 11:49:00 +00004242 array_index_(0),
4243 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4244 is_first_char_(true),
Ben Murdochc7cc0282012-03-05 14:35:55 +00004245 is_valid_(true) {
4246 ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
4247}
Steve Blocka7e24c12009-10-30 11:49:00 +00004248
4249
4250bool StringHasher::has_trivial_hash() {
Steve Blockd0582a62009-12-15 09:54:21 +00004251 return length_ > String::kMaxHashCalcLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00004252}
4253
4254
Ben Murdoch85b71792012-04-11 18:30:58 +01004255void StringHasher::AddCharacter(uc32 c) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004256 // Use the Jenkins one-at-a-time hash function to update the hash
4257 // for the given character.
4258 raw_running_hash_ += c;
4259 raw_running_hash_ += (raw_running_hash_ << 10);
4260 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4261 // Incremental array index computation.
4262 if (is_array_index_) {
4263 if (c < '0' || c > '9') {
4264 is_array_index_ = false;
4265 } else {
4266 int d = c - '0';
4267 if (is_first_char_) {
4268 is_first_char_ = false;
4269 if (c == '0' && length_ > 1) {
4270 is_array_index_ = false;
4271 return;
4272 }
4273 }
4274 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4275 is_array_index_ = false;
4276 } else {
4277 array_index_ = array_index_ * 10 + d;
4278 }
4279 }
4280 }
4281}
4282
4283
Ben Murdoch85b71792012-04-11 18:30:58 +01004284void StringHasher::AddCharacterNoIndex(uc32 c) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004285 ASSERT(!is_array_index());
4286 raw_running_hash_ += c;
4287 raw_running_hash_ += (raw_running_hash_ << 10);
4288 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4289}
4290
4291
4292uint32_t StringHasher::GetHash() {
4293 // Get the calculated raw hash value and do some more bit ops to distribute
4294 // the hash further. Ensure that we never return zero as the hash value.
4295 uint32_t result = raw_running_hash_;
4296 result += (result << 3);
4297 result ^= (result >> 11);
4298 result += (result << 15);
Ben Murdochc7cc0282012-03-05 14:35:55 +00004299 if ((result & String::kHashBitMask) == 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004300 result = 27;
4301 }
4302 return result;
4303}
4304
4305
Steve Block44f0eee2011-05-26 01:26:41 +01004306template <typename schar>
Ben Murdochc7cc0282012-03-05 14:35:55 +00004307uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) {
4308 StringHasher hasher(length, seed);
Steve Block44f0eee2011-05-26 01:26:41 +01004309 if (!hasher.has_trivial_hash()) {
4310 int i;
4311 for (i = 0; hasher.is_array_index() && (i < length); i++) {
4312 hasher.AddCharacter(chars[i]);
4313 }
4314 for (; i < length; i++) {
4315 hasher.AddCharacterNoIndex(chars[i]);
4316 }
4317 }
4318 return hasher.GetHashField();
4319}
4320
4321
Steve Blocka7e24c12009-10-30 11:49:00 +00004322bool String::AsArrayIndex(uint32_t* index) {
Steve Blockd0582a62009-12-15 09:54:21 +00004323 uint32_t field = hash_field();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004324 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4325 return false;
4326 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004327 return SlowAsArrayIndex(index);
4328}
4329
4330
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004331Object* JSReceiver::GetPrototype() {
4332 return HeapObject::cast(this)->map()->prototype();
Steve Blocka7e24c12009-10-30 11:49:00 +00004333}
4334
4335
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004336bool JSReceiver::HasProperty(String* name) {
4337 if (IsJSProxy()) {
4338 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4339 }
4340 return GetPropertyAttribute(name) != ABSENT;
4341}
4342
4343
4344bool JSReceiver::HasLocalProperty(String* name) {
4345 if (IsJSProxy()) {
4346 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4347 }
4348 return GetLocalPropertyAttribute(name) != ABSENT;
4349}
4350
4351
4352PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004353 return GetPropertyAttributeWithReceiver(this, key);
4354}
4355
Steve Blockd0582a62009-12-15 09:54:21 +00004356// TODO(504): this may be useful in other places too where JSGlobalProxy
4357// is used.
4358Object* JSObject::BypassGlobalProxy() {
4359 if (IsJSGlobalProxy()) {
4360 Object* proto = GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01004361 if (proto->IsNull()) return GetHeap()->undefined_value();
Steve Blockd0582a62009-12-15 09:54:21 +00004362 ASSERT(proto->IsJSGlobalObject());
4363 return proto;
4364 }
4365 return this;
4366}
4367
4368
Ben Murdoch85b71792012-04-11 18:30:58 +01004369bool JSObject::HasHiddenPropertiesObject() {
4370 ASSERT(!IsJSGlobalProxy());
4371 return GetPropertyAttributePostInterceptor(this,
4372 GetHeap()->hidden_symbol(),
4373 false) != ABSENT;
Steve Blockd0582a62009-12-15 09:54:21 +00004374}
4375
4376
Ben Murdoch85b71792012-04-11 18:30:58 +01004377Object* JSObject::GetHiddenPropertiesObject() {
4378 ASSERT(!IsJSGlobalProxy());
4379 PropertyAttributes attributes;
4380 // You can't install a getter on a property indexed by the hidden symbol,
4381 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
4382 // object.
4383 Object* result =
4384 GetLocalPropertyPostInterceptor(this,
4385 GetHeap()->hidden_symbol(),
4386 &attributes)->ToObjectUnchecked();
4387 return result;
4388}
4389
4390
4391MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
4392 ASSERT(!IsJSGlobalProxy());
4393 return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
4394 hidden_obj,
4395 DONT_ENUM,
4396 kNonStrictMode);
4397}
4398
4399
4400bool JSObject::HasHiddenProperties() {
4401 return !GetHiddenProperties(OMIT_CREATION)->ToObjectChecked()->IsUndefined();
4402}
4403
4404
4405bool JSObject::HasElement(uint32_t index) {
4406 return HasElementWithReceiver(this, index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004407}
4408
4409
4410bool AccessorInfo::all_can_read() {
4411 return BooleanBit::get(flag(), kAllCanReadBit);
4412}
4413
4414
4415void AccessorInfo::set_all_can_read(bool value) {
4416 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4417}
4418
4419
4420bool AccessorInfo::all_can_write() {
4421 return BooleanBit::get(flag(), kAllCanWriteBit);
4422}
4423
4424
4425void AccessorInfo::set_all_can_write(bool value) {
4426 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4427}
4428
4429
4430bool AccessorInfo::prohibits_overwriting() {
4431 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4432}
4433
4434
4435void AccessorInfo::set_prohibits_overwriting(bool value) {
4436 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4437}
4438
4439
4440PropertyAttributes AccessorInfo::property_attributes() {
4441 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4442}
4443
4444
4445void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004446 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
Steve Blocka7e24c12009-10-30 11:49:00 +00004447}
4448
Ben Murdoch8b112d22011-06-08 16:22:53 +01004449
4450template<typename Shape, typename Key>
4451void Dictionary<Shape, Key>::SetEntry(int entry,
4452 Object* key,
4453 Object* value) {
4454 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4455}
4456
4457
Steve Blocka7e24c12009-10-30 11:49:00 +00004458template<typename Shape, typename Key>
4459void Dictionary<Shape, Key>::SetEntry(int entry,
4460 Object* key,
4461 Object* value,
4462 PropertyDetails details) {
4463 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4464 int index = HashTable<Shape, Key>::EntryToIndex(entry);
Leon Clarke4515c472010-02-03 11:58:03 +00004465 AssertNoAllocation no_gc;
4466 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +00004467 FixedArray::set(index, key, mode);
4468 FixedArray::set(index+1, value, mode);
Ben Murdoch85b71792012-04-11 18:30:58 +01004469 FixedArray::fast_set(this, index+2, details.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00004470}
4471
4472
Steve Block44f0eee2011-05-26 01:26:41 +01004473bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4474 ASSERT(other->IsNumber());
4475 return key == static_cast<uint32_t>(other->Number());
4476}
4477
4478
Ben Murdochc7cc0282012-03-05 14:35:55 +00004479uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
4480 return ComputeIntegerHash(key, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01004481}
4482
4483
Ben Murdochc7cc0282012-03-05 14:35:55 +00004484uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
4485 Object* other) {
Steve Block44f0eee2011-05-26 01:26:41 +01004486 ASSERT(other->IsNumber());
Ben Murdochc7cc0282012-03-05 14:35:55 +00004487 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
Steve Block44f0eee2011-05-26 01:26:41 +01004488}
4489
Ben Murdochc7cc0282012-03-05 14:35:55 +00004490uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
4491 return ComputeIntegerHash(key, seed);
4492}
4493
4494uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
4495 uint32_t seed,
4496 Object* other) {
4497 ASSERT(other->IsNumber());
4498 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
4499}
Steve Block44f0eee2011-05-26 01:26:41 +01004500
4501MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4502 return Isolate::Current()->heap()->NumberFromUint32(key);
4503}
4504
4505
4506bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4507 // We know that all entries in a hash table had their hash keys created.
4508 // Use that knowledge to have fast failure.
4509 if (key->Hash() != String::cast(other)->Hash()) return false;
4510 return key->Equals(String::cast(other));
4511}
4512
4513
4514uint32_t StringDictionaryShape::Hash(String* key) {
4515 return key->Hash();
4516}
4517
4518
4519uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4520 return String::cast(other)->Hash();
4521}
4522
4523
4524MaybeObject* StringDictionaryShape::AsObject(String* key) {
4525 return key;
4526}
4527
4528
Ben Murdoch85b71792012-04-11 18:30:58 +01004529bool ObjectHashTableShape::IsMatch(JSObject* key, Object* other) {
4530 return key == JSObject::cast(other);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004531}
4532
4533
Ben Murdoch85b71792012-04-11 18:30:58 +01004534uint32_t ObjectHashTableShape::Hash(JSObject* key) {
4535 MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION);
4536 ASSERT(!maybe_hash->IsFailure());
4537 return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004538}
4539
4540
Ben Murdoch85b71792012-04-11 18:30:58 +01004541uint32_t ObjectHashTableShape::HashForObject(JSObject* key, Object* other) {
4542 MaybeObject* maybe_hash = JSObject::cast(other)->GetIdentityHash(
4543 JSObject::OMIT_CREATION);
4544 ASSERT(!maybe_hash->IsFailure());
4545 return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004546}
4547
4548
Ben Murdoch85b71792012-04-11 18:30:58 +01004549MaybeObject* ObjectHashTableShape::AsObject(JSObject* key) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004550 return key;
4551}
4552
4553
Ben Murdoch85b71792012-04-11 18:30:58 +01004554void ObjectHashTable::RemoveEntry(int entry) {
4555 RemoveEntry(entry, GetHeap());
4556}
4557
4558
Steve Block44f0eee2011-05-26 01:26:41 +01004559void Map::ClearCodeCache(Heap* heap) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004560 // No write barrier is needed since empty_fixed_array is not in new space.
4561 // Please note this function is used during marking:
4562 // - MarkCompactCollector::MarkUnmarkedObject
Steve Block44f0eee2011-05-26 01:26:41 +01004563 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4564 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
Steve Blocka7e24c12009-10-30 11:49:00 +00004565}
4566
4567
4568void JSArray::EnsureSize(int required_size) {
Ben Murdoch85b71792012-04-11 18:30:58 +01004569 ASSERT(HasFastElements());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004570 FixedArray* elts = FixedArray::cast(elements());
Steve Blockd0582a62009-12-15 09:54:21 +00004571 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4572 if (elts->length() < required_size) {
4573 // Doubling in size would be overkill, but leave some slack to avoid
4574 // constantly growing.
4575 Expand(required_size + (required_size >> 3));
4576 // It's a performance benefit to keep a frequently used array in new-space.
Steve Block44f0eee2011-05-26 01:26:41 +01004577 } else if (!GetHeap()->new_space()->Contains(elts) &&
Steve Blockd0582a62009-12-15 09:54:21 +00004578 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4579 // Expand will allocate a new backing store in new space even if the size
4580 // we asked for isn't larger than what we had before.
4581 Expand(required_size);
4582 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004583}
4584
4585
Leon Clarke4515c472010-02-03 11:58:03 +00004586void JSArray::set_length(Smi* length) {
4587 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4588}
4589
4590
Ben Murdoch85b71792012-04-11 18:30:58 +01004591void JSArray::SetContent(FixedArray* storage) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00004592 set_length(Smi::FromInt(storage->length()));
Ben Murdoch85b71792012-04-11 18:30:58 +01004593 set_elements(storage);
Steve Blocka7e24c12009-10-30 11:49:00 +00004594}
4595
4596
John Reck59135872010-11-02 12:39:01 -07004597MaybeObject* FixedArray::Copy() {
Steve Blocka7e24c12009-10-30 11:49:00 +00004598 if (length() == 0) return this;
Steve Block44f0eee2011-05-26 01:26:41 +01004599 return GetHeap()->CopyFixedArray(this);
4600}
4601
4602
4603Relocatable::Relocatable(Isolate* isolate) {
4604 ASSERT(isolate == Isolate::Current());
4605 isolate_ = isolate;
4606 prev_ = isolate->relocatable_top();
4607 isolate->set_relocatable_top(this);
4608}
4609
4610
4611Relocatable::~Relocatable() {
4612 ASSERT(isolate_ == Isolate::Current());
4613 ASSERT_EQ(isolate_->relocatable_top(), this);
4614 isolate_->set_relocatable_top(prev_);
Steve Blocka7e24c12009-10-30 11:49:00 +00004615}
4616
4617
Iain Merrick75681382010-08-19 15:07:18 +01004618int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4619 return map->instance_size();
4620}
4621
4622
Ben Murdoch257744e2011-11-30 15:57:28 +00004623void Foreign::ForeignIterateBody(ObjectVisitor* v) {
Iain Merrick75681382010-08-19 15:07:18 +01004624 v->VisitExternalReference(
Ben Murdoch85b71792012-04-11 18:30:58 +01004625 reinterpret_cast<Address *>(FIELD_ADDR(this, kAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01004626}
4627
4628
4629template<typename StaticVisitor>
Ben Murdoch257744e2011-11-30 15:57:28 +00004630void Foreign::ForeignIterateBody() {
Iain Merrick75681382010-08-19 15:07:18 +01004631 StaticVisitor::VisitExternalReference(
Ben Murdoch85b71792012-04-11 18:30:58 +01004632 reinterpret_cast<Address *>(FIELD_ADDR(this, kAddressOffset)));
Iain Merrick75681382010-08-19 15:07:18 +01004633}
4634
4635
4636void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4637 typedef v8::String::ExternalAsciiStringResource Resource;
4638 v->VisitExternalAsciiString(
4639 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4640}
4641
4642
4643template<typename StaticVisitor>
4644void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4645 typedef v8::String::ExternalAsciiStringResource Resource;
4646 StaticVisitor::VisitExternalAsciiString(
4647 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4648}
4649
4650
4651void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4652 typedef v8::String::ExternalStringResource Resource;
4653 v->VisitExternalTwoByteString(
4654 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4655}
4656
4657
4658template<typename StaticVisitor>
4659void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4660 typedef v8::String::ExternalStringResource Resource;
4661 StaticVisitor::VisitExternalTwoByteString(
4662 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4663}
4664
4665#define SLOT_ADDR(obj, offset) \
4666 reinterpret_cast<Object**>((obj)->address() + offset)
4667
4668template<int start_offset, int end_offset, int size>
4669void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4670 HeapObject* obj,
4671 ObjectVisitor* v) {
4672 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4673}
4674
4675
4676template<int start_offset>
4677void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4678 int object_size,
4679 ObjectVisitor* v) {
4680 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4681}
4682
4683#undef SLOT_ADDR
4684
Ben Murdoch85b71792012-04-11 18:30:58 +01004685
Steve Blocka7e24c12009-10-30 11:49:00 +00004686#undef CAST_ACCESSOR
4687#undef INT_ACCESSORS
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01004688#undef SMI_ACCESSORS
Ben Murdoch85b71792012-04-11 18:30:58 +01004689#undef ACCESSORS
Steve Blocka7e24c12009-10-30 11:49:00 +00004690#undef FIELD_ADDR
4691#undef READ_FIELD
4692#undef WRITE_FIELD
4693#undef WRITE_BARRIER
4694#undef CONDITIONAL_WRITE_BARRIER
Ben Murdoch85b71792012-04-11 18:30:58 +01004695#undef READ_MEMADDR_FIELD
4696#undef WRITE_MEMADDR_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00004697#undef READ_DOUBLE_FIELD
4698#undef WRITE_DOUBLE_FIELD
4699#undef READ_INT_FIELD
4700#undef WRITE_INT_FIELD
Steve Blocka7e24c12009-10-30 11:49:00 +00004701#undef READ_SHORT_FIELD
4702#undef WRITE_SHORT_FIELD
4703#undef READ_BYTE_FIELD
4704#undef WRITE_BYTE_FIELD
4705
4706
4707} } // namespace v8::internal
4708
4709#endif // V8_OBJECTS_INL_H_