blob: 793591247834f4dc82ec0802944837b184c66788 [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// Copyright 2010 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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//
ager@chromium.org32912102009-01-16 10:38:43 +000030// - The use of macros in these inline functions may seem superfluous
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000031// 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
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000038#include "objects.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#include "contexts.h"
40#include "conversions-inl.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000041#include "heap.h"
42#include "memory.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043#include "property.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000044#include "spaces.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
kasperl@chromium.org71affb52009-05-26 05:44:31 +000046namespace v8 {
47namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000048
49PropertyDetails::PropertyDetails(Smi* smi) {
50 value_ = smi->value();
51}
52
53
54Smi* PropertyDetails::AsSmi() {
55 return Smi::FromInt(value_);
56}
57
58
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000059PropertyDetails PropertyDetails::AsDeleted() {
60 PropertyDetails d(DONT_ENUM, NORMAL);
61 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
62 return PropertyDetails(smi);
63}
64
65
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066#define CAST_ACCESSOR(type) \
67 type* type::cast(Object* object) { \
68 ASSERT(object->Is##type()); \
69 return reinterpret_cast<type*>(object); \
70 }
71
72
73#define INT_ACCESSORS(holder, name, offset) \
74 int holder::name() { return READ_INT_FIELD(this, offset); } \
75 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
76
77
78#define ACCESSORS(holder, name, type, offset) \
79 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000080 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000081 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000082 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000083 }
84
85
86#define SMI_ACCESSORS(holder, name, offset) \
87 int holder::name() { \
88 Object* value = READ_FIELD(this, offset); \
89 return Smi::cast(value)->value(); \
90 } \
91 void holder::set_##name(int value) { \
92 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
93 }
94
95
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000096#define BOOL_GETTER(holder, field, name, offset) \
97 bool holder::name() { \
98 return BooleanBit::get(field(), offset); \
99 } \
100
101
102#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103 bool holder::name() { \
104 return BooleanBit::get(field(), offset); \
105 } \
106 void holder::set_##name(bool value) { \
107 set_##field(BooleanBit::set(field(), offset, value)); \
108 }
109
110
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000111bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
112 // There is a constraint on the object; check.
113 if (!this->IsJSObject()) return false;
114 // Fetch the constructor function of the object.
115 Object* cons_obj = JSObject::cast(this)->map()->constructor();
116 if (!cons_obj->IsJSFunction()) return false;
117 JSFunction* fun = JSFunction::cast(cons_obj);
118 // Iterate through the chain of inheriting function templates to
119 // see if the required one occurs.
120 for (Object* type = fun->shared()->function_data();
121 type->IsFunctionTemplateInfo();
122 type = FunctionTemplateInfo::cast(type)->parent_template()) {
123 if (type == expected) return true;
124 }
125 // Didn't find the required type in the inheritance chain.
126 return false;
127}
128
129
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130bool Object::IsSmi() {
131 return HAS_SMI_TAG(this);
132}
133
134
135bool Object::IsHeapObject() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000136 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000137}
138
139
140bool Object::IsHeapNumber() {
141 return Object::IsHeapObject()
142 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
143}
144
145
146bool Object::IsString() {
147 return Object::IsHeapObject()
148 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
149}
150
151
ager@chromium.org870a0b62008-11-04 11:43:05 +0000152bool Object::IsSymbol() {
153 if (!this->IsHeapObject()) return false;
154 uint32_t type = HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000155 // Because the symbol tag is non-zero and no non-string types have the
156 // symbol bit set we can test for symbols with a very simple test
157 // operation.
158 ASSERT(kSymbolTag != 0);
159 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
160 return (type & kIsSymbolMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161}
162
163
164bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000165 if (!this->IsHeapObject()) return false;
166 uint32_t type = HeapObject::cast(this)->map()->instance_type();
167 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
168 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169}
170
171
ager@chromium.org870a0b62008-11-04 11:43:05 +0000172bool Object::IsSeqString() {
173 if (!IsString()) return false;
174 return StringShape(String::cast(this)).IsSequential();
175}
176
177
178bool Object::IsSeqAsciiString() {
179 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000180 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000181 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000182}
183
184
185bool Object::IsSeqTwoByteString() {
186 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000187 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000188 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189}
190
191
192bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000193 if (!IsString()) return false;
194 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195}
196
197
198bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000199 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000200 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000201 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202}
203
204
205bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000206 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000207 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000208 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000209}
210
211
ager@chromium.org870a0b62008-11-04 11:43:05 +0000212StringShape::StringShape(String* str)
213 : type_(str->map()->instance_type()) {
214 set_valid();
215 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216}
217
218
ager@chromium.org870a0b62008-11-04 11:43:05 +0000219StringShape::StringShape(Map* map)
220 : type_(map->instance_type()) {
221 set_valid();
222 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223}
224
225
ager@chromium.org870a0b62008-11-04 11:43:05 +0000226StringShape::StringShape(InstanceType t)
227 : type_(static_cast<uint32_t>(t)) {
228 set_valid();
229 ASSERT((type_ & kIsNotStringMask) == kStringTag);
230}
231
232
233bool StringShape::IsSymbol() {
234 ASSERT(valid());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000235 ASSERT(kSymbolTag != 0);
236 return (type_ & kIsSymbolMask) != 0;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000237}
238
239
ager@chromium.org5ec48922009-05-05 07:25:34 +0000240bool String::IsAsciiRepresentation() {
241 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000242 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000243}
244
245
ager@chromium.org5ec48922009-05-05 07:25:34 +0000246bool String::IsTwoByteRepresentation() {
247 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000248 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000249}
250
251
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000252bool String::HasOnlyAsciiChars() {
253 uint32_t type = map()->instance_type();
254 return (type & kStringEncodingMask) == kAsciiStringTag ||
255 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000256}
257
258
ager@chromium.org870a0b62008-11-04 11:43:05 +0000259bool StringShape::IsCons() {
260 return (type_ & kStringRepresentationMask) == kConsStringTag;
261}
262
263
ager@chromium.org870a0b62008-11-04 11:43:05 +0000264bool StringShape::IsExternal() {
265 return (type_ & kStringRepresentationMask) == kExternalStringTag;
266}
267
268
269bool StringShape::IsSequential() {
270 return (type_ & kStringRepresentationMask) == kSeqStringTag;
271}
272
273
274StringRepresentationTag StringShape::representation_tag() {
275 uint32_t tag = (type_ & kStringRepresentationMask);
276 return static_cast<StringRepresentationTag>(tag);
277}
278
279
280uint32_t StringShape::full_representation_tag() {
281 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
282}
283
284
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000285STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
286 Internals::kFullStringRepresentationMask);
287
288
ager@chromium.org870a0b62008-11-04 11:43:05 +0000289bool StringShape::IsSequentialAscii() {
290 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
291}
292
293
294bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000295 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000296}
297
298
299bool StringShape::IsExternalAscii() {
300 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
301}
302
303
304bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000305 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306}
307
308
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000309STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
310 Internals::kExternalTwoByteRepresentationTag);
311
312
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000313uc32 FlatStringReader::Get(int index) {
314 ASSERT(0 <= index && index <= length_);
315 if (is_ascii_) {
316 return static_cast<const byte*>(start_)[index];
317 } else {
318 return static_cast<const uc16*>(start_)[index];
319 }
320}
321
322
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000323bool Object::IsNumber() {
324 return IsSmi() || IsHeapNumber();
325}
326
327
328bool Object::IsByteArray() {
329 return Object::IsHeapObject()
330 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
331}
332
333
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000334bool Object::IsPixelArray() {
335 return Object::IsHeapObject() &&
336 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
337}
338
339
ager@chromium.org3811b432009-10-28 14:53:37 +0000340bool Object::IsExternalArray() {
341 if (!Object::IsHeapObject())
342 return false;
343 InstanceType instance_type =
344 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000345 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
346 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000347}
348
349
350bool Object::IsExternalByteArray() {
351 return Object::IsHeapObject() &&
352 HeapObject::cast(this)->map()->instance_type() ==
353 EXTERNAL_BYTE_ARRAY_TYPE;
354}
355
356
357bool Object::IsExternalUnsignedByteArray() {
358 return Object::IsHeapObject() &&
359 HeapObject::cast(this)->map()->instance_type() ==
360 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
361}
362
363
364bool Object::IsExternalShortArray() {
365 return Object::IsHeapObject() &&
366 HeapObject::cast(this)->map()->instance_type() ==
367 EXTERNAL_SHORT_ARRAY_TYPE;
368}
369
370
371bool Object::IsExternalUnsignedShortArray() {
372 return Object::IsHeapObject() &&
373 HeapObject::cast(this)->map()->instance_type() ==
374 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
375}
376
377
378bool Object::IsExternalIntArray() {
379 return Object::IsHeapObject() &&
380 HeapObject::cast(this)->map()->instance_type() ==
381 EXTERNAL_INT_ARRAY_TYPE;
382}
383
384
385bool Object::IsExternalUnsignedIntArray() {
386 return Object::IsHeapObject() &&
387 HeapObject::cast(this)->map()->instance_type() ==
388 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
389}
390
391
392bool Object::IsExternalFloatArray() {
393 return Object::IsHeapObject() &&
394 HeapObject::cast(this)->map()->instance_type() ==
395 EXTERNAL_FLOAT_ARRAY_TYPE;
396}
397
398
lrn@chromium.org303ada72010-10-27 09:33:13 +0000399bool MaybeObject::IsFailure() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000400 return HAS_FAILURE_TAG(this);
401}
402
403
lrn@chromium.org303ada72010-10-27 09:33:13 +0000404bool MaybeObject::IsRetryAfterGC() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000405 return HAS_FAILURE_TAG(this)
406 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
407}
408
409
lrn@chromium.org303ada72010-10-27 09:33:13 +0000410bool MaybeObject::IsOutOfMemory() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000411 return HAS_FAILURE_TAG(this)
412 && Failure::cast(this)->IsOutOfMemoryException();
413}
414
415
lrn@chromium.org303ada72010-10-27 09:33:13 +0000416bool MaybeObject::IsException() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417 return this == Failure::Exception();
418}
419
420
lrn@chromium.org303ada72010-10-27 09:33:13 +0000421bool MaybeObject::IsTheHole() {
422 return this == Heap::the_hole_value();
423}
424
425
426Failure* Failure::cast(MaybeObject* obj) {
427 ASSERT(HAS_FAILURE_TAG(obj));
428 return reinterpret_cast<Failure*>(obj);
429}
430
431
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432bool Object::IsJSObject() {
433 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000434 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000435}
436
437
ager@chromium.org32912102009-01-16 10:38:43 +0000438bool Object::IsJSContextExtensionObject() {
439 return IsHeapObject()
440 && (HeapObject::cast(this)->map()->instance_type() ==
441 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
442}
443
444
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445bool Object::IsMap() {
446 return Object::IsHeapObject()
447 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
448}
449
450
451bool Object::IsFixedArray() {
452 return Object::IsHeapObject()
453 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
454}
455
456
457bool Object::IsDescriptorArray() {
458 return IsFixedArray();
459}
460
461
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000462bool Object::IsDeoptimizationInputData() {
463 // Must be a fixed array.
464 if (!IsFixedArray()) return false;
465
466 // There's no sure way to detect the difference between a fixed array and
467 // a deoptimization data array. Since this is used for asserts we can
468 // check that the length is zero or else the fixed size plus a multiple of
469 // the entry size.
470 int length = FixedArray::cast(this)->length();
471 if (length == 0) return true;
472
473 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
474 return length >= 0 &&
475 length % DeoptimizationInputData::kDeoptEntrySize == 0;
476}
477
478
479bool Object::IsDeoptimizationOutputData() {
480 if (!IsFixedArray()) return false;
481 // There's actually no way to see the difference between a fixed array and
482 // a deoptimization data array. Since this is used for asserts we can check
483 // that the length is plausible though.
484 if (FixedArray::cast(this)->length() % 2 != 0) return false;
485 return true;
486}
487
488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489bool Object::IsContext() {
490 return Object::IsHeapObject()
491 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000492 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493 HeapObject::cast(this)->map() == Heap::global_context_map());
494}
495
496
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000497bool Object::IsCatchContext() {
498 return Object::IsHeapObject()
499 && HeapObject::cast(this)->map() == Heap::catch_context_map();
500}
501
502
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503bool Object::IsGlobalContext() {
504 return Object::IsHeapObject()
505 && HeapObject::cast(this)->map() == Heap::global_context_map();
506}
507
508
509bool Object::IsJSFunction() {
510 return Object::IsHeapObject()
511 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
512}
513
514
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000515template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000516 return obj->IsJSFunction();
517}
518
519
520bool Object::IsCode() {
521 return Object::IsHeapObject()
522 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
523}
524
525
526bool Object::IsOddball() {
527 return Object::IsHeapObject()
528 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
529}
530
531
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000532bool Object::IsJSGlobalPropertyCell() {
533 return Object::IsHeapObject()
534 && HeapObject::cast(this)->map()->instance_type()
535 == JS_GLOBAL_PROPERTY_CELL_TYPE;
536}
537
538
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539bool Object::IsSharedFunctionInfo() {
540 return Object::IsHeapObject() &&
541 (HeapObject::cast(this)->map()->instance_type() ==
542 SHARED_FUNCTION_INFO_TYPE);
543}
544
545
546bool Object::IsJSValue() {
547 return Object::IsHeapObject()
548 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
549}
550
551
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000552bool Object::IsStringWrapper() {
553 return IsJSValue() && JSValue::cast(this)->value()->IsString();
554}
555
556
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557bool Object::IsProxy() {
558 return Object::IsHeapObject()
559 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
560}
561
562
563bool Object::IsBoolean() {
564 return IsTrue() || IsFalse();
565}
566
567
568bool Object::IsJSArray() {
569 return Object::IsHeapObject()
570 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
571}
572
573
ager@chromium.org236ad962008-09-25 09:45:57 +0000574bool Object::IsJSRegExp() {
575 return Object::IsHeapObject()
576 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
577}
578
579
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000580template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581 return obj->IsJSArray();
582}
583
584
585bool Object::IsHashTable() {
586 return Object::IsHeapObject()
587 && HeapObject::cast(this)->map() == Heap::hash_table_map();
588}
589
590
591bool Object::IsDictionary() {
592 return IsHashTable() && this != Heap::symbol_table();
593}
594
595
596bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000597 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598}
599
600
ager@chromium.orgac091b72010-05-05 07:34:42 +0000601bool Object::IsJSFunctionResultCache() {
602 if (!IsFixedArray()) return false;
603 FixedArray* self = FixedArray::cast(this);
604 int length = self->length();
605 if (length < JSFunctionResultCache::kEntriesIndex) return false;
606 if ((length - JSFunctionResultCache::kEntriesIndex)
607 % JSFunctionResultCache::kEntrySize != 0) {
608 return false;
609 }
610#ifdef DEBUG
611 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
612#endif
613 return true;
614}
615
616
ricow@chromium.org65fae842010-08-25 15:26:24 +0000617bool Object::IsNormalizedMapCache() {
618 if (!IsFixedArray()) return false;
619 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
620 return false;
621 }
622#ifdef DEBUG
623 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
624#endif
625 return true;
626}
627
628
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000629bool Object::IsCompilationCacheTable() {
630 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000631}
632
633
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000634bool Object::IsCodeCacheHashTable() {
635 return IsHashTable();
636}
637
638
ager@chromium.org236ad962008-09-25 09:45:57 +0000639bool Object::IsMapCache() {
640 return IsHashTable();
641}
642
643
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644bool Object::IsPrimitive() {
645 return IsOddball() || IsNumber() || IsString();
646}
647
648
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000649bool Object::IsJSGlobalProxy() {
650 bool result = IsHeapObject() &&
651 (HeapObject::cast(this)->map()->instance_type() ==
652 JS_GLOBAL_PROXY_TYPE);
653 ASSERT(!result || IsAccessCheckNeeded());
654 return result;
655}
656
657
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000658bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000659 if (!IsHeapObject()) return false;
660
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000661 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000662 return type == JS_GLOBAL_OBJECT_TYPE ||
663 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000664}
665
666
667bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668 return IsHeapObject() &&
669 (HeapObject::cast(this)->map()->instance_type() ==
670 JS_GLOBAL_OBJECT_TYPE);
671}
672
673
674bool Object::IsJSBuiltinsObject() {
675 return IsHeapObject() &&
676 (HeapObject::cast(this)->map()->instance_type() ==
677 JS_BUILTINS_OBJECT_TYPE);
678}
679
680
681bool Object::IsUndetectableObject() {
682 return IsHeapObject()
683 && HeapObject::cast(this)->map()->is_undetectable();
684}
685
686
687bool Object::IsAccessCheckNeeded() {
688 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000689 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690}
691
692
693bool Object::IsStruct() {
694 if (!IsHeapObject()) return false;
695 switch (HeapObject::cast(this)->map()->instance_type()) {
696#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
697 STRUCT_LIST(MAKE_STRUCT_CASE)
698#undef MAKE_STRUCT_CASE
699 default: return false;
700 }
701}
702
703
704#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
705 bool Object::Is##Name() { \
706 return Object::IsHeapObject() \
707 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
708 }
709 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
710#undef MAKE_STRUCT_PREDICATE
711
712
713bool Object::IsUndefined() {
714 return this == Heap::undefined_value();
715}
716
717
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718bool Object::IsNull() {
719 return this == Heap::null_value();
720}
721
722
723bool Object::IsTrue() {
724 return this == Heap::true_value();
725}
726
727
728bool Object::IsFalse() {
729 return this == Heap::false_value();
730}
731
732
733double Object::Number() {
734 ASSERT(IsNumber());
735 return IsSmi()
736 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
737 : reinterpret_cast<HeapNumber*>(this)->value();
738}
739
740
741
lrn@chromium.org303ada72010-10-27 09:33:13 +0000742MaybeObject* Object::ToSmi() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743 if (IsSmi()) return this;
744 if (IsHeapNumber()) {
745 double value = HeapNumber::cast(this)->value();
746 int int_value = FastD2I(value);
747 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
748 return Smi::FromInt(int_value);
749 }
750 }
751 return Failure::Exception();
752}
753
754
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000755bool Object::HasSpecificClassOf(String* name) {
756 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
757}
758
759
lrn@chromium.org303ada72010-10-27 09:33:13 +0000760MaybeObject* Object::GetElement(uint32_t index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000761 return GetElementWithReceiver(this, index);
762}
763
764
lrn@chromium.org303ada72010-10-27 09:33:13 +0000765Object* Object::GetElementNoExceptionThrown(uint32_t index) {
766 MaybeObject* maybe = GetElementWithReceiver(this, index);
767 ASSERT(!maybe->IsFailure());
768 Object* result = NULL; // Initialization to please compiler.
769 maybe->ToObject(&result);
770 return result;
771}
772
773
774MaybeObject* Object::GetProperty(String* key) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000775 PropertyAttributes attributes;
776 return GetPropertyWithReceiver(this, key, &attributes);
777}
778
779
lrn@chromium.org303ada72010-10-27 09:33:13 +0000780MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781 return GetPropertyWithReceiver(this, key, attributes);
782}
783
784
785#define FIELD_ADDR(p, offset) \
786 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
787
788#define READ_FIELD(p, offset) \
789 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
790
791#define WRITE_FIELD(p, offset, value) \
792 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
793
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000794
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000795#define WRITE_BARRIER(object, offset) \
796 Heap::RecordWrite(object->address(), offset);
797
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000798// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000799// write due to the assert validating the written value.
800#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
801 if (mode == UPDATE_WRITE_BARRIER) { \
802 Heap::RecordWrite(object->address(), offset); \
803 } else { \
804 ASSERT(mode == SKIP_WRITE_BARRIER); \
805 ASSERT(Heap::InNewSpace(object) || \
kmillikin@chromium.orgb8dc8eb2010-04-01 07:13:38 +0000806 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000807 Page::FromAddress(object->address())-> \
808 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000809 }
810
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000811#define READ_DOUBLE_FIELD(p, offset) \
812 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
813
814#define WRITE_DOUBLE_FIELD(p, offset, value) \
815 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
816
817#define READ_INT_FIELD(p, offset) \
818 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
819
820#define WRITE_INT_FIELD(p, offset, value) \
821 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
822
ager@chromium.org3e875802009-06-29 08:26:34 +0000823#define READ_INTPTR_FIELD(p, offset) \
824 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
825
826#define WRITE_INTPTR_FIELD(p, offset, value) \
827 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
828
ager@chromium.org7c537e22008-10-16 08:43:32 +0000829#define READ_UINT32_FIELD(p, offset) \
830 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
831
832#define WRITE_UINT32_FIELD(p, offset, value) \
833 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
834
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835#define READ_SHORT_FIELD(p, offset) \
836 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
837
838#define WRITE_SHORT_FIELD(p, offset, value) \
839 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
840
841#define READ_BYTE_FIELD(p, offset) \
842 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
843
844#define WRITE_BYTE_FIELD(p, offset, value) \
845 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
846
847
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000848Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
849 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850}
851
852
853int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000854 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000855}
856
857
858Smi* Smi::FromInt(int value) {
859 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000860 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000861 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000862 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000863 return reinterpret_cast<Smi*>(tagged_value);
864}
865
866
867Smi* Smi::FromIntptr(intptr_t value) {
868 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000869 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
870 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871}
872
873
874Failure::Type Failure::type() const {
875 return static_cast<Type>(value() & kFailureTypeTagMask);
876}
877
878
879bool Failure::IsInternalError() const {
880 return type() == INTERNAL_ERROR;
881}
882
883
884bool Failure::IsOutOfMemoryException() const {
885 return type() == OUT_OF_MEMORY_EXCEPTION;
886}
887
888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000889AllocationSpace Failure::allocation_space() const {
890 ASSERT_EQ(RETRY_AFTER_GC, type());
891 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
892 & kSpaceTagMask);
893}
894
895
896Failure* Failure::InternalError() {
897 return Construct(INTERNAL_ERROR);
898}
899
900
901Failure* Failure::Exception() {
902 return Construct(EXCEPTION);
903}
904
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000905
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000906Failure* Failure::OutOfMemoryException() {
907 return Construct(OUT_OF_MEMORY_EXCEPTION);
908}
909
910
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000911intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000912 return static_cast<intptr_t>(
913 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914}
915
916
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000917Failure* Failure::RetryAfterGC() {
918 return RetryAfterGC(NEW_SPACE);
919}
920
921
922Failure* Failure::RetryAfterGC(AllocationSpace space) {
923 ASSERT((space & ~kSpaceTagMask) == 0);
924 return Construct(RETRY_AFTER_GC, space);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000925}
926
927
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000928Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000929 uintptr_t info =
930 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000931 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000932 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000933}
934
935
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000936bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000937#ifdef DEBUG
938 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
939#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000940
941#ifdef V8_TARGET_ARCH_X64
942 // To be representable as a long smi, the value must be a 32-bit integer.
943 bool result = (value == static_cast<int32_t>(value));
944#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000945 // To be representable as an tagged small integer, the two
946 // most-significant bits of 'value' must be either 00 or 11 due to
947 // sign-extension. To check this we add 01 to the two
948 // most-significant bits, and check if the most-significant bit is 0
949 //
950 // CAUTION: The original code below:
951 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
952 // may lead to incorrect results according to the C language spec, and
953 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
954 // compiler may produce undefined results in case of signed integer
955 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000956 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000957#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000958 ASSERT(result == in_range);
959 return result;
960}
961
962
kasper.lund7276f142008-07-30 08:49:36 +0000963MapWord MapWord::FromMap(Map* map) {
964 return MapWord(reinterpret_cast<uintptr_t>(map));
965}
966
967
968Map* MapWord::ToMap() {
969 return reinterpret_cast<Map*>(value_);
970}
971
972
973bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000974 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000975}
976
977
978MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000979 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
980 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000981}
982
983
984HeapObject* MapWord::ToForwardingAddress() {
985 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000986 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000987}
988
989
990bool MapWord::IsMarked() {
991 return (value_ & kMarkingMask) == 0;
992}
993
994
995void MapWord::SetMark() {
996 value_ &= ~kMarkingMask;
997}
998
999
1000void MapWord::ClearMark() {
1001 value_ |= kMarkingMask;
1002}
1003
1004
1005bool MapWord::IsOverflowed() {
1006 return (value_ & kOverflowMask) != 0;
1007}
1008
1009
1010void MapWord::SetOverflow() {
1011 value_ |= kOverflowMask;
1012}
1013
1014
1015void MapWord::ClearOverflow() {
1016 value_ &= ~kOverflowMask;
1017}
1018
1019
1020MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1021 // Offset is the distance in live bytes from the first live object in the
1022 // same page. The offset between two objects in the same page should not
1023 // exceed the object area size of a page.
1024 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1025
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001026 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001027 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1028
1029 Page* map_page = Page::FromAddress(map_address);
1030 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1031
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001032 uintptr_t map_page_offset =
1033 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001034
1035 uintptr_t encoding =
1036 (compact_offset << kForwardingOffsetShift) |
1037 (map_page_offset << kMapPageOffsetShift) |
1038 (map_page->mc_page_index << kMapPageIndexShift);
1039 return MapWord(encoding);
1040}
1041
1042
1043Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001044 int map_page_index =
1045 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001046 ASSERT_MAP_PAGE_INDEX(map_page_index);
1047
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001048 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001049 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1050 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001051
1052 return (map_space->PageAddress(map_page_index) + map_page_offset);
1053}
1054
1055
1056int MapWord::DecodeOffset() {
1057 // The offset field is represented in the kForwardingOffsetBits
1058 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001059 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1060 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1061 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001062}
1063
1064
1065MapWord MapWord::FromEncodedAddress(Address address) {
1066 return MapWord(reinterpret_cast<uintptr_t>(address));
1067}
1068
1069
1070Address MapWord::ToEncodedAddress() {
1071 return reinterpret_cast<Address>(value_);
1072}
1073
1074
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001075#ifdef DEBUG
1076void HeapObject::VerifyObjectField(int offset) {
1077 VerifyPointer(READ_FIELD(this, offset));
1078}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001079
1080void HeapObject::VerifySmiField(int offset) {
1081 ASSERT(READ_FIELD(this, offset)->IsSmi());
1082}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001083#endif
1084
1085
1086Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001087 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088}
1089
1090
1091void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001092 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001093}
1094
1095
kasper.lund7276f142008-07-30 08:49:36 +00001096MapWord HeapObject::map_word() {
1097 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1098}
1099
1100
1101void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001102 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001103 // here.
1104 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1105}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106
1107
1108HeapObject* HeapObject::FromAddress(Address address) {
1109 ASSERT_TAG_ALIGNED(address);
1110 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1111}
1112
1113
1114Address HeapObject::address() {
1115 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1116}
1117
1118
1119int HeapObject::Size() {
1120 return SizeFromMap(map());
1121}
1122
1123
1124void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1125 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1126 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1127}
1128
1129
1130void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1131 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1132}
1133
1134
kasper.lund7276f142008-07-30 08:49:36 +00001135bool HeapObject::IsMarked() {
1136 return map_word().IsMarked();
1137}
1138
1139
1140void HeapObject::SetMark() {
1141 ASSERT(!IsMarked());
1142 MapWord first_word = map_word();
1143 first_word.SetMark();
1144 set_map_word(first_word);
1145}
1146
1147
1148void HeapObject::ClearMark() {
1149 ASSERT(IsMarked());
1150 MapWord first_word = map_word();
1151 first_word.ClearMark();
1152 set_map_word(first_word);
1153}
1154
1155
1156bool HeapObject::IsOverflowed() {
1157 return map_word().IsOverflowed();
1158}
1159
1160
1161void HeapObject::SetOverflow() {
1162 MapWord first_word = map_word();
1163 first_word.SetOverflow();
1164 set_map_word(first_word);
1165}
1166
1167
1168void HeapObject::ClearOverflow() {
1169 ASSERT(IsOverflowed());
1170 MapWord first_word = map_word();
1171 first_word.ClearOverflow();
1172 set_map_word(first_word);
1173}
1174
1175
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001176double HeapNumber::value() {
1177 return READ_DOUBLE_FIELD(this, kValueOffset);
1178}
1179
1180
1181void HeapNumber::set_value(double value) {
1182 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1183}
1184
1185
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001186int HeapNumber::get_exponent() {
1187 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1188 kExponentShift) - kExponentBias;
1189}
1190
1191
1192int HeapNumber::get_sign() {
1193 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1194}
1195
1196
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001197ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001198
1199
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001200HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001201 Object* array = READ_FIELD(this, kElementsOffset);
1202 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001203 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1204 array->IsExternalArray());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001205 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001206}
1207
1208
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001209void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001210 ASSERT(map()->has_fast_elements() ==
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001211 (value->map() == Heap::fixed_array_map() ||
1212 value->map() == Heap::fixed_cow_array_map()));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001213 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001214 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1215 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001216 WRITE_FIELD(this, kElementsOffset, value);
1217 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1218}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001219
1220
1221void JSObject::initialize_properties() {
1222 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1223 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1224}
1225
1226
1227void JSObject::initialize_elements() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001228 ASSERT(map()->has_fast_elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001229 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1230 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1231}
1232
1233
lrn@chromium.org303ada72010-10-27 09:33:13 +00001234MaybeObject* JSObject::ResetElements() {
1235 Object* obj;
1236 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1237 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1238 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001239 set_map(Map::cast(obj));
1240 initialize_elements();
1241 return this;
1242}
1243
1244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245ACCESSORS(Oddball, to_string, String, kToStringOffset)
1246ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1247
1248
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001249Object* JSGlobalPropertyCell::value() {
1250 return READ_FIELD(this, kValueOffset);
1251}
1252
1253
1254void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1255 // The write barrier is not used for global property cells.
1256 ASSERT(!val->IsJSGlobalPropertyCell());
1257 WRITE_FIELD(this, kValueOffset, val);
1258}
1259
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001260
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001261int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001262 InstanceType type = map()->instance_type();
1263 // Check for the most common kind of JavaScript object before
1264 // falling into the generic switch. This speeds up the internal
1265 // field operations considerably on average.
1266 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1267 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001268 case JS_GLOBAL_PROXY_TYPE:
1269 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 case JS_GLOBAL_OBJECT_TYPE:
1271 return JSGlobalObject::kSize;
1272 case JS_BUILTINS_OBJECT_TYPE:
1273 return JSBuiltinsObject::kSize;
1274 case JS_FUNCTION_TYPE:
1275 return JSFunction::kSize;
1276 case JS_VALUE_TYPE:
1277 return JSValue::kSize;
1278 case JS_ARRAY_TYPE:
1279 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001280 case JS_REGEXP_TYPE:
1281 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001282 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001283 return JSObject::kHeaderSize;
1284 default:
1285 UNREACHABLE();
1286 return 0;
1287 }
1288}
1289
1290
1291int JSObject::GetInternalFieldCount() {
1292 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001293 // Make sure to adjust for the number of in-object properties. These
1294 // properties do contribute to the size, but are not internal fields.
1295 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1296 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297}
1298
1299
1300Object* JSObject::GetInternalField(int index) {
1301 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001302 // Internal objects do follow immediately after the header, whereas in-object
1303 // properties are at the end of the object. Therefore there is no need
1304 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001305 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1306}
1307
1308
1309void JSObject::SetInternalField(int index, Object* value) {
1310 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001311 // Internal objects do follow immediately after the header, whereas in-object
1312 // properties are at the end of the object. Therefore there is no need
1313 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001314 int offset = GetHeaderSize() + (kPointerSize * index);
1315 WRITE_FIELD(this, offset, value);
1316 WRITE_BARRIER(this, offset);
1317}
1318
1319
ager@chromium.org7c537e22008-10-16 08:43:32 +00001320// Access fast-case object properties at index. The use of these routines
1321// is needed to correctly distinguish between properties stored in-object and
1322// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001323Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001324 // Adjust for the number of properties stored in the object.
1325 index -= map()->inobject_properties();
1326 if (index < 0) {
1327 int offset = map()->instance_size() + (index * kPointerSize);
1328 return READ_FIELD(this, offset);
1329 } else {
1330 ASSERT(index < properties()->length());
1331 return properties()->get(index);
1332 }
1333}
1334
1335
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001336Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001337 // Adjust for the number of properties stored in the object.
1338 index -= map()->inobject_properties();
1339 if (index < 0) {
1340 int offset = map()->instance_size() + (index * kPointerSize);
1341 WRITE_FIELD(this, offset, value);
1342 WRITE_BARRIER(this, offset);
1343 } else {
1344 ASSERT(index < properties()->length());
1345 properties()->set(index, value);
1346 }
1347 return value;
1348}
1349
1350
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001351Object* JSObject::InObjectPropertyAt(int index) {
1352 // Adjust for the number of properties stored in the object.
1353 index -= map()->inobject_properties();
1354 ASSERT(index < 0);
1355 int offset = map()->instance_size() + (index * kPointerSize);
1356 return READ_FIELD(this, offset);
1357}
1358
1359
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001360Object* JSObject::InObjectPropertyAtPut(int index,
1361 Object* value,
1362 WriteBarrierMode mode) {
1363 // Adjust for the number of properties stored in the object.
1364 index -= map()->inobject_properties();
1365 ASSERT(index < 0);
1366 int offset = map()->instance_size() + (index * kPointerSize);
1367 WRITE_FIELD(this, offset, value);
1368 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1369 return value;
1370}
1371
1372
1373
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001374void JSObject::InitializeBody(int object_size, Object* value) {
1375 ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001376 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001377 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001378 }
1379}
1380
1381
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001382bool JSObject::HasFastProperties() {
1383 return !properties()->IsDictionary();
1384}
1385
1386
1387int JSObject::MaxFastProperties() {
1388 // Allow extra fast properties if the object has more than
1389 // kMaxFastProperties in-object properties. When this is the case,
1390 // it is very unlikely that the object is being used as a dictionary
1391 // and there is a good chance that allowing more map transitions
1392 // will be worth it.
1393 return Max(map()->inobject_properties(), kMaxFastProperties);
1394}
1395
1396
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001397void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001398 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001399 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001400 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001401 }
1402}
1403
1404
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001405bool Object::ToArrayIndex(uint32_t* index) {
1406 if (IsSmi()) {
1407 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001408 if (value < 0) return false;
1409 *index = value;
1410 return true;
1411 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001412 if (IsHeapNumber()) {
1413 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001414 uint32_t uint_value = static_cast<uint32_t>(value);
1415 if (value == static_cast<double>(uint_value)) {
1416 *index = uint_value;
1417 return true;
1418 }
1419 }
1420 return false;
1421}
1422
1423
1424bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1425 if (!this->IsJSValue()) return false;
1426
1427 JSValue* js_value = JSValue::cast(this);
1428 if (!js_value->value()->IsString()) return false;
1429
1430 String* str = String::cast(js_value->value());
1431 if (index >= (uint32_t)str->length()) return false;
1432
1433 return true;
1434}
1435
1436
1437Object* FixedArray::get(int index) {
1438 ASSERT(index >= 0 && index < this->length());
1439 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1440}
1441
1442
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001443void FixedArray::set(int index, Smi* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001444 ASSERT(map() != Heap::fixed_cow_array_map());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001445 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1446 int offset = kHeaderSize + index * kPointerSize;
1447 WRITE_FIELD(this, offset, value);
1448}
1449
1450
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001451void FixedArray::set(int index, Object* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001452 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001453 ASSERT(index >= 0 && index < this->length());
1454 int offset = kHeaderSize + index * kPointerSize;
1455 WRITE_FIELD(this, offset, value);
1456 WRITE_BARRIER(this, offset);
1457}
1458
1459
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001460WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1462 return UPDATE_WRITE_BARRIER;
1463}
1464
1465
1466void FixedArray::set(int index,
1467 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001468 WriteBarrierMode mode) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001469 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001470 ASSERT(index >= 0 && index < this->length());
1471 int offset = kHeaderSize + index * kPointerSize;
1472 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001473 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474}
1475
1476
1477void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001478 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001479 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001480 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001481 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1482}
1483
1484
1485void FixedArray::set_undefined(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001486 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001487 ASSERT(index >= 0 && index < this->length());
1488 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1489 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1490 Heap::undefined_value());
1491}
1492
1493
ager@chromium.org236ad962008-09-25 09:45:57 +00001494void FixedArray::set_null(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001495 ASSERT(map() != Heap::fixed_cow_array_map());
ager@chromium.org236ad962008-09-25 09:45:57 +00001496 ASSERT(index >= 0 && index < this->length());
1497 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1498 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1499}
1500
1501
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502void FixedArray::set_the_hole(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001503 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001504 ASSERT(index >= 0 && index < this->length());
1505 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1506 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1507}
1508
1509
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001510void FixedArray::set_unchecked(int index, Smi* value) {
1511 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1512 int offset = kHeaderSize + index * kPointerSize;
1513 WRITE_FIELD(this, offset, value);
1514}
1515
1516
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001517void FixedArray::set_unchecked(int index,
1518 Object* value,
1519 WriteBarrierMode mode) {
1520 int offset = kHeaderSize + index * kPointerSize;
1521 WRITE_FIELD(this, offset, value);
1522 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1523}
1524
1525
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001526void FixedArray::set_null_unchecked(int index) {
1527 ASSERT(index >= 0 && index < this->length());
1528 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1529 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1530}
1531
1532
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001533Object** FixedArray::data_start() {
1534 return HeapObject::RawField(this, kHeaderSize);
1535}
1536
1537
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001538bool DescriptorArray::IsEmpty() {
1539 ASSERT(this == Heap::empty_descriptor_array() ||
1540 this->length() > 2);
1541 return this == Heap::empty_descriptor_array();
1542}
1543
1544
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1546 Object* tmp = array->get(first);
1547 fast_set(array, first, array->get(second));
1548 fast_set(array, second, tmp);
1549}
1550
1551
1552int DescriptorArray::Search(String* name) {
1553 SLOW_ASSERT(IsSortedNoDuplicates());
1554
1555 // Check for empty descriptor array.
1556 int nof = number_of_descriptors();
1557 if (nof == 0) return kNotFound;
1558
1559 // Fast case: do linear search for small arrays.
1560 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001561 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001562 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001563 }
1564
1565 // Slow case: perform binary search.
1566 return BinarySearch(name, 0, nof - 1);
1567}
1568
1569
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001570int DescriptorArray::SearchWithCache(String* name) {
1571 int number = DescriptorLookupCache::Lookup(this, name);
1572 if (number == DescriptorLookupCache::kAbsent) {
1573 number = Search(name);
1574 DescriptorLookupCache::Update(this, name, number);
1575 }
1576 return number;
1577}
1578
1579
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580String* DescriptorArray::GetKey(int descriptor_number) {
1581 ASSERT(descriptor_number < number_of_descriptors());
1582 return String::cast(get(ToKeyIndex(descriptor_number)));
1583}
1584
1585
1586Object* DescriptorArray::GetValue(int descriptor_number) {
1587 ASSERT(descriptor_number < number_of_descriptors());
1588 return GetContentArray()->get(ToValueIndex(descriptor_number));
1589}
1590
1591
1592Smi* DescriptorArray::GetDetails(int descriptor_number) {
1593 ASSERT(descriptor_number < number_of_descriptors());
1594 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1595}
1596
1597
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001598PropertyType DescriptorArray::GetType(int descriptor_number) {
1599 ASSERT(descriptor_number < number_of_descriptors());
1600 return PropertyDetails(GetDetails(descriptor_number)).type();
1601}
1602
1603
1604int DescriptorArray::GetFieldIndex(int descriptor_number) {
1605 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1606}
1607
1608
1609JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1610 return JSFunction::cast(GetValue(descriptor_number));
1611}
1612
1613
1614Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1615 ASSERT(GetType(descriptor_number) == CALLBACKS);
1616 return GetValue(descriptor_number);
1617}
1618
1619
1620AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1621 ASSERT(GetType(descriptor_number) == CALLBACKS);
1622 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1623 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1624}
1625
1626
1627bool DescriptorArray::IsProperty(int descriptor_number) {
1628 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1629}
1630
1631
1632bool DescriptorArray::IsTransition(int descriptor_number) {
1633 PropertyType t = GetType(descriptor_number);
1634 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1635}
1636
1637
1638bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1639 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1640}
1641
1642
1643bool DescriptorArray::IsDontEnum(int descriptor_number) {
1644 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1645}
1646
1647
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1649 desc->Init(GetKey(descriptor_number),
1650 GetValue(descriptor_number),
1651 GetDetails(descriptor_number));
1652}
1653
1654
1655void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1656 // Range check.
1657 ASSERT(descriptor_number < number_of_descriptors());
1658
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001659 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001660 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1661 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1662
1663 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1664 FixedArray* content_array = GetContentArray();
1665 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1666 fast_set(content_array, ToDetailsIndex(descriptor_number),
1667 desc->GetDetails().AsSmi());
1668}
1669
1670
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001671void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1672 Descriptor desc;
1673 src->Get(src_index, &desc);
1674 Set(index, &desc);
1675}
1676
1677
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001678void DescriptorArray::Swap(int first, int second) {
1679 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1680 FixedArray* content_array = GetContentArray();
1681 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1682 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1683}
1684
1685
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001686bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001687 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001688 if (!max_index_object->IsSmi()) return false;
1689 return 0 !=
1690 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1691}
1692
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001693uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001694 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001695 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001696 if (!max_index_object->IsSmi()) return 0;
1697 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1698 return value >> kRequiresSlowElementsTagSize;
1699}
1700
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001701void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001702 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001703}
1704
1705
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001706// ------------------------------------
1707// Cast operations
1708
1709
1710CAST_ACCESSOR(FixedArray)
1711CAST_ACCESSOR(DescriptorArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001712CAST_ACCESSOR(DeoptimizationInputData)
1713CAST_ACCESSOR(DeoptimizationOutputData)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001714CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001715CAST_ACCESSOR(JSFunctionResultCache)
ricow@chromium.org65fae842010-08-25 15:26:24 +00001716CAST_ACCESSOR(NormalizedMapCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001717CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001718CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001719CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001720CAST_ACCESSOR(String)
1721CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001722CAST_ACCESSOR(SeqAsciiString)
1723CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001724CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725CAST_ACCESSOR(ExternalString)
1726CAST_ACCESSOR(ExternalAsciiString)
1727CAST_ACCESSOR(ExternalTwoByteString)
1728CAST_ACCESSOR(JSObject)
1729CAST_ACCESSOR(Smi)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730CAST_ACCESSOR(HeapObject)
1731CAST_ACCESSOR(HeapNumber)
1732CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001733CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001734CAST_ACCESSOR(SharedFunctionInfo)
1735CAST_ACCESSOR(Map)
1736CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001737CAST_ACCESSOR(GlobalObject)
1738CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739CAST_ACCESSOR(JSGlobalObject)
1740CAST_ACCESSOR(JSBuiltinsObject)
1741CAST_ACCESSOR(Code)
1742CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001743CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744CAST_ACCESSOR(Proxy)
1745CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001746CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001747CAST_ACCESSOR(ExternalArray)
1748CAST_ACCESSOR(ExternalByteArray)
1749CAST_ACCESSOR(ExternalUnsignedByteArray)
1750CAST_ACCESSOR(ExternalShortArray)
1751CAST_ACCESSOR(ExternalUnsignedShortArray)
1752CAST_ACCESSOR(ExternalIntArray)
1753CAST_ACCESSOR(ExternalUnsignedIntArray)
1754CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001755CAST_ACCESSOR(Struct)
1756
1757
1758#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1759 STRUCT_LIST(MAKE_STRUCT_CAST)
1760#undef MAKE_STRUCT_CAST
1761
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001762
1763template <typename Shape, typename Key>
1764HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001765 ASSERT(obj->IsHashTable());
1766 return reinterpret_cast<HashTable*>(obj);
1767}
1768
1769
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001770SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1771SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1772
1773INT_ACCESSORS(PixelArray, length, kLengthOffset)
1774INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001775
1776
ager@chromium.orgac091b72010-05-05 07:34:42 +00001777SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001778
1779
1780uint32_t String::hash_field() {
1781 return READ_UINT32_FIELD(this, kHashFieldOffset);
1782}
1783
1784
1785void String::set_hash_field(uint32_t value) {
1786 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001787#if V8_HOST_ARCH_64_BIT
1788 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1789#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001790}
1791
1792
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001793bool String::Equals(String* other) {
1794 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001795 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1796 return false;
1797 }
1798 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001799}
1800
1801
lrn@chromium.org303ada72010-10-27 09:33:13 +00001802MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001803 if (!StringShape(this).IsCons()) return this;
1804 ConsString* cons = ConsString::cast(this);
1805 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001806 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001807}
1808
1809
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001810String* String::TryFlattenGetString(PretenureFlag pretenure) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001811 MaybeObject* flat = TryFlatten(pretenure);
1812 Object* successfully_flattened;
1813 if (flat->ToObject(&successfully_flattened)) {
1814 return String::cast(successfully_flattened);
1815 }
1816 return this;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001817}
1818
1819
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001820uint16_t String::Get(int index) {
1821 ASSERT(index >= 0 && index < length());
1822 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001823 case kSeqStringTag | kAsciiStringTag:
1824 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1825 case kSeqStringTag | kTwoByteStringTag:
1826 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1827 case kConsStringTag | kAsciiStringTag:
1828 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001829 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001830 case kExternalStringTag | kAsciiStringTag:
1831 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1832 case kExternalStringTag | kTwoByteStringTag:
1833 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001834 default:
1835 break;
1836 }
1837
1838 UNREACHABLE();
1839 return 0;
1840}
1841
1842
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001843void String::Set(int index, uint16_t value) {
1844 ASSERT(index >= 0 && index < length());
1845 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001846
ager@chromium.org5ec48922009-05-05 07:25:34 +00001847 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001848 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1849 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001850}
1851
1852
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001853bool String::IsFlat() {
1854 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001855 case kConsStringTag: {
1856 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001857 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001858 return second->length() == 0;
1859 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001860 default:
1861 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001862 }
1863}
1864
1865
ager@chromium.org7c537e22008-10-16 08:43:32 +00001866uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001867 ASSERT(index >= 0 && index < length());
1868 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1869}
1870
1871
ager@chromium.org7c537e22008-10-16 08:43:32 +00001872void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001873 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1874 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1875 static_cast<byte>(value));
1876}
1877
1878
ager@chromium.org7c537e22008-10-16 08:43:32 +00001879Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001880 return FIELD_ADDR(this, kHeaderSize);
1881}
1882
1883
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001884char* SeqAsciiString::GetChars() {
1885 return reinterpret_cast<char*>(GetCharsAddress());
1886}
1887
1888
ager@chromium.org7c537e22008-10-16 08:43:32 +00001889Address SeqTwoByteString::GetCharsAddress() {
1890 return FIELD_ADDR(this, kHeaderSize);
1891}
1892
1893
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001894uc16* SeqTwoByteString::GetChars() {
1895 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1896}
1897
1898
ager@chromium.org7c537e22008-10-16 08:43:32 +00001899uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001900 ASSERT(index >= 0 && index < length());
1901 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1902}
1903
1904
ager@chromium.org7c537e22008-10-16 08:43:32 +00001905void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001906 ASSERT(index >= 0 && index < length());
1907 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1908}
1909
1910
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001911int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001912 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001913}
1914
1915
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001916int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001917 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001918}
1919
1920
ager@chromium.org870a0b62008-11-04 11:43:05 +00001921String* ConsString::first() {
1922 return String::cast(READ_FIELD(this, kFirstOffset));
1923}
1924
1925
1926Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001927 return READ_FIELD(this, kFirstOffset);
1928}
1929
1930
ager@chromium.org870a0b62008-11-04 11:43:05 +00001931void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001932 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001933 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001934}
1935
1936
ager@chromium.org870a0b62008-11-04 11:43:05 +00001937String* ConsString::second() {
1938 return String::cast(READ_FIELD(this, kSecondOffset));
1939}
1940
1941
1942Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001943 return READ_FIELD(this, kSecondOffset);
1944}
1945
1946
ager@chromium.org870a0b62008-11-04 11:43:05 +00001947void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001948 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001949 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001950}
1951
1952
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001953ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1954 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1955}
1956
1957
1958void ExternalAsciiString::set_resource(
1959 ExternalAsciiString::Resource* resource) {
1960 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1961}
1962
1963
1964ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1965 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1966}
1967
1968
1969void ExternalTwoByteString::set_resource(
1970 ExternalTwoByteString::Resource* resource) {
1971 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1972}
1973
1974
ager@chromium.orgac091b72010-05-05 07:34:42 +00001975void JSFunctionResultCache::MakeZeroSize() {
1976 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1977 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1978}
1979
1980
1981void JSFunctionResultCache::Clear() {
1982 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1983 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001984 MemsetPointer(entries_start,
1985 Heap::the_hole_value(),
1986 cache_size - kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001987 MakeZeroSize();
1988}
1989
1990
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001991byte ByteArray::get(int index) {
1992 ASSERT(index >= 0 && index < this->length());
1993 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1994}
1995
1996
1997void ByteArray::set(int index, byte value) {
1998 ASSERT(index >= 0 && index < this->length());
1999 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2000}
2001
2002
2003int ByteArray::get_int(int index) {
2004 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2005 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2006}
2007
2008
2009ByteArray* ByteArray::FromDataStartAddress(Address address) {
2010 ASSERT_TAG_ALIGNED(address);
2011 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2012}
2013
2014
2015Address ByteArray::GetDataStartAddress() {
2016 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2017}
2018
2019
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002020uint8_t* PixelArray::external_pointer() {
2021 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2022 return reinterpret_cast<uint8_t*>(ptr);
2023}
2024
2025
2026void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
2027 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2028 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2029}
2030
2031
2032uint8_t PixelArray::get(int index) {
2033 ASSERT((index >= 0) && (index < this->length()));
2034 uint8_t* ptr = external_pointer();
2035 return ptr[index];
2036}
2037
2038
2039void PixelArray::set(int index, uint8_t value) {
2040 ASSERT((index >= 0) && (index < this->length()));
2041 uint8_t* ptr = external_pointer();
2042 ptr[index] = value;
2043}
2044
2045
ager@chromium.org3811b432009-10-28 14:53:37 +00002046void* ExternalArray::external_pointer() {
2047 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2048 return reinterpret_cast<void*>(ptr);
2049}
2050
2051
2052void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2053 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2054 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2055}
2056
2057
2058int8_t ExternalByteArray::get(int index) {
2059 ASSERT((index >= 0) && (index < this->length()));
2060 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2061 return ptr[index];
2062}
2063
2064
2065void ExternalByteArray::set(int index, int8_t value) {
2066 ASSERT((index >= 0) && (index < this->length()));
2067 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2068 ptr[index] = value;
2069}
2070
2071
2072uint8_t ExternalUnsignedByteArray::get(int index) {
2073 ASSERT((index >= 0) && (index < this->length()));
2074 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2075 return ptr[index];
2076}
2077
2078
2079void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2080 ASSERT((index >= 0) && (index < this->length()));
2081 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2082 ptr[index] = value;
2083}
2084
2085
2086int16_t ExternalShortArray::get(int index) {
2087 ASSERT((index >= 0) && (index < this->length()));
2088 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2089 return ptr[index];
2090}
2091
2092
2093void ExternalShortArray::set(int index, int16_t value) {
2094 ASSERT((index >= 0) && (index < this->length()));
2095 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2096 ptr[index] = value;
2097}
2098
2099
2100uint16_t ExternalUnsignedShortArray::get(int index) {
2101 ASSERT((index >= 0) && (index < this->length()));
2102 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2103 return ptr[index];
2104}
2105
2106
2107void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2108 ASSERT((index >= 0) && (index < this->length()));
2109 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2110 ptr[index] = value;
2111}
2112
2113
2114int32_t ExternalIntArray::get(int index) {
2115 ASSERT((index >= 0) && (index < this->length()));
2116 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2117 return ptr[index];
2118}
2119
2120
2121void ExternalIntArray::set(int index, int32_t value) {
2122 ASSERT((index >= 0) && (index < this->length()));
2123 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2124 ptr[index] = value;
2125}
2126
2127
2128uint32_t ExternalUnsignedIntArray::get(int index) {
2129 ASSERT((index >= 0) && (index < this->length()));
2130 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2131 return ptr[index];
2132}
2133
2134
2135void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2136 ASSERT((index >= 0) && (index < this->length()));
2137 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2138 ptr[index] = value;
2139}
2140
2141
2142float ExternalFloatArray::get(int index) {
2143 ASSERT((index >= 0) && (index < this->length()));
2144 float* ptr = static_cast<float*>(external_pointer());
2145 return ptr[index];
2146}
2147
2148
2149void ExternalFloatArray::set(int index, float value) {
2150 ASSERT((index >= 0) && (index < this->length()));
2151 float* ptr = static_cast<float*>(external_pointer());
2152 ptr[index] = value;
2153}
2154
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002155
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00002156int Map::visitor_id() {
2157 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2158}
2159
2160
2161void Map::set_visitor_id(int id) {
2162 ASSERT(0 <= id && id < 256);
2163 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2164}
2165
ager@chromium.org3811b432009-10-28 14:53:37 +00002166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002167int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002168 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2169}
2170
2171
2172int Map::inobject_properties() {
2173 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002174}
2175
2176
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002177int Map::pre_allocated_property_fields() {
2178 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2179}
2180
2181
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002182int HeapObject::SizeFromMap(Map* map) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002183 int instance_size = map->instance_size();
2184 if (instance_size != kVariableSizeSentinel) return instance_size;
2185 // We can ignore the "symbol" bit becase it is only set for symbols
2186 // and implies a string type.
2187 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002188 // Only inline the most frequent cases.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002189 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002190 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002191 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002192 if (instance_type == ASCII_STRING_TYPE) {
2193 return SeqAsciiString::SizeFor(
2194 reinterpret_cast<SeqAsciiString*>(this)->length());
2195 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002196 if (instance_type == BYTE_ARRAY_TYPE) {
2197 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2198 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002199 if (instance_type == STRING_TYPE) {
2200 return SeqTwoByteString::SizeFor(
2201 reinterpret_cast<SeqTwoByteString*>(this)->length());
2202 }
2203 ASSERT(instance_type == CODE_TYPE);
2204 return reinterpret_cast<Code*>(this)->CodeSize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002205}
2206
2207
2208void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002209 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002210 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002211 ASSERT(0 <= value && value < 256);
2212 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2213}
2214
2215
ager@chromium.org7c537e22008-10-16 08:43:32 +00002216void Map::set_inobject_properties(int value) {
2217 ASSERT(0 <= value && value < 256);
2218 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2219}
2220
2221
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002222void Map::set_pre_allocated_property_fields(int value) {
2223 ASSERT(0 <= value && value < 256);
2224 WRITE_BYTE_FIELD(this,
2225 kPreAllocatedPropertyFieldsOffset,
2226 static_cast<byte>(value));
2227}
2228
2229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002230InstanceType Map::instance_type() {
2231 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2232}
2233
2234
2235void Map::set_instance_type(InstanceType value) {
2236 ASSERT(0 <= value && value < 256);
2237 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2238}
2239
2240
2241int Map::unused_property_fields() {
2242 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2243}
2244
2245
2246void Map::set_unused_property_fields(int value) {
2247 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2248}
2249
2250
2251byte Map::bit_field() {
2252 return READ_BYTE_FIELD(this, kBitFieldOffset);
2253}
2254
2255
2256void Map::set_bit_field(byte value) {
2257 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2258}
2259
2260
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002261byte Map::bit_field2() {
2262 return READ_BYTE_FIELD(this, kBitField2Offset);
2263}
2264
2265
2266void Map::set_bit_field2(byte value) {
2267 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2268}
2269
2270
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002271void Map::set_non_instance_prototype(bool value) {
2272 if (value) {
2273 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2274 } else {
2275 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2276 }
2277}
2278
2279
2280bool Map::has_non_instance_prototype() {
2281 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2282}
2283
2284
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002285void Map::set_function_with_prototype(bool value) {
2286 if (value) {
2287 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2288 } else {
2289 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2290 }
2291}
2292
2293
2294bool Map::function_with_prototype() {
2295 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2296}
2297
2298
ager@chromium.org870a0b62008-11-04 11:43:05 +00002299void Map::set_is_access_check_needed(bool access_check_needed) {
2300 if (access_check_needed) {
2301 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2302 } else {
2303 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2304 }
2305}
2306
2307
2308bool Map::is_access_check_needed() {
2309 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2310}
2311
2312
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002313void Map::set_is_extensible(bool value) {
2314 if (value) {
2315 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2316 } else {
2317 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2318 }
2319}
2320
2321bool Map::is_extensible() {
2322 return ((1 << kIsExtensible) & bit_field2()) != 0;
2323}
2324
2325
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002326void Map::set_attached_to_shared_function_info(bool value) {
2327 if (value) {
2328 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2329 } else {
2330 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2331 }
2332}
2333
2334bool Map::attached_to_shared_function_info() {
2335 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2336}
2337
2338
2339void Map::set_is_shared(bool value) {
2340 if (value) {
2341 set_bit_field2(bit_field2() | (1 << kIsShared));
2342 } else {
2343 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2344 }
2345}
2346
2347bool Map::is_shared() {
2348 return ((1 << kIsShared) & bit_field2()) != 0;
2349}
2350
2351
2352JSFunction* Map::unchecked_constructor() {
2353 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2354}
2355
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002356
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002357Code::Flags Code::flags() {
2358 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2359}
2360
2361
2362void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002363 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002364 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002365 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2366 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002367 ExtractArgumentsCountFromFlags(flags) >= 0);
2368 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2369}
2370
2371
2372Code::Kind Code::kind() {
2373 return ExtractKindFromFlags(flags());
2374}
2375
2376
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002377InLoopFlag Code::ic_in_loop() {
2378 return ExtractICInLoopFromFlags(flags());
2379}
2380
2381
kasper.lund7276f142008-07-30 08:49:36 +00002382InlineCacheState Code::ic_state() {
2383 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002384 // Only allow uninitialized or debugger states for non-IC code
2385 // objects. This is used in the debugger to determine whether or not
2386 // a call to code object has been replaced with a debug break call.
2387 ASSERT(is_inline_cache_stub() ||
2388 result == UNINITIALIZED ||
2389 result == DEBUG_BREAK ||
2390 result == DEBUG_PREPARE_STEP_IN);
2391 return result;
2392}
2393
2394
2395PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002396 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002397 return ExtractTypeFromFlags(flags());
2398}
2399
2400
2401int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002402 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002403 return ExtractArgumentsCountFromFlags(flags());
2404}
2405
2406
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002407int Code::major_key() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002408 ASSERT(kind() == STUB ||
2409 kind() == BINARY_OP_IC ||
2410 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2411 kind() == COMPARE_IC);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002412 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
kasper.lund7276f142008-07-30 08:49:36 +00002413}
2414
2415
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002416void Code::set_major_key(int major) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002417 ASSERT(kind() == STUB ||
2418 kind() == BINARY_OP_IC ||
2419 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2420 kind() == COMPARE_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002421 ASSERT(0 <= major && major < 256);
2422 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002423}
2424
2425
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002426bool Code::optimizable() {
2427 ASSERT(kind() == FUNCTION);
2428 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2429}
2430
2431
2432void Code::set_optimizable(bool value) {
2433 ASSERT(kind() == FUNCTION);
2434 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2435}
2436
2437
2438bool Code::has_deoptimization_support() {
2439 ASSERT(kind() == FUNCTION);
2440 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2441}
2442
2443
2444void Code::set_has_deoptimization_support(bool value) {
2445 ASSERT(kind() == FUNCTION);
2446 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2447}
2448
2449
2450int Code::allow_osr_at_loop_nesting_level() {
2451 ASSERT(kind() == FUNCTION);
2452 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2453}
2454
2455
2456void Code::set_allow_osr_at_loop_nesting_level(int level) {
2457 ASSERT(kind() == FUNCTION);
2458 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2459 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2460}
2461
2462
2463unsigned Code::stack_slots() {
2464 ASSERT(kind() == OPTIMIZED_FUNCTION);
2465 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2466}
2467
2468
2469void Code::set_stack_slots(unsigned slots) {
2470 ASSERT(kind() == OPTIMIZED_FUNCTION);
2471 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2472}
2473
2474
2475unsigned Code::safepoint_table_start() {
2476 ASSERT(kind() == OPTIMIZED_FUNCTION);
2477 return READ_UINT32_FIELD(this, kSafepointTableStartOffset);
2478}
2479
2480
2481void Code::set_safepoint_table_start(unsigned offset) {
2482 ASSERT(kind() == OPTIMIZED_FUNCTION);
2483 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2484 WRITE_UINT32_FIELD(this, kSafepointTableStartOffset, offset);
2485}
2486
2487
2488unsigned Code::stack_check_table_start() {
2489 ASSERT(kind() == FUNCTION);
2490 return READ_UINT32_FIELD(this, kStackCheckTableStartOffset);
2491}
2492
2493
2494void Code::set_stack_check_table_start(unsigned offset) {
2495 ASSERT(kind() == FUNCTION);
2496 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2497 WRITE_UINT32_FIELD(this, kStackCheckTableStartOffset, offset);
2498}
2499
2500
2501CheckType Code::check_type() {
2502 ASSERT(is_call_stub() || is_keyed_call_stub());
2503 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2504 return static_cast<CheckType>(type);
2505}
2506
2507
2508void Code::set_check_type(CheckType value) {
2509 ASSERT(is_call_stub() || is_keyed_call_stub());
2510 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2511}
2512
2513
2514byte Code::binary_op_type() {
2515 ASSERT(is_binary_op_stub());
2516 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2517}
2518
2519
2520void Code::set_binary_op_type(byte value) {
2521 ASSERT(is_binary_op_stub());
2522 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2523}
2524
2525
2526byte Code::type_recording_binary_op_type() {
2527 ASSERT(is_type_recording_binary_op_stub());
2528 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2529}
2530
2531
2532void Code::set_type_recording_binary_op_type(byte value) {
2533 ASSERT(is_type_recording_binary_op_stub());
2534 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2535}
2536
2537
2538byte Code::type_recording_binary_op_result_type() {
2539 ASSERT(is_type_recording_binary_op_stub());
2540 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2541}
2542
2543
2544void Code::set_type_recording_binary_op_result_type(byte value) {
2545 ASSERT(is_type_recording_binary_op_stub());
2546 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2547}
2548
2549
2550byte Code::compare_state() {
2551 ASSERT(is_compare_ic_stub());
2552 return READ_BYTE_FIELD(this, kCompareStateOffset);
2553}
2554
2555
2556void Code::set_compare_state(byte value) {
2557 ASSERT(is_compare_ic_stub());
2558 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2559}
2560
2561
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002562bool Code::is_inline_cache_stub() {
2563 Kind kind = this->kind();
2564 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2565}
2566
2567
2568Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002569 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002570 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002571 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002572 int argc,
2573 InlineCacheHolderFlag holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002574 // Compute the bit mask.
2575 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002576 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002577 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002578 bits |= type << kFlagsTypeShift;
2579 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002580 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002581 // Cast to flags and validate result before returning it.
2582 Flags result = static_cast<Flags>(bits);
2583 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002584 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002585 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002586 ASSERT(ExtractTypeFromFlags(result) == type);
2587 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2588 return result;
2589}
2590
2591
2592Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2593 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002594 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002595 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002596 int argc) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002597 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002598}
2599
2600
2601Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2602 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2603 return static_cast<Kind>(bits);
2604}
2605
2606
kasper.lund7276f142008-07-30 08:49:36 +00002607InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2608 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002609 return static_cast<InlineCacheState>(bits);
2610}
2611
2612
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002613InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2614 int bits = (flags & kFlagsICInLoopMask);
2615 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2616}
2617
2618
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002619PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2620 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2621 return static_cast<PropertyType>(bits);
2622}
2623
2624
2625int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2626 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2627}
2628
2629
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002630InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2631 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2632 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2633}
2634
2635
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002636Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2637 int bits = flags & ~kFlagsTypeMask;
2638 return static_cast<Flags>(bits);
2639}
2640
2641
ager@chromium.org8bb60582008-12-11 12:02:20 +00002642Code* Code::GetCodeFromTargetAddress(Address address) {
2643 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2644 // GetCodeFromTargetAddress might be called when marking objects during mark
2645 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2646 // Code::cast. Code::cast does not work when the object's map is
2647 // marked.
2648 Code* result = reinterpret_cast<Code*>(code);
2649 return result;
2650}
2651
2652
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002653Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2654 return HeapObject::
2655 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2656}
2657
2658
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002659Object* Map::prototype() {
2660 return READ_FIELD(this, kPrototypeOffset);
2661}
2662
2663
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002664void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002665 ASSERT(value->IsNull() || value->IsJSObject());
2666 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002667 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002668}
2669
2670
lrn@chromium.org303ada72010-10-27 09:33:13 +00002671MaybeObject* Map::GetFastElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002672 if (has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002673 Object* obj;
2674 { MaybeObject* maybe_obj = CopyDropTransitions();
2675 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2676 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002677 Map* new_map = Map::cast(obj);
2678 new_map->set_has_fast_elements(true);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002679 Counters::map_slow_to_fast_elements.Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002680 return new_map;
2681}
2682
2683
lrn@chromium.org303ada72010-10-27 09:33:13 +00002684MaybeObject* Map::GetSlowElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002685 if (!has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002686 Object* obj;
2687 { MaybeObject* maybe_obj = CopyDropTransitions();
2688 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2689 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002690 Map* new_map = Map::cast(obj);
2691 new_map->set_has_fast_elements(false);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002692 Counters::map_fast_to_slow_elements.Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002693 return new_map;
2694}
2695
2696
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002697ACCESSORS(Map, instance_descriptors, DescriptorArray,
2698 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002699ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002700ACCESSORS(Map, constructor, Object, kConstructorOffset)
2701
2702ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2703ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002704ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002705
2706ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2707ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002708ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002709
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002710ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002711
2712ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2713ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2714ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2715ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2716ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2717
2718ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2719ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2720ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2721
2722ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2723ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2724ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2725ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2726ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2727ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2728
2729ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2730ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2731
2732ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2733ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2734
2735ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2736ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002737ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2738 kPropertyAccessorsOffset)
2739ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2740 kPrototypeTemplateOffset)
2741ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2742ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2743 kNamedPropertyHandlerOffset)
2744ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2745 kIndexedPropertyHandlerOffset)
2746ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2747 kInstanceTemplateOffset)
2748ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2749ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002750ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2751 kInstanceCallHandlerOffset)
2752ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2753 kAccessCheckInfoOffset)
2754ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2755
2756ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002757ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2758 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002759
2760ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2761ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2762
2763ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2764
2765ACCESSORS(Script, source, Object, kSourceOffset)
2766ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002767ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002768ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2769ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002770ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002771ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002772ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2773ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002774ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002775ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002776ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002777ACCESSORS(Script, eval_from_instructions_offset, Smi,
2778 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002779
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002780#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2782ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2783ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2784ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2785
2786ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2787ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2788ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2789ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002790#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002791
2792ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002793ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002794ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002795ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2796 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002797ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002798ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2799ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002800ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002801ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2802 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002803
2804BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2805 kHiddenPrototypeBit)
2806BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2807BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2808 kNeedsAccessCheckBit)
2809BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2810 kIsExpressionBit)
2811BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2812 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002813BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002814 has_only_simple_this_property_assignments,
2815 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002816BOOL_ACCESSORS(SharedFunctionInfo,
2817 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002818 try_full_codegen,
2819 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002820BOOL_ACCESSORS(SharedFunctionInfo,
2821 compiler_hints,
2822 allows_lazy_compilation,
2823 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002824
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002825
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002826#if V8_HOST_ARCH_32_BIT
2827SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2828SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002829 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002830SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002831 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002832SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2833SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002834 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002835SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2836SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002837 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002838SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002839 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002840SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002841 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002842SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002843#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002844
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002845#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002846 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002847 int holder::name() { \
2848 int value = READ_INT_FIELD(this, offset); \
2849 ASSERT(kHeapObjectTag == 1); \
2850 ASSERT((value & kHeapObjectTag) == 0); \
2851 return value >> 1; \
2852 } \
2853 void holder::set_##name(int value) { \
2854 ASSERT(kHeapObjectTag == 1); \
2855 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2856 (value & 0xC0000000) == 0x000000000); \
2857 WRITE_INT_FIELD(this, \
2858 offset, \
2859 (value << 1) & ~kHeapObjectTag); \
2860 }
2861
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002862#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2863 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002864 INT_ACCESSORS(holder, name, offset)
2865
2866
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002867PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002868PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2869 formal_parameter_count,
2870 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002871
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002872PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2873 expected_nof_properties,
2874 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002875PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2876
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002877PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
2878PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2879 start_position_and_type,
2880 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002881
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002882PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2883 function_token_position,
2884 kFunctionTokenPositionOffset)
2885PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2886 compiler_hints,
2887 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002888
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002889PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2890 this_property_assignments_count,
2891 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002892PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002893#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002894
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002895
2896int SharedFunctionInfo::construction_count() {
2897 return READ_BYTE_FIELD(this, kConstructionCountOffset);
2898}
2899
2900
2901void SharedFunctionInfo::set_construction_count(int value) {
2902 ASSERT(0 <= value && value < 256);
2903 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
2904}
2905
2906
2907bool SharedFunctionInfo::live_objects_may_exist() {
2908 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
2909}
2910
2911
2912void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
2913 if (value) {
2914 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
2915 } else {
2916 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
2917 }
2918}
2919
2920
2921bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
2922 return initial_map() != Heap::undefined_value();
2923}
2924
2925
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002926bool SharedFunctionInfo::optimization_disabled() {
2927 return BooleanBit::get(compiler_hints(), kOptimizationDisabled);
2928}
2929
2930
2931void SharedFunctionInfo::set_optimization_disabled(bool disable) {
2932 set_compiler_hints(BooleanBit::set(compiler_hints(),
2933 kOptimizationDisabled,
2934 disable));
2935 // If disabling optimizations we reflect that in the code object so
2936 // it will not be counted as optimizable code.
2937 if ((code()->kind() == Code::FUNCTION) && disable) {
2938 code()->set_optimizable(false);
2939 }
2940}
2941
2942
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002943ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2944ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2945
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002946bool Script::HasValidSource() {
2947 Object* src = this->source();
2948 if (!src->IsString()) return true;
2949 String* src_str = String::cast(src);
2950 if (!StringShape(src_str).IsExternal()) return true;
2951 if (src_str->IsAsciiRepresentation()) {
2952 return ExternalAsciiString::cast(src)->resource() != NULL;
2953 } else if (src_str->IsTwoByteRepresentation()) {
2954 return ExternalTwoByteString::cast(src)->resource() != NULL;
2955 }
2956 return true;
2957}
2958
2959
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002960void SharedFunctionInfo::DontAdaptArguments() {
2961 ASSERT(code()->kind() == Code::BUILTIN);
2962 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2963}
2964
2965
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002966int SharedFunctionInfo::start_position() {
2967 return start_position_and_type() >> kStartPositionShift;
2968}
2969
2970
2971void SharedFunctionInfo::set_start_position(int start_position) {
2972 set_start_position_and_type((start_position << kStartPositionShift)
2973 | (start_position_and_type() & ~kStartPositionMask));
2974}
2975
2976
2977Code* SharedFunctionInfo::code() {
2978 return Code::cast(READ_FIELD(this, kCodeOffset));
2979}
2980
2981
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002982Code* SharedFunctionInfo::unchecked_code() {
2983 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2984}
2985
2986
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002987void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002988 // If optimization has been disabled for the shared function info,
2989 // reflect that in the code object so it will not be counted as
2990 // optimizable code.
2991 ASSERT(value->kind() != Code::FUNCTION ||
2992 !value->optimizable() ||
2993 this->code() == Builtins::builtin(Builtins::Illegal) ||
2994 this->allows_lazy_compilation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002995 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002996 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002997}
2998
2999
ager@chromium.orgb5737492010-07-15 09:29:43 +00003000SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3001 return reinterpret_cast<SerializedScopeInfo*>(
3002 READ_FIELD(this, kScopeInfoOffset));
3003}
3004
3005
3006void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3007 WriteBarrierMode mode) {
3008 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3009 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
3010}
3011
3012
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003013Smi* SharedFunctionInfo::deopt_counter() {
3014 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3015}
3016
3017
3018void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3019 WRITE_FIELD(this, kDeoptCounterOffset, value);
3020}
3021
3022
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003023bool SharedFunctionInfo::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003024 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003025}
3026
3027
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003028bool SharedFunctionInfo::IsApiFunction() {
3029 return function_data()->IsFunctionTemplateInfo();
3030}
3031
3032
3033FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3034 ASSERT(IsApiFunction());
3035 return FunctionTemplateInfo::cast(function_data());
3036}
3037
3038
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003039bool SharedFunctionInfo::HasBuiltinFunctionId() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003040 return function_data()->IsSmi();
3041}
3042
3043
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003044bool SharedFunctionInfo::IsBuiltinMathFunction() {
3045 return HasBuiltinFunctionId() &&
3046 builtin_function_id() >= kFirstMathFunctionId;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003047}
3048
3049
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003050BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3051 ASSERT(HasBuiltinFunctionId());
3052 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003053}
3054
3055
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003056int SharedFunctionInfo::code_age() {
3057 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3058}
3059
3060
3061void SharedFunctionInfo::set_code_age(int code_age) {
3062 set_compiler_hints(compiler_hints() |
3063 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3064}
3065
3066
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003067bool SharedFunctionInfo::has_deoptimization_support() {
3068 Code* code = this->code();
3069 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3070}
3071
3072
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003073bool JSFunction::IsBuiltin() {
3074 return context()->global()->IsJSBuiltinsObject();
3075}
3076
3077
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003078bool JSFunction::NeedsArgumentsAdaption() {
3079 return shared()->formal_parameter_count() !=
3080 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3081}
3082
3083
3084bool JSFunction::IsOptimized() {
3085 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3086}
3087
3088
3089bool JSFunction::IsMarkedForLazyRecompilation() {
3090 return code() == Builtins::builtin(Builtins::LazyRecompile);
3091}
3092
3093
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003094Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003095 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003096}
3097
3098
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003099Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003100 return reinterpret_cast<Code*>(
3101 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003102}
3103
3104
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003105void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003106 // Skip the write barrier because code is never in new space.
3107 ASSERT(!Heap::InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003108 Address entry = value->entry();
3109 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003110}
3111
3112
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003113void JSFunction::ReplaceCode(Code* code) {
3114 bool was_optimized = IsOptimized();
3115 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3116
3117 set_code(code);
3118
3119 // Add/remove the function from the list of optimized functions for this
3120 // context based on the state change.
3121 if (!was_optimized && is_optimized) {
3122 context()->global_context()->AddOptimizedFunction(this);
3123 }
3124 if (was_optimized && !is_optimized) {
3125 context()->global_context()->RemoveOptimizedFunction(this);
3126 }
3127}
3128
3129
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003130Context* JSFunction::context() {
3131 return Context::cast(READ_FIELD(this, kContextOffset));
3132}
3133
3134
3135Object* JSFunction::unchecked_context() {
3136 return READ_FIELD(this, kContextOffset);
3137}
3138
3139
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003140SharedFunctionInfo* JSFunction::unchecked_shared() {
3141 return reinterpret_cast<SharedFunctionInfo*>(
3142 READ_FIELD(this, kSharedFunctionInfoOffset));
3143}
3144
3145
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003146void JSFunction::set_context(Object* value) {
3147 ASSERT(value == Heap::undefined_value() || value->IsContext());
3148 WRITE_FIELD(this, kContextOffset, value);
3149 WRITE_BARRIER(this, kContextOffset);
3150}
3151
3152ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3153 kPrototypeOrInitialMapOffset)
3154
3155
3156Map* JSFunction::initial_map() {
3157 return Map::cast(prototype_or_initial_map());
3158}
3159
3160
3161void JSFunction::set_initial_map(Map* value) {
3162 set_prototype_or_initial_map(value);
3163}
3164
3165
3166bool JSFunction::has_initial_map() {
3167 return prototype_or_initial_map()->IsMap();
3168}
3169
3170
3171bool JSFunction::has_instance_prototype() {
3172 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3173}
3174
3175
3176bool JSFunction::has_prototype() {
3177 return map()->has_non_instance_prototype() || has_instance_prototype();
3178}
3179
3180
3181Object* JSFunction::instance_prototype() {
3182 ASSERT(has_instance_prototype());
3183 if (has_initial_map()) return initial_map()->prototype();
3184 // When there is no initial map and the prototype is a JSObject, the
3185 // initial map field is used for the prototype field.
3186 return prototype_or_initial_map();
3187}
3188
3189
3190Object* JSFunction::prototype() {
3191 ASSERT(has_prototype());
3192 // If the function's prototype property has been set to a non-JSObject
3193 // value, that value is stored in the constructor field of the map.
3194 if (map()->has_non_instance_prototype()) return map()->constructor();
3195 return instance_prototype();
3196}
3197
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003198bool JSFunction::should_have_prototype() {
3199 return map()->function_with_prototype();
3200}
3201
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003202
3203bool JSFunction::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003204 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003205}
3206
3207
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003208int JSFunction::NumberOfLiterals() {
3209 return literals()->length();
3210}
3211
3212
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003213Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
3214 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003215 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003216}
3217
3218
3219void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3220 Object* value) {
3221 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003222 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3223 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3224}
3225
3226
3227Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
3228 ASSERT(0 <= id && id < kJSBuiltinsCount);
3229 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3230}
3231
3232
3233void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3234 Code* value) {
3235 ASSERT(0 <= id && id < kJSBuiltinsCount);
3236 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3237 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003238}
3239
3240
3241Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00003242 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003243}
3244
3245
3246void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00003247 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003248}
3249
3250
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003251ACCESSORS(JSValue, value, Object, kValueOffset)
3252
3253
3254JSValue* JSValue::cast(Object* obj) {
3255 ASSERT(obj->IsJSValue());
3256 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3257 return reinterpret_cast<JSValue*>(obj);
3258}
3259
3260
3261INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003262ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003263ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003264
3265
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003266byte* Code::instruction_start() {
3267 return FIELD_ADDR(this, kHeaderSize);
3268}
3269
3270
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003271byte* Code::instruction_end() {
3272 return instruction_start() + instruction_size();
3273}
3274
3275
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003276int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003277 return RoundUp(instruction_size(), kObjectAlignment);
3278}
3279
3280
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003281FixedArray* Code::unchecked_deoptimization_data() {
3282 return reinterpret_cast<FixedArray*>(
3283 READ_FIELD(this, kDeoptimizationDataOffset));
3284}
3285
3286
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003287ByteArray* Code::unchecked_relocation_info() {
3288 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003289}
3290
3291
3292byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003293 return unchecked_relocation_info()->GetDataStartAddress();
3294}
3295
3296
3297int Code::relocation_size() {
3298 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003299}
3300
3301
3302byte* Code::entry() {
3303 return instruction_start();
3304}
3305
3306
3307bool Code::contains(byte* pc) {
3308 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003309 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003310}
3311
3312
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003313ACCESSORS(JSArray, length, Object, kLengthOffset)
3314
3315
ager@chromium.org236ad962008-09-25 09:45:57 +00003316ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003317
3318
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003319JSRegExp::Type JSRegExp::TypeTag() {
3320 Object* data = this->data();
3321 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3322 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3323 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003324}
3325
3326
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003327int JSRegExp::CaptureCount() {
3328 switch (TypeTag()) {
3329 case ATOM:
3330 return 0;
3331 case IRREGEXP:
3332 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3333 default:
3334 UNREACHABLE();
3335 return -1;
3336 }
3337}
3338
3339
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003340JSRegExp::Flags JSRegExp::GetFlags() {
3341 ASSERT(this->data()->IsFixedArray());
3342 Object* data = this->data();
3343 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3344 return Flags(smi->value());
3345}
3346
3347
3348String* JSRegExp::Pattern() {
3349 ASSERT(this->data()->IsFixedArray());
3350 Object* data = this->data();
3351 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3352 return pattern;
3353}
3354
3355
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003356Object* JSRegExp::DataAt(int index) {
3357 ASSERT(TypeTag() != NOT_COMPILED);
3358 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003359}
3360
3361
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003362void JSRegExp::SetDataAt(int index, Object* value) {
3363 ASSERT(TypeTag() != NOT_COMPILED);
3364 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3365 FixedArray::cast(data())->set(index, value);
3366}
3367
3368
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003369JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003370 if (map()->has_fast_elements()) {
3371 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3372 elements()->map() == Heap::fixed_cow_array_map());
3373 return FAST_ELEMENTS;
3374 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003375 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003376 if (array->IsFixedArray()) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003377 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3378 // FixedArray, but FAST_ELEMENTS is already handled above.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003379 ASSERT(array->IsDictionary());
3380 return DICTIONARY_ELEMENTS;
3381 }
ager@chromium.org3811b432009-10-28 14:53:37 +00003382 if (array->IsExternalArray()) {
3383 switch (array->map()->instance_type()) {
3384 case EXTERNAL_BYTE_ARRAY_TYPE:
3385 return EXTERNAL_BYTE_ELEMENTS;
3386 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3387 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3388 case EXTERNAL_SHORT_ARRAY_TYPE:
3389 return EXTERNAL_SHORT_ELEMENTS;
3390 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3391 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3392 case EXTERNAL_INT_ARRAY_TYPE:
3393 return EXTERNAL_INT_ELEMENTS;
3394 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3395 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3396 default:
3397 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3398 return EXTERNAL_FLOAT_ELEMENTS;
3399 }
3400 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003401 ASSERT(array->IsPixelArray());
3402 return PIXEL_ELEMENTS;
3403}
3404
3405
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003406bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003407 return GetElementsKind() == FAST_ELEMENTS;
3408}
3409
3410
3411bool JSObject::HasDictionaryElements() {
3412 return GetElementsKind() == DICTIONARY_ELEMENTS;
3413}
3414
3415
3416bool JSObject::HasPixelElements() {
3417 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003418}
3419
3420
ager@chromium.org3811b432009-10-28 14:53:37 +00003421bool JSObject::HasExternalArrayElements() {
3422 return (HasExternalByteElements() ||
3423 HasExternalUnsignedByteElements() ||
3424 HasExternalShortElements() ||
3425 HasExternalUnsignedShortElements() ||
3426 HasExternalIntElements() ||
3427 HasExternalUnsignedIntElements() ||
3428 HasExternalFloatElements());
3429}
3430
3431
3432bool JSObject::HasExternalByteElements() {
3433 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3434}
3435
3436
3437bool JSObject::HasExternalUnsignedByteElements() {
3438 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3439}
3440
3441
3442bool JSObject::HasExternalShortElements() {
3443 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3444}
3445
3446
3447bool JSObject::HasExternalUnsignedShortElements() {
3448 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3449}
3450
3451
3452bool JSObject::HasExternalIntElements() {
3453 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3454}
3455
3456
3457bool JSObject::HasExternalUnsignedIntElements() {
3458 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3459}
3460
3461
3462bool JSObject::HasExternalFloatElements() {
3463 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3464}
3465
3466
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003467bool JSObject::HasNamedInterceptor() {
3468 return map()->has_named_interceptor();
3469}
3470
3471
3472bool JSObject::HasIndexedInterceptor() {
3473 return map()->has_indexed_interceptor();
3474}
3475
3476
ager@chromium.org5c838252010-02-19 08:53:10 +00003477bool JSObject::AllowsSetElementsLength() {
3478 bool result = elements()->IsFixedArray();
3479 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3480 return result;
3481}
3482
3483
lrn@chromium.org303ada72010-10-27 09:33:13 +00003484MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003485 ASSERT(HasFastElements());
3486 FixedArray* elems = FixedArray::cast(elements());
3487 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003488 Object* writable_elems;
3489 { MaybeObject* maybe_writable_elems =
3490 Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
3491 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3492 return maybe_writable_elems;
3493 }
3494 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003495 set_elements(FixedArray::cast(writable_elems));
3496 Counters::cow_arrays_converted.Increment();
3497 return writable_elems;
3498}
3499
3500
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003501StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003502 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003503 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003504}
3505
3506
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003507NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003508 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003509 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003510}
3511
3512
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003513bool String::IsHashFieldComputed(uint32_t field) {
3514 return (field & kHashNotComputedMask) == 0;
3515}
3516
3517
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003518bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003519 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003520}
3521
3522
3523uint32_t String::Hash() {
3524 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003525 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003526 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003527 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003528 return ComputeAndSetHash();
3529}
3530
3531
ager@chromium.org7c537e22008-10-16 08:43:32 +00003532StringHasher::StringHasher(int length)
3533 : length_(length),
3534 raw_running_hash_(0),
3535 array_index_(0),
3536 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3537 is_first_char_(true),
3538 is_valid_(true) { }
3539
3540
3541bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003542 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003543}
3544
3545
3546void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003547 // Use the Jenkins one-at-a-time hash function to update the hash
3548 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003549 raw_running_hash_ += c;
3550 raw_running_hash_ += (raw_running_hash_ << 10);
3551 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003552 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003553 if (is_array_index_) {
3554 if (c < '0' || c > '9') {
3555 is_array_index_ = false;
3556 } else {
3557 int d = c - '0';
3558 if (is_first_char_) {
3559 is_first_char_ = false;
3560 if (c == '0' && length_ > 1) {
3561 is_array_index_ = false;
3562 return;
3563 }
3564 }
3565 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3566 is_array_index_ = false;
3567 } else {
3568 array_index_ = array_index_ * 10 + d;
3569 }
3570 }
3571 }
3572}
3573
3574
3575void StringHasher::AddCharacterNoIndex(uc32 c) {
3576 ASSERT(!is_array_index());
3577 raw_running_hash_ += c;
3578 raw_running_hash_ += (raw_running_hash_ << 10);
3579 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3580}
3581
3582
3583uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003584 // Get the calculated raw hash value and do some more bit ops to distribute
3585 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003586 uint32_t result = raw_running_hash_;
3587 result += (result << 3);
3588 result ^= (result >> 11);
3589 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003590 if (result == 0) {
3591 result = 27;
3592 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003593 return result;
3594}
3595
3596
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003597bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003598 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003599 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3600 return false;
3601 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003602 return SlowAsArrayIndex(index);
3603}
3604
3605
3606Object* JSObject::GetPrototype() {
3607 return JSObject::cast(this)->map()->prototype();
3608}
3609
3610
3611PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3612 return GetPropertyAttributeWithReceiver(this, key);
3613}
3614
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003615// TODO(504): this may be useful in other places too where JSGlobalProxy
3616// is used.
3617Object* JSObject::BypassGlobalProxy() {
3618 if (IsJSGlobalProxy()) {
3619 Object* proto = GetPrototype();
3620 if (proto->IsNull()) return Heap::undefined_value();
3621 ASSERT(proto->IsJSGlobalObject());
3622 return proto;
3623 }
3624 return this;
3625}
3626
3627
3628bool JSObject::HasHiddenPropertiesObject() {
3629 ASSERT(!IsJSGlobalProxy());
3630 return GetPropertyAttributePostInterceptor(this,
3631 Heap::hidden_symbol(),
3632 false) != ABSENT;
3633}
3634
3635
3636Object* JSObject::GetHiddenPropertiesObject() {
3637 ASSERT(!IsJSGlobalProxy());
3638 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003639 // You can't install a getter on a property indexed by the hidden symbol,
3640 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3641 // object.
3642 Object* result =
3643 GetLocalPropertyPostInterceptor(this,
3644 Heap::hidden_symbol(),
3645 &attributes)->ToObjectUnchecked();
3646 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003647}
3648
3649
lrn@chromium.org303ada72010-10-27 09:33:13 +00003650MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003651 ASSERT(!IsJSGlobalProxy());
3652 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3653 hidden_obj,
3654 DONT_ENUM);
3655}
3656
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003657
3658bool JSObject::HasElement(uint32_t index) {
3659 return HasElementWithReceiver(this, index);
3660}
3661
3662
3663bool AccessorInfo::all_can_read() {
3664 return BooleanBit::get(flag(), kAllCanReadBit);
3665}
3666
3667
3668void AccessorInfo::set_all_can_read(bool value) {
3669 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3670}
3671
3672
3673bool AccessorInfo::all_can_write() {
3674 return BooleanBit::get(flag(), kAllCanWriteBit);
3675}
3676
3677
3678void AccessorInfo::set_all_can_write(bool value) {
3679 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3680}
3681
3682
ager@chromium.org870a0b62008-11-04 11:43:05 +00003683bool AccessorInfo::prohibits_overwriting() {
3684 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3685}
3686
3687
3688void AccessorInfo::set_prohibits_overwriting(bool value) {
3689 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3690}
3691
3692
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003693PropertyAttributes AccessorInfo::property_attributes() {
3694 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3695}
3696
3697
3698void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3699 ASSERT(AttributesField::is_valid(attributes));
3700 int rest_value = flag()->value() & ~AttributesField::mask();
3701 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3702}
3703
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003704template<typename Shape, typename Key>
3705void Dictionary<Shape, Key>::SetEntry(int entry,
3706 Object* key,
3707 Object* value,
3708 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003709 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003710 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003711 AssertNoAllocation no_gc;
3712 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003713 FixedArray::set(index, key, mode);
3714 FixedArray::set(index+1, value, mode);
3715 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003716}
3717
3718
3719void Map::ClearCodeCache() {
3720 // No write barrier is needed since empty_fixed_array is not in new space.
3721 // Please note this function is used during marking:
3722 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003723 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3724 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003725}
3726
3727
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003728void JSArray::EnsureSize(int required_size) {
3729 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003730 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003731 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3732 if (elts->length() < required_size) {
3733 // Doubling in size would be overkill, but leave some slack to avoid
3734 // constantly growing.
3735 Expand(required_size + (required_size >> 3));
3736 // It's a performance benefit to keep a frequently used array in new-space.
3737 } else if (!Heap::new_space()->Contains(elts) &&
3738 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3739 // Expand will allocate a new backing store in new space even if the size
3740 // we asked for isn't larger than what we had before.
3741 Expand(required_size);
3742 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003743}
3744
3745
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003746void JSArray::set_length(Smi* length) {
3747 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3748}
3749
3750
ager@chromium.org7c537e22008-10-16 08:43:32 +00003751void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003752 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003753 set_elements(storage);
3754}
3755
3756
lrn@chromium.org303ada72010-10-27 09:33:13 +00003757MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003758 if (length() == 0) return this;
3759 return Heap::CopyFixedArray(this);
3760}
3761
3762
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003763int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3764 return map->instance_size();
3765}
3766
3767
3768void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3769 v->VisitExternalReference(
3770 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3771}
3772
3773
3774template<typename StaticVisitor>
3775void Proxy::ProxyIterateBody() {
3776 StaticVisitor::VisitExternalReference(
3777 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3778}
3779
3780
3781void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3782 typedef v8::String::ExternalAsciiStringResource Resource;
3783 v->VisitExternalAsciiString(
3784 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3785}
3786
3787
3788template<typename StaticVisitor>
3789void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3790 typedef v8::String::ExternalAsciiStringResource Resource;
3791 StaticVisitor::VisitExternalAsciiString(
3792 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3793}
3794
3795
3796void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3797 typedef v8::String::ExternalStringResource Resource;
3798 v->VisitExternalTwoByteString(
3799 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3800}
3801
3802
3803template<typename StaticVisitor>
3804void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3805 typedef v8::String::ExternalStringResource Resource;
3806 StaticVisitor::VisitExternalTwoByteString(
3807 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3808}
3809
3810#define SLOT_ADDR(obj, offset) \
3811 reinterpret_cast<Object**>((obj)->address() + offset)
3812
3813template<int start_offset, int end_offset, int size>
3814void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3815 HeapObject* obj,
3816 ObjectVisitor* v) {
3817 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3818}
3819
3820
3821template<int start_offset>
3822void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3823 int object_size,
3824 ObjectVisitor* v) {
3825 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3826}
3827
3828#undef SLOT_ADDR
3829
3830
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003831#undef CAST_ACCESSOR
3832#undef INT_ACCESSORS
3833#undef SMI_ACCESSORS
3834#undef ACCESSORS
3835#undef FIELD_ADDR
3836#undef READ_FIELD
3837#undef WRITE_FIELD
3838#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003839#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003840#undef READ_MEMADDR_FIELD
3841#undef WRITE_MEMADDR_FIELD
3842#undef READ_DOUBLE_FIELD
3843#undef WRITE_DOUBLE_FIELD
3844#undef READ_INT_FIELD
3845#undef WRITE_INT_FIELD
3846#undef READ_SHORT_FIELD
3847#undef WRITE_SHORT_FIELD
3848#undef READ_BYTE_FIELD
3849#undef WRITE_BYTE_FIELD
3850
3851
3852} } // namespace v8::internal
3853
3854#endif // V8_OBJECTS_INL_H_