blob: 591012805b0c8c44d3009c2deb5ed80ceeae81cb [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
3039bool SharedFunctionInfo::HasCustomCallGenerator() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003040 return function_data()->IsSmi();
3041}
3042
3043
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003044MathFunctionId SharedFunctionInfo::math_function_id() {
3045 return static_cast<MathFunctionId>(
3046 (compiler_hints() >> kMathFunctionShift) & kMathFunctionMask);
3047}
3048
3049
3050void SharedFunctionInfo::set_math_function_id(int math_fn) {
3051 ASSERT(math_fn <= max_math_id_number());
3052 set_compiler_hints(compiler_hints() |
3053 ((math_fn & kMathFunctionMask) << kMathFunctionShift));
3054}
3055
3056
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003057int SharedFunctionInfo::custom_call_generator_id() {
3058 ASSERT(HasCustomCallGenerator());
3059 return Smi::cast(function_data())->value();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003060}
3061
3062
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003063int SharedFunctionInfo::code_age() {
3064 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3065}
3066
3067
3068void SharedFunctionInfo::set_code_age(int code_age) {
3069 set_compiler_hints(compiler_hints() |
3070 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3071}
3072
3073
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003074bool SharedFunctionInfo::has_deoptimization_support() {
3075 Code* code = this->code();
3076 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3077}
3078
3079
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003080bool JSFunction::IsBuiltin() {
3081 return context()->global()->IsJSBuiltinsObject();
3082}
3083
3084
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003085bool JSFunction::NeedsArgumentsAdaption() {
3086 return shared()->formal_parameter_count() !=
3087 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3088}
3089
3090
3091bool JSFunction::IsOptimized() {
3092 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3093}
3094
3095
3096bool JSFunction::IsMarkedForLazyRecompilation() {
3097 return code() == Builtins::builtin(Builtins::LazyRecompile);
3098}
3099
3100
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003101Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003102 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003103}
3104
3105
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003106Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003107 return reinterpret_cast<Code*>(
3108 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003109}
3110
3111
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003112void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003113 // Skip the write barrier because code is never in new space.
3114 ASSERT(!Heap::InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003115 Address entry = value->entry();
3116 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003117}
3118
3119
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003120void JSFunction::ReplaceCode(Code* code) {
3121 bool was_optimized = IsOptimized();
3122 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3123
3124 set_code(code);
3125
3126 // Add/remove the function from the list of optimized functions for this
3127 // context based on the state change.
3128 if (!was_optimized && is_optimized) {
3129 context()->global_context()->AddOptimizedFunction(this);
3130 }
3131 if (was_optimized && !is_optimized) {
3132 context()->global_context()->RemoveOptimizedFunction(this);
3133 }
3134}
3135
3136
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003137Context* JSFunction::context() {
3138 return Context::cast(READ_FIELD(this, kContextOffset));
3139}
3140
3141
3142Object* JSFunction::unchecked_context() {
3143 return READ_FIELD(this, kContextOffset);
3144}
3145
3146
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003147SharedFunctionInfo* JSFunction::unchecked_shared() {
3148 return reinterpret_cast<SharedFunctionInfo*>(
3149 READ_FIELD(this, kSharedFunctionInfoOffset));
3150}
3151
3152
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003153void JSFunction::set_context(Object* value) {
3154 ASSERT(value == Heap::undefined_value() || value->IsContext());
3155 WRITE_FIELD(this, kContextOffset, value);
3156 WRITE_BARRIER(this, kContextOffset);
3157}
3158
3159ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3160 kPrototypeOrInitialMapOffset)
3161
3162
3163Map* JSFunction::initial_map() {
3164 return Map::cast(prototype_or_initial_map());
3165}
3166
3167
3168void JSFunction::set_initial_map(Map* value) {
3169 set_prototype_or_initial_map(value);
3170}
3171
3172
3173bool JSFunction::has_initial_map() {
3174 return prototype_or_initial_map()->IsMap();
3175}
3176
3177
3178bool JSFunction::has_instance_prototype() {
3179 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3180}
3181
3182
3183bool JSFunction::has_prototype() {
3184 return map()->has_non_instance_prototype() || has_instance_prototype();
3185}
3186
3187
3188Object* JSFunction::instance_prototype() {
3189 ASSERT(has_instance_prototype());
3190 if (has_initial_map()) return initial_map()->prototype();
3191 // When there is no initial map and the prototype is a JSObject, the
3192 // initial map field is used for the prototype field.
3193 return prototype_or_initial_map();
3194}
3195
3196
3197Object* JSFunction::prototype() {
3198 ASSERT(has_prototype());
3199 // If the function's prototype property has been set to a non-JSObject
3200 // value, that value is stored in the constructor field of the map.
3201 if (map()->has_non_instance_prototype()) return map()->constructor();
3202 return instance_prototype();
3203}
3204
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003205bool JSFunction::should_have_prototype() {
3206 return map()->function_with_prototype();
3207}
3208
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003209
3210bool JSFunction::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003211 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003212}
3213
3214
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003215int JSFunction::NumberOfLiterals() {
3216 return literals()->length();
3217}
3218
3219
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003220Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
3221 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003222 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003223}
3224
3225
3226void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3227 Object* value) {
3228 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003229 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3230 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3231}
3232
3233
3234Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
3235 ASSERT(0 <= id && id < kJSBuiltinsCount);
3236 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3237}
3238
3239
3240void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3241 Code* value) {
3242 ASSERT(0 <= id && id < kJSBuiltinsCount);
3243 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3244 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003245}
3246
3247
3248Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00003249 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003250}
3251
3252
3253void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00003254 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003255}
3256
3257
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003258ACCESSORS(JSValue, value, Object, kValueOffset)
3259
3260
3261JSValue* JSValue::cast(Object* obj) {
3262 ASSERT(obj->IsJSValue());
3263 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3264 return reinterpret_cast<JSValue*>(obj);
3265}
3266
3267
3268INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003269ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003270ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003271
3272
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003273byte* Code::instruction_start() {
3274 return FIELD_ADDR(this, kHeaderSize);
3275}
3276
3277
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003278byte* Code::instruction_end() {
3279 return instruction_start() + instruction_size();
3280}
3281
3282
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003283int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003284 return RoundUp(instruction_size(), kObjectAlignment);
3285}
3286
3287
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003288FixedArray* Code::unchecked_deoptimization_data() {
3289 return reinterpret_cast<FixedArray*>(
3290 READ_FIELD(this, kDeoptimizationDataOffset));
3291}
3292
3293
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003294ByteArray* Code::unchecked_relocation_info() {
3295 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003296}
3297
3298
3299byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003300 return unchecked_relocation_info()->GetDataStartAddress();
3301}
3302
3303
3304int Code::relocation_size() {
3305 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003306}
3307
3308
3309byte* Code::entry() {
3310 return instruction_start();
3311}
3312
3313
3314bool Code::contains(byte* pc) {
3315 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003316 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003317}
3318
3319
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003320ACCESSORS(JSArray, length, Object, kLengthOffset)
3321
3322
ager@chromium.org236ad962008-09-25 09:45:57 +00003323ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003324
3325
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003326JSRegExp::Type JSRegExp::TypeTag() {
3327 Object* data = this->data();
3328 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3329 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3330 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003331}
3332
3333
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003334int JSRegExp::CaptureCount() {
3335 switch (TypeTag()) {
3336 case ATOM:
3337 return 0;
3338 case IRREGEXP:
3339 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3340 default:
3341 UNREACHABLE();
3342 return -1;
3343 }
3344}
3345
3346
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003347JSRegExp::Flags JSRegExp::GetFlags() {
3348 ASSERT(this->data()->IsFixedArray());
3349 Object* data = this->data();
3350 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3351 return Flags(smi->value());
3352}
3353
3354
3355String* JSRegExp::Pattern() {
3356 ASSERT(this->data()->IsFixedArray());
3357 Object* data = this->data();
3358 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3359 return pattern;
3360}
3361
3362
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003363Object* JSRegExp::DataAt(int index) {
3364 ASSERT(TypeTag() != NOT_COMPILED);
3365 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003366}
3367
3368
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003369void JSRegExp::SetDataAt(int index, Object* value) {
3370 ASSERT(TypeTag() != NOT_COMPILED);
3371 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3372 FixedArray::cast(data())->set(index, value);
3373}
3374
3375
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003376JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003377 if (map()->has_fast_elements()) {
3378 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3379 elements()->map() == Heap::fixed_cow_array_map());
3380 return FAST_ELEMENTS;
3381 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003382 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003383 if (array->IsFixedArray()) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003384 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3385 // FixedArray, but FAST_ELEMENTS is already handled above.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003386 ASSERT(array->IsDictionary());
3387 return DICTIONARY_ELEMENTS;
3388 }
ager@chromium.org3811b432009-10-28 14:53:37 +00003389 if (array->IsExternalArray()) {
3390 switch (array->map()->instance_type()) {
3391 case EXTERNAL_BYTE_ARRAY_TYPE:
3392 return EXTERNAL_BYTE_ELEMENTS;
3393 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3394 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3395 case EXTERNAL_SHORT_ARRAY_TYPE:
3396 return EXTERNAL_SHORT_ELEMENTS;
3397 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3398 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3399 case EXTERNAL_INT_ARRAY_TYPE:
3400 return EXTERNAL_INT_ELEMENTS;
3401 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3402 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3403 default:
3404 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3405 return EXTERNAL_FLOAT_ELEMENTS;
3406 }
3407 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003408 ASSERT(array->IsPixelArray());
3409 return PIXEL_ELEMENTS;
3410}
3411
3412
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003413bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003414 return GetElementsKind() == FAST_ELEMENTS;
3415}
3416
3417
3418bool JSObject::HasDictionaryElements() {
3419 return GetElementsKind() == DICTIONARY_ELEMENTS;
3420}
3421
3422
3423bool JSObject::HasPixelElements() {
3424 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003425}
3426
3427
ager@chromium.org3811b432009-10-28 14:53:37 +00003428bool JSObject::HasExternalArrayElements() {
3429 return (HasExternalByteElements() ||
3430 HasExternalUnsignedByteElements() ||
3431 HasExternalShortElements() ||
3432 HasExternalUnsignedShortElements() ||
3433 HasExternalIntElements() ||
3434 HasExternalUnsignedIntElements() ||
3435 HasExternalFloatElements());
3436}
3437
3438
3439bool JSObject::HasExternalByteElements() {
3440 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3441}
3442
3443
3444bool JSObject::HasExternalUnsignedByteElements() {
3445 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3446}
3447
3448
3449bool JSObject::HasExternalShortElements() {
3450 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3451}
3452
3453
3454bool JSObject::HasExternalUnsignedShortElements() {
3455 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3456}
3457
3458
3459bool JSObject::HasExternalIntElements() {
3460 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3461}
3462
3463
3464bool JSObject::HasExternalUnsignedIntElements() {
3465 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3466}
3467
3468
3469bool JSObject::HasExternalFloatElements() {
3470 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3471}
3472
3473
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003474bool JSObject::HasNamedInterceptor() {
3475 return map()->has_named_interceptor();
3476}
3477
3478
3479bool JSObject::HasIndexedInterceptor() {
3480 return map()->has_indexed_interceptor();
3481}
3482
3483
ager@chromium.org5c838252010-02-19 08:53:10 +00003484bool JSObject::AllowsSetElementsLength() {
3485 bool result = elements()->IsFixedArray();
3486 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3487 return result;
3488}
3489
3490
lrn@chromium.org303ada72010-10-27 09:33:13 +00003491MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003492 ASSERT(HasFastElements());
3493 FixedArray* elems = FixedArray::cast(elements());
3494 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003495 Object* writable_elems;
3496 { MaybeObject* maybe_writable_elems =
3497 Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
3498 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3499 return maybe_writable_elems;
3500 }
3501 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003502 set_elements(FixedArray::cast(writable_elems));
3503 Counters::cow_arrays_converted.Increment();
3504 return writable_elems;
3505}
3506
3507
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003508StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003509 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003510 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003511}
3512
3513
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003514NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003515 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003516 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003517}
3518
3519
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003520bool String::IsHashFieldComputed(uint32_t field) {
3521 return (field & kHashNotComputedMask) == 0;
3522}
3523
3524
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003525bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003526 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003527}
3528
3529
3530uint32_t String::Hash() {
3531 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003532 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003533 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003534 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003535 return ComputeAndSetHash();
3536}
3537
3538
ager@chromium.org7c537e22008-10-16 08:43:32 +00003539StringHasher::StringHasher(int length)
3540 : length_(length),
3541 raw_running_hash_(0),
3542 array_index_(0),
3543 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3544 is_first_char_(true),
3545 is_valid_(true) { }
3546
3547
3548bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003549 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003550}
3551
3552
3553void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003554 // Use the Jenkins one-at-a-time hash function to update the hash
3555 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003556 raw_running_hash_ += c;
3557 raw_running_hash_ += (raw_running_hash_ << 10);
3558 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003559 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003560 if (is_array_index_) {
3561 if (c < '0' || c > '9') {
3562 is_array_index_ = false;
3563 } else {
3564 int d = c - '0';
3565 if (is_first_char_) {
3566 is_first_char_ = false;
3567 if (c == '0' && length_ > 1) {
3568 is_array_index_ = false;
3569 return;
3570 }
3571 }
3572 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3573 is_array_index_ = false;
3574 } else {
3575 array_index_ = array_index_ * 10 + d;
3576 }
3577 }
3578 }
3579}
3580
3581
3582void StringHasher::AddCharacterNoIndex(uc32 c) {
3583 ASSERT(!is_array_index());
3584 raw_running_hash_ += c;
3585 raw_running_hash_ += (raw_running_hash_ << 10);
3586 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3587}
3588
3589
3590uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003591 // Get the calculated raw hash value and do some more bit ops to distribute
3592 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003593 uint32_t result = raw_running_hash_;
3594 result += (result << 3);
3595 result ^= (result >> 11);
3596 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003597 if (result == 0) {
3598 result = 27;
3599 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003600 return result;
3601}
3602
3603
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003604bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003605 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003606 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3607 return false;
3608 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003609 return SlowAsArrayIndex(index);
3610}
3611
3612
3613Object* JSObject::GetPrototype() {
3614 return JSObject::cast(this)->map()->prototype();
3615}
3616
3617
3618PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3619 return GetPropertyAttributeWithReceiver(this, key);
3620}
3621
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003622// TODO(504): this may be useful in other places too where JSGlobalProxy
3623// is used.
3624Object* JSObject::BypassGlobalProxy() {
3625 if (IsJSGlobalProxy()) {
3626 Object* proto = GetPrototype();
3627 if (proto->IsNull()) return Heap::undefined_value();
3628 ASSERT(proto->IsJSGlobalObject());
3629 return proto;
3630 }
3631 return this;
3632}
3633
3634
3635bool JSObject::HasHiddenPropertiesObject() {
3636 ASSERT(!IsJSGlobalProxy());
3637 return GetPropertyAttributePostInterceptor(this,
3638 Heap::hidden_symbol(),
3639 false) != ABSENT;
3640}
3641
3642
3643Object* JSObject::GetHiddenPropertiesObject() {
3644 ASSERT(!IsJSGlobalProxy());
3645 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003646 // You can't install a getter on a property indexed by the hidden symbol,
3647 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3648 // object.
3649 Object* result =
3650 GetLocalPropertyPostInterceptor(this,
3651 Heap::hidden_symbol(),
3652 &attributes)->ToObjectUnchecked();
3653 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003654}
3655
3656
lrn@chromium.org303ada72010-10-27 09:33:13 +00003657MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003658 ASSERT(!IsJSGlobalProxy());
3659 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3660 hidden_obj,
3661 DONT_ENUM);
3662}
3663
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003664
3665bool JSObject::HasElement(uint32_t index) {
3666 return HasElementWithReceiver(this, index);
3667}
3668
3669
3670bool AccessorInfo::all_can_read() {
3671 return BooleanBit::get(flag(), kAllCanReadBit);
3672}
3673
3674
3675void AccessorInfo::set_all_can_read(bool value) {
3676 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3677}
3678
3679
3680bool AccessorInfo::all_can_write() {
3681 return BooleanBit::get(flag(), kAllCanWriteBit);
3682}
3683
3684
3685void AccessorInfo::set_all_can_write(bool value) {
3686 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3687}
3688
3689
ager@chromium.org870a0b62008-11-04 11:43:05 +00003690bool AccessorInfo::prohibits_overwriting() {
3691 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3692}
3693
3694
3695void AccessorInfo::set_prohibits_overwriting(bool value) {
3696 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3697}
3698
3699
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003700PropertyAttributes AccessorInfo::property_attributes() {
3701 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3702}
3703
3704
3705void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3706 ASSERT(AttributesField::is_valid(attributes));
3707 int rest_value = flag()->value() & ~AttributesField::mask();
3708 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3709}
3710
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003711template<typename Shape, typename Key>
3712void Dictionary<Shape, Key>::SetEntry(int entry,
3713 Object* key,
3714 Object* value,
3715 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003716 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003717 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003718 AssertNoAllocation no_gc;
3719 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003720 FixedArray::set(index, key, mode);
3721 FixedArray::set(index+1, value, mode);
3722 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003723}
3724
3725
3726void Map::ClearCodeCache() {
3727 // No write barrier is needed since empty_fixed_array is not in new space.
3728 // Please note this function is used during marking:
3729 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003730 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3731 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003732}
3733
3734
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003735void JSArray::EnsureSize(int required_size) {
3736 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003737 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003738 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3739 if (elts->length() < required_size) {
3740 // Doubling in size would be overkill, but leave some slack to avoid
3741 // constantly growing.
3742 Expand(required_size + (required_size >> 3));
3743 // It's a performance benefit to keep a frequently used array in new-space.
3744 } else if (!Heap::new_space()->Contains(elts) &&
3745 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3746 // Expand will allocate a new backing store in new space even if the size
3747 // we asked for isn't larger than what we had before.
3748 Expand(required_size);
3749 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003750}
3751
3752
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003753void JSArray::set_length(Smi* length) {
3754 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3755}
3756
3757
ager@chromium.org7c537e22008-10-16 08:43:32 +00003758void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003759 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003760 set_elements(storage);
3761}
3762
3763
lrn@chromium.org303ada72010-10-27 09:33:13 +00003764MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003765 if (length() == 0) return this;
3766 return Heap::CopyFixedArray(this);
3767}
3768
3769
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003770int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3771 return map->instance_size();
3772}
3773
3774
3775void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3776 v->VisitExternalReference(
3777 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3778}
3779
3780
3781template<typename StaticVisitor>
3782void Proxy::ProxyIterateBody() {
3783 StaticVisitor::VisitExternalReference(
3784 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3785}
3786
3787
3788void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3789 typedef v8::String::ExternalAsciiStringResource Resource;
3790 v->VisitExternalAsciiString(
3791 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3792}
3793
3794
3795template<typename StaticVisitor>
3796void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3797 typedef v8::String::ExternalAsciiStringResource Resource;
3798 StaticVisitor::VisitExternalAsciiString(
3799 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3800}
3801
3802
3803void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3804 typedef v8::String::ExternalStringResource Resource;
3805 v->VisitExternalTwoByteString(
3806 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3807}
3808
3809
3810template<typename StaticVisitor>
3811void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3812 typedef v8::String::ExternalStringResource Resource;
3813 StaticVisitor::VisitExternalTwoByteString(
3814 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3815}
3816
3817#define SLOT_ADDR(obj, offset) \
3818 reinterpret_cast<Object**>((obj)->address() + offset)
3819
3820template<int start_offset, int end_offset, int size>
3821void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3822 HeapObject* obj,
3823 ObjectVisitor* v) {
3824 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3825}
3826
3827
3828template<int start_offset>
3829void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3830 int object_size,
3831 ObjectVisitor* v) {
3832 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3833}
3834
3835#undef SLOT_ADDR
3836
3837
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003838#undef CAST_ACCESSOR
3839#undef INT_ACCESSORS
3840#undef SMI_ACCESSORS
3841#undef ACCESSORS
3842#undef FIELD_ADDR
3843#undef READ_FIELD
3844#undef WRITE_FIELD
3845#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003846#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003847#undef READ_MEMADDR_FIELD
3848#undef WRITE_MEMADDR_FIELD
3849#undef READ_DOUBLE_FIELD
3850#undef WRITE_DOUBLE_FIELD
3851#undef READ_INT_FIELD
3852#undef WRITE_INT_FIELD
3853#undef READ_SHORT_FIELD
3854#undef WRITE_SHORT_FIELD
3855#undef READ_BYTE_FIELD
3856#undef WRITE_BYTE_FIELD
3857
3858
3859} } // namespace v8::internal
3860
3861#endif // V8_OBJECTS_INL_H_