blob: 922c0548f670b44633e958b4df8502a375c7ebcf [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"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000042#include "isolate.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"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000045#include "v8memory.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
kasperl@chromium.org71affb52009-05-26 05:44:31 +000047namespace v8 {
48namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
50PropertyDetails::PropertyDetails(Smi* smi) {
51 value_ = smi->value();
52}
53
54
55Smi* PropertyDetails::AsSmi() {
56 return Smi::FromInt(value_);
57}
58
59
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000060PropertyDetails PropertyDetails::AsDeleted() {
ager@chromium.org378b34e2011-01-28 08:04:38 +000061 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000062 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); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000082 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); \
83 }
84
85
86// GC-safe accessors do not use HeapObject::GetHeap(), but access TLS instead.
87#define ACCESSORS_GCSAFE(holder, name, type, offset) \
88 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
89 void holder::set_##name(type* value, WriteBarrierMode mode) { \
90 WRITE_FIELD(this, offset, value); \
91 CONDITIONAL_WRITE_BARRIER(HEAP, this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092 }
93
94
95#define SMI_ACCESSORS(holder, name, offset) \
96 int holder::name() { \
97 Object* value = READ_FIELD(this, offset); \
98 return Smi::cast(value)->value(); \
99 } \
100 void holder::set_##name(int value) { \
101 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
102 }
103
104
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000105#define BOOL_GETTER(holder, field, name, offset) \
106 bool holder::name() { \
107 return BooleanBit::get(field(), offset); \
108 } \
109
110
111#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112 bool holder::name() { \
113 return BooleanBit::get(field(), offset); \
114 } \
115 void holder::set_##name(bool value) { \
116 set_##field(BooleanBit::set(field(), offset, value)); \
117 }
118
119
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000120bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
121 // There is a constraint on the object; check.
122 if (!this->IsJSObject()) return false;
123 // Fetch the constructor function of the object.
124 Object* cons_obj = JSObject::cast(this)->map()->constructor();
125 if (!cons_obj->IsJSFunction()) return false;
126 JSFunction* fun = JSFunction::cast(cons_obj);
127 // Iterate through the chain of inheriting function templates to
128 // see if the required one occurs.
129 for (Object* type = fun->shared()->function_data();
130 type->IsFunctionTemplateInfo();
131 type = FunctionTemplateInfo::cast(type)->parent_template()) {
132 if (type == expected) return true;
133 }
134 // Didn't find the required type in the inheritance chain.
135 return false;
136}
137
138
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000139bool Object::IsSmi() {
140 return HAS_SMI_TAG(this);
141}
142
143
144bool Object::IsHeapObject() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000145 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146}
147
148
149bool Object::IsHeapNumber() {
150 return Object::IsHeapObject()
151 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
152}
153
154
155bool Object::IsString() {
156 return Object::IsHeapObject()
157 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
158}
159
160
ager@chromium.org870a0b62008-11-04 11:43:05 +0000161bool Object::IsSymbol() {
162 if (!this->IsHeapObject()) return false;
163 uint32_t type = HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000164 // Because the symbol tag is non-zero and no non-string types have the
165 // symbol bit set we can test for symbols with a very simple test
166 // operation.
167 ASSERT(kSymbolTag != 0);
168 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
169 return (type & kIsSymbolMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000170}
171
172
173bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000174 if (!this->IsHeapObject()) return false;
175 uint32_t type = HeapObject::cast(this)->map()->instance_type();
176 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
177 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178}
179
180
ager@chromium.org870a0b62008-11-04 11:43:05 +0000181bool Object::IsSeqString() {
182 if (!IsString()) return false;
183 return StringShape(String::cast(this)).IsSequential();
184}
185
186
187bool Object::IsSeqAsciiString() {
188 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000189 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000190 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000191}
192
193
194bool Object::IsSeqTwoByteString() {
195 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000196 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000197 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198}
199
200
201bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000202 if (!IsString()) return false;
203 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204}
205
206
207bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000208 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000209 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000210 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000211}
212
213
214bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000215 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000216 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000217 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218}
219
220
ager@chromium.org870a0b62008-11-04 11:43:05 +0000221StringShape::StringShape(String* str)
222 : type_(str->map()->instance_type()) {
223 set_valid();
224 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000225}
226
227
ager@chromium.org870a0b62008-11-04 11:43:05 +0000228StringShape::StringShape(Map* map)
229 : type_(map->instance_type()) {
230 set_valid();
231 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000232}
233
234
ager@chromium.org870a0b62008-11-04 11:43:05 +0000235StringShape::StringShape(InstanceType t)
236 : type_(static_cast<uint32_t>(t)) {
237 set_valid();
238 ASSERT((type_ & kIsNotStringMask) == kStringTag);
239}
240
241
242bool StringShape::IsSymbol() {
243 ASSERT(valid());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000244 ASSERT(kSymbolTag != 0);
245 return (type_ & kIsSymbolMask) != 0;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000246}
247
248
ager@chromium.org5ec48922009-05-05 07:25:34 +0000249bool String::IsAsciiRepresentation() {
250 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000251 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000252}
253
254
ager@chromium.org5ec48922009-05-05 07:25:34 +0000255bool String::IsTwoByteRepresentation() {
256 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000257 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000258}
259
260
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000261bool String::HasOnlyAsciiChars() {
262 uint32_t type = map()->instance_type();
263 return (type & kStringEncodingMask) == kAsciiStringTag ||
264 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000265}
266
267
ager@chromium.org870a0b62008-11-04 11:43:05 +0000268bool StringShape::IsCons() {
269 return (type_ & kStringRepresentationMask) == kConsStringTag;
270}
271
272
ager@chromium.org870a0b62008-11-04 11:43:05 +0000273bool StringShape::IsExternal() {
274 return (type_ & kStringRepresentationMask) == kExternalStringTag;
275}
276
277
278bool StringShape::IsSequential() {
279 return (type_ & kStringRepresentationMask) == kSeqStringTag;
280}
281
282
283StringRepresentationTag StringShape::representation_tag() {
284 uint32_t tag = (type_ & kStringRepresentationMask);
285 return static_cast<StringRepresentationTag>(tag);
286}
287
288
289uint32_t StringShape::full_representation_tag() {
290 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
291}
292
293
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000294STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
295 Internals::kFullStringRepresentationMask);
296
297
ager@chromium.org870a0b62008-11-04 11:43:05 +0000298bool StringShape::IsSequentialAscii() {
299 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
300}
301
302
303bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000304 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000305}
306
307
308bool StringShape::IsExternalAscii() {
309 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
310}
311
312
313bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000314 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315}
316
317
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000318STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
319 Internals::kExternalTwoByteRepresentationTag);
320
321
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000322uc32 FlatStringReader::Get(int index) {
323 ASSERT(0 <= index && index <= length_);
324 if (is_ascii_) {
325 return static_cast<const byte*>(start_)[index];
326 } else {
327 return static_cast<const uc16*>(start_)[index];
328 }
329}
330
331
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332bool Object::IsNumber() {
333 return IsSmi() || IsHeapNumber();
334}
335
336
337bool Object::IsByteArray() {
338 return Object::IsHeapObject()
339 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
340}
341
342
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000343bool Object::IsExternalPixelArray() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000344 return Object::IsHeapObject() &&
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000345 HeapObject::cast(this)->map()->instance_type() ==
346 EXTERNAL_PIXEL_ARRAY_TYPE;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000347}
348
349
ager@chromium.org3811b432009-10-28 14:53:37 +0000350bool Object::IsExternalArray() {
351 if (!Object::IsHeapObject())
352 return false;
353 InstanceType instance_type =
354 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000355 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
356 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000357}
358
359
360bool Object::IsExternalByteArray() {
361 return Object::IsHeapObject() &&
362 HeapObject::cast(this)->map()->instance_type() ==
363 EXTERNAL_BYTE_ARRAY_TYPE;
364}
365
366
367bool Object::IsExternalUnsignedByteArray() {
368 return Object::IsHeapObject() &&
369 HeapObject::cast(this)->map()->instance_type() ==
370 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
371}
372
373
374bool Object::IsExternalShortArray() {
375 return Object::IsHeapObject() &&
376 HeapObject::cast(this)->map()->instance_type() ==
377 EXTERNAL_SHORT_ARRAY_TYPE;
378}
379
380
381bool Object::IsExternalUnsignedShortArray() {
382 return Object::IsHeapObject() &&
383 HeapObject::cast(this)->map()->instance_type() ==
384 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
385}
386
387
388bool Object::IsExternalIntArray() {
389 return Object::IsHeapObject() &&
390 HeapObject::cast(this)->map()->instance_type() ==
391 EXTERNAL_INT_ARRAY_TYPE;
392}
393
394
395bool Object::IsExternalUnsignedIntArray() {
396 return Object::IsHeapObject() &&
397 HeapObject::cast(this)->map()->instance_type() ==
398 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
399}
400
401
402bool Object::IsExternalFloatArray() {
403 return Object::IsHeapObject() &&
404 HeapObject::cast(this)->map()->instance_type() ==
405 EXTERNAL_FLOAT_ARRAY_TYPE;
406}
407
408
lrn@chromium.org303ada72010-10-27 09:33:13 +0000409bool MaybeObject::IsFailure() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 return HAS_FAILURE_TAG(this);
411}
412
413
lrn@chromium.org303ada72010-10-27 09:33:13 +0000414bool MaybeObject::IsRetryAfterGC() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415 return HAS_FAILURE_TAG(this)
416 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
417}
418
419
lrn@chromium.org303ada72010-10-27 09:33:13 +0000420bool MaybeObject::IsOutOfMemory() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000421 return HAS_FAILURE_TAG(this)
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000422 && Failure::cast(this)->IsOutOfMemoryException();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000423}
424
425
lrn@chromium.org303ada72010-10-27 09:33:13 +0000426bool MaybeObject::IsException() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 return this == Failure::Exception();
428}
429
430
lrn@chromium.org303ada72010-10-27 09:33:13 +0000431bool MaybeObject::IsTheHole() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000432 return !IsFailure() && ToObjectUnchecked()->IsTheHole();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000433}
434
435
436Failure* Failure::cast(MaybeObject* obj) {
437 ASSERT(HAS_FAILURE_TAG(obj));
438 return reinterpret_cast<Failure*>(obj);
439}
440
441
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000442bool Object::IsJSObject() {
443 return IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000444 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445}
446
447
ager@chromium.org32912102009-01-16 10:38:43 +0000448bool Object::IsJSContextExtensionObject() {
449 return IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000450 && (HeapObject::cast(this)->map()->instance_type() ==
451 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
ager@chromium.org32912102009-01-16 10:38:43 +0000452}
453
454
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455bool Object::IsMap() {
456 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000457 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000458}
459
460
461bool Object::IsFixedArray() {
462 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000463 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464}
465
466
467bool Object::IsDescriptorArray() {
468 return IsFixedArray();
469}
470
471
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000472bool Object::IsDeoptimizationInputData() {
473 // Must be a fixed array.
474 if (!IsFixedArray()) return false;
475
476 // There's no sure way to detect the difference between a fixed array and
477 // a deoptimization data array. Since this is used for asserts we can
478 // check that the length is zero or else the fixed size plus a multiple of
479 // the entry size.
480 int length = FixedArray::cast(this)->length();
481 if (length == 0) return true;
482
483 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
484 return length >= 0 &&
485 length % DeoptimizationInputData::kDeoptEntrySize == 0;
486}
487
488
489bool Object::IsDeoptimizationOutputData() {
490 if (!IsFixedArray()) return false;
491 // There's actually no way to see the difference between a fixed array and
492 // a deoptimization data array. Since this is used for asserts we can check
493 // that the length is plausible though.
494 if (FixedArray::cast(this)->length() % 2 != 0) return false;
495 return true;
496}
497
498
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499bool Object::IsContext() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000500 if (Object::IsHeapObject()) {
501 Heap* heap = HeapObject::cast(this)->GetHeap();
502 return (HeapObject::cast(this)->map() == heap->context_map() ||
503 HeapObject::cast(this)->map() == heap->catch_context_map() ||
504 HeapObject::cast(this)->map() == heap->global_context_map());
505 }
506 return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507}
508
509
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000510bool Object::IsCatchContext() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000511 return Object::IsHeapObject() &&
512 HeapObject::cast(this)->map() ==
513 HeapObject::cast(this)->GetHeap()->catch_context_map();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000514}
515
516
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517bool Object::IsGlobalContext() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000518 return Object::IsHeapObject() &&
519 HeapObject::cast(this)->map() ==
520 HeapObject::cast(this)->GetHeap()->global_context_map();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521}
522
523
524bool Object::IsJSFunction() {
525 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000526 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527}
528
529
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000530template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531 return obj->IsJSFunction();
532}
533
534
535bool Object::IsCode() {
536 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000537 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000538}
539
540
541bool Object::IsOddball() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542 ASSERT(HEAP->is_safe_to_read_maps());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543 return Object::IsHeapObject()
544 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
545}
546
547
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000548bool Object::IsJSGlobalPropertyCell() {
549 return Object::IsHeapObject()
550 && HeapObject::cast(this)->map()->instance_type()
551 == JS_GLOBAL_PROPERTY_CELL_TYPE;
552}
553
554
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000555bool Object::IsSharedFunctionInfo() {
556 return Object::IsHeapObject() &&
557 (HeapObject::cast(this)->map()->instance_type() ==
558 SHARED_FUNCTION_INFO_TYPE);
559}
560
561
562bool Object::IsJSValue() {
563 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000564 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
565}
566
567
568bool Object::IsJSMessageObject() {
569 return Object::IsHeapObject()
570 && (HeapObject::cast(this)->map()->instance_type() ==
571 JS_MESSAGE_OBJECT_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572}
573
574
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000575bool Object::IsStringWrapper() {
576 return IsJSValue() && JSValue::cast(this)->value()->IsString();
577}
578
579
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580bool Object::IsProxy() {
581 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000582 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583}
584
585
586bool Object::IsBoolean() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000587 return IsOddball() &&
588 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000589}
590
591
592bool Object::IsJSArray() {
593 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000594 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595}
596
597
ager@chromium.org236ad962008-09-25 09:45:57 +0000598bool Object::IsJSRegExp() {
599 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000600 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
ager@chromium.org236ad962008-09-25 09:45:57 +0000601}
602
603
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000604template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605 return obj->IsJSArray();
606}
607
608
609bool Object::IsHashTable() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000610 return Object::IsHeapObject() &&
611 HeapObject::cast(this)->map() ==
612 HeapObject::cast(this)->GetHeap()->hash_table_map();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613}
614
615
616bool Object::IsDictionary() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000617 return IsHashTable() && this !=
618 HeapObject::cast(this)->GetHeap()->symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619}
620
621
622bool Object::IsSymbolTable() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000623 return IsHashTable() && this ==
624 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000625}
626
627
ager@chromium.orgac091b72010-05-05 07:34:42 +0000628bool Object::IsJSFunctionResultCache() {
629 if (!IsFixedArray()) return false;
630 FixedArray* self = FixedArray::cast(this);
631 int length = self->length();
632 if (length < JSFunctionResultCache::kEntriesIndex) return false;
633 if ((length - JSFunctionResultCache::kEntriesIndex)
634 % JSFunctionResultCache::kEntrySize != 0) {
635 return false;
636 }
637#ifdef DEBUG
638 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
639#endif
640 return true;
641}
642
643
ricow@chromium.org65fae842010-08-25 15:26:24 +0000644bool Object::IsNormalizedMapCache() {
645 if (!IsFixedArray()) return false;
646 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
647 return false;
648 }
649#ifdef DEBUG
650 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
651#endif
652 return true;
653}
654
655
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000656bool Object::IsCompilationCacheTable() {
657 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000658}
659
660
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000661bool Object::IsCodeCacheHashTable() {
662 return IsHashTable();
663}
664
665
ager@chromium.org236ad962008-09-25 09:45:57 +0000666bool Object::IsMapCache() {
667 return IsHashTable();
668}
669
670
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000671bool Object::IsPrimitive() {
672 return IsOddball() || IsNumber() || IsString();
673}
674
675
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000676bool Object::IsJSGlobalProxy() {
677 bool result = IsHeapObject() &&
678 (HeapObject::cast(this)->map()->instance_type() ==
679 JS_GLOBAL_PROXY_TYPE);
680 ASSERT(!result || IsAccessCheckNeeded());
681 return result;
682}
683
684
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000686 if (!IsHeapObject()) return false;
687
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000688 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000689 return type == JS_GLOBAL_OBJECT_TYPE ||
690 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000691}
692
693
694bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695 return IsHeapObject() &&
696 (HeapObject::cast(this)->map()->instance_type() ==
697 JS_GLOBAL_OBJECT_TYPE);
698}
699
700
701bool Object::IsJSBuiltinsObject() {
702 return IsHeapObject() &&
703 (HeapObject::cast(this)->map()->instance_type() ==
704 JS_BUILTINS_OBJECT_TYPE);
705}
706
707
708bool Object::IsUndetectableObject() {
709 return IsHeapObject()
710 && HeapObject::cast(this)->map()->is_undetectable();
711}
712
713
714bool Object::IsAccessCheckNeeded() {
715 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000716 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717}
718
719
720bool Object::IsStruct() {
721 if (!IsHeapObject()) return false;
722 switch (HeapObject::cast(this)->map()->instance_type()) {
723#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
724 STRUCT_LIST(MAKE_STRUCT_CASE)
725#undef MAKE_STRUCT_CASE
726 default: return false;
727 }
728}
729
730
731#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
732 bool Object::Is##Name() { \
733 return Object::IsHeapObject() \
734 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
735 }
736 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
737#undef MAKE_STRUCT_PREDICATE
738
739
740bool Object::IsUndefined() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000741 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000742}
743
744
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745bool Object::IsNull() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000746 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
747}
748
749
750bool Object::IsTheHole() {
751 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752}
753
754
755bool Object::IsTrue() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000756 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757}
758
759
760bool Object::IsFalse() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000761 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762}
763
764
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000765bool Object::IsArgumentsMarker() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000766 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000767}
768
769
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000770double Object::Number() {
771 ASSERT(IsNumber());
772 return IsSmi()
773 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
774 : reinterpret_cast<HeapNumber*>(this)->value();
775}
776
777
lrn@chromium.org303ada72010-10-27 09:33:13 +0000778MaybeObject* Object::ToSmi() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000779 if (IsSmi()) return this;
780 if (IsHeapNumber()) {
781 double value = HeapNumber::cast(this)->value();
782 int int_value = FastD2I(value);
783 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
784 return Smi::FromInt(int_value);
785 }
786 }
787 return Failure::Exception();
788}
789
790
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000791bool Object::HasSpecificClassOf(String* name) {
792 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
793}
794
795
lrn@chromium.org303ada72010-10-27 09:33:13 +0000796MaybeObject* Object::GetElement(uint32_t index) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000797 // GetElement can trigger a getter which can cause allocation.
798 // This was not always the case. This ASSERT is here to catch
799 // leftover incorrect uses.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000800 ASSERT(HEAP->IsAllocationAllowed());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000801 return GetElementWithReceiver(this, index);
802}
803
804
lrn@chromium.org303ada72010-10-27 09:33:13 +0000805Object* Object::GetElementNoExceptionThrown(uint32_t index) {
806 MaybeObject* maybe = GetElementWithReceiver(this, index);
807 ASSERT(!maybe->IsFailure());
808 Object* result = NULL; // Initialization to please compiler.
809 maybe->ToObject(&result);
810 return result;
811}
812
813
814MaybeObject* Object::GetProperty(String* key) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815 PropertyAttributes attributes;
816 return GetPropertyWithReceiver(this, key, &attributes);
817}
818
819
lrn@chromium.org303ada72010-10-27 09:33:13 +0000820MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000821 return GetPropertyWithReceiver(this, key, attributes);
822}
823
824
825#define FIELD_ADDR(p, offset) \
826 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
827
828#define READ_FIELD(p, offset) \
829 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
830
831#define WRITE_FIELD(p, offset, value) \
832 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
833
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000834// TODO(isolates): Pass heap in to these macros.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835#define WRITE_BARRIER(object, offset) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000836 object->GetHeap()->RecordWrite(object->address(), offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000837
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000838// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000839// write due to the assert validating the written value.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000840#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, mode) \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000841 if (mode == UPDATE_WRITE_BARRIER) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000842 heap->RecordWrite(object->address(), offset); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000843 } else { \
844 ASSERT(mode == SKIP_WRITE_BARRIER); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000845 ASSERT(heap->InNewSpace(object) || \
846 !heap->InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000847 Page::FromAddress(object->address())-> \
848 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000849 }
850
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000851#define READ_DOUBLE_FIELD(p, offset) \
852 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
853
854#define WRITE_DOUBLE_FIELD(p, offset, value) \
855 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
856
857#define READ_INT_FIELD(p, offset) \
858 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
859
860#define WRITE_INT_FIELD(p, offset, value) \
861 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
862
ager@chromium.org3e875802009-06-29 08:26:34 +0000863#define READ_INTPTR_FIELD(p, offset) \
864 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
865
866#define WRITE_INTPTR_FIELD(p, offset, value) \
867 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
868
ager@chromium.org7c537e22008-10-16 08:43:32 +0000869#define READ_UINT32_FIELD(p, offset) \
870 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
871
872#define WRITE_UINT32_FIELD(p, offset, value) \
873 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
874
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875#define READ_SHORT_FIELD(p, offset) \
876 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
877
878#define WRITE_SHORT_FIELD(p, offset, value) \
879 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
880
881#define READ_BYTE_FIELD(p, offset) \
882 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
883
884#define WRITE_BYTE_FIELD(p, offset, value) \
885 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
886
887
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000888Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
889 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890}
891
892
893int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000894 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000895}
896
897
898Smi* Smi::FromInt(int value) {
899 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000900 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000901 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000902 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000903 return reinterpret_cast<Smi*>(tagged_value);
904}
905
906
907Smi* Smi::FromIntptr(intptr_t value) {
908 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000909 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
910 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911}
912
913
914Failure::Type Failure::type() const {
915 return static_cast<Type>(value() & kFailureTypeTagMask);
916}
917
918
919bool Failure::IsInternalError() const {
920 return type() == INTERNAL_ERROR;
921}
922
923
924bool Failure::IsOutOfMemoryException() const {
925 return type() == OUT_OF_MEMORY_EXCEPTION;
926}
927
928
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000929AllocationSpace Failure::allocation_space() const {
930 ASSERT_EQ(RETRY_AFTER_GC, type());
931 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
932 & kSpaceTagMask);
933}
934
935
936Failure* Failure::InternalError() {
937 return Construct(INTERNAL_ERROR);
938}
939
940
941Failure* Failure::Exception() {
942 return Construct(EXCEPTION);
943}
944
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000945
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000946Failure* Failure::OutOfMemoryException() {
947 return Construct(OUT_OF_MEMORY_EXCEPTION);
948}
949
950
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000951intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000952 return static_cast<intptr_t>(
953 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000954}
955
956
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000957Failure* Failure::RetryAfterGC() {
958 return RetryAfterGC(NEW_SPACE);
959}
960
961
962Failure* Failure::RetryAfterGC(AllocationSpace space) {
963 ASSERT((space & ~kSpaceTagMask) == 0);
964 return Construct(RETRY_AFTER_GC, space);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000965}
966
967
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000968Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000969 uintptr_t info =
970 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000971 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000972 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973}
974
975
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000976bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000977#ifdef DEBUG
978 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
979#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000980
981#ifdef V8_TARGET_ARCH_X64
982 // To be representable as a long smi, the value must be a 32-bit integer.
983 bool result = (value == static_cast<int32_t>(value));
984#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000985 // To be representable as an tagged small integer, the two
986 // most-significant bits of 'value' must be either 00 or 11 due to
987 // sign-extension. To check this we add 01 to the two
988 // most-significant bits, and check if the most-significant bit is 0
989 //
990 // CAUTION: The original code below:
991 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
992 // may lead to incorrect results according to the C language spec, and
993 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
994 // compiler may produce undefined results in case of signed integer
995 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000996 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000997#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000998 ASSERT(result == in_range);
999 return result;
1000}
1001
1002
kasper.lund7276f142008-07-30 08:49:36 +00001003MapWord MapWord::FromMap(Map* map) {
1004 return MapWord(reinterpret_cast<uintptr_t>(map));
1005}
1006
1007
1008Map* MapWord::ToMap() {
1009 return reinterpret_cast<Map*>(value_);
1010}
1011
1012
1013bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001014 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +00001015}
1016
1017
1018MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001019 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1020 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +00001021}
1022
1023
1024HeapObject* MapWord::ToForwardingAddress() {
1025 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +00001026 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +00001027}
1028
1029
1030bool MapWord::IsMarked() {
1031 return (value_ & kMarkingMask) == 0;
1032}
1033
1034
1035void MapWord::SetMark() {
1036 value_ &= ~kMarkingMask;
1037}
1038
1039
1040void MapWord::ClearMark() {
1041 value_ |= kMarkingMask;
1042}
1043
1044
1045bool MapWord::IsOverflowed() {
1046 return (value_ & kOverflowMask) != 0;
1047}
1048
1049
1050void MapWord::SetOverflow() {
1051 value_ |= kOverflowMask;
1052}
1053
1054
1055void MapWord::ClearOverflow() {
1056 value_ &= ~kOverflowMask;
1057}
1058
1059
1060MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1061 // Offset is the distance in live bytes from the first live object in the
1062 // same page. The offset between two objects in the same page should not
1063 // exceed the object area size of a page.
1064 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1065
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001066 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001067 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1068
1069 Page* map_page = Page::FromAddress(map_address);
1070 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1071
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001072 uintptr_t map_page_offset =
1073 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001074
1075 uintptr_t encoding =
1076 (compact_offset << kForwardingOffsetShift) |
1077 (map_page_offset << kMapPageOffsetShift) |
1078 (map_page->mc_page_index << kMapPageIndexShift);
1079 return MapWord(encoding);
1080}
1081
1082
1083Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001084 int map_page_index =
1085 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001086 ASSERT_MAP_PAGE_INDEX(map_page_index);
1087
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001088 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001089 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1090 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001091
1092 return (map_space->PageAddress(map_page_index) + map_page_offset);
1093}
1094
1095
1096int MapWord::DecodeOffset() {
1097 // The offset field is represented in the kForwardingOffsetBits
1098 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001099 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1100 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1101 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001102}
1103
1104
1105MapWord MapWord::FromEncodedAddress(Address address) {
1106 return MapWord(reinterpret_cast<uintptr_t>(address));
1107}
1108
1109
1110Address MapWord::ToEncodedAddress() {
1111 return reinterpret_cast<Address>(value_);
1112}
1113
1114
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001115#ifdef DEBUG
1116void HeapObject::VerifyObjectField(int offset) {
1117 VerifyPointer(READ_FIELD(this, offset));
1118}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001119
1120void HeapObject::VerifySmiField(int offset) {
1121 ASSERT(READ_FIELD(this, offset)->IsSmi());
1122}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123#endif
1124
1125
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001126Heap* HeapObject::GetHeap() {
1127 // During GC, the map pointer in HeapObject is used in various ways that
1128 // prevent us from retrieving Heap from the map.
1129 // Assert that we are not in GC, implement GC code in a way that it doesn't
1130 // pull heap from the map.
1131 ASSERT(HEAP->is_safe_to_read_maps());
1132 return map()->heap();
1133}
1134
1135
1136Isolate* HeapObject::GetIsolate() {
1137 return GetHeap()->isolate();
1138}
1139
1140
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001141Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001142 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001143}
1144
1145
1146void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001147 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001148}
1149
1150
kasper.lund7276f142008-07-30 08:49:36 +00001151MapWord HeapObject::map_word() {
1152 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1153}
1154
1155
1156void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001157 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001158 // here.
1159 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1160}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001161
1162
1163HeapObject* HeapObject::FromAddress(Address address) {
1164 ASSERT_TAG_ALIGNED(address);
1165 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1166}
1167
1168
1169Address HeapObject::address() {
1170 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1171}
1172
1173
1174int HeapObject::Size() {
1175 return SizeFromMap(map());
1176}
1177
1178
1179void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1180 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1181 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1182}
1183
1184
1185void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1186 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1187}
1188
1189
kasper.lund7276f142008-07-30 08:49:36 +00001190bool HeapObject::IsMarked() {
1191 return map_word().IsMarked();
1192}
1193
1194
1195void HeapObject::SetMark() {
1196 ASSERT(!IsMarked());
1197 MapWord first_word = map_word();
1198 first_word.SetMark();
1199 set_map_word(first_word);
1200}
1201
1202
1203void HeapObject::ClearMark() {
1204 ASSERT(IsMarked());
1205 MapWord first_word = map_word();
1206 first_word.ClearMark();
1207 set_map_word(first_word);
1208}
1209
1210
1211bool HeapObject::IsOverflowed() {
1212 return map_word().IsOverflowed();
1213}
1214
1215
1216void HeapObject::SetOverflow() {
1217 MapWord first_word = map_word();
1218 first_word.SetOverflow();
1219 set_map_word(first_word);
1220}
1221
1222
1223void HeapObject::ClearOverflow() {
1224 ASSERT(IsOverflowed());
1225 MapWord first_word = map_word();
1226 first_word.ClearOverflow();
1227 set_map_word(first_word);
1228}
1229
1230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001231double HeapNumber::value() {
1232 return READ_DOUBLE_FIELD(this, kValueOffset);
1233}
1234
1235
1236void HeapNumber::set_value(double value) {
1237 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1238}
1239
1240
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001241int HeapNumber::get_exponent() {
1242 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1243 kExponentShift) - kExponentBias;
1244}
1245
1246
1247int HeapNumber::get_sign() {
1248 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1249}
1250
1251
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001253
1254
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001255HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001256 Object* array = READ_FIELD(this, kElementsOffset);
1257 // In the assert below Dictionary is covered under FixedArray.
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001258 ASSERT(array->IsFixedArray() || array->IsExternalArray());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001259 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001260}
1261
1262
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001263void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001264 ASSERT(map()->has_fast_elements() ==
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001265 (value->map() == GetHeap()->fixed_array_map() ||
1266 value->map() == GetHeap()->fixed_cow_array_map()));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001267 // In the assert below Dictionary is covered under FixedArray.
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001268 ASSERT(value->IsFixedArray() || value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001269 WRITE_FIELD(this, kElementsOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001270 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, mode);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001271}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272
1273
1274void JSObject::initialize_properties() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001275 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1276 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277}
1278
1279
1280void JSObject::initialize_elements() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001281 ASSERT(map()->has_fast_elements());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001282 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1283 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284}
1285
1286
lrn@chromium.org303ada72010-10-27 09:33:13 +00001287MaybeObject* JSObject::ResetElements() {
1288 Object* obj;
1289 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1290 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1291 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001292 set_map(Map::cast(obj));
1293 initialize_elements();
1294 return this;
1295}
1296
1297
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001298ACCESSORS(Oddball, to_string, String, kToStringOffset)
1299ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1300
1301
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001302byte Oddball::kind() {
1303 return READ_BYTE_FIELD(this, kKindOffset);
1304}
1305
1306
1307void Oddball::set_kind(byte value) {
1308 WRITE_BYTE_FIELD(this, kKindOffset, value);
1309}
1310
1311
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001312Object* JSGlobalPropertyCell::value() {
1313 return READ_FIELD(this, kValueOffset);
1314}
1315
1316
1317void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1318 // The write barrier is not used for global property cells.
1319 ASSERT(!val->IsJSGlobalPropertyCell());
1320 WRITE_FIELD(this, kValueOffset, val);
1321}
1322
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001323
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001325 InstanceType type = map()->instance_type();
1326 // Check for the most common kind of JavaScript object before
1327 // falling into the generic switch. This speeds up the internal
1328 // field operations considerably on average.
1329 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1330 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001331 case JS_GLOBAL_PROXY_TYPE:
1332 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001333 case JS_GLOBAL_OBJECT_TYPE:
1334 return JSGlobalObject::kSize;
1335 case JS_BUILTINS_OBJECT_TYPE:
1336 return JSBuiltinsObject::kSize;
1337 case JS_FUNCTION_TYPE:
1338 return JSFunction::kSize;
1339 case JS_VALUE_TYPE:
1340 return JSValue::kSize;
1341 case JS_ARRAY_TYPE:
1342 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001343 case JS_REGEXP_TYPE:
1344 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001345 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001346 return JSObject::kHeaderSize;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001347 case JS_MESSAGE_OBJECT_TYPE:
1348 return JSMessageObject::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001349 default:
1350 UNREACHABLE();
1351 return 0;
1352 }
1353}
1354
1355
1356int JSObject::GetInternalFieldCount() {
1357 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001358 // Make sure to adjust for the number of in-object properties. These
1359 // properties do contribute to the size, but are not internal fields.
1360 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1361 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001362}
1363
1364
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001365int JSObject::GetInternalFieldOffset(int index) {
1366 ASSERT(index < GetInternalFieldCount() && index >= 0);
1367 return GetHeaderSize() + (kPointerSize * index);
1368}
1369
1370
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001371Object* JSObject::GetInternalField(int index) {
1372 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001373 // Internal objects do follow immediately after the header, whereas in-object
1374 // properties are at the end of the object. Therefore there is no need
1375 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001376 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1377}
1378
1379
1380void JSObject::SetInternalField(int index, Object* value) {
1381 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001382 // Internal objects do follow immediately after the header, whereas in-object
1383 // properties are at the end of the object. Therefore there is no need
1384 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001385 int offset = GetHeaderSize() + (kPointerSize * index);
1386 WRITE_FIELD(this, offset, value);
1387 WRITE_BARRIER(this, offset);
1388}
1389
1390
ager@chromium.org7c537e22008-10-16 08:43:32 +00001391// Access fast-case object properties at index. The use of these routines
1392// is needed to correctly distinguish between properties stored in-object and
1393// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001394Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001395 // Adjust for the number of properties stored in the object.
1396 index -= map()->inobject_properties();
1397 if (index < 0) {
1398 int offset = map()->instance_size() + (index * kPointerSize);
1399 return READ_FIELD(this, offset);
1400 } else {
1401 ASSERT(index < properties()->length());
1402 return properties()->get(index);
1403 }
1404}
1405
1406
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001407Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001408 // Adjust for the number of properties stored in the object.
1409 index -= map()->inobject_properties();
1410 if (index < 0) {
1411 int offset = map()->instance_size() + (index * kPointerSize);
1412 WRITE_FIELD(this, offset, value);
1413 WRITE_BARRIER(this, offset);
1414 } else {
1415 ASSERT(index < properties()->length());
1416 properties()->set(index, value);
1417 }
1418 return value;
1419}
1420
1421
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001422int JSObject::GetInObjectPropertyOffset(int index) {
1423 // Adjust for the number of properties stored in the object.
1424 index -= map()->inobject_properties();
1425 ASSERT(index < 0);
1426 return map()->instance_size() + (index * kPointerSize);
1427}
1428
1429
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001430Object* JSObject::InObjectPropertyAt(int index) {
1431 // Adjust for the number of properties stored in the object.
1432 index -= map()->inobject_properties();
1433 ASSERT(index < 0);
1434 int offset = map()->instance_size() + (index * kPointerSize);
1435 return READ_FIELD(this, offset);
1436}
1437
1438
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001439Object* JSObject::InObjectPropertyAtPut(int index,
1440 Object* value,
1441 WriteBarrierMode mode) {
1442 // Adjust for the number of properties stored in the object.
1443 index -= map()->inobject_properties();
1444 ASSERT(index < 0);
1445 int offset = map()->instance_size() + (index * kPointerSize);
1446 WRITE_FIELD(this, offset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001447 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001448 return value;
1449}
1450
1451
1452
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001453void JSObject::InitializeBody(int object_size, Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001454 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001455 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001456 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001457 }
1458}
1459
1460
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001461bool JSObject::HasFastProperties() {
1462 return !properties()->IsDictionary();
1463}
1464
1465
1466int JSObject::MaxFastProperties() {
1467 // Allow extra fast properties if the object has more than
1468 // kMaxFastProperties in-object properties. When this is the case,
1469 // it is very unlikely that the object is being used as a dictionary
1470 // and there is a good chance that allowing more map transitions
1471 // will be worth it.
1472 return Max(map()->inobject_properties(), kMaxFastProperties);
1473}
1474
1475
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476void Struct::InitializeBody(int object_size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001477 Object* value = GetHeap()->undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001478 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001479 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001480 }
1481}
1482
1483
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001484bool Object::ToArrayIndex(uint32_t* index) {
1485 if (IsSmi()) {
1486 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001487 if (value < 0) return false;
1488 *index = value;
1489 return true;
1490 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001491 if (IsHeapNumber()) {
1492 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001493 uint32_t uint_value = static_cast<uint32_t>(value);
1494 if (value == static_cast<double>(uint_value)) {
1495 *index = uint_value;
1496 return true;
1497 }
1498 }
1499 return false;
1500}
1501
1502
1503bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1504 if (!this->IsJSValue()) return false;
1505
1506 JSValue* js_value = JSValue::cast(this);
1507 if (!js_value->value()->IsString()) return false;
1508
1509 String* str = String::cast(js_value->value());
1510 if (index >= (uint32_t)str->length()) return false;
1511
1512 return true;
1513}
1514
1515
1516Object* FixedArray::get(int index) {
1517 ASSERT(index >= 0 && index < this->length());
1518 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1519}
1520
1521
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001522void FixedArray::set(int index, Smi* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001523 ASSERT(map() != HEAP->fixed_cow_array_map());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001524 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1525 int offset = kHeaderSize + index * kPointerSize;
1526 WRITE_FIELD(this, offset, value);
1527}
1528
1529
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001530void FixedArray::set(int index, Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001531 ASSERT(map() != HEAP->fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001532 ASSERT(index >= 0 && index < this->length());
1533 int offset = kHeaderSize + index * kPointerSize;
1534 WRITE_FIELD(this, offset, value);
1535 WRITE_BARRIER(this, offset);
1536}
1537
1538
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001539WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001540 if (GetHeap()->InNewSpace(this)) return SKIP_WRITE_BARRIER;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001541 return UPDATE_WRITE_BARRIER;
1542}
1543
1544
1545void FixedArray::set(int index,
1546 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001547 WriteBarrierMode mode) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001548 ASSERT(map() != HEAP->fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549 ASSERT(index >= 0 && index < this->length());
1550 int offset = kHeaderSize + index * kPointerSize;
1551 WRITE_FIELD(this, offset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001552 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001553}
1554
1555
1556void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001557 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001558 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001559 ASSERT(!HEAP->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001560 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1561}
1562
1563
1564void FixedArray::set_undefined(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001565 ASSERT(map() != HEAP->fixed_cow_array_map());
1566 set_undefined(GetHeap(), index);
1567}
1568
1569
1570void FixedArray::set_undefined(Heap* heap, int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001571 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001572 ASSERT(!heap->InNewSpace(heap->undefined_value()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001573 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001574 heap->undefined_value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001575}
1576
1577
ager@chromium.org236ad962008-09-25 09:45:57 +00001578void FixedArray::set_null(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001579 set_null(GetHeap(), index);
1580}
1581
1582
1583void FixedArray::set_null(Heap* heap, int index) {
ager@chromium.org236ad962008-09-25 09:45:57 +00001584 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001585 ASSERT(!heap->InNewSpace(heap->null_value()));
1586 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
ager@chromium.org236ad962008-09-25 09:45:57 +00001587}
1588
1589
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001590void FixedArray::set_the_hole(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001591 ASSERT(map() != HEAP->fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001592 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001593 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1594 WRITE_FIELD(this,
1595 kHeaderSize + index * kPointerSize,
1596 GetHeap()->the_hole_value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001597}
1598
1599
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001600void FixedArray::set_unchecked(int index, Smi* value) {
1601 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1602 int offset = kHeaderSize + index * kPointerSize;
1603 WRITE_FIELD(this, offset, value);
1604}
1605
1606
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001607void FixedArray::set_unchecked(Heap* heap,
1608 int index,
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001609 Object* value,
1610 WriteBarrierMode mode) {
1611 int offset = kHeaderSize + index * kPointerSize;
1612 WRITE_FIELD(this, offset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001613 CONDITIONAL_WRITE_BARRIER(heap, this, offset, mode);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001614}
1615
1616
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001617void FixedArray::set_null_unchecked(Heap* heap, int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001618 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001619 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1620 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001621}
1622
1623
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001624Object** FixedArray::data_start() {
1625 return HeapObject::RawField(this, kHeaderSize);
1626}
1627
1628
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001629bool DescriptorArray::IsEmpty() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001630 ASSERT(this->length() > kFirstIndex ||
1631 this == HEAP->empty_descriptor_array());
1632 return length() <= kFirstIndex;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001633}
1634
1635
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001636void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1637 Object* tmp = array->get(first);
1638 fast_set(array, first, array->get(second));
1639 fast_set(array, second, tmp);
1640}
1641
1642
1643int DescriptorArray::Search(String* name) {
1644 SLOW_ASSERT(IsSortedNoDuplicates());
1645
1646 // Check for empty descriptor array.
1647 int nof = number_of_descriptors();
1648 if (nof == 0) return kNotFound;
1649
1650 // Fast case: do linear search for small arrays.
1651 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001652 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001653 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001654 }
1655
1656 // Slow case: perform binary search.
1657 return BinarySearch(name, 0, nof - 1);
1658}
1659
1660
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001661int DescriptorArray::SearchWithCache(String* name) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001662 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001663 if (number == DescriptorLookupCache::kAbsent) {
1664 number = Search(name);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001665 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001666 }
1667 return number;
1668}
1669
1670
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001671String* DescriptorArray::GetKey(int descriptor_number) {
1672 ASSERT(descriptor_number < number_of_descriptors());
1673 return String::cast(get(ToKeyIndex(descriptor_number)));
1674}
1675
1676
1677Object* DescriptorArray::GetValue(int descriptor_number) {
1678 ASSERT(descriptor_number < number_of_descriptors());
1679 return GetContentArray()->get(ToValueIndex(descriptor_number));
1680}
1681
1682
1683Smi* DescriptorArray::GetDetails(int descriptor_number) {
1684 ASSERT(descriptor_number < number_of_descriptors());
1685 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1686}
1687
1688
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001689PropertyType DescriptorArray::GetType(int descriptor_number) {
1690 ASSERT(descriptor_number < number_of_descriptors());
1691 return PropertyDetails(GetDetails(descriptor_number)).type();
1692}
1693
1694
1695int DescriptorArray::GetFieldIndex(int descriptor_number) {
1696 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1697}
1698
1699
1700JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1701 return JSFunction::cast(GetValue(descriptor_number));
1702}
1703
1704
1705Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1706 ASSERT(GetType(descriptor_number) == CALLBACKS);
1707 return GetValue(descriptor_number);
1708}
1709
1710
1711AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1712 ASSERT(GetType(descriptor_number) == CALLBACKS);
1713 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1714 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1715}
1716
1717
1718bool DescriptorArray::IsProperty(int descriptor_number) {
1719 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1720}
1721
1722
1723bool DescriptorArray::IsTransition(int descriptor_number) {
1724 PropertyType t = GetType(descriptor_number);
1725 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1726}
1727
1728
1729bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1730 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1731}
1732
1733
1734bool DescriptorArray::IsDontEnum(int descriptor_number) {
1735 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1736}
1737
1738
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1740 desc->Init(GetKey(descriptor_number),
1741 GetValue(descriptor_number),
1742 GetDetails(descriptor_number));
1743}
1744
1745
1746void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1747 // Range check.
1748 ASSERT(descriptor_number < number_of_descriptors());
1749
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001750 // Make sure none of the elements in desc are in new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001751 ASSERT(!HEAP->InNewSpace(desc->GetKey()));
1752 ASSERT(!HEAP->InNewSpace(desc->GetValue()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001753
1754 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1755 FixedArray* content_array = GetContentArray();
1756 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1757 fast_set(content_array, ToDetailsIndex(descriptor_number),
1758 desc->GetDetails().AsSmi());
1759}
1760
1761
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001762void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1763 Descriptor desc;
1764 src->Get(src_index, &desc);
1765 Set(index, &desc);
1766}
1767
1768
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001769void DescriptorArray::Swap(int first, int second) {
1770 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1771 FixedArray* content_array = GetContentArray();
1772 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1773 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1774}
1775
1776
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001777template<typename Shape, typename Key>
1778int HashTable<Shape, Key>::FindEntry(Key key) {
1779 return FindEntry(GetIsolate(), key);
1780}
1781
1782
1783// Find entry for key otherwise return kNotFound.
1784template<typename Shape, typename Key>
1785int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
1786 uint32_t capacity = Capacity();
1787 uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
1788 uint32_t count = 1;
1789 // EnsureCapacity will guarantee the hash table is never full.
1790 while (true) {
1791 Object* element = KeyAt(entry);
1792 if (element == isolate->heap()->undefined_value()) break; // Empty entry.
1793 if (element != isolate->heap()->null_value() &&
1794 Shape::IsMatch(key, element)) return entry;
1795 entry = NextProbe(entry, count++, capacity);
1796 }
1797 return kNotFound;
1798}
1799
1800
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001801bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001802 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001803 if (!max_index_object->IsSmi()) return false;
1804 return 0 !=
1805 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1806}
1807
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001808uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001809 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001810 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001811 if (!max_index_object->IsSmi()) return 0;
1812 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1813 return value >> kRequiresSlowElementsTagSize;
1814}
1815
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001816void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001817 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001818}
1819
1820
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001821// ------------------------------------
1822// Cast operations
1823
1824
1825CAST_ACCESSOR(FixedArray)
1826CAST_ACCESSOR(DescriptorArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001827CAST_ACCESSOR(DeoptimizationInputData)
1828CAST_ACCESSOR(DeoptimizationOutputData)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001829CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001830CAST_ACCESSOR(JSFunctionResultCache)
ricow@chromium.org65fae842010-08-25 15:26:24 +00001831CAST_ACCESSOR(NormalizedMapCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001832CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001833CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001834CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001835CAST_ACCESSOR(String)
1836CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001837CAST_ACCESSOR(SeqAsciiString)
1838CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001839CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001840CAST_ACCESSOR(ExternalString)
1841CAST_ACCESSOR(ExternalAsciiString)
1842CAST_ACCESSOR(ExternalTwoByteString)
1843CAST_ACCESSOR(JSObject)
1844CAST_ACCESSOR(Smi)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001845CAST_ACCESSOR(HeapObject)
1846CAST_ACCESSOR(HeapNumber)
1847CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001848CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001849CAST_ACCESSOR(SharedFunctionInfo)
1850CAST_ACCESSOR(Map)
1851CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001852CAST_ACCESSOR(GlobalObject)
1853CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001854CAST_ACCESSOR(JSGlobalObject)
1855CAST_ACCESSOR(JSBuiltinsObject)
1856CAST_ACCESSOR(Code)
1857CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001858CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001859CAST_ACCESSOR(Proxy)
1860CAST_ACCESSOR(ByteArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001861CAST_ACCESSOR(ExternalArray)
1862CAST_ACCESSOR(ExternalByteArray)
1863CAST_ACCESSOR(ExternalUnsignedByteArray)
1864CAST_ACCESSOR(ExternalShortArray)
1865CAST_ACCESSOR(ExternalUnsignedShortArray)
1866CAST_ACCESSOR(ExternalIntArray)
1867CAST_ACCESSOR(ExternalUnsignedIntArray)
1868CAST_ACCESSOR(ExternalFloatArray)
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001869CAST_ACCESSOR(ExternalPixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001870CAST_ACCESSOR(Struct)
1871
1872
1873#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1874 STRUCT_LIST(MAKE_STRUCT_CAST)
1875#undef MAKE_STRUCT_CAST
1876
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001877
1878template <typename Shape, typename Key>
1879HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001880 ASSERT(obj->IsHashTable());
1881 return reinterpret_cast<HashTable*>(obj);
1882}
1883
1884
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001885SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1886SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1887
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001888INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889
1890
ager@chromium.orgac091b72010-05-05 07:34:42 +00001891SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001892
1893
1894uint32_t String::hash_field() {
1895 return READ_UINT32_FIELD(this, kHashFieldOffset);
1896}
1897
1898
1899void String::set_hash_field(uint32_t value) {
1900 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001901#if V8_HOST_ARCH_64_BIT
1902 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1903#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001904}
1905
1906
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001907bool String::Equals(String* other) {
1908 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001909 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1910 return false;
1911 }
1912 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001913}
1914
1915
lrn@chromium.org303ada72010-10-27 09:33:13 +00001916MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001917 if (!StringShape(this).IsCons()) return this;
1918 ConsString* cons = ConsString::cast(this);
1919 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001920 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001921}
1922
1923
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001924String* String::TryFlattenGetString(PretenureFlag pretenure) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001925 MaybeObject* flat = TryFlatten(pretenure);
1926 Object* successfully_flattened;
1927 if (flat->ToObject(&successfully_flattened)) {
1928 return String::cast(successfully_flattened);
1929 }
1930 return this;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001931}
1932
1933
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001934uint16_t String::Get(int index) {
1935 ASSERT(index >= 0 && index < length());
1936 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001937 case kSeqStringTag | kAsciiStringTag:
1938 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1939 case kSeqStringTag | kTwoByteStringTag:
1940 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1941 case kConsStringTag | kAsciiStringTag:
1942 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001943 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001944 case kExternalStringTag | kAsciiStringTag:
1945 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1946 case kExternalStringTag | kTwoByteStringTag:
1947 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001948 default:
1949 break;
1950 }
1951
1952 UNREACHABLE();
1953 return 0;
1954}
1955
1956
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001957void String::Set(int index, uint16_t value) {
1958 ASSERT(index >= 0 && index < length());
1959 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001960
ager@chromium.org5ec48922009-05-05 07:25:34 +00001961 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001962 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1963 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001964}
1965
1966
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001967bool String::IsFlat() {
1968 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001969 case kConsStringTag: {
1970 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001971 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001972 return second->length() == 0;
1973 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001974 default:
1975 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001976 }
1977}
1978
1979
ager@chromium.org7c537e22008-10-16 08:43:32 +00001980uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001981 ASSERT(index >= 0 && index < length());
1982 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1983}
1984
1985
ager@chromium.org7c537e22008-10-16 08:43:32 +00001986void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001987 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1988 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1989 static_cast<byte>(value));
1990}
1991
1992
ager@chromium.org7c537e22008-10-16 08:43:32 +00001993Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001994 return FIELD_ADDR(this, kHeaderSize);
1995}
1996
1997
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001998char* SeqAsciiString::GetChars() {
1999 return reinterpret_cast<char*>(GetCharsAddress());
2000}
2001
2002
ager@chromium.org7c537e22008-10-16 08:43:32 +00002003Address SeqTwoByteString::GetCharsAddress() {
2004 return FIELD_ADDR(this, kHeaderSize);
2005}
2006
2007
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002008uc16* SeqTwoByteString::GetChars() {
2009 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2010}
2011
2012
ager@chromium.org7c537e22008-10-16 08:43:32 +00002013uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002014 ASSERT(index >= 0 && index < length());
2015 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2016}
2017
2018
ager@chromium.org7c537e22008-10-16 08:43:32 +00002019void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002020 ASSERT(index >= 0 && index < length());
2021 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2022}
2023
2024
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002025int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00002026 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002027}
2028
2029
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002030int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00002031 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002032}
2033
2034
ager@chromium.org870a0b62008-11-04 11:43:05 +00002035String* ConsString::first() {
2036 return String::cast(READ_FIELD(this, kFirstOffset));
2037}
2038
2039
2040Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002041 return READ_FIELD(this, kFirstOffset);
2042}
2043
2044
ager@chromium.org870a0b62008-11-04 11:43:05 +00002045void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002046 WRITE_FIELD(this, kFirstOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002047 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002048}
2049
2050
ager@chromium.org870a0b62008-11-04 11:43:05 +00002051String* ConsString::second() {
2052 return String::cast(READ_FIELD(this, kSecondOffset));
2053}
2054
2055
2056Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002057 return READ_FIELD(this, kSecondOffset);
2058}
2059
2060
ager@chromium.org870a0b62008-11-04 11:43:05 +00002061void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002062 WRITE_FIELD(this, kSecondOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002063 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002064}
2065
2066
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002067ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2068 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2069}
2070
2071
2072void ExternalAsciiString::set_resource(
2073 ExternalAsciiString::Resource* resource) {
2074 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
2075}
2076
2077
2078ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2079 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2080}
2081
2082
2083void ExternalTwoByteString::set_resource(
2084 ExternalTwoByteString::Resource* resource) {
2085 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
2086}
2087
2088
ager@chromium.orgac091b72010-05-05 07:34:42 +00002089void JSFunctionResultCache::MakeZeroSize() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002090 set_finger_index(kEntriesIndex);
2091 set_size(kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002092}
2093
2094
2095void JSFunctionResultCache::Clear() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002096 int cache_size = size();
ager@chromium.orgac091b72010-05-05 07:34:42 +00002097 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00002098 MemsetPointer(entries_start,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002099 GetHeap()->the_hole_value(),
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00002100 cache_size - kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002101 MakeZeroSize();
2102}
2103
2104
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002105int JSFunctionResultCache::size() {
2106 return Smi::cast(get(kCacheSizeIndex))->value();
2107}
2108
2109
2110void JSFunctionResultCache::set_size(int size) {
2111 set(kCacheSizeIndex, Smi::FromInt(size));
2112}
2113
2114
2115int JSFunctionResultCache::finger_index() {
2116 return Smi::cast(get(kFingerIndex))->value();
2117}
2118
2119
2120void JSFunctionResultCache::set_finger_index(int finger_index) {
2121 set(kFingerIndex, Smi::FromInt(finger_index));
2122}
2123
2124
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002125byte ByteArray::get(int index) {
2126 ASSERT(index >= 0 && index < this->length());
2127 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2128}
2129
2130
2131void ByteArray::set(int index, byte value) {
2132 ASSERT(index >= 0 && index < this->length());
2133 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2134}
2135
2136
2137int ByteArray::get_int(int index) {
2138 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2139 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2140}
2141
2142
2143ByteArray* ByteArray::FromDataStartAddress(Address address) {
2144 ASSERT_TAG_ALIGNED(address);
2145 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2146}
2147
2148
2149Address ByteArray::GetDataStartAddress() {
2150 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2151}
2152
2153
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002154uint8_t* ExternalPixelArray::external_pixel_pointer() {
2155 return reinterpret_cast<uint8_t*>(external_pointer());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002156}
2157
2158
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002159uint8_t ExternalPixelArray::get(int index) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002160 ASSERT((index >= 0) && (index < this->length()));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002161 uint8_t* ptr = external_pixel_pointer();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002162 return ptr[index];
2163}
2164
2165
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002166void ExternalPixelArray::set(int index, uint8_t value) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002167 ASSERT((index >= 0) && (index < this->length()));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002168 uint8_t* ptr = external_pixel_pointer();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002169 ptr[index] = value;
2170}
2171
2172
ager@chromium.org3811b432009-10-28 14:53:37 +00002173void* ExternalArray::external_pointer() {
2174 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2175 return reinterpret_cast<void*>(ptr);
2176}
2177
2178
2179void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2180 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2181 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2182}
2183
2184
2185int8_t ExternalByteArray::get(int index) {
2186 ASSERT((index >= 0) && (index < this->length()));
2187 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2188 return ptr[index];
2189}
2190
2191
2192void ExternalByteArray::set(int index, int8_t value) {
2193 ASSERT((index >= 0) && (index < this->length()));
2194 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2195 ptr[index] = value;
2196}
2197
2198
2199uint8_t ExternalUnsignedByteArray::get(int index) {
2200 ASSERT((index >= 0) && (index < this->length()));
2201 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2202 return ptr[index];
2203}
2204
2205
2206void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2207 ASSERT((index >= 0) && (index < this->length()));
2208 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2209 ptr[index] = value;
2210}
2211
2212
2213int16_t ExternalShortArray::get(int index) {
2214 ASSERT((index >= 0) && (index < this->length()));
2215 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2216 return ptr[index];
2217}
2218
2219
2220void ExternalShortArray::set(int index, int16_t value) {
2221 ASSERT((index >= 0) && (index < this->length()));
2222 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2223 ptr[index] = value;
2224}
2225
2226
2227uint16_t ExternalUnsignedShortArray::get(int index) {
2228 ASSERT((index >= 0) && (index < this->length()));
2229 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2230 return ptr[index];
2231}
2232
2233
2234void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2235 ASSERT((index >= 0) && (index < this->length()));
2236 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2237 ptr[index] = value;
2238}
2239
2240
2241int32_t ExternalIntArray::get(int index) {
2242 ASSERT((index >= 0) && (index < this->length()));
2243 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2244 return ptr[index];
2245}
2246
2247
2248void ExternalIntArray::set(int index, int32_t value) {
2249 ASSERT((index >= 0) && (index < this->length()));
2250 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2251 ptr[index] = value;
2252}
2253
2254
2255uint32_t ExternalUnsignedIntArray::get(int index) {
2256 ASSERT((index >= 0) && (index < this->length()));
2257 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2258 return ptr[index];
2259}
2260
2261
2262void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2263 ASSERT((index >= 0) && (index < this->length()));
2264 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2265 ptr[index] = value;
2266}
2267
2268
2269float ExternalFloatArray::get(int index) {
2270 ASSERT((index >= 0) && (index < this->length()));
2271 float* ptr = static_cast<float*>(external_pointer());
2272 return ptr[index];
2273}
2274
2275
2276void ExternalFloatArray::set(int index, float value) {
2277 ASSERT((index >= 0) && (index < this->length()));
2278 float* ptr = static_cast<float*>(external_pointer());
2279 ptr[index] = value;
2280}
2281
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002282
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00002283int Map::visitor_id() {
2284 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2285}
2286
2287
2288void Map::set_visitor_id(int id) {
2289 ASSERT(0 <= id && id < 256);
2290 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2291}
2292
ager@chromium.org3811b432009-10-28 14:53:37 +00002293
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002294int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002295 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2296}
2297
2298
2299int Map::inobject_properties() {
2300 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002301}
2302
2303
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002304int Map::pre_allocated_property_fields() {
2305 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2306}
2307
2308
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002309int HeapObject::SizeFromMap(Map* map) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002310 int instance_size = map->instance_size();
2311 if (instance_size != kVariableSizeSentinel) return instance_size;
2312 // We can ignore the "symbol" bit becase it is only set for symbols
2313 // and implies a string type.
2314 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002315 // Only inline the most frequent cases.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002316 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002317 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002318 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002319 if (instance_type == ASCII_STRING_TYPE) {
2320 return SeqAsciiString::SizeFor(
2321 reinterpret_cast<SeqAsciiString*>(this)->length());
2322 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002323 if (instance_type == BYTE_ARRAY_TYPE) {
2324 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2325 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002326 if (instance_type == STRING_TYPE) {
2327 return SeqTwoByteString::SizeFor(
2328 reinterpret_cast<SeqTwoByteString*>(this)->length());
2329 }
2330 ASSERT(instance_type == CODE_TYPE);
2331 return reinterpret_cast<Code*>(this)->CodeSize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002332}
2333
2334
2335void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002336 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002337 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002338 ASSERT(0 <= value && value < 256);
2339 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2340}
2341
2342
ager@chromium.org7c537e22008-10-16 08:43:32 +00002343void Map::set_inobject_properties(int value) {
2344 ASSERT(0 <= value && value < 256);
2345 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2346}
2347
2348
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002349void Map::set_pre_allocated_property_fields(int value) {
2350 ASSERT(0 <= value && value < 256);
2351 WRITE_BYTE_FIELD(this,
2352 kPreAllocatedPropertyFieldsOffset,
2353 static_cast<byte>(value));
2354}
2355
2356
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002357InstanceType Map::instance_type() {
2358 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2359}
2360
2361
2362void Map::set_instance_type(InstanceType value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002363 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2364}
2365
2366
2367int Map::unused_property_fields() {
2368 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2369}
2370
2371
2372void Map::set_unused_property_fields(int value) {
2373 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2374}
2375
2376
2377byte Map::bit_field() {
2378 return READ_BYTE_FIELD(this, kBitFieldOffset);
2379}
2380
2381
2382void Map::set_bit_field(byte value) {
2383 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2384}
2385
2386
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002387byte Map::bit_field2() {
2388 return READ_BYTE_FIELD(this, kBitField2Offset);
2389}
2390
2391
2392void Map::set_bit_field2(byte value) {
2393 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2394}
2395
2396
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002397void Map::set_non_instance_prototype(bool value) {
2398 if (value) {
2399 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2400 } else {
2401 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2402 }
2403}
2404
2405
2406bool Map::has_non_instance_prototype() {
2407 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2408}
2409
2410
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002411void Map::set_function_with_prototype(bool value) {
2412 if (value) {
2413 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2414 } else {
2415 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2416 }
2417}
2418
2419
2420bool Map::function_with_prototype() {
2421 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2422}
2423
2424
ager@chromium.org870a0b62008-11-04 11:43:05 +00002425void Map::set_is_access_check_needed(bool access_check_needed) {
2426 if (access_check_needed) {
2427 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2428 } else {
2429 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2430 }
2431}
2432
2433
2434bool Map::is_access_check_needed() {
2435 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2436}
2437
2438
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002439void Map::set_is_extensible(bool value) {
2440 if (value) {
2441 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2442 } else {
2443 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2444 }
2445}
2446
2447bool Map::is_extensible() {
2448 return ((1 << kIsExtensible) & bit_field2()) != 0;
2449}
2450
2451
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002452void Map::set_attached_to_shared_function_info(bool value) {
2453 if (value) {
2454 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2455 } else {
2456 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2457 }
2458}
2459
2460bool Map::attached_to_shared_function_info() {
2461 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2462}
2463
2464
2465void Map::set_is_shared(bool value) {
2466 if (value) {
2467 set_bit_field2(bit_field2() | (1 << kIsShared));
2468 } else {
2469 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2470 }
2471}
2472
2473bool Map::is_shared() {
2474 return ((1 << kIsShared) & bit_field2()) != 0;
2475}
2476
2477
2478JSFunction* Map::unchecked_constructor() {
2479 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2480}
2481
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002482
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002483Code::Flags Code::flags() {
2484 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2485}
2486
2487
2488void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002489 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002490 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002491 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2492 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002493 ExtractArgumentsCountFromFlags(flags) >= 0);
2494 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2495}
2496
2497
2498Code::Kind Code::kind() {
2499 return ExtractKindFromFlags(flags());
2500}
2501
2502
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002503InLoopFlag Code::ic_in_loop() {
2504 return ExtractICInLoopFromFlags(flags());
2505}
2506
2507
kasper.lund7276f142008-07-30 08:49:36 +00002508InlineCacheState Code::ic_state() {
2509 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002510 // Only allow uninitialized or debugger states for non-IC code
2511 // objects. This is used in the debugger to determine whether or not
2512 // a call to code object has been replaced with a debug break call.
2513 ASSERT(is_inline_cache_stub() ||
2514 result == UNINITIALIZED ||
2515 result == DEBUG_BREAK ||
2516 result == DEBUG_PREPARE_STEP_IN);
2517 return result;
2518}
2519
2520
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002521Code::ExtraICState Code::extra_ic_state() {
2522 ASSERT(is_inline_cache_stub());
2523 return ExtractExtraICStateFromFlags(flags());
2524}
2525
2526
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002527PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002528 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002529 return ExtractTypeFromFlags(flags());
2530}
2531
2532
2533int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002534 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002535 return ExtractArgumentsCountFromFlags(flags());
2536}
2537
2538
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002539int Code::major_key() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002540 ASSERT(kind() == STUB ||
2541 kind() == BINARY_OP_IC ||
2542 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2543 kind() == COMPARE_IC);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002544 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
kasper.lund7276f142008-07-30 08:49:36 +00002545}
2546
2547
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002548void Code::set_major_key(int major) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002549 ASSERT(kind() == STUB ||
2550 kind() == BINARY_OP_IC ||
2551 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2552 kind() == COMPARE_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002553 ASSERT(0 <= major && major < 256);
2554 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002555}
2556
2557
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002558bool Code::optimizable() {
2559 ASSERT(kind() == FUNCTION);
2560 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2561}
2562
2563
2564void Code::set_optimizable(bool value) {
2565 ASSERT(kind() == FUNCTION);
2566 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2567}
2568
2569
2570bool Code::has_deoptimization_support() {
2571 ASSERT(kind() == FUNCTION);
2572 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2573}
2574
2575
2576void Code::set_has_deoptimization_support(bool value) {
2577 ASSERT(kind() == FUNCTION);
2578 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2579}
2580
2581
2582int Code::allow_osr_at_loop_nesting_level() {
2583 ASSERT(kind() == FUNCTION);
2584 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2585}
2586
2587
2588void Code::set_allow_osr_at_loop_nesting_level(int level) {
2589 ASSERT(kind() == FUNCTION);
2590 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2591 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2592}
2593
2594
2595unsigned Code::stack_slots() {
2596 ASSERT(kind() == OPTIMIZED_FUNCTION);
2597 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2598}
2599
2600
2601void Code::set_stack_slots(unsigned slots) {
2602 ASSERT(kind() == OPTIMIZED_FUNCTION);
2603 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2604}
2605
2606
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002607unsigned Code::safepoint_table_offset() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002608 ASSERT(kind() == OPTIMIZED_FUNCTION);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002609 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002610}
2611
2612
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002613void Code::set_safepoint_table_offset(unsigned offset) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002614 ASSERT(kind() == OPTIMIZED_FUNCTION);
2615 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002616 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002617}
2618
2619
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002620unsigned Code::stack_check_table_offset() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002621 ASSERT(kind() == FUNCTION);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002622 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002623}
2624
2625
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002626void Code::set_stack_check_table_offset(unsigned offset) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002627 ASSERT(kind() == FUNCTION);
2628 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002629 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002630}
2631
2632
2633CheckType Code::check_type() {
2634 ASSERT(is_call_stub() || is_keyed_call_stub());
2635 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2636 return static_cast<CheckType>(type);
2637}
2638
2639
2640void Code::set_check_type(CheckType value) {
2641 ASSERT(is_call_stub() || is_keyed_call_stub());
2642 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2643}
2644
2645
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002646ExternalArrayType Code::external_array_type() {
2647 ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
2648 byte type = READ_BYTE_FIELD(this, kExternalArrayTypeOffset);
2649 return static_cast<ExternalArrayType>(type);
2650}
2651
2652
2653void Code::set_external_array_type(ExternalArrayType value) {
2654 ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
2655 WRITE_BYTE_FIELD(this, kExternalArrayTypeOffset, value);
2656}
2657
2658
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002659byte Code::binary_op_type() {
2660 ASSERT(is_binary_op_stub());
2661 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2662}
2663
2664
2665void Code::set_binary_op_type(byte value) {
2666 ASSERT(is_binary_op_stub());
2667 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2668}
2669
2670
2671byte Code::type_recording_binary_op_type() {
2672 ASSERT(is_type_recording_binary_op_stub());
2673 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2674}
2675
2676
2677void Code::set_type_recording_binary_op_type(byte value) {
2678 ASSERT(is_type_recording_binary_op_stub());
2679 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2680}
2681
2682
2683byte Code::type_recording_binary_op_result_type() {
2684 ASSERT(is_type_recording_binary_op_stub());
2685 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2686}
2687
2688
2689void Code::set_type_recording_binary_op_result_type(byte value) {
2690 ASSERT(is_type_recording_binary_op_stub());
2691 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2692}
2693
2694
2695byte Code::compare_state() {
2696 ASSERT(is_compare_ic_stub());
2697 return READ_BYTE_FIELD(this, kCompareStateOffset);
2698}
2699
2700
2701void Code::set_compare_state(byte value) {
2702 ASSERT(is_compare_ic_stub());
2703 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2704}
2705
2706
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002707bool Code::is_inline_cache_stub() {
2708 Kind kind = this->kind();
2709 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2710}
2711
2712
2713Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002714 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002715 InlineCacheState ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002716 ExtraICState extra_ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002717 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002718 int argc,
2719 InlineCacheHolderFlag holder) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002720 // Extra IC state is only allowed for monomorphic call IC stubs
2721 // or for store IC stubs.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002722 ASSERT(extra_ic_state == kNoExtraICState ||
2723 (kind == CALL_IC && (ic_state == MONOMORPHIC ||
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002724 ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)) ||
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00002725 (kind == STORE_IC) ||
2726 (kind == KEYED_STORE_IC));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002727 // Compute the bit mask.
2728 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002729 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002730 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002731 bits |= type << kFlagsTypeShift;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002732 bits |= extra_ic_state << kFlagsExtraICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002733 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002734 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002735 // Cast to flags and validate result before returning it.
2736 Flags result = static_cast<Flags>(bits);
2737 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002738 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002739 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002740 ASSERT(ExtractTypeFromFlags(result) == type);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002741 ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002742 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2743 return result;
2744}
2745
2746
2747Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2748 PropertyType type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002749 ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002750 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002751 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002752 int argc) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002753 return ComputeFlags(
2754 kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002755}
2756
2757
2758Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2759 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2760 return static_cast<Kind>(bits);
2761}
2762
2763
kasper.lund7276f142008-07-30 08:49:36 +00002764InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2765 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002766 return static_cast<InlineCacheState>(bits);
2767}
2768
2769
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002770Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
2771 int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
2772 return static_cast<ExtraICState>(bits);
2773}
2774
2775
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002776InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2777 int bits = (flags & kFlagsICInLoopMask);
2778 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2779}
2780
2781
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002782PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2783 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2784 return static_cast<PropertyType>(bits);
2785}
2786
2787
2788int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2789 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2790}
2791
2792
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002793InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2794 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2795 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2796}
2797
2798
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002799Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2800 int bits = flags & ~kFlagsTypeMask;
2801 return static_cast<Flags>(bits);
2802}
2803
2804
ager@chromium.org8bb60582008-12-11 12:02:20 +00002805Code* Code::GetCodeFromTargetAddress(Address address) {
2806 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2807 // GetCodeFromTargetAddress might be called when marking objects during mark
2808 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2809 // Code::cast. Code::cast does not work when the object's map is
2810 // marked.
2811 Code* result = reinterpret_cast<Code*>(code);
2812 return result;
2813}
2814
2815
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002816Isolate* Map::isolate() {
2817 return heap()->isolate();
2818}
2819
2820
2821Heap* Map::heap() {
2822 // NOTE: address() helper is not used to save one instruction.
2823 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
2824 ASSERT(heap != NULL);
2825 ASSERT(heap->isolate() == Isolate::Current());
2826 return heap;
2827}
2828
2829
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002830Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2831 return HeapObject::
2832 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2833}
2834
2835
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002836Object* Map::prototype() {
2837 return READ_FIELD(this, kPrototypeOffset);
2838}
2839
2840
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002841void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002842 ASSERT(value->IsNull() || value->IsJSObject());
2843 WRITE_FIELD(this, kPrototypeOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002844 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002845}
2846
2847
lrn@chromium.org303ada72010-10-27 09:33:13 +00002848MaybeObject* Map::GetFastElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002849 if (has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002850 Object* obj;
2851 { MaybeObject* maybe_obj = CopyDropTransitions();
2852 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2853 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002854 Map* new_map = Map::cast(obj);
2855 new_map->set_has_fast_elements(true);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002856 isolate()->counters()->map_slow_to_fast_elements()->Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002857 return new_map;
2858}
2859
2860
lrn@chromium.org303ada72010-10-27 09:33:13 +00002861MaybeObject* Map::GetSlowElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002862 if (!has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002863 Object* obj;
2864 { MaybeObject* maybe_obj = CopyDropTransitions();
2865 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2866 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002867 Map* new_map = Map::cast(obj);
2868 new_map->set_has_fast_elements(false);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002869 isolate()->counters()->map_fast_to_slow_elements()->Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002870 return new_map;
2871}
2872
2873
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002874MaybeObject* Map::NewExternalArrayElementsMap() {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002875 // TODO(danno): Special case empty object map (or most common case)
2876 // to return a pre-canned pixel array map.
2877 Object* obj;
2878 { MaybeObject* maybe_obj = CopyDropTransitions();
2879 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2880 }
2881 Map* new_map = Map::cast(obj);
2882 new_map->set_has_fast_elements(false);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002883 new_map->set_has_external_array_elements(true);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002884 isolate()->counters()->map_to_external_array_elements()->Increment();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002885 return new_map;
2886}
2887
2888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002889ACCESSORS(Map, instance_descriptors, DescriptorArray,
2890 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002891ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002892ACCESSORS(Map, constructor, Object, kConstructorOffset)
2893
2894ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2895ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002896ACCESSORS_GCSAFE(JSFunction, next_function_link, Object,
2897 kNextFunctionLinkOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002898
2899ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2900ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002901ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002902
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002903ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002904
2905ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2906ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2907ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2908ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2909ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2910
2911ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2912ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2913ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2914
2915ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2916ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2917ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2918ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2919ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2920ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2921
2922ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2923ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2924
2925ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2926ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2927
2928ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2929ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002930ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2931 kPropertyAccessorsOffset)
2932ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2933 kPrototypeTemplateOffset)
2934ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2935ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2936 kNamedPropertyHandlerOffset)
2937ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2938 kIndexedPropertyHandlerOffset)
2939ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2940 kInstanceTemplateOffset)
2941ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2942ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002943ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2944 kInstanceCallHandlerOffset)
2945ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2946 kAccessCheckInfoOffset)
2947ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2948
2949ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002950ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2951 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002952
2953ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2954ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2955
2956ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2957
2958ACCESSORS(Script, source, Object, kSourceOffset)
2959ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002960ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002961ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2962ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002963ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002964ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002965ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2966ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002967ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002968ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002969ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002970ACCESSORS(Script, eval_from_instructions_offset, Smi,
2971 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002972
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002973#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002974ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2975ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2976ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2977ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2978
2979ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2980ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2981ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2982ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002983#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002984
2985ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002986ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2987ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002988ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2989 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002990ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002991ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2992ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002993ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002994ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2995 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002996
2997BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2998 kHiddenPrototypeBit)
2999BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3000BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3001 kNeedsAccessCheckBit)
3002BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3003 kIsExpressionBit)
3004BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3005 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003006BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003007 has_only_simple_this_property_assignments,
3008 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003009BOOL_ACCESSORS(SharedFunctionInfo,
3010 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003011 try_full_codegen,
3012 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00003013BOOL_ACCESSORS(SharedFunctionInfo,
3014 compiler_hints,
3015 allows_lazy_compilation,
3016 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003017
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003018
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003019#if V8_HOST_ARCH_32_BIT
3020SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3021SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003022 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003023SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003024 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003025SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3026SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003027 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003028SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3029SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003030 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003031SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003032 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003033SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003034 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003035SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003036#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003037
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003038#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003039 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003040 int holder::name() { \
3041 int value = READ_INT_FIELD(this, offset); \
3042 ASSERT(kHeapObjectTag == 1); \
3043 ASSERT((value & kHeapObjectTag) == 0); \
3044 return value >> 1; \
3045 } \
3046 void holder::set_##name(int value) { \
3047 ASSERT(kHeapObjectTag == 1); \
3048 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3049 (value & 0xC0000000) == 0x000000000); \
3050 WRITE_INT_FIELD(this, \
3051 offset, \
3052 (value << 1) & ~kHeapObjectTag); \
3053 }
3054
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003055#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3056 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003057 INT_ACCESSORS(holder, name, offset)
3058
3059
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003060PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003061PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3062 formal_parameter_count,
3063 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003064
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003065PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3066 expected_nof_properties,
3067 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003068PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3069
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003070PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3071PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3072 start_position_and_type,
3073 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003074
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003075PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3076 function_token_position,
3077 kFunctionTokenPositionOffset)
3078PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3079 compiler_hints,
3080 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003081
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003082PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3083 this_property_assignments_count,
3084 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003085PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003086#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003087
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003088
3089int SharedFunctionInfo::construction_count() {
3090 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3091}
3092
3093
3094void SharedFunctionInfo::set_construction_count(int value) {
3095 ASSERT(0 <= value && value < 256);
3096 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3097}
3098
3099
3100bool SharedFunctionInfo::live_objects_may_exist() {
3101 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
3102}
3103
3104
3105void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
3106 if (value) {
3107 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
3108 } else {
3109 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
3110 }
3111}
3112
3113
3114bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003115 return initial_map() != HEAP->undefined_value();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003116}
3117
3118
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003119bool SharedFunctionInfo::optimization_disabled() {
3120 return BooleanBit::get(compiler_hints(), kOptimizationDisabled);
3121}
3122
3123
3124void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3125 set_compiler_hints(BooleanBit::set(compiler_hints(),
3126 kOptimizationDisabled,
3127 disable));
3128 // If disabling optimizations we reflect that in the code object so
3129 // it will not be counted as optimizable code.
3130 if ((code()->kind() == Code::FUNCTION) && disable) {
3131 code()->set_optimizable(false);
3132 }
3133}
3134
3135
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003136bool SharedFunctionInfo::strict_mode() {
3137 return BooleanBit::get(compiler_hints(), kStrictModeFunction);
3138}
3139
3140
3141void SharedFunctionInfo::set_strict_mode(bool value) {
3142 set_compiler_hints(BooleanBit::set(compiler_hints(),
3143 kStrictModeFunction,
3144 value));
3145}
3146
3147
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003148ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3149ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3150
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00003151bool Script::HasValidSource() {
3152 Object* src = this->source();
3153 if (!src->IsString()) return true;
3154 String* src_str = String::cast(src);
3155 if (!StringShape(src_str).IsExternal()) return true;
3156 if (src_str->IsAsciiRepresentation()) {
3157 return ExternalAsciiString::cast(src)->resource() != NULL;
3158 } else if (src_str->IsTwoByteRepresentation()) {
3159 return ExternalTwoByteString::cast(src)->resource() != NULL;
3160 }
3161 return true;
3162}
3163
3164
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003165void SharedFunctionInfo::DontAdaptArguments() {
3166 ASSERT(code()->kind() == Code::BUILTIN);
3167 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3168}
3169
3170
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003171int SharedFunctionInfo::start_position() {
3172 return start_position_and_type() >> kStartPositionShift;
3173}
3174
3175
3176void SharedFunctionInfo::set_start_position(int start_position) {
3177 set_start_position_and_type((start_position << kStartPositionShift)
3178 | (start_position_and_type() & ~kStartPositionMask));
3179}
3180
3181
3182Code* SharedFunctionInfo::code() {
3183 return Code::cast(READ_FIELD(this, kCodeOffset));
3184}
3185
3186
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003187Code* SharedFunctionInfo::unchecked_code() {
3188 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3189}
3190
3191
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003192void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003193 WRITE_FIELD(this, kCodeOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003194 ASSERT(!Isolate::Current()->heap()->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003195}
3196
3197
ager@chromium.orgb5737492010-07-15 09:29:43 +00003198SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3199 return reinterpret_cast<SerializedScopeInfo*>(
3200 READ_FIELD(this, kScopeInfoOffset));
3201}
3202
3203
3204void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3205 WriteBarrierMode mode) {
3206 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003207 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode);
ager@chromium.orgb5737492010-07-15 09:29:43 +00003208}
3209
3210
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003211Smi* SharedFunctionInfo::deopt_counter() {
3212 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3213}
3214
3215
3216void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3217 WRITE_FIELD(this, kDeoptCounterOffset, value);
3218}
3219
3220
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003221bool SharedFunctionInfo::is_compiled() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003222 return code() !=
3223 Isolate::Current()->builtins()->builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003224}
3225
3226
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003227bool SharedFunctionInfo::IsApiFunction() {
3228 return function_data()->IsFunctionTemplateInfo();
3229}
3230
3231
3232FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3233 ASSERT(IsApiFunction());
3234 return FunctionTemplateInfo::cast(function_data());
3235}
3236
3237
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003238bool SharedFunctionInfo::HasBuiltinFunctionId() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003239 return function_data()->IsSmi();
3240}
3241
3242
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003243BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3244 ASSERT(HasBuiltinFunctionId());
3245 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003246}
3247
3248
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003249int SharedFunctionInfo::code_age() {
3250 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3251}
3252
3253
3254void SharedFunctionInfo::set_code_age(int code_age) {
3255 set_compiler_hints(compiler_hints() |
3256 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3257}
3258
3259
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003260bool SharedFunctionInfo::has_deoptimization_support() {
3261 Code* code = this->code();
3262 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3263}
3264
3265
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003266bool JSFunction::IsBuiltin() {
3267 return context()->global()->IsJSBuiltinsObject();
3268}
3269
3270
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003271bool JSFunction::NeedsArgumentsAdaption() {
3272 return shared()->formal_parameter_count() !=
3273 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3274}
3275
3276
3277bool JSFunction::IsOptimized() {
3278 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3279}
3280
3281
3282bool JSFunction::IsMarkedForLazyRecompilation() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003283 return code() == GetIsolate()->builtins()->builtin(Builtins::LazyRecompile);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003284}
3285
3286
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003287Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003288 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003289}
3290
3291
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003292Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003293 return reinterpret_cast<Code*>(
3294 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003295}
3296
3297
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003298void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003299 // Skip the write barrier because code is never in new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003300 ASSERT(!HEAP->InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003301 Address entry = value->entry();
3302 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003303}
3304
3305
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003306void JSFunction::ReplaceCode(Code* code) {
3307 bool was_optimized = IsOptimized();
3308 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3309
3310 set_code(code);
3311
3312 // Add/remove the function from the list of optimized functions for this
3313 // context based on the state change.
3314 if (!was_optimized && is_optimized) {
3315 context()->global_context()->AddOptimizedFunction(this);
3316 }
3317 if (was_optimized && !is_optimized) {
3318 context()->global_context()->RemoveOptimizedFunction(this);
3319 }
3320}
3321
3322
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003323Context* JSFunction::context() {
3324 return Context::cast(READ_FIELD(this, kContextOffset));
3325}
3326
3327
3328Object* JSFunction::unchecked_context() {
3329 return READ_FIELD(this, kContextOffset);
3330}
3331
3332
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003333SharedFunctionInfo* JSFunction::unchecked_shared() {
3334 return reinterpret_cast<SharedFunctionInfo*>(
3335 READ_FIELD(this, kSharedFunctionInfoOffset));
3336}
3337
3338
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003339void JSFunction::set_context(Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003340 ASSERT(value->IsUndefined() || value->IsContext());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003341 WRITE_FIELD(this, kContextOffset, value);
3342 WRITE_BARRIER(this, kContextOffset);
3343}
3344
3345ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3346 kPrototypeOrInitialMapOffset)
3347
3348
3349Map* JSFunction::initial_map() {
3350 return Map::cast(prototype_or_initial_map());
3351}
3352
3353
3354void JSFunction::set_initial_map(Map* value) {
3355 set_prototype_or_initial_map(value);
3356}
3357
3358
3359bool JSFunction::has_initial_map() {
3360 return prototype_or_initial_map()->IsMap();
3361}
3362
3363
3364bool JSFunction::has_instance_prototype() {
3365 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3366}
3367
3368
3369bool JSFunction::has_prototype() {
3370 return map()->has_non_instance_prototype() || has_instance_prototype();
3371}
3372
3373
3374Object* JSFunction::instance_prototype() {
3375 ASSERT(has_instance_prototype());
3376 if (has_initial_map()) return initial_map()->prototype();
3377 // When there is no initial map and the prototype is a JSObject, the
3378 // initial map field is used for the prototype field.
3379 return prototype_or_initial_map();
3380}
3381
3382
3383Object* JSFunction::prototype() {
3384 ASSERT(has_prototype());
3385 // If the function's prototype property has been set to a non-JSObject
3386 // value, that value is stored in the constructor field of the map.
3387 if (map()->has_non_instance_prototype()) return map()->constructor();
3388 return instance_prototype();
3389}
3390
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003391bool JSFunction::should_have_prototype() {
3392 return map()->function_with_prototype();
3393}
3394
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003395
3396bool JSFunction::is_compiled() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003397 return code() != GetIsolate()->builtins()->builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003398}
3399
3400
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003401int JSFunction::NumberOfLiterals() {
3402 return literals()->length();
3403}
3404
3405
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003406Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003407 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003408 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003409}
3410
3411
3412void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3413 Object* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003414 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003415 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3416 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3417}
3418
3419
3420Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003421 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003422 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3423}
3424
3425
3426void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3427 Code* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003428 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003429 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003430 ASSERT(!HEAP->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003431}
3432
3433
3434Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00003435 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003436}
3437
3438
3439void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00003440 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003441}
3442
3443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003444ACCESSORS(JSValue, value, Object, kValueOffset)
3445
3446
3447JSValue* JSValue::cast(Object* obj) {
3448 ASSERT(obj->IsJSValue());
3449 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3450 return reinterpret_cast<JSValue*>(obj);
3451}
3452
3453
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003454ACCESSORS(JSMessageObject, type, String, kTypeOffset)
3455ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
3456ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
3457ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
3458ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
3459SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
3460SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
3461
3462
3463JSMessageObject* JSMessageObject::cast(Object* obj) {
3464 ASSERT(obj->IsJSMessageObject());
3465 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
3466 return reinterpret_cast<JSMessageObject*>(obj);
3467}
3468
3469
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003470INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003471ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003472ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003473
3474
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003475byte* Code::instruction_start() {
3476 return FIELD_ADDR(this, kHeaderSize);
3477}
3478
3479
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003480byte* Code::instruction_end() {
3481 return instruction_start() + instruction_size();
3482}
3483
3484
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003485int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003486 return RoundUp(instruction_size(), kObjectAlignment);
3487}
3488
3489
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003490FixedArray* Code::unchecked_deoptimization_data() {
3491 return reinterpret_cast<FixedArray*>(
3492 READ_FIELD(this, kDeoptimizationDataOffset));
3493}
3494
3495
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003496ByteArray* Code::unchecked_relocation_info() {
3497 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003498}
3499
3500
3501byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003502 return unchecked_relocation_info()->GetDataStartAddress();
3503}
3504
3505
3506int Code::relocation_size() {
3507 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003508}
3509
3510
3511byte* Code::entry() {
3512 return instruction_start();
3513}
3514
3515
3516bool Code::contains(byte* pc) {
3517 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003518 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003519}
3520
3521
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003522ACCESSORS(JSArray, length, Object, kLengthOffset)
3523
3524
ager@chromium.org236ad962008-09-25 09:45:57 +00003525ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003526
3527
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003528JSRegExp::Type JSRegExp::TypeTag() {
3529 Object* data = this->data();
3530 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3531 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3532 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003533}
3534
3535
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003536int JSRegExp::CaptureCount() {
3537 switch (TypeTag()) {
3538 case ATOM:
3539 return 0;
3540 case IRREGEXP:
3541 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3542 default:
3543 UNREACHABLE();
3544 return -1;
3545 }
3546}
3547
3548
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003549JSRegExp::Flags JSRegExp::GetFlags() {
3550 ASSERT(this->data()->IsFixedArray());
3551 Object* data = this->data();
3552 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3553 return Flags(smi->value());
3554}
3555
3556
3557String* JSRegExp::Pattern() {
3558 ASSERT(this->data()->IsFixedArray());
3559 Object* data = this->data();
3560 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3561 return pattern;
3562}
3563
3564
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003565Object* JSRegExp::DataAt(int index) {
3566 ASSERT(TypeTag() != NOT_COMPILED);
3567 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003568}
3569
3570
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003571void JSRegExp::SetDataAt(int index, Object* value) {
3572 ASSERT(TypeTag() != NOT_COMPILED);
3573 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3574 FixedArray::cast(data())->set(index, value);
3575}
3576
3577
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003578JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003579 if (map()->has_fast_elements()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003580 ASSERT(elements()->map() == GetHeap()->fixed_array_map() ||
3581 elements()->map() == GetHeap()->fixed_cow_array_map());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003582 return FAST_ELEMENTS;
3583 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003584 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003585 if (array->IsFixedArray()) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003586 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3587 // FixedArray, but FAST_ELEMENTS is already handled above.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003588 ASSERT(array->IsDictionary());
3589 return DICTIONARY_ELEMENTS;
3590 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003591 ASSERT(!map()->has_fast_elements());
ager@chromium.org3811b432009-10-28 14:53:37 +00003592 if (array->IsExternalArray()) {
3593 switch (array->map()->instance_type()) {
3594 case EXTERNAL_BYTE_ARRAY_TYPE:
3595 return EXTERNAL_BYTE_ELEMENTS;
3596 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3597 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3598 case EXTERNAL_SHORT_ARRAY_TYPE:
3599 return EXTERNAL_SHORT_ELEMENTS;
3600 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3601 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3602 case EXTERNAL_INT_ARRAY_TYPE:
3603 return EXTERNAL_INT_ELEMENTS;
3604 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3605 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003606 case EXTERNAL_PIXEL_ARRAY_TYPE:
3607 return EXTERNAL_PIXEL_ELEMENTS;
ager@chromium.org3811b432009-10-28 14:53:37 +00003608 default:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003609 break;
ager@chromium.org3811b432009-10-28 14:53:37 +00003610 }
3611 }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003612 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3613 return EXTERNAL_FLOAT_ELEMENTS;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003614}
3615
3616
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003617bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003618 return GetElementsKind() == FAST_ELEMENTS;
3619}
3620
3621
3622bool JSObject::HasDictionaryElements() {
3623 return GetElementsKind() == DICTIONARY_ELEMENTS;
3624}
3625
3626
ager@chromium.org3811b432009-10-28 14:53:37 +00003627bool JSObject::HasExternalArrayElements() {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003628 HeapObject* array = elements();
3629 ASSERT(array != NULL);
3630 return array->IsExternalArray();
ager@chromium.org3811b432009-10-28 14:53:37 +00003631}
3632
3633
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003634#define EXTERNAL_ELEMENTS_CHECK(name, type) \
3635bool JSObject::HasExternal##name##Elements() { \
3636 HeapObject* array = elements(); \
3637 ASSERT(array != NULL); \
3638 if (!array->IsHeapObject()) \
3639 return false; \
3640 return array->map()->instance_type() == type; \
ager@chromium.org3811b432009-10-28 14:53:37 +00003641}
3642
3643
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003644EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
3645EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
3646EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
3647EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
3648 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
3649EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
3650EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
3651 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
3652EXTERNAL_ELEMENTS_CHECK(Float,
3653 EXTERNAL_FLOAT_ARRAY_TYPE)
3654EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
ager@chromium.org3811b432009-10-28 14:53:37 +00003655
3656
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003657bool JSObject::HasNamedInterceptor() {
3658 return map()->has_named_interceptor();
3659}
3660
3661
3662bool JSObject::HasIndexedInterceptor() {
3663 return map()->has_indexed_interceptor();
3664}
3665
3666
ager@chromium.org5c838252010-02-19 08:53:10 +00003667bool JSObject::AllowsSetElementsLength() {
3668 bool result = elements()->IsFixedArray();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003669 ASSERT(result == !HasExternalArrayElements());
ager@chromium.org5c838252010-02-19 08:53:10 +00003670 return result;
3671}
3672
3673
lrn@chromium.org303ada72010-10-27 09:33:13 +00003674MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003675 ASSERT(HasFastElements());
3676 FixedArray* elems = FixedArray::cast(elements());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003677 Isolate* isolate = GetIsolate();
3678 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003679 Object* writable_elems;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003680 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
3681 elems, isolate->heap()->fixed_array_map());
lrn@chromium.org303ada72010-10-27 09:33:13 +00003682 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3683 return maybe_writable_elems;
3684 }
3685 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003686 set_elements(FixedArray::cast(writable_elems));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003687 isolate->counters()->cow_arrays_converted()->Increment();
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003688 return writable_elems;
3689}
3690
3691
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003692StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003693 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003694 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003695}
3696
3697
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003698NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003699 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003700 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003701}
3702
3703
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003704bool String::IsHashFieldComputed(uint32_t field) {
3705 return (field & kHashNotComputedMask) == 0;
3706}
3707
3708
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003709bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003710 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003711}
3712
3713
3714uint32_t String::Hash() {
3715 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003716 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003717 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003718 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003719 return ComputeAndSetHash();
3720}
3721
3722
ager@chromium.org7c537e22008-10-16 08:43:32 +00003723StringHasher::StringHasher(int length)
3724 : length_(length),
3725 raw_running_hash_(0),
3726 array_index_(0),
3727 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3728 is_first_char_(true),
3729 is_valid_(true) { }
3730
3731
3732bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003733 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003734}
3735
3736
3737void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003738 // Use the Jenkins one-at-a-time hash function to update the hash
3739 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003740 raw_running_hash_ += c;
3741 raw_running_hash_ += (raw_running_hash_ << 10);
3742 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003743 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003744 if (is_array_index_) {
3745 if (c < '0' || c > '9') {
3746 is_array_index_ = false;
3747 } else {
3748 int d = c - '0';
3749 if (is_first_char_) {
3750 is_first_char_ = false;
3751 if (c == '0' && length_ > 1) {
3752 is_array_index_ = false;
3753 return;
3754 }
3755 }
3756 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3757 is_array_index_ = false;
3758 } else {
3759 array_index_ = array_index_ * 10 + d;
3760 }
3761 }
3762 }
3763}
3764
3765
3766void StringHasher::AddCharacterNoIndex(uc32 c) {
3767 ASSERT(!is_array_index());
3768 raw_running_hash_ += c;
3769 raw_running_hash_ += (raw_running_hash_ << 10);
3770 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3771}
3772
3773
3774uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003775 // Get the calculated raw hash value and do some more bit ops to distribute
3776 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003777 uint32_t result = raw_running_hash_;
3778 result += (result << 3);
3779 result ^= (result >> 11);
3780 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003781 if (result == 0) {
3782 result = 27;
3783 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003784 return result;
3785}
3786
3787
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00003788template <typename schar>
3789uint32_t HashSequentialString(const schar* chars, int length) {
3790 StringHasher hasher(length);
3791 if (!hasher.has_trivial_hash()) {
3792 int i;
3793 for (i = 0; hasher.is_array_index() && (i < length); i++) {
3794 hasher.AddCharacter(chars[i]);
3795 }
3796 for (; i < length; i++) {
3797 hasher.AddCharacterNoIndex(chars[i]);
3798 }
3799 }
3800 return hasher.GetHashField();
3801}
3802
3803
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003804bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003805 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003806 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3807 return false;
3808 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003809 return SlowAsArrayIndex(index);
3810}
3811
3812
3813Object* JSObject::GetPrototype() {
3814 return JSObject::cast(this)->map()->prototype();
3815}
3816
3817
3818PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3819 return GetPropertyAttributeWithReceiver(this, key);
3820}
3821
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003822// TODO(504): this may be useful in other places too where JSGlobalProxy
3823// is used.
3824Object* JSObject::BypassGlobalProxy() {
3825 if (IsJSGlobalProxy()) {
3826 Object* proto = GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003827 if (proto->IsNull()) return GetHeap()->undefined_value();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003828 ASSERT(proto->IsJSGlobalObject());
3829 return proto;
3830 }
3831 return this;
3832}
3833
3834
3835bool JSObject::HasHiddenPropertiesObject() {
3836 ASSERT(!IsJSGlobalProxy());
3837 return GetPropertyAttributePostInterceptor(this,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003838 GetHeap()->hidden_symbol(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003839 false) != ABSENT;
3840}
3841
3842
3843Object* JSObject::GetHiddenPropertiesObject() {
3844 ASSERT(!IsJSGlobalProxy());
3845 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003846 // You can't install a getter on a property indexed by the hidden symbol,
3847 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3848 // object.
3849 Object* result =
3850 GetLocalPropertyPostInterceptor(this,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003851 GetHeap()->hidden_symbol(),
lrn@chromium.org303ada72010-10-27 09:33:13 +00003852 &attributes)->ToObjectUnchecked();
3853 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003854}
3855
3856
lrn@chromium.org303ada72010-10-27 09:33:13 +00003857MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003858 ASSERT(!IsJSGlobalProxy());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003859 return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003860 hidden_obj,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00003861 DONT_ENUM,
3862 kNonStrictMode);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003863}
3864
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003865
3866bool JSObject::HasElement(uint32_t index) {
3867 return HasElementWithReceiver(this, index);
3868}
3869
3870
3871bool AccessorInfo::all_can_read() {
3872 return BooleanBit::get(flag(), kAllCanReadBit);
3873}
3874
3875
3876void AccessorInfo::set_all_can_read(bool value) {
3877 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3878}
3879
3880
3881bool AccessorInfo::all_can_write() {
3882 return BooleanBit::get(flag(), kAllCanWriteBit);
3883}
3884
3885
3886void AccessorInfo::set_all_can_write(bool value) {
3887 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3888}
3889
3890
ager@chromium.org870a0b62008-11-04 11:43:05 +00003891bool AccessorInfo::prohibits_overwriting() {
3892 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3893}
3894
3895
3896void AccessorInfo::set_prohibits_overwriting(bool value) {
3897 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3898}
3899
3900
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003901PropertyAttributes AccessorInfo::property_attributes() {
3902 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3903}
3904
3905
3906void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3907 ASSERT(AttributesField::is_valid(attributes));
3908 int rest_value = flag()->value() & ~AttributesField::mask();
3909 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3910}
3911
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003912template<typename Shape, typename Key>
3913void Dictionary<Shape, Key>::SetEntry(int entry,
3914 Object* key,
3915 Object* value,
3916 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003917 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003918 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003919 AssertNoAllocation no_gc;
3920 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003921 FixedArray::set(index, key, mode);
3922 FixedArray::set(index+1, value, mode);
3923 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003924}
3925
3926
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003927bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
3928 ASSERT(other->IsNumber());
3929 return key == static_cast<uint32_t>(other->Number());
3930}
3931
3932
3933uint32_t NumberDictionaryShape::Hash(uint32_t key) {
3934 return ComputeIntegerHash(key);
3935}
3936
3937
3938uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
3939 ASSERT(other->IsNumber());
3940 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
3941}
3942
3943
3944MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
3945 return Isolate::Current()->heap()->NumberFromUint32(key);
3946}
3947
3948
3949bool StringDictionaryShape::IsMatch(String* key, Object* other) {
3950 // We know that all entries in a hash table had their hash keys created.
3951 // Use that knowledge to have fast failure.
3952 if (key->Hash() != String::cast(other)->Hash()) return false;
3953 return key->Equals(String::cast(other));
3954}
3955
3956
3957uint32_t StringDictionaryShape::Hash(String* key) {
3958 return key->Hash();
3959}
3960
3961
3962uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
3963 return String::cast(other)->Hash();
3964}
3965
3966
3967MaybeObject* StringDictionaryShape::AsObject(String* key) {
3968 return key;
3969}
3970
3971
3972void Map::ClearCodeCache(Heap* heap) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003973 // No write barrier is needed since empty_fixed_array is not in new space.
3974 // Please note this function is used during marking:
3975 // - MarkCompactCollector::MarkUnmarkedObject
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003976 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
3977 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003978}
3979
3980
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003981void JSArray::EnsureSize(int required_size) {
3982 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003983 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003984 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3985 if (elts->length() < required_size) {
3986 // Doubling in size would be overkill, but leave some slack to avoid
3987 // constantly growing.
3988 Expand(required_size + (required_size >> 3));
3989 // It's a performance benefit to keep a frequently used array in new-space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003990 } else if (!GetHeap()->new_space()->Contains(elts) &&
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003991 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3992 // Expand will allocate a new backing store in new space even if the size
3993 // we asked for isn't larger than what we had before.
3994 Expand(required_size);
3995 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003996}
3997
3998
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003999void JSArray::set_length(Smi* length) {
4000 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4001}
4002
4003
ager@chromium.org7c537e22008-10-16 08:43:32 +00004004void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00004005 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00004006 set_elements(storage);
4007}
4008
4009
lrn@chromium.org303ada72010-10-27 09:33:13 +00004010MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004011 if (length() == 0) return this;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004012 return GetHeap()->CopyFixedArray(this);
4013}
4014
4015
4016Relocatable::Relocatable(Isolate* isolate) {
4017 ASSERT(isolate == Isolate::Current());
4018 isolate_ = isolate;
4019 prev_ = isolate->relocatable_top();
4020 isolate->set_relocatable_top(this);
4021}
4022
4023
4024Relocatable::~Relocatable() {
4025 ASSERT(isolate_ == Isolate::Current());
4026 ASSERT_EQ(isolate_->relocatable_top(), this);
4027 isolate_->set_relocatable_top(prev_);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004028}
4029
4030
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004031int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4032 return map->instance_size();
4033}
4034
4035
4036void Proxy::ProxyIterateBody(ObjectVisitor* v) {
4037 v->VisitExternalReference(
4038 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
4039}
4040
4041
4042template<typename StaticVisitor>
4043void Proxy::ProxyIterateBody() {
4044 StaticVisitor::VisitExternalReference(
4045 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
4046}
4047
4048
4049void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4050 typedef v8::String::ExternalAsciiStringResource Resource;
4051 v->VisitExternalAsciiString(
4052 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4053}
4054
4055
4056template<typename StaticVisitor>
4057void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4058 typedef v8::String::ExternalAsciiStringResource Resource;
4059 StaticVisitor::VisitExternalAsciiString(
4060 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4061}
4062
4063
4064void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4065 typedef v8::String::ExternalStringResource Resource;
4066 v->VisitExternalTwoByteString(
4067 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4068}
4069
4070
4071template<typename StaticVisitor>
4072void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4073 typedef v8::String::ExternalStringResource Resource;
4074 StaticVisitor::VisitExternalTwoByteString(
4075 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4076}
4077
4078#define SLOT_ADDR(obj, offset) \
4079 reinterpret_cast<Object**>((obj)->address() + offset)
4080
4081template<int start_offset, int end_offset, int size>
4082void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4083 HeapObject* obj,
4084 ObjectVisitor* v) {
4085 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4086}
4087
4088
4089template<int start_offset>
4090void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4091 int object_size,
4092 ObjectVisitor* v) {
4093 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4094}
4095
4096#undef SLOT_ADDR
4097
4098
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004099#undef CAST_ACCESSOR
4100#undef INT_ACCESSORS
4101#undef SMI_ACCESSORS
4102#undef ACCESSORS
4103#undef FIELD_ADDR
4104#undef READ_FIELD
4105#undef WRITE_FIELD
4106#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004107#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004108#undef READ_MEMADDR_FIELD
4109#undef WRITE_MEMADDR_FIELD
4110#undef READ_DOUBLE_FIELD
4111#undef WRITE_DOUBLE_FIELD
4112#undef READ_INT_FIELD
4113#undef WRITE_INT_FIELD
4114#undef READ_SHORT_FIELD
4115#undef WRITE_SHORT_FIELD
4116#undef READ_BYTE_FIELD
4117#undef WRITE_BYTE_FIELD
4118
4119
4120} } // namespace v8::internal
4121
4122#endif // V8_OBJECTS_INL_H_