blob: 21e318bfce4f95256ccf99672fdb12db97fd96e0 [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
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000733bool Object::IsArgumentsMarker() {
734 return this == Heap::arguments_marker();
735}
736
737
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000738double Object::Number() {
739 ASSERT(IsNumber());
740 return IsSmi()
741 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
742 : reinterpret_cast<HeapNumber*>(this)->value();
743}
744
745
746
lrn@chromium.org303ada72010-10-27 09:33:13 +0000747MaybeObject* Object::ToSmi() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000748 if (IsSmi()) return this;
749 if (IsHeapNumber()) {
750 double value = HeapNumber::cast(this)->value();
751 int int_value = FastD2I(value);
752 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
753 return Smi::FromInt(int_value);
754 }
755 }
756 return Failure::Exception();
757}
758
759
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000760bool Object::HasSpecificClassOf(String* name) {
761 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
762}
763
764
lrn@chromium.org303ada72010-10-27 09:33:13 +0000765MaybeObject* Object::GetElement(uint32_t index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766 return GetElementWithReceiver(this, index);
767}
768
769
lrn@chromium.org303ada72010-10-27 09:33:13 +0000770Object* Object::GetElementNoExceptionThrown(uint32_t index) {
771 MaybeObject* maybe = GetElementWithReceiver(this, index);
772 ASSERT(!maybe->IsFailure());
773 Object* result = NULL; // Initialization to please compiler.
774 maybe->ToObject(&result);
775 return result;
776}
777
778
779MaybeObject* Object::GetProperty(String* key) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780 PropertyAttributes attributes;
781 return GetPropertyWithReceiver(this, key, &attributes);
782}
783
784
lrn@chromium.org303ada72010-10-27 09:33:13 +0000785MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000786 return GetPropertyWithReceiver(this, key, attributes);
787}
788
789
790#define FIELD_ADDR(p, offset) \
791 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
792
793#define READ_FIELD(p, offset) \
794 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
795
796#define WRITE_FIELD(p, offset, value) \
797 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
798
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000799
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000800#define WRITE_BARRIER(object, offset) \
801 Heap::RecordWrite(object->address(), offset);
802
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000803// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000804// write due to the assert validating the written value.
805#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
806 if (mode == UPDATE_WRITE_BARRIER) { \
807 Heap::RecordWrite(object->address(), offset); \
808 } else { \
809 ASSERT(mode == SKIP_WRITE_BARRIER); \
810 ASSERT(Heap::InNewSpace(object) || \
kmillikin@chromium.orgb8dc8eb2010-04-01 07:13:38 +0000811 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000812 Page::FromAddress(object->address())-> \
813 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000814 }
815
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816#define READ_DOUBLE_FIELD(p, offset) \
817 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
818
819#define WRITE_DOUBLE_FIELD(p, offset, value) \
820 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
821
822#define READ_INT_FIELD(p, offset) \
823 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
824
825#define WRITE_INT_FIELD(p, offset, value) \
826 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
827
ager@chromium.org3e875802009-06-29 08:26:34 +0000828#define READ_INTPTR_FIELD(p, offset) \
829 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
830
831#define WRITE_INTPTR_FIELD(p, offset, value) \
832 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
833
ager@chromium.org7c537e22008-10-16 08:43:32 +0000834#define READ_UINT32_FIELD(p, offset) \
835 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
836
837#define WRITE_UINT32_FIELD(p, offset, value) \
838 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
839
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840#define READ_SHORT_FIELD(p, offset) \
841 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
842
843#define WRITE_SHORT_FIELD(p, offset, value) \
844 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
845
846#define READ_BYTE_FIELD(p, offset) \
847 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
848
849#define WRITE_BYTE_FIELD(p, offset, value) \
850 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
851
852
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000853Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
854 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000855}
856
857
858int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000859 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000860}
861
862
863Smi* Smi::FromInt(int value) {
864 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000865 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000866 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000867 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000868 return reinterpret_cast<Smi*>(tagged_value);
869}
870
871
872Smi* Smi::FromIntptr(intptr_t value) {
873 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000874 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
875 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000876}
877
878
879Failure::Type Failure::type() const {
880 return static_cast<Type>(value() & kFailureTypeTagMask);
881}
882
883
884bool Failure::IsInternalError() const {
885 return type() == INTERNAL_ERROR;
886}
887
888
889bool Failure::IsOutOfMemoryException() const {
890 return type() == OUT_OF_MEMORY_EXCEPTION;
891}
892
893
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000894AllocationSpace Failure::allocation_space() const {
895 ASSERT_EQ(RETRY_AFTER_GC, type());
896 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
897 & kSpaceTagMask);
898}
899
900
901Failure* Failure::InternalError() {
902 return Construct(INTERNAL_ERROR);
903}
904
905
906Failure* Failure::Exception() {
907 return Construct(EXCEPTION);
908}
909
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000910
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911Failure* Failure::OutOfMemoryException() {
912 return Construct(OUT_OF_MEMORY_EXCEPTION);
913}
914
915
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000916intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000917 return static_cast<intptr_t>(
918 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000919}
920
921
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000922Failure* Failure::RetryAfterGC() {
923 return RetryAfterGC(NEW_SPACE);
924}
925
926
927Failure* Failure::RetryAfterGC(AllocationSpace space) {
928 ASSERT((space & ~kSpaceTagMask) == 0);
929 return Construct(RETRY_AFTER_GC, space);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000930}
931
932
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000933Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000934 uintptr_t info =
935 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000936 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000937 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000938}
939
940
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000941bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000942#ifdef DEBUG
943 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
944#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000945
946#ifdef V8_TARGET_ARCH_X64
947 // To be representable as a long smi, the value must be a 32-bit integer.
948 bool result = (value == static_cast<int32_t>(value));
949#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000950 // To be representable as an tagged small integer, the two
951 // most-significant bits of 'value' must be either 00 or 11 due to
952 // sign-extension. To check this we add 01 to the two
953 // most-significant bits, and check if the most-significant bit is 0
954 //
955 // CAUTION: The original code below:
956 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
957 // may lead to incorrect results according to the C language spec, and
958 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
959 // compiler may produce undefined results in case of signed integer
960 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000961 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000962#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000963 ASSERT(result == in_range);
964 return result;
965}
966
967
kasper.lund7276f142008-07-30 08:49:36 +0000968MapWord MapWord::FromMap(Map* map) {
969 return MapWord(reinterpret_cast<uintptr_t>(map));
970}
971
972
973Map* MapWord::ToMap() {
974 return reinterpret_cast<Map*>(value_);
975}
976
977
978bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000979 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000980}
981
982
983MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000984 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
985 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000986}
987
988
989HeapObject* MapWord::ToForwardingAddress() {
990 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000991 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000992}
993
994
995bool MapWord::IsMarked() {
996 return (value_ & kMarkingMask) == 0;
997}
998
999
1000void MapWord::SetMark() {
1001 value_ &= ~kMarkingMask;
1002}
1003
1004
1005void MapWord::ClearMark() {
1006 value_ |= kMarkingMask;
1007}
1008
1009
1010bool MapWord::IsOverflowed() {
1011 return (value_ & kOverflowMask) != 0;
1012}
1013
1014
1015void MapWord::SetOverflow() {
1016 value_ |= kOverflowMask;
1017}
1018
1019
1020void MapWord::ClearOverflow() {
1021 value_ &= ~kOverflowMask;
1022}
1023
1024
1025MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1026 // Offset is the distance in live bytes from the first live object in the
1027 // same page. The offset between two objects in the same page should not
1028 // exceed the object area size of a page.
1029 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1030
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001031 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001032 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1033
1034 Page* map_page = Page::FromAddress(map_address);
1035 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1036
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001037 uintptr_t map_page_offset =
1038 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001039
1040 uintptr_t encoding =
1041 (compact_offset << kForwardingOffsetShift) |
1042 (map_page_offset << kMapPageOffsetShift) |
1043 (map_page->mc_page_index << kMapPageIndexShift);
1044 return MapWord(encoding);
1045}
1046
1047
1048Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001049 int map_page_index =
1050 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001051 ASSERT_MAP_PAGE_INDEX(map_page_index);
1052
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001053 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001054 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1055 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001056
1057 return (map_space->PageAddress(map_page_index) + map_page_offset);
1058}
1059
1060
1061int MapWord::DecodeOffset() {
1062 // The offset field is represented in the kForwardingOffsetBits
1063 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001064 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1065 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1066 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001067}
1068
1069
1070MapWord MapWord::FromEncodedAddress(Address address) {
1071 return MapWord(reinterpret_cast<uintptr_t>(address));
1072}
1073
1074
1075Address MapWord::ToEncodedAddress() {
1076 return reinterpret_cast<Address>(value_);
1077}
1078
1079
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001080#ifdef DEBUG
1081void HeapObject::VerifyObjectField(int offset) {
1082 VerifyPointer(READ_FIELD(this, offset));
1083}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001084
1085void HeapObject::VerifySmiField(int offset) {
1086 ASSERT(READ_FIELD(this, offset)->IsSmi());
1087}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088#endif
1089
1090
1091Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001092 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001093}
1094
1095
1096void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001097 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001098}
1099
1100
kasper.lund7276f142008-07-30 08:49:36 +00001101MapWord HeapObject::map_word() {
1102 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1103}
1104
1105
1106void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001107 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001108 // here.
1109 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1110}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001111
1112
1113HeapObject* HeapObject::FromAddress(Address address) {
1114 ASSERT_TAG_ALIGNED(address);
1115 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1116}
1117
1118
1119Address HeapObject::address() {
1120 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1121}
1122
1123
1124int HeapObject::Size() {
1125 return SizeFromMap(map());
1126}
1127
1128
1129void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1130 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1131 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1132}
1133
1134
1135void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1136 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1137}
1138
1139
kasper.lund7276f142008-07-30 08:49:36 +00001140bool HeapObject::IsMarked() {
1141 return map_word().IsMarked();
1142}
1143
1144
1145void HeapObject::SetMark() {
1146 ASSERT(!IsMarked());
1147 MapWord first_word = map_word();
1148 first_word.SetMark();
1149 set_map_word(first_word);
1150}
1151
1152
1153void HeapObject::ClearMark() {
1154 ASSERT(IsMarked());
1155 MapWord first_word = map_word();
1156 first_word.ClearMark();
1157 set_map_word(first_word);
1158}
1159
1160
1161bool HeapObject::IsOverflowed() {
1162 return map_word().IsOverflowed();
1163}
1164
1165
1166void HeapObject::SetOverflow() {
1167 MapWord first_word = map_word();
1168 first_word.SetOverflow();
1169 set_map_word(first_word);
1170}
1171
1172
1173void HeapObject::ClearOverflow() {
1174 ASSERT(IsOverflowed());
1175 MapWord first_word = map_word();
1176 first_word.ClearOverflow();
1177 set_map_word(first_word);
1178}
1179
1180
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001181double HeapNumber::value() {
1182 return READ_DOUBLE_FIELD(this, kValueOffset);
1183}
1184
1185
1186void HeapNumber::set_value(double value) {
1187 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1188}
1189
1190
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001191int HeapNumber::get_exponent() {
1192 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1193 kExponentShift) - kExponentBias;
1194}
1195
1196
1197int HeapNumber::get_sign() {
1198 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1199}
1200
1201
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001202ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001203
1204
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001205HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001206 Object* array = READ_FIELD(this, kElementsOffset);
1207 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001208 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1209 array->IsExternalArray());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001210 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001211}
1212
1213
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001214void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001215 ASSERT(map()->has_fast_elements() ==
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001216 (value->map() == Heap::fixed_array_map() ||
1217 value->map() == Heap::fixed_cow_array_map()));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001218 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001219 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1220 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001221 WRITE_FIELD(this, kElementsOffset, value);
1222 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1223}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001224
1225
1226void JSObject::initialize_properties() {
1227 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1228 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1229}
1230
1231
1232void JSObject::initialize_elements() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001233 ASSERT(map()->has_fast_elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001234 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1235 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1236}
1237
1238
lrn@chromium.org303ada72010-10-27 09:33:13 +00001239MaybeObject* JSObject::ResetElements() {
1240 Object* obj;
1241 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1242 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1243 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001244 set_map(Map::cast(obj));
1245 initialize_elements();
1246 return this;
1247}
1248
1249
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001250ACCESSORS(Oddball, to_string, String, kToStringOffset)
1251ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1252
1253
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001254Object* JSGlobalPropertyCell::value() {
1255 return READ_FIELD(this, kValueOffset);
1256}
1257
1258
1259void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1260 // The write barrier is not used for global property cells.
1261 ASSERT(!val->IsJSGlobalPropertyCell());
1262 WRITE_FIELD(this, kValueOffset, val);
1263}
1264
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001265
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001266int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001267 InstanceType type = map()->instance_type();
1268 // Check for the most common kind of JavaScript object before
1269 // falling into the generic switch. This speeds up the internal
1270 // field operations considerably on average.
1271 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1272 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001273 case JS_GLOBAL_PROXY_TYPE:
1274 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001275 case JS_GLOBAL_OBJECT_TYPE:
1276 return JSGlobalObject::kSize;
1277 case JS_BUILTINS_OBJECT_TYPE:
1278 return JSBuiltinsObject::kSize;
1279 case JS_FUNCTION_TYPE:
1280 return JSFunction::kSize;
1281 case JS_VALUE_TYPE:
1282 return JSValue::kSize;
1283 case JS_ARRAY_TYPE:
1284 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001285 case JS_REGEXP_TYPE:
1286 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001287 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001288 return JSObject::kHeaderSize;
1289 default:
1290 UNREACHABLE();
1291 return 0;
1292 }
1293}
1294
1295
1296int JSObject::GetInternalFieldCount() {
1297 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001298 // Make sure to adjust for the number of in-object properties. These
1299 // properties do contribute to the size, but are not internal fields.
1300 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1301 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001302}
1303
1304
1305Object* JSObject::GetInternalField(int index) {
1306 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001307 // Internal objects do follow immediately after the header, whereas in-object
1308 // properties are at the end of the object. Therefore there is no need
1309 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001310 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1311}
1312
1313
1314void JSObject::SetInternalField(int index, Object* value) {
1315 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001316 // Internal objects do follow immediately after the header, whereas in-object
1317 // properties are at the end of the object. Therefore there is no need
1318 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001319 int offset = GetHeaderSize() + (kPointerSize * index);
1320 WRITE_FIELD(this, offset, value);
1321 WRITE_BARRIER(this, offset);
1322}
1323
1324
ager@chromium.org7c537e22008-10-16 08:43:32 +00001325// Access fast-case object properties at index. The use of these routines
1326// is needed to correctly distinguish between properties stored in-object and
1327// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001328Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001329 // Adjust for the number of properties stored in the object.
1330 index -= map()->inobject_properties();
1331 if (index < 0) {
1332 int offset = map()->instance_size() + (index * kPointerSize);
1333 return READ_FIELD(this, offset);
1334 } else {
1335 ASSERT(index < properties()->length());
1336 return properties()->get(index);
1337 }
1338}
1339
1340
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001341Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001342 // Adjust for the number of properties stored in the object.
1343 index -= map()->inobject_properties();
1344 if (index < 0) {
1345 int offset = map()->instance_size() + (index * kPointerSize);
1346 WRITE_FIELD(this, offset, value);
1347 WRITE_BARRIER(this, offset);
1348 } else {
1349 ASSERT(index < properties()->length());
1350 properties()->set(index, value);
1351 }
1352 return value;
1353}
1354
1355
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001356Object* JSObject::InObjectPropertyAt(int index) {
1357 // Adjust for the number of properties stored in the object.
1358 index -= map()->inobject_properties();
1359 ASSERT(index < 0);
1360 int offset = map()->instance_size() + (index * kPointerSize);
1361 return READ_FIELD(this, offset);
1362}
1363
1364
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001365Object* JSObject::InObjectPropertyAtPut(int index,
1366 Object* value,
1367 WriteBarrierMode mode) {
1368 // Adjust for the number of properties stored in the object.
1369 index -= map()->inobject_properties();
1370 ASSERT(index < 0);
1371 int offset = map()->instance_size() + (index * kPointerSize);
1372 WRITE_FIELD(this, offset, value);
1373 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1374 return value;
1375}
1376
1377
1378
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001379void JSObject::InitializeBody(int object_size, Object* value) {
1380 ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001381 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001382 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001383 }
1384}
1385
1386
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001387bool JSObject::HasFastProperties() {
1388 return !properties()->IsDictionary();
1389}
1390
1391
1392int JSObject::MaxFastProperties() {
1393 // Allow extra fast properties if the object has more than
1394 // kMaxFastProperties in-object properties. When this is the case,
1395 // it is very unlikely that the object is being used as a dictionary
1396 // and there is a good chance that allowing more map transitions
1397 // will be worth it.
1398 return Max(map()->inobject_properties(), kMaxFastProperties);
1399}
1400
1401
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001402void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001403 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001404 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001405 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001406 }
1407}
1408
1409
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001410bool Object::ToArrayIndex(uint32_t* index) {
1411 if (IsSmi()) {
1412 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001413 if (value < 0) return false;
1414 *index = value;
1415 return true;
1416 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001417 if (IsHeapNumber()) {
1418 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001419 uint32_t uint_value = static_cast<uint32_t>(value);
1420 if (value == static_cast<double>(uint_value)) {
1421 *index = uint_value;
1422 return true;
1423 }
1424 }
1425 return false;
1426}
1427
1428
1429bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1430 if (!this->IsJSValue()) return false;
1431
1432 JSValue* js_value = JSValue::cast(this);
1433 if (!js_value->value()->IsString()) return false;
1434
1435 String* str = String::cast(js_value->value());
1436 if (index >= (uint32_t)str->length()) return false;
1437
1438 return true;
1439}
1440
1441
1442Object* FixedArray::get(int index) {
1443 ASSERT(index >= 0 && index < this->length());
1444 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1445}
1446
1447
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001448void FixedArray::set(int index, Smi* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001449 ASSERT(map() != Heap::fixed_cow_array_map());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001450 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1451 int offset = kHeaderSize + index * kPointerSize;
1452 WRITE_FIELD(this, offset, value);
1453}
1454
1455
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456void FixedArray::set(int index, Object* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001457 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001458 ASSERT(index >= 0 && index < this->length());
1459 int offset = kHeaderSize + index * kPointerSize;
1460 WRITE_FIELD(this, offset, value);
1461 WRITE_BARRIER(this, offset);
1462}
1463
1464
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001465WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001466 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1467 return UPDATE_WRITE_BARRIER;
1468}
1469
1470
1471void FixedArray::set(int index,
1472 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001473 WriteBarrierMode mode) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001474 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001475 ASSERT(index >= 0 && index < this->length());
1476 int offset = kHeaderSize + index * kPointerSize;
1477 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001478 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001479}
1480
1481
1482void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001483 ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001484 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001485 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001486 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1487}
1488
1489
1490void FixedArray::set_undefined(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001491 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001492 ASSERT(index >= 0 && index < this->length());
1493 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1494 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1495 Heap::undefined_value());
1496}
1497
1498
ager@chromium.org236ad962008-09-25 09:45:57 +00001499void FixedArray::set_null(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001500 ASSERT(map() != Heap::fixed_cow_array_map());
ager@chromium.org236ad962008-09-25 09:45:57 +00001501 ASSERT(index >= 0 && index < this->length());
1502 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1503 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1504}
1505
1506
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001507void FixedArray::set_the_hole(int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001508 ASSERT(map() != Heap::fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001509 ASSERT(index >= 0 && index < this->length());
1510 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1511 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1512}
1513
1514
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001515void FixedArray::set_unchecked(int index, Smi* value) {
1516 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1517 int offset = kHeaderSize + index * kPointerSize;
1518 WRITE_FIELD(this, offset, value);
1519}
1520
1521
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001522void FixedArray::set_unchecked(int index,
1523 Object* value,
1524 WriteBarrierMode mode) {
1525 int offset = kHeaderSize + index * kPointerSize;
1526 WRITE_FIELD(this, offset, value);
1527 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1528}
1529
1530
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001531void FixedArray::set_null_unchecked(int index) {
1532 ASSERT(index >= 0 && index < this->length());
1533 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1534 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1535}
1536
1537
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001538Object** FixedArray::data_start() {
1539 return HeapObject::RawField(this, kHeaderSize);
1540}
1541
1542
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001543bool DescriptorArray::IsEmpty() {
1544 ASSERT(this == Heap::empty_descriptor_array() ||
1545 this->length() > 2);
1546 return this == Heap::empty_descriptor_array();
1547}
1548
1549
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001550void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1551 Object* tmp = array->get(first);
1552 fast_set(array, first, array->get(second));
1553 fast_set(array, second, tmp);
1554}
1555
1556
1557int DescriptorArray::Search(String* name) {
1558 SLOW_ASSERT(IsSortedNoDuplicates());
1559
1560 // Check for empty descriptor array.
1561 int nof = number_of_descriptors();
1562 if (nof == 0) return kNotFound;
1563
1564 // Fast case: do linear search for small arrays.
1565 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001566 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001567 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001568 }
1569
1570 // Slow case: perform binary search.
1571 return BinarySearch(name, 0, nof - 1);
1572}
1573
1574
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001575int DescriptorArray::SearchWithCache(String* name) {
1576 int number = DescriptorLookupCache::Lookup(this, name);
1577 if (number == DescriptorLookupCache::kAbsent) {
1578 number = Search(name);
1579 DescriptorLookupCache::Update(this, name, number);
1580 }
1581 return number;
1582}
1583
1584
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585String* DescriptorArray::GetKey(int descriptor_number) {
1586 ASSERT(descriptor_number < number_of_descriptors());
1587 return String::cast(get(ToKeyIndex(descriptor_number)));
1588}
1589
1590
1591Object* DescriptorArray::GetValue(int descriptor_number) {
1592 ASSERT(descriptor_number < number_of_descriptors());
1593 return GetContentArray()->get(ToValueIndex(descriptor_number));
1594}
1595
1596
1597Smi* DescriptorArray::GetDetails(int descriptor_number) {
1598 ASSERT(descriptor_number < number_of_descriptors());
1599 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1600}
1601
1602
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001603PropertyType DescriptorArray::GetType(int descriptor_number) {
1604 ASSERT(descriptor_number < number_of_descriptors());
1605 return PropertyDetails(GetDetails(descriptor_number)).type();
1606}
1607
1608
1609int DescriptorArray::GetFieldIndex(int descriptor_number) {
1610 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1611}
1612
1613
1614JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1615 return JSFunction::cast(GetValue(descriptor_number));
1616}
1617
1618
1619Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1620 ASSERT(GetType(descriptor_number) == CALLBACKS);
1621 return GetValue(descriptor_number);
1622}
1623
1624
1625AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1626 ASSERT(GetType(descriptor_number) == CALLBACKS);
1627 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1628 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1629}
1630
1631
1632bool DescriptorArray::IsProperty(int descriptor_number) {
1633 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1634}
1635
1636
1637bool DescriptorArray::IsTransition(int descriptor_number) {
1638 PropertyType t = GetType(descriptor_number);
1639 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1640}
1641
1642
1643bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1644 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1645}
1646
1647
1648bool DescriptorArray::IsDontEnum(int descriptor_number) {
1649 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1650}
1651
1652
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001653void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1654 desc->Init(GetKey(descriptor_number),
1655 GetValue(descriptor_number),
1656 GetDetails(descriptor_number));
1657}
1658
1659
1660void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1661 // Range check.
1662 ASSERT(descriptor_number < number_of_descriptors());
1663
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001664 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001665 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1666 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1667
1668 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1669 FixedArray* content_array = GetContentArray();
1670 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1671 fast_set(content_array, ToDetailsIndex(descriptor_number),
1672 desc->GetDetails().AsSmi());
1673}
1674
1675
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001676void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1677 Descriptor desc;
1678 src->Get(src_index, &desc);
1679 Set(index, &desc);
1680}
1681
1682
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001683void DescriptorArray::Swap(int first, int second) {
1684 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1685 FixedArray* content_array = GetContentArray();
1686 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1687 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1688}
1689
1690
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001691bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001692 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001693 if (!max_index_object->IsSmi()) return false;
1694 return 0 !=
1695 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1696}
1697
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001698uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001699 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001700 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001701 if (!max_index_object->IsSmi()) return 0;
1702 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1703 return value >> kRequiresSlowElementsTagSize;
1704}
1705
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001706void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001707 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001708}
1709
1710
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001711// ------------------------------------
1712// Cast operations
1713
1714
1715CAST_ACCESSOR(FixedArray)
1716CAST_ACCESSOR(DescriptorArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001717CAST_ACCESSOR(DeoptimizationInputData)
1718CAST_ACCESSOR(DeoptimizationOutputData)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001719CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001720CAST_ACCESSOR(JSFunctionResultCache)
ricow@chromium.org65fae842010-08-25 15:26:24 +00001721CAST_ACCESSOR(NormalizedMapCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001722CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001723CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001724CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725CAST_ACCESSOR(String)
1726CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001727CAST_ACCESSOR(SeqAsciiString)
1728CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001729CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730CAST_ACCESSOR(ExternalString)
1731CAST_ACCESSOR(ExternalAsciiString)
1732CAST_ACCESSOR(ExternalTwoByteString)
1733CAST_ACCESSOR(JSObject)
1734CAST_ACCESSOR(Smi)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001735CAST_ACCESSOR(HeapObject)
1736CAST_ACCESSOR(HeapNumber)
1737CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001738CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739CAST_ACCESSOR(SharedFunctionInfo)
1740CAST_ACCESSOR(Map)
1741CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001742CAST_ACCESSOR(GlobalObject)
1743CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744CAST_ACCESSOR(JSGlobalObject)
1745CAST_ACCESSOR(JSBuiltinsObject)
1746CAST_ACCESSOR(Code)
1747CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001748CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749CAST_ACCESSOR(Proxy)
1750CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001751CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001752CAST_ACCESSOR(ExternalArray)
1753CAST_ACCESSOR(ExternalByteArray)
1754CAST_ACCESSOR(ExternalUnsignedByteArray)
1755CAST_ACCESSOR(ExternalShortArray)
1756CAST_ACCESSOR(ExternalUnsignedShortArray)
1757CAST_ACCESSOR(ExternalIntArray)
1758CAST_ACCESSOR(ExternalUnsignedIntArray)
1759CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001760CAST_ACCESSOR(Struct)
1761
1762
1763#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1764 STRUCT_LIST(MAKE_STRUCT_CAST)
1765#undef MAKE_STRUCT_CAST
1766
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001767
1768template <typename Shape, typename Key>
1769HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001770 ASSERT(obj->IsHashTable());
1771 return reinterpret_cast<HashTable*>(obj);
1772}
1773
1774
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001775SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1776SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1777
1778INT_ACCESSORS(PixelArray, length, kLengthOffset)
1779INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001780
1781
ager@chromium.orgac091b72010-05-05 07:34:42 +00001782SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001783
1784
1785uint32_t String::hash_field() {
1786 return READ_UINT32_FIELD(this, kHashFieldOffset);
1787}
1788
1789
1790void String::set_hash_field(uint32_t value) {
1791 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001792#if V8_HOST_ARCH_64_BIT
1793 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1794#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001795}
1796
1797
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001798bool String::Equals(String* other) {
1799 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001800 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1801 return false;
1802 }
1803 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001804}
1805
1806
lrn@chromium.org303ada72010-10-27 09:33:13 +00001807MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001808 if (!StringShape(this).IsCons()) return this;
1809 ConsString* cons = ConsString::cast(this);
1810 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001811 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001812}
1813
1814
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001815String* String::TryFlattenGetString(PretenureFlag pretenure) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001816 MaybeObject* flat = TryFlatten(pretenure);
1817 Object* successfully_flattened;
1818 if (flat->ToObject(&successfully_flattened)) {
1819 return String::cast(successfully_flattened);
1820 }
1821 return this;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001822}
1823
1824
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001825uint16_t String::Get(int index) {
1826 ASSERT(index >= 0 && index < length());
1827 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001828 case kSeqStringTag | kAsciiStringTag:
1829 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1830 case kSeqStringTag | kTwoByteStringTag:
1831 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1832 case kConsStringTag | kAsciiStringTag:
1833 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001834 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001835 case kExternalStringTag | kAsciiStringTag:
1836 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1837 case kExternalStringTag | kTwoByteStringTag:
1838 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001839 default:
1840 break;
1841 }
1842
1843 UNREACHABLE();
1844 return 0;
1845}
1846
1847
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001848void String::Set(int index, uint16_t value) {
1849 ASSERT(index >= 0 && index < length());
1850 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001851
ager@chromium.org5ec48922009-05-05 07:25:34 +00001852 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001853 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1854 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001855}
1856
1857
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001858bool String::IsFlat() {
1859 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001860 case kConsStringTag: {
1861 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001862 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001863 return second->length() == 0;
1864 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001865 default:
1866 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001867 }
1868}
1869
1870
ager@chromium.org7c537e22008-10-16 08:43:32 +00001871uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001872 ASSERT(index >= 0 && index < length());
1873 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1874}
1875
1876
ager@chromium.org7c537e22008-10-16 08:43:32 +00001877void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001878 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1879 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1880 static_cast<byte>(value));
1881}
1882
1883
ager@chromium.org7c537e22008-10-16 08:43:32 +00001884Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001885 return FIELD_ADDR(this, kHeaderSize);
1886}
1887
1888
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001889char* SeqAsciiString::GetChars() {
1890 return reinterpret_cast<char*>(GetCharsAddress());
1891}
1892
1893
ager@chromium.org7c537e22008-10-16 08:43:32 +00001894Address SeqTwoByteString::GetCharsAddress() {
1895 return FIELD_ADDR(this, kHeaderSize);
1896}
1897
1898
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001899uc16* SeqTwoByteString::GetChars() {
1900 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1901}
1902
1903
ager@chromium.org7c537e22008-10-16 08:43:32 +00001904uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001905 ASSERT(index >= 0 && index < length());
1906 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1907}
1908
1909
ager@chromium.org7c537e22008-10-16 08:43:32 +00001910void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001911 ASSERT(index >= 0 && index < length());
1912 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1913}
1914
1915
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001916int SeqTwoByteString::SeqTwoByteStringSize(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.orgbb29dc92009-03-24 13:25:23 +00001921int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001922 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001923}
1924
1925
ager@chromium.org870a0b62008-11-04 11:43:05 +00001926String* ConsString::first() {
1927 return String::cast(READ_FIELD(this, kFirstOffset));
1928}
1929
1930
1931Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001932 return READ_FIELD(this, kFirstOffset);
1933}
1934
1935
ager@chromium.org870a0b62008-11-04 11:43:05 +00001936void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001937 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001938 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001939}
1940
1941
ager@chromium.org870a0b62008-11-04 11:43:05 +00001942String* ConsString::second() {
1943 return String::cast(READ_FIELD(this, kSecondOffset));
1944}
1945
1946
1947Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001948 return READ_FIELD(this, kSecondOffset);
1949}
1950
1951
ager@chromium.org870a0b62008-11-04 11:43:05 +00001952void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001953 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001954 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001955}
1956
1957
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001958ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1959 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1960}
1961
1962
1963void ExternalAsciiString::set_resource(
1964 ExternalAsciiString::Resource* resource) {
1965 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1966}
1967
1968
1969ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1970 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1971}
1972
1973
1974void ExternalTwoByteString::set_resource(
1975 ExternalTwoByteString::Resource* resource) {
1976 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1977}
1978
1979
ager@chromium.orgac091b72010-05-05 07:34:42 +00001980void JSFunctionResultCache::MakeZeroSize() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001981 set_finger_index(kEntriesIndex);
1982 set_size(kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001983}
1984
1985
1986void JSFunctionResultCache::Clear() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001987 int cache_size = size();
ager@chromium.orgac091b72010-05-05 07:34:42 +00001988 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001989 MemsetPointer(entries_start,
1990 Heap::the_hole_value(),
1991 cache_size - kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001992 MakeZeroSize();
1993}
1994
1995
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001996int JSFunctionResultCache::size() {
1997 return Smi::cast(get(kCacheSizeIndex))->value();
1998}
1999
2000
2001void JSFunctionResultCache::set_size(int size) {
2002 set(kCacheSizeIndex, Smi::FromInt(size));
2003}
2004
2005
2006int JSFunctionResultCache::finger_index() {
2007 return Smi::cast(get(kFingerIndex))->value();
2008}
2009
2010
2011void JSFunctionResultCache::set_finger_index(int finger_index) {
2012 set(kFingerIndex, Smi::FromInt(finger_index));
2013}
2014
2015
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002016byte ByteArray::get(int index) {
2017 ASSERT(index >= 0 && index < this->length());
2018 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2019}
2020
2021
2022void ByteArray::set(int index, byte value) {
2023 ASSERT(index >= 0 && index < this->length());
2024 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2025}
2026
2027
2028int ByteArray::get_int(int index) {
2029 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2030 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2031}
2032
2033
2034ByteArray* ByteArray::FromDataStartAddress(Address address) {
2035 ASSERT_TAG_ALIGNED(address);
2036 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2037}
2038
2039
2040Address ByteArray::GetDataStartAddress() {
2041 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2042}
2043
2044
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002045uint8_t* PixelArray::external_pointer() {
2046 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2047 return reinterpret_cast<uint8_t*>(ptr);
2048}
2049
2050
2051void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
2052 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2053 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2054}
2055
2056
2057uint8_t PixelArray::get(int index) {
2058 ASSERT((index >= 0) && (index < this->length()));
2059 uint8_t* ptr = external_pointer();
2060 return ptr[index];
2061}
2062
2063
2064void PixelArray::set(int index, uint8_t value) {
2065 ASSERT((index >= 0) && (index < this->length()));
2066 uint8_t* ptr = external_pointer();
2067 ptr[index] = value;
2068}
2069
2070
ager@chromium.org3811b432009-10-28 14:53:37 +00002071void* ExternalArray::external_pointer() {
2072 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2073 return reinterpret_cast<void*>(ptr);
2074}
2075
2076
2077void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2078 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2079 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2080}
2081
2082
2083int8_t ExternalByteArray::get(int index) {
2084 ASSERT((index >= 0) && (index < this->length()));
2085 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2086 return ptr[index];
2087}
2088
2089
2090void ExternalByteArray::set(int index, int8_t value) {
2091 ASSERT((index >= 0) && (index < this->length()));
2092 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2093 ptr[index] = value;
2094}
2095
2096
2097uint8_t ExternalUnsignedByteArray::get(int index) {
2098 ASSERT((index >= 0) && (index < this->length()));
2099 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2100 return ptr[index];
2101}
2102
2103
2104void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2105 ASSERT((index >= 0) && (index < this->length()));
2106 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2107 ptr[index] = value;
2108}
2109
2110
2111int16_t ExternalShortArray::get(int index) {
2112 ASSERT((index >= 0) && (index < this->length()));
2113 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2114 return ptr[index];
2115}
2116
2117
2118void ExternalShortArray::set(int index, int16_t value) {
2119 ASSERT((index >= 0) && (index < this->length()));
2120 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2121 ptr[index] = value;
2122}
2123
2124
2125uint16_t ExternalUnsignedShortArray::get(int index) {
2126 ASSERT((index >= 0) && (index < this->length()));
2127 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2128 return ptr[index];
2129}
2130
2131
2132void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2133 ASSERT((index >= 0) && (index < this->length()));
2134 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2135 ptr[index] = value;
2136}
2137
2138
2139int32_t ExternalIntArray::get(int index) {
2140 ASSERT((index >= 0) && (index < this->length()));
2141 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2142 return ptr[index];
2143}
2144
2145
2146void ExternalIntArray::set(int index, int32_t value) {
2147 ASSERT((index >= 0) && (index < this->length()));
2148 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2149 ptr[index] = value;
2150}
2151
2152
2153uint32_t ExternalUnsignedIntArray::get(int index) {
2154 ASSERT((index >= 0) && (index < this->length()));
2155 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2156 return ptr[index];
2157}
2158
2159
2160void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2161 ASSERT((index >= 0) && (index < this->length()));
2162 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2163 ptr[index] = value;
2164}
2165
2166
2167float ExternalFloatArray::get(int index) {
2168 ASSERT((index >= 0) && (index < this->length()));
2169 float* ptr = static_cast<float*>(external_pointer());
2170 return ptr[index];
2171}
2172
2173
2174void ExternalFloatArray::set(int index, float value) {
2175 ASSERT((index >= 0) && (index < this->length()));
2176 float* ptr = static_cast<float*>(external_pointer());
2177 ptr[index] = value;
2178}
2179
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002180
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00002181int Map::visitor_id() {
2182 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2183}
2184
2185
2186void Map::set_visitor_id(int id) {
2187 ASSERT(0 <= id && id < 256);
2188 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2189}
2190
ager@chromium.org3811b432009-10-28 14:53:37 +00002191
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002193 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2194}
2195
2196
2197int Map::inobject_properties() {
2198 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002199}
2200
2201
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002202int Map::pre_allocated_property_fields() {
2203 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2204}
2205
2206
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002207int HeapObject::SizeFromMap(Map* map) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002208 int instance_size = map->instance_size();
2209 if (instance_size != kVariableSizeSentinel) return instance_size;
2210 // We can ignore the "symbol" bit becase it is only set for symbols
2211 // and implies a string type.
2212 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002213 // Only inline the most frequent cases.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002214 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002215 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002216 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002217 if (instance_type == ASCII_STRING_TYPE) {
2218 return SeqAsciiString::SizeFor(
2219 reinterpret_cast<SeqAsciiString*>(this)->length());
2220 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002221 if (instance_type == BYTE_ARRAY_TYPE) {
2222 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2223 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002224 if (instance_type == STRING_TYPE) {
2225 return SeqTwoByteString::SizeFor(
2226 reinterpret_cast<SeqTwoByteString*>(this)->length());
2227 }
2228 ASSERT(instance_type == CODE_TYPE);
2229 return reinterpret_cast<Code*>(this)->CodeSize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002230}
2231
2232
2233void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002234 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002235 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002236 ASSERT(0 <= value && value < 256);
2237 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2238}
2239
2240
ager@chromium.org7c537e22008-10-16 08:43:32 +00002241void Map::set_inobject_properties(int value) {
2242 ASSERT(0 <= value && value < 256);
2243 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2244}
2245
2246
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002247void Map::set_pre_allocated_property_fields(int value) {
2248 ASSERT(0 <= value && value < 256);
2249 WRITE_BYTE_FIELD(this,
2250 kPreAllocatedPropertyFieldsOffset,
2251 static_cast<byte>(value));
2252}
2253
2254
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002255InstanceType Map::instance_type() {
2256 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2257}
2258
2259
2260void Map::set_instance_type(InstanceType value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002261 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2262}
2263
2264
2265int Map::unused_property_fields() {
2266 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2267}
2268
2269
2270void Map::set_unused_property_fields(int value) {
2271 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2272}
2273
2274
2275byte Map::bit_field() {
2276 return READ_BYTE_FIELD(this, kBitFieldOffset);
2277}
2278
2279
2280void Map::set_bit_field(byte value) {
2281 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2282}
2283
2284
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002285byte Map::bit_field2() {
2286 return READ_BYTE_FIELD(this, kBitField2Offset);
2287}
2288
2289
2290void Map::set_bit_field2(byte value) {
2291 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2292}
2293
2294
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002295void Map::set_non_instance_prototype(bool value) {
2296 if (value) {
2297 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2298 } else {
2299 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2300 }
2301}
2302
2303
2304bool Map::has_non_instance_prototype() {
2305 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2306}
2307
2308
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002309void Map::set_function_with_prototype(bool value) {
2310 if (value) {
2311 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2312 } else {
2313 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2314 }
2315}
2316
2317
2318bool Map::function_with_prototype() {
2319 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2320}
2321
2322
ager@chromium.org870a0b62008-11-04 11:43:05 +00002323void Map::set_is_access_check_needed(bool access_check_needed) {
2324 if (access_check_needed) {
2325 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2326 } else {
2327 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2328 }
2329}
2330
2331
2332bool Map::is_access_check_needed() {
2333 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2334}
2335
2336
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002337void Map::set_is_extensible(bool value) {
2338 if (value) {
2339 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2340 } else {
2341 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2342 }
2343}
2344
2345bool Map::is_extensible() {
2346 return ((1 << kIsExtensible) & bit_field2()) != 0;
2347}
2348
2349
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002350void Map::set_attached_to_shared_function_info(bool value) {
2351 if (value) {
2352 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2353 } else {
2354 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2355 }
2356}
2357
2358bool Map::attached_to_shared_function_info() {
2359 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2360}
2361
2362
2363void Map::set_is_shared(bool value) {
2364 if (value) {
2365 set_bit_field2(bit_field2() | (1 << kIsShared));
2366 } else {
2367 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2368 }
2369}
2370
2371bool Map::is_shared() {
2372 return ((1 << kIsShared) & bit_field2()) != 0;
2373}
2374
2375
2376JSFunction* Map::unchecked_constructor() {
2377 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2378}
2379
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002380
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002381Code::Flags Code::flags() {
2382 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2383}
2384
2385
2386void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002387 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002388 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002389 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2390 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002391 ExtractArgumentsCountFromFlags(flags) >= 0);
2392 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2393}
2394
2395
2396Code::Kind Code::kind() {
2397 return ExtractKindFromFlags(flags());
2398}
2399
2400
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002401InLoopFlag Code::ic_in_loop() {
2402 return ExtractICInLoopFromFlags(flags());
2403}
2404
2405
kasper.lund7276f142008-07-30 08:49:36 +00002406InlineCacheState Code::ic_state() {
2407 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002408 // Only allow uninitialized or debugger states for non-IC code
2409 // objects. This is used in the debugger to determine whether or not
2410 // a call to code object has been replaced with a debug break call.
2411 ASSERT(is_inline_cache_stub() ||
2412 result == UNINITIALIZED ||
2413 result == DEBUG_BREAK ||
2414 result == DEBUG_PREPARE_STEP_IN);
2415 return result;
2416}
2417
2418
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002419Code::ExtraICState Code::extra_ic_state() {
2420 ASSERT(is_inline_cache_stub());
2421 return ExtractExtraICStateFromFlags(flags());
2422}
2423
2424
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002425PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002426 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002427 return ExtractTypeFromFlags(flags());
2428}
2429
2430
2431int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002432 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002433 return ExtractArgumentsCountFromFlags(flags());
2434}
2435
2436
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002437int Code::major_key() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002438 ASSERT(kind() == STUB ||
2439 kind() == BINARY_OP_IC ||
2440 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2441 kind() == COMPARE_IC);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002442 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
kasper.lund7276f142008-07-30 08:49:36 +00002443}
2444
2445
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002446void Code::set_major_key(int major) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002447 ASSERT(kind() == STUB ||
2448 kind() == BINARY_OP_IC ||
2449 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2450 kind() == COMPARE_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002451 ASSERT(0 <= major && major < 256);
2452 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002453}
2454
2455
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002456bool Code::optimizable() {
2457 ASSERT(kind() == FUNCTION);
2458 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2459}
2460
2461
2462void Code::set_optimizable(bool value) {
2463 ASSERT(kind() == FUNCTION);
2464 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2465}
2466
2467
2468bool Code::has_deoptimization_support() {
2469 ASSERT(kind() == FUNCTION);
2470 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2471}
2472
2473
2474void Code::set_has_deoptimization_support(bool value) {
2475 ASSERT(kind() == FUNCTION);
2476 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2477}
2478
2479
2480int Code::allow_osr_at_loop_nesting_level() {
2481 ASSERT(kind() == FUNCTION);
2482 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2483}
2484
2485
2486void Code::set_allow_osr_at_loop_nesting_level(int level) {
2487 ASSERT(kind() == FUNCTION);
2488 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2489 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2490}
2491
2492
2493unsigned Code::stack_slots() {
2494 ASSERT(kind() == OPTIMIZED_FUNCTION);
2495 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2496}
2497
2498
2499void Code::set_stack_slots(unsigned slots) {
2500 ASSERT(kind() == OPTIMIZED_FUNCTION);
2501 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2502}
2503
2504
2505unsigned Code::safepoint_table_start() {
2506 ASSERT(kind() == OPTIMIZED_FUNCTION);
2507 return READ_UINT32_FIELD(this, kSafepointTableStartOffset);
2508}
2509
2510
2511void Code::set_safepoint_table_start(unsigned offset) {
2512 ASSERT(kind() == OPTIMIZED_FUNCTION);
2513 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2514 WRITE_UINT32_FIELD(this, kSafepointTableStartOffset, offset);
2515}
2516
2517
2518unsigned Code::stack_check_table_start() {
2519 ASSERT(kind() == FUNCTION);
2520 return READ_UINT32_FIELD(this, kStackCheckTableStartOffset);
2521}
2522
2523
2524void Code::set_stack_check_table_start(unsigned offset) {
2525 ASSERT(kind() == FUNCTION);
2526 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2527 WRITE_UINT32_FIELD(this, kStackCheckTableStartOffset, offset);
2528}
2529
2530
2531CheckType Code::check_type() {
2532 ASSERT(is_call_stub() || is_keyed_call_stub());
2533 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2534 return static_cast<CheckType>(type);
2535}
2536
2537
2538void Code::set_check_type(CheckType value) {
2539 ASSERT(is_call_stub() || is_keyed_call_stub());
2540 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2541}
2542
2543
2544byte Code::binary_op_type() {
2545 ASSERT(is_binary_op_stub());
2546 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2547}
2548
2549
2550void Code::set_binary_op_type(byte value) {
2551 ASSERT(is_binary_op_stub());
2552 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2553}
2554
2555
2556byte Code::type_recording_binary_op_type() {
2557 ASSERT(is_type_recording_binary_op_stub());
2558 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2559}
2560
2561
2562void Code::set_type_recording_binary_op_type(byte value) {
2563 ASSERT(is_type_recording_binary_op_stub());
2564 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2565}
2566
2567
2568byte Code::type_recording_binary_op_result_type() {
2569 ASSERT(is_type_recording_binary_op_stub());
2570 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2571}
2572
2573
2574void Code::set_type_recording_binary_op_result_type(byte value) {
2575 ASSERT(is_type_recording_binary_op_stub());
2576 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2577}
2578
2579
2580byte Code::compare_state() {
2581 ASSERT(is_compare_ic_stub());
2582 return READ_BYTE_FIELD(this, kCompareStateOffset);
2583}
2584
2585
2586void Code::set_compare_state(byte value) {
2587 ASSERT(is_compare_ic_stub());
2588 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2589}
2590
2591
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002592bool Code::is_inline_cache_stub() {
2593 Kind kind = this->kind();
2594 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2595}
2596
2597
2598Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002599 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002600 InlineCacheState ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002601 ExtraICState extra_ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002602 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002603 int argc,
2604 InlineCacheHolderFlag holder) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002605 // Extra IC state is only allowed for monomorphic call IC stubs.
2606 ASSERT(extra_ic_state == kNoExtraICState ||
2607 (kind == CALL_IC && (ic_state == MONOMORPHIC ||
2608 ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002609 // Compute the bit mask.
2610 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002611 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002612 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002613 bits |= type << kFlagsTypeShift;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002614 bits |= extra_ic_state << kFlagsExtraICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002615 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002616 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002617 // Cast to flags and validate result before returning it.
2618 Flags result = static_cast<Flags>(bits);
2619 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002620 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002621 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002622 ASSERT(ExtractTypeFromFlags(result) == type);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002623 ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002624 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2625 return result;
2626}
2627
2628
2629Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2630 PropertyType type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002631 ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002632 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002633 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002634 int argc) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002635 return ComputeFlags(
2636 kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002637}
2638
2639
2640Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2641 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2642 return static_cast<Kind>(bits);
2643}
2644
2645
kasper.lund7276f142008-07-30 08:49:36 +00002646InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2647 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002648 return static_cast<InlineCacheState>(bits);
2649}
2650
2651
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002652Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
2653 int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
2654 return static_cast<ExtraICState>(bits);
2655}
2656
2657
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002658InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2659 int bits = (flags & kFlagsICInLoopMask);
2660 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2661}
2662
2663
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002664PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2665 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2666 return static_cast<PropertyType>(bits);
2667}
2668
2669
2670int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2671 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2672}
2673
2674
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002675InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2676 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2677 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2678}
2679
2680
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002681Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2682 int bits = flags & ~kFlagsTypeMask;
2683 return static_cast<Flags>(bits);
2684}
2685
2686
ager@chromium.org8bb60582008-12-11 12:02:20 +00002687Code* Code::GetCodeFromTargetAddress(Address address) {
2688 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2689 // GetCodeFromTargetAddress might be called when marking objects during mark
2690 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2691 // Code::cast. Code::cast does not work when the object's map is
2692 // marked.
2693 Code* result = reinterpret_cast<Code*>(code);
2694 return result;
2695}
2696
2697
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002698Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2699 return HeapObject::
2700 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2701}
2702
2703
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002704Object* Map::prototype() {
2705 return READ_FIELD(this, kPrototypeOffset);
2706}
2707
2708
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002709void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002710 ASSERT(value->IsNull() || value->IsJSObject());
2711 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002712 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002713}
2714
2715
lrn@chromium.org303ada72010-10-27 09:33:13 +00002716MaybeObject* Map::GetFastElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002717 if (has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002718 Object* obj;
2719 { MaybeObject* maybe_obj = CopyDropTransitions();
2720 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2721 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002722 Map* new_map = Map::cast(obj);
2723 new_map->set_has_fast_elements(true);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002724 Counters::map_slow_to_fast_elements.Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002725 return new_map;
2726}
2727
2728
lrn@chromium.org303ada72010-10-27 09:33:13 +00002729MaybeObject* Map::GetSlowElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002730 if (!has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002731 Object* obj;
2732 { MaybeObject* maybe_obj = CopyDropTransitions();
2733 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2734 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002735 Map* new_map = Map::cast(obj);
2736 new_map->set_has_fast_elements(false);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002737 Counters::map_fast_to_slow_elements.Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002738 return new_map;
2739}
2740
2741
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002742ACCESSORS(Map, instance_descriptors, DescriptorArray,
2743 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002744ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002745ACCESSORS(Map, constructor, Object, kConstructorOffset)
2746
2747ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2748ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002749ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002750
2751ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2752ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002753ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002754
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002755ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002756
2757ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2758ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2759ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2760ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2761ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2762
2763ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2764ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2765ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2766
2767ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2768ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2769ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2770ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2771ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2772ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2773
2774ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2775ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2776
2777ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2778ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2779
2780ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2781ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002782ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2783 kPropertyAccessorsOffset)
2784ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2785 kPrototypeTemplateOffset)
2786ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2787ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2788 kNamedPropertyHandlerOffset)
2789ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2790 kIndexedPropertyHandlerOffset)
2791ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2792 kInstanceTemplateOffset)
2793ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2794ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002795ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2796 kInstanceCallHandlerOffset)
2797ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2798 kAccessCheckInfoOffset)
2799ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2800
2801ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002802ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2803 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002804
2805ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2806ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2807
2808ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2809
2810ACCESSORS(Script, source, Object, kSourceOffset)
2811ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002812ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002813ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2814ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002815ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002816ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002817ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2818ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002819ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002820ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002821ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002822ACCESSORS(Script, eval_from_instructions_offset, Smi,
2823 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002824
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002825#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002826ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2827ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2828ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2829ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2830
2831ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2832ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2833ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2834ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002835#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002836
2837ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002838ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002839ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002840ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2841 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002842ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002843ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2844ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002845ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002846ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2847 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002848
2849BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2850 kHiddenPrototypeBit)
2851BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2852BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2853 kNeedsAccessCheckBit)
2854BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2855 kIsExpressionBit)
2856BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2857 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002858BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002859 has_only_simple_this_property_assignments,
2860 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002861BOOL_ACCESSORS(SharedFunctionInfo,
2862 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002863 try_full_codegen,
2864 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002865BOOL_ACCESSORS(SharedFunctionInfo,
2866 compiler_hints,
2867 allows_lazy_compilation,
2868 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002869
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002870
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002871#if V8_HOST_ARCH_32_BIT
2872SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2873SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002874 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002875SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002876 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002877SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2878SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002879 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002880SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2881SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002882 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002883SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002884 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002885SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002886 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002887SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002888#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002889
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002890#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002891 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002892 int holder::name() { \
2893 int value = READ_INT_FIELD(this, offset); \
2894 ASSERT(kHeapObjectTag == 1); \
2895 ASSERT((value & kHeapObjectTag) == 0); \
2896 return value >> 1; \
2897 } \
2898 void holder::set_##name(int value) { \
2899 ASSERT(kHeapObjectTag == 1); \
2900 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2901 (value & 0xC0000000) == 0x000000000); \
2902 WRITE_INT_FIELD(this, \
2903 offset, \
2904 (value << 1) & ~kHeapObjectTag); \
2905 }
2906
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002907#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2908 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002909 INT_ACCESSORS(holder, name, offset)
2910
2911
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002912PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002913PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2914 formal_parameter_count,
2915 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002916
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002917PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2918 expected_nof_properties,
2919 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002920PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2921
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002922PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
2923PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2924 start_position_and_type,
2925 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002926
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002927PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2928 function_token_position,
2929 kFunctionTokenPositionOffset)
2930PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
2931 compiler_hints,
2932 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002933
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00002934PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
2935 this_property_assignments_count,
2936 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002937PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002938#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002939
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002940
2941int SharedFunctionInfo::construction_count() {
2942 return READ_BYTE_FIELD(this, kConstructionCountOffset);
2943}
2944
2945
2946void SharedFunctionInfo::set_construction_count(int value) {
2947 ASSERT(0 <= value && value < 256);
2948 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
2949}
2950
2951
2952bool SharedFunctionInfo::live_objects_may_exist() {
2953 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
2954}
2955
2956
2957void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
2958 if (value) {
2959 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
2960 } else {
2961 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
2962 }
2963}
2964
2965
2966bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
2967 return initial_map() != Heap::undefined_value();
2968}
2969
2970
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002971bool SharedFunctionInfo::optimization_disabled() {
2972 return BooleanBit::get(compiler_hints(), kOptimizationDisabled);
2973}
2974
2975
2976void SharedFunctionInfo::set_optimization_disabled(bool disable) {
2977 set_compiler_hints(BooleanBit::set(compiler_hints(),
2978 kOptimizationDisabled,
2979 disable));
2980 // If disabling optimizations we reflect that in the code object so
2981 // it will not be counted as optimizable code.
2982 if ((code()->kind() == Code::FUNCTION) && disable) {
2983 code()->set_optimizable(false);
2984 }
2985}
2986
2987
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002988ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2989ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2990
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002991bool Script::HasValidSource() {
2992 Object* src = this->source();
2993 if (!src->IsString()) return true;
2994 String* src_str = String::cast(src);
2995 if (!StringShape(src_str).IsExternal()) return true;
2996 if (src_str->IsAsciiRepresentation()) {
2997 return ExternalAsciiString::cast(src)->resource() != NULL;
2998 } else if (src_str->IsTwoByteRepresentation()) {
2999 return ExternalTwoByteString::cast(src)->resource() != NULL;
3000 }
3001 return true;
3002}
3003
3004
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003005void SharedFunctionInfo::DontAdaptArguments() {
3006 ASSERT(code()->kind() == Code::BUILTIN);
3007 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3008}
3009
3010
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003011int SharedFunctionInfo::start_position() {
3012 return start_position_and_type() >> kStartPositionShift;
3013}
3014
3015
3016void SharedFunctionInfo::set_start_position(int start_position) {
3017 set_start_position_and_type((start_position << kStartPositionShift)
3018 | (start_position_and_type() & ~kStartPositionMask));
3019}
3020
3021
3022Code* SharedFunctionInfo::code() {
3023 return Code::cast(READ_FIELD(this, kCodeOffset));
3024}
3025
3026
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003027Code* SharedFunctionInfo::unchecked_code() {
3028 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3029}
3030
3031
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003032void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003033 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003034 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003035}
3036
3037
ager@chromium.orgb5737492010-07-15 09:29:43 +00003038SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3039 return reinterpret_cast<SerializedScopeInfo*>(
3040 READ_FIELD(this, kScopeInfoOffset));
3041}
3042
3043
3044void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3045 WriteBarrierMode mode) {
3046 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3047 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
3048}
3049
3050
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003051Smi* SharedFunctionInfo::deopt_counter() {
3052 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3053}
3054
3055
3056void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3057 WRITE_FIELD(this, kDeoptCounterOffset, value);
3058}
3059
3060
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003061bool SharedFunctionInfo::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003062 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003063}
3064
3065
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003066bool SharedFunctionInfo::IsApiFunction() {
3067 return function_data()->IsFunctionTemplateInfo();
3068}
3069
3070
3071FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3072 ASSERT(IsApiFunction());
3073 return FunctionTemplateInfo::cast(function_data());
3074}
3075
3076
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003077bool SharedFunctionInfo::HasBuiltinFunctionId() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003078 return function_data()->IsSmi();
3079}
3080
3081
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003082BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3083 ASSERT(HasBuiltinFunctionId());
3084 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003085}
3086
3087
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003088int SharedFunctionInfo::code_age() {
3089 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3090}
3091
3092
3093void SharedFunctionInfo::set_code_age(int code_age) {
3094 set_compiler_hints(compiler_hints() |
3095 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3096}
3097
3098
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003099bool SharedFunctionInfo::has_deoptimization_support() {
3100 Code* code = this->code();
3101 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3102}
3103
3104
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003105bool JSFunction::IsBuiltin() {
3106 return context()->global()->IsJSBuiltinsObject();
3107}
3108
3109
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003110bool JSFunction::NeedsArgumentsAdaption() {
3111 return shared()->formal_parameter_count() !=
3112 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3113}
3114
3115
3116bool JSFunction::IsOptimized() {
3117 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3118}
3119
3120
3121bool JSFunction::IsMarkedForLazyRecompilation() {
3122 return code() == Builtins::builtin(Builtins::LazyRecompile);
3123}
3124
3125
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003126Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003127 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003128}
3129
3130
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003131Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003132 return reinterpret_cast<Code*>(
3133 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003134}
3135
3136
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003137void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003138 // Skip the write barrier because code is never in new space.
3139 ASSERT(!Heap::InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003140 Address entry = value->entry();
3141 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003142}
3143
3144
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003145void JSFunction::ReplaceCode(Code* code) {
3146 bool was_optimized = IsOptimized();
3147 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3148
3149 set_code(code);
3150
3151 // Add/remove the function from the list of optimized functions for this
3152 // context based on the state change.
3153 if (!was_optimized && is_optimized) {
3154 context()->global_context()->AddOptimizedFunction(this);
3155 }
3156 if (was_optimized && !is_optimized) {
3157 context()->global_context()->RemoveOptimizedFunction(this);
3158 }
3159}
3160
3161
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003162Context* JSFunction::context() {
3163 return Context::cast(READ_FIELD(this, kContextOffset));
3164}
3165
3166
3167Object* JSFunction::unchecked_context() {
3168 return READ_FIELD(this, kContextOffset);
3169}
3170
3171
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003172SharedFunctionInfo* JSFunction::unchecked_shared() {
3173 return reinterpret_cast<SharedFunctionInfo*>(
3174 READ_FIELD(this, kSharedFunctionInfoOffset));
3175}
3176
3177
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003178void JSFunction::set_context(Object* value) {
3179 ASSERT(value == Heap::undefined_value() || value->IsContext());
3180 WRITE_FIELD(this, kContextOffset, value);
3181 WRITE_BARRIER(this, kContextOffset);
3182}
3183
3184ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3185 kPrototypeOrInitialMapOffset)
3186
3187
3188Map* JSFunction::initial_map() {
3189 return Map::cast(prototype_or_initial_map());
3190}
3191
3192
3193void JSFunction::set_initial_map(Map* value) {
3194 set_prototype_or_initial_map(value);
3195}
3196
3197
3198bool JSFunction::has_initial_map() {
3199 return prototype_or_initial_map()->IsMap();
3200}
3201
3202
3203bool JSFunction::has_instance_prototype() {
3204 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3205}
3206
3207
3208bool JSFunction::has_prototype() {
3209 return map()->has_non_instance_prototype() || has_instance_prototype();
3210}
3211
3212
3213Object* JSFunction::instance_prototype() {
3214 ASSERT(has_instance_prototype());
3215 if (has_initial_map()) return initial_map()->prototype();
3216 // When there is no initial map and the prototype is a JSObject, the
3217 // initial map field is used for the prototype field.
3218 return prototype_or_initial_map();
3219}
3220
3221
3222Object* JSFunction::prototype() {
3223 ASSERT(has_prototype());
3224 // If the function's prototype property has been set to a non-JSObject
3225 // value, that value is stored in the constructor field of the map.
3226 if (map()->has_non_instance_prototype()) return map()->constructor();
3227 return instance_prototype();
3228}
3229
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003230bool JSFunction::should_have_prototype() {
3231 return map()->function_with_prototype();
3232}
3233
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003234
3235bool JSFunction::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003236 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003237}
3238
3239
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003240int JSFunction::NumberOfLiterals() {
3241 return literals()->length();
3242}
3243
3244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003245Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003246 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003247 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003248}
3249
3250
3251void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3252 Object* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003253 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003254 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3255 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3256}
3257
3258
3259Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003260 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003261 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3262}
3263
3264
3265void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3266 Code* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003267 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003268 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3269 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003270}
3271
3272
3273Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00003274 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003275}
3276
3277
3278void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00003279 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003280}
3281
3282
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003283ACCESSORS(JSValue, value, Object, kValueOffset)
3284
3285
3286JSValue* JSValue::cast(Object* obj) {
3287 ASSERT(obj->IsJSValue());
3288 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3289 return reinterpret_cast<JSValue*>(obj);
3290}
3291
3292
3293INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003294ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003295ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003296
3297
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003298byte* Code::instruction_start() {
3299 return FIELD_ADDR(this, kHeaderSize);
3300}
3301
3302
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003303byte* Code::instruction_end() {
3304 return instruction_start() + instruction_size();
3305}
3306
3307
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003308int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003309 return RoundUp(instruction_size(), kObjectAlignment);
3310}
3311
3312
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003313FixedArray* Code::unchecked_deoptimization_data() {
3314 return reinterpret_cast<FixedArray*>(
3315 READ_FIELD(this, kDeoptimizationDataOffset));
3316}
3317
3318
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003319ByteArray* Code::unchecked_relocation_info() {
3320 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003321}
3322
3323
3324byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003325 return unchecked_relocation_info()->GetDataStartAddress();
3326}
3327
3328
3329int Code::relocation_size() {
3330 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003331}
3332
3333
3334byte* Code::entry() {
3335 return instruction_start();
3336}
3337
3338
3339bool Code::contains(byte* pc) {
3340 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003341 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003342}
3343
3344
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003345ACCESSORS(JSArray, length, Object, kLengthOffset)
3346
3347
ager@chromium.org236ad962008-09-25 09:45:57 +00003348ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003349
3350
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003351JSRegExp::Type JSRegExp::TypeTag() {
3352 Object* data = this->data();
3353 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3354 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3355 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003356}
3357
3358
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003359int JSRegExp::CaptureCount() {
3360 switch (TypeTag()) {
3361 case ATOM:
3362 return 0;
3363 case IRREGEXP:
3364 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3365 default:
3366 UNREACHABLE();
3367 return -1;
3368 }
3369}
3370
3371
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003372JSRegExp::Flags JSRegExp::GetFlags() {
3373 ASSERT(this->data()->IsFixedArray());
3374 Object* data = this->data();
3375 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3376 return Flags(smi->value());
3377}
3378
3379
3380String* JSRegExp::Pattern() {
3381 ASSERT(this->data()->IsFixedArray());
3382 Object* data = this->data();
3383 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3384 return pattern;
3385}
3386
3387
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003388Object* JSRegExp::DataAt(int index) {
3389 ASSERT(TypeTag() != NOT_COMPILED);
3390 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003391}
3392
3393
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003394void JSRegExp::SetDataAt(int index, Object* value) {
3395 ASSERT(TypeTag() != NOT_COMPILED);
3396 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3397 FixedArray::cast(data())->set(index, value);
3398}
3399
3400
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003401JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003402 if (map()->has_fast_elements()) {
3403 ASSERT(elements()->map() == Heap::fixed_array_map() ||
3404 elements()->map() == Heap::fixed_cow_array_map());
3405 return FAST_ELEMENTS;
3406 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003407 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003408 if (array->IsFixedArray()) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003409 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3410 // FixedArray, but FAST_ELEMENTS is already handled above.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003411 ASSERT(array->IsDictionary());
3412 return DICTIONARY_ELEMENTS;
3413 }
ager@chromium.org3811b432009-10-28 14:53:37 +00003414 if (array->IsExternalArray()) {
3415 switch (array->map()->instance_type()) {
3416 case EXTERNAL_BYTE_ARRAY_TYPE:
3417 return EXTERNAL_BYTE_ELEMENTS;
3418 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3419 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3420 case EXTERNAL_SHORT_ARRAY_TYPE:
3421 return EXTERNAL_SHORT_ELEMENTS;
3422 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3423 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3424 case EXTERNAL_INT_ARRAY_TYPE:
3425 return EXTERNAL_INT_ELEMENTS;
3426 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3427 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3428 default:
3429 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3430 return EXTERNAL_FLOAT_ELEMENTS;
3431 }
3432 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003433 ASSERT(array->IsPixelArray());
3434 return PIXEL_ELEMENTS;
3435}
3436
3437
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003438bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003439 return GetElementsKind() == FAST_ELEMENTS;
3440}
3441
3442
3443bool JSObject::HasDictionaryElements() {
3444 return GetElementsKind() == DICTIONARY_ELEMENTS;
3445}
3446
3447
3448bool JSObject::HasPixelElements() {
3449 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003450}
3451
3452
ager@chromium.org3811b432009-10-28 14:53:37 +00003453bool JSObject::HasExternalArrayElements() {
3454 return (HasExternalByteElements() ||
3455 HasExternalUnsignedByteElements() ||
3456 HasExternalShortElements() ||
3457 HasExternalUnsignedShortElements() ||
3458 HasExternalIntElements() ||
3459 HasExternalUnsignedIntElements() ||
3460 HasExternalFloatElements());
3461}
3462
3463
3464bool JSObject::HasExternalByteElements() {
3465 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3466}
3467
3468
3469bool JSObject::HasExternalUnsignedByteElements() {
3470 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3471}
3472
3473
3474bool JSObject::HasExternalShortElements() {
3475 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3476}
3477
3478
3479bool JSObject::HasExternalUnsignedShortElements() {
3480 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3481}
3482
3483
3484bool JSObject::HasExternalIntElements() {
3485 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3486}
3487
3488
3489bool JSObject::HasExternalUnsignedIntElements() {
3490 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3491}
3492
3493
3494bool JSObject::HasExternalFloatElements() {
3495 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3496}
3497
3498
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003499bool JSObject::HasNamedInterceptor() {
3500 return map()->has_named_interceptor();
3501}
3502
3503
3504bool JSObject::HasIndexedInterceptor() {
3505 return map()->has_indexed_interceptor();
3506}
3507
3508
ager@chromium.org5c838252010-02-19 08:53:10 +00003509bool JSObject::AllowsSetElementsLength() {
3510 bool result = elements()->IsFixedArray();
3511 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3512 return result;
3513}
3514
3515
lrn@chromium.org303ada72010-10-27 09:33:13 +00003516MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003517 ASSERT(HasFastElements());
3518 FixedArray* elems = FixedArray::cast(elements());
3519 if (elems->map() != Heap::fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003520 Object* writable_elems;
3521 { MaybeObject* maybe_writable_elems =
3522 Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
3523 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3524 return maybe_writable_elems;
3525 }
3526 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003527 set_elements(FixedArray::cast(writable_elems));
3528 Counters::cow_arrays_converted.Increment();
3529 return writable_elems;
3530}
3531
3532
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003533StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003534 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003535 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003536}
3537
3538
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003539NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003540 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003541 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003542}
3543
3544
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003545bool String::IsHashFieldComputed(uint32_t field) {
3546 return (field & kHashNotComputedMask) == 0;
3547}
3548
3549
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003550bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003551 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003552}
3553
3554
3555uint32_t String::Hash() {
3556 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003557 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003558 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003559 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003560 return ComputeAndSetHash();
3561}
3562
3563
ager@chromium.org7c537e22008-10-16 08:43:32 +00003564StringHasher::StringHasher(int length)
3565 : length_(length),
3566 raw_running_hash_(0),
3567 array_index_(0),
3568 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3569 is_first_char_(true),
3570 is_valid_(true) { }
3571
3572
3573bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003574 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003575}
3576
3577
3578void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003579 // Use the Jenkins one-at-a-time hash function to update the hash
3580 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003581 raw_running_hash_ += c;
3582 raw_running_hash_ += (raw_running_hash_ << 10);
3583 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003584 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003585 if (is_array_index_) {
3586 if (c < '0' || c > '9') {
3587 is_array_index_ = false;
3588 } else {
3589 int d = c - '0';
3590 if (is_first_char_) {
3591 is_first_char_ = false;
3592 if (c == '0' && length_ > 1) {
3593 is_array_index_ = false;
3594 return;
3595 }
3596 }
3597 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3598 is_array_index_ = false;
3599 } else {
3600 array_index_ = array_index_ * 10 + d;
3601 }
3602 }
3603 }
3604}
3605
3606
3607void StringHasher::AddCharacterNoIndex(uc32 c) {
3608 ASSERT(!is_array_index());
3609 raw_running_hash_ += c;
3610 raw_running_hash_ += (raw_running_hash_ << 10);
3611 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3612}
3613
3614
3615uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003616 // Get the calculated raw hash value and do some more bit ops to distribute
3617 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003618 uint32_t result = raw_running_hash_;
3619 result += (result << 3);
3620 result ^= (result >> 11);
3621 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003622 if (result == 0) {
3623 result = 27;
3624 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003625 return result;
3626}
3627
3628
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003629bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003630 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003631 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3632 return false;
3633 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003634 return SlowAsArrayIndex(index);
3635}
3636
3637
3638Object* JSObject::GetPrototype() {
3639 return JSObject::cast(this)->map()->prototype();
3640}
3641
3642
3643PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3644 return GetPropertyAttributeWithReceiver(this, key);
3645}
3646
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003647// TODO(504): this may be useful in other places too where JSGlobalProxy
3648// is used.
3649Object* JSObject::BypassGlobalProxy() {
3650 if (IsJSGlobalProxy()) {
3651 Object* proto = GetPrototype();
3652 if (proto->IsNull()) return Heap::undefined_value();
3653 ASSERT(proto->IsJSGlobalObject());
3654 return proto;
3655 }
3656 return this;
3657}
3658
3659
3660bool JSObject::HasHiddenPropertiesObject() {
3661 ASSERT(!IsJSGlobalProxy());
3662 return GetPropertyAttributePostInterceptor(this,
3663 Heap::hidden_symbol(),
3664 false) != ABSENT;
3665}
3666
3667
3668Object* JSObject::GetHiddenPropertiesObject() {
3669 ASSERT(!IsJSGlobalProxy());
3670 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003671 // You can't install a getter on a property indexed by the hidden symbol,
3672 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3673 // object.
3674 Object* result =
3675 GetLocalPropertyPostInterceptor(this,
3676 Heap::hidden_symbol(),
3677 &attributes)->ToObjectUnchecked();
3678 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003679}
3680
3681
lrn@chromium.org303ada72010-10-27 09:33:13 +00003682MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003683 ASSERT(!IsJSGlobalProxy());
3684 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3685 hidden_obj,
3686 DONT_ENUM);
3687}
3688
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003689
3690bool JSObject::HasElement(uint32_t index) {
3691 return HasElementWithReceiver(this, index);
3692}
3693
3694
3695bool AccessorInfo::all_can_read() {
3696 return BooleanBit::get(flag(), kAllCanReadBit);
3697}
3698
3699
3700void AccessorInfo::set_all_can_read(bool value) {
3701 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3702}
3703
3704
3705bool AccessorInfo::all_can_write() {
3706 return BooleanBit::get(flag(), kAllCanWriteBit);
3707}
3708
3709
3710void AccessorInfo::set_all_can_write(bool value) {
3711 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3712}
3713
3714
ager@chromium.org870a0b62008-11-04 11:43:05 +00003715bool AccessorInfo::prohibits_overwriting() {
3716 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3717}
3718
3719
3720void AccessorInfo::set_prohibits_overwriting(bool value) {
3721 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3722}
3723
3724
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003725PropertyAttributes AccessorInfo::property_attributes() {
3726 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3727}
3728
3729
3730void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3731 ASSERT(AttributesField::is_valid(attributes));
3732 int rest_value = flag()->value() & ~AttributesField::mask();
3733 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3734}
3735
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003736template<typename Shape, typename Key>
3737void Dictionary<Shape, Key>::SetEntry(int entry,
3738 Object* key,
3739 Object* value,
3740 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003741 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003742 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003743 AssertNoAllocation no_gc;
3744 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003745 FixedArray::set(index, key, mode);
3746 FixedArray::set(index+1, value, mode);
3747 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003748}
3749
3750
3751void Map::ClearCodeCache() {
3752 // No write barrier is needed since empty_fixed_array is not in new space.
3753 // Please note this function is used during marking:
3754 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003755 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3756 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003757}
3758
3759
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003760void JSArray::EnsureSize(int required_size) {
3761 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003762 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003763 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3764 if (elts->length() < required_size) {
3765 // Doubling in size would be overkill, but leave some slack to avoid
3766 // constantly growing.
3767 Expand(required_size + (required_size >> 3));
3768 // It's a performance benefit to keep a frequently used array in new-space.
3769 } else if (!Heap::new_space()->Contains(elts) &&
3770 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3771 // Expand will allocate a new backing store in new space even if the size
3772 // we asked for isn't larger than what we had before.
3773 Expand(required_size);
3774 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003775}
3776
3777
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003778void JSArray::set_length(Smi* length) {
3779 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3780}
3781
3782
ager@chromium.org7c537e22008-10-16 08:43:32 +00003783void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003784 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003785 set_elements(storage);
3786}
3787
3788
lrn@chromium.org303ada72010-10-27 09:33:13 +00003789MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003790 if (length() == 0) return this;
3791 return Heap::CopyFixedArray(this);
3792}
3793
3794
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003795int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3796 return map->instance_size();
3797}
3798
3799
3800void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3801 v->VisitExternalReference(
3802 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3803}
3804
3805
3806template<typename StaticVisitor>
3807void Proxy::ProxyIterateBody() {
3808 StaticVisitor::VisitExternalReference(
3809 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3810}
3811
3812
3813void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3814 typedef v8::String::ExternalAsciiStringResource Resource;
3815 v->VisitExternalAsciiString(
3816 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3817}
3818
3819
3820template<typename StaticVisitor>
3821void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3822 typedef v8::String::ExternalAsciiStringResource Resource;
3823 StaticVisitor::VisitExternalAsciiString(
3824 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3825}
3826
3827
3828void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3829 typedef v8::String::ExternalStringResource Resource;
3830 v->VisitExternalTwoByteString(
3831 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3832}
3833
3834
3835template<typename StaticVisitor>
3836void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3837 typedef v8::String::ExternalStringResource Resource;
3838 StaticVisitor::VisitExternalTwoByteString(
3839 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3840}
3841
3842#define SLOT_ADDR(obj, offset) \
3843 reinterpret_cast<Object**>((obj)->address() + offset)
3844
3845template<int start_offset, int end_offset, int size>
3846void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3847 HeapObject* obj,
3848 ObjectVisitor* v) {
3849 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3850}
3851
3852
3853template<int start_offset>
3854void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3855 int object_size,
3856 ObjectVisitor* v) {
3857 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3858}
3859
3860#undef SLOT_ADDR
3861
3862
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003863#undef CAST_ACCESSOR
3864#undef INT_ACCESSORS
3865#undef SMI_ACCESSORS
3866#undef ACCESSORS
3867#undef FIELD_ADDR
3868#undef READ_FIELD
3869#undef WRITE_FIELD
3870#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003871#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003872#undef READ_MEMADDR_FIELD
3873#undef WRITE_MEMADDR_FIELD
3874#undef READ_DOUBLE_FIELD
3875#undef WRITE_DOUBLE_FIELD
3876#undef READ_INT_FIELD
3877#undef WRITE_INT_FIELD
3878#undef READ_SHORT_FIELD
3879#undef WRITE_SHORT_FIELD
3880#undef READ_BYTE_FIELD
3881#undef WRITE_BYTE_FIELD
3882
3883
3884} } // namespace v8::internal
3885
3886#endif // V8_OBJECTS_INL_H_