blob: 36e5c6fdf51310b0ac222dc58ef92b630c9505d0 [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);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001725 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
1726 t == EXTERNAL_ARRAY_TRANSITION;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001727}
1728
1729
1730bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1731 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1732}
1733
1734
1735bool DescriptorArray::IsDontEnum(int descriptor_number) {
1736 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1737}
1738
1739
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001740void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1741 desc->Init(GetKey(descriptor_number),
1742 GetValue(descriptor_number),
1743 GetDetails(descriptor_number));
1744}
1745
1746
1747void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1748 // Range check.
1749 ASSERT(descriptor_number < number_of_descriptors());
1750
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001751 // Make sure none of the elements in desc are in new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001752 ASSERT(!HEAP->InNewSpace(desc->GetKey()));
1753 ASSERT(!HEAP->InNewSpace(desc->GetValue()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001754
1755 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1756 FixedArray* content_array = GetContentArray();
1757 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1758 fast_set(content_array, ToDetailsIndex(descriptor_number),
1759 desc->GetDetails().AsSmi());
1760}
1761
1762
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001763void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1764 Descriptor desc;
1765 src->Get(src_index, &desc);
1766 Set(index, &desc);
1767}
1768
1769
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001770void DescriptorArray::Swap(int first, int second) {
1771 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1772 FixedArray* content_array = GetContentArray();
1773 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1774 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1775}
1776
1777
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001778template<typename Shape, typename Key>
1779int HashTable<Shape, Key>::FindEntry(Key key) {
1780 return FindEntry(GetIsolate(), key);
1781}
1782
1783
1784// Find entry for key otherwise return kNotFound.
1785template<typename Shape, typename Key>
1786int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
1787 uint32_t capacity = Capacity();
1788 uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
1789 uint32_t count = 1;
1790 // EnsureCapacity will guarantee the hash table is never full.
1791 while (true) {
1792 Object* element = KeyAt(entry);
1793 if (element == isolate->heap()->undefined_value()) break; // Empty entry.
1794 if (element != isolate->heap()->null_value() &&
1795 Shape::IsMatch(key, element)) return entry;
1796 entry = NextProbe(entry, count++, capacity);
1797 }
1798 return kNotFound;
1799}
1800
1801
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001802bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001803 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001804 if (!max_index_object->IsSmi()) return false;
1805 return 0 !=
1806 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1807}
1808
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001809uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001810 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001811 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001812 if (!max_index_object->IsSmi()) return 0;
1813 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1814 return value >> kRequiresSlowElementsTagSize;
1815}
1816
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001817void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001818 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001819}
1820
1821
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001822// ------------------------------------
1823// Cast operations
1824
1825
1826CAST_ACCESSOR(FixedArray)
1827CAST_ACCESSOR(DescriptorArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001828CAST_ACCESSOR(DeoptimizationInputData)
1829CAST_ACCESSOR(DeoptimizationOutputData)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001830CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001831CAST_ACCESSOR(JSFunctionResultCache)
ricow@chromium.org65fae842010-08-25 15:26:24 +00001832CAST_ACCESSOR(NormalizedMapCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001833CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001834CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001835CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001836CAST_ACCESSOR(String)
1837CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001838CAST_ACCESSOR(SeqAsciiString)
1839CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001840CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001841CAST_ACCESSOR(ExternalString)
1842CAST_ACCESSOR(ExternalAsciiString)
1843CAST_ACCESSOR(ExternalTwoByteString)
1844CAST_ACCESSOR(JSObject)
1845CAST_ACCESSOR(Smi)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001846CAST_ACCESSOR(HeapObject)
1847CAST_ACCESSOR(HeapNumber)
1848CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001849CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001850CAST_ACCESSOR(SharedFunctionInfo)
1851CAST_ACCESSOR(Map)
1852CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001853CAST_ACCESSOR(GlobalObject)
1854CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001855CAST_ACCESSOR(JSGlobalObject)
1856CAST_ACCESSOR(JSBuiltinsObject)
1857CAST_ACCESSOR(Code)
1858CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001859CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001860CAST_ACCESSOR(Proxy)
1861CAST_ACCESSOR(ByteArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001862CAST_ACCESSOR(ExternalArray)
1863CAST_ACCESSOR(ExternalByteArray)
1864CAST_ACCESSOR(ExternalUnsignedByteArray)
1865CAST_ACCESSOR(ExternalShortArray)
1866CAST_ACCESSOR(ExternalUnsignedShortArray)
1867CAST_ACCESSOR(ExternalIntArray)
1868CAST_ACCESSOR(ExternalUnsignedIntArray)
1869CAST_ACCESSOR(ExternalFloatArray)
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001870CAST_ACCESSOR(ExternalPixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001871CAST_ACCESSOR(Struct)
1872
1873
1874#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1875 STRUCT_LIST(MAKE_STRUCT_CAST)
1876#undef MAKE_STRUCT_CAST
1877
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001878
1879template <typename Shape, typename Key>
1880HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001881 ASSERT(obj->IsHashTable());
1882 return reinterpret_cast<HashTable*>(obj);
1883}
1884
1885
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001886SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1887SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1888
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001889INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001890
1891
ager@chromium.orgac091b72010-05-05 07:34:42 +00001892SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001893
1894
1895uint32_t String::hash_field() {
1896 return READ_UINT32_FIELD(this, kHashFieldOffset);
1897}
1898
1899
1900void String::set_hash_field(uint32_t value) {
1901 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001902#if V8_HOST_ARCH_64_BIT
1903 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1904#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001905}
1906
1907
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001908bool String::Equals(String* other) {
1909 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001910 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1911 return false;
1912 }
1913 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001914}
1915
1916
lrn@chromium.org303ada72010-10-27 09:33:13 +00001917MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001918 if (!StringShape(this).IsCons()) return this;
1919 ConsString* cons = ConsString::cast(this);
1920 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001921 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001922}
1923
1924
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001925String* String::TryFlattenGetString(PretenureFlag pretenure) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001926 MaybeObject* flat = TryFlatten(pretenure);
1927 Object* successfully_flattened;
1928 if (flat->ToObject(&successfully_flattened)) {
1929 return String::cast(successfully_flattened);
1930 }
1931 return this;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001932}
1933
1934
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001935uint16_t String::Get(int index) {
1936 ASSERT(index >= 0 && index < length());
1937 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001938 case kSeqStringTag | kAsciiStringTag:
1939 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1940 case kSeqStringTag | kTwoByteStringTag:
1941 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1942 case kConsStringTag | kAsciiStringTag:
1943 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001944 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001945 case kExternalStringTag | kAsciiStringTag:
1946 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1947 case kExternalStringTag | kTwoByteStringTag:
1948 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001949 default:
1950 break;
1951 }
1952
1953 UNREACHABLE();
1954 return 0;
1955}
1956
1957
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001958void String::Set(int index, uint16_t value) {
1959 ASSERT(index >= 0 && index < length());
1960 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001961
ager@chromium.org5ec48922009-05-05 07:25:34 +00001962 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001963 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1964 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001965}
1966
1967
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001968bool String::IsFlat() {
1969 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001970 case kConsStringTag: {
1971 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001972 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001973 return second->length() == 0;
1974 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001975 default:
1976 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001977 }
1978}
1979
1980
ager@chromium.org7c537e22008-10-16 08:43:32 +00001981uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001982 ASSERT(index >= 0 && index < length());
1983 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1984}
1985
1986
ager@chromium.org7c537e22008-10-16 08:43:32 +00001987void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001988 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1989 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1990 static_cast<byte>(value));
1991}
1992
1993
ager@chromium.org7c537e22008-10-16 08:43:32 +00001994Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995 return FIELD_ADDR(this, kHeaderSize);
1996}
1997
1998
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001999char* SeqAsciiString::GetChars() {
2000 return reinterpret_cast<char*>(GetCharsAddress());
2001}
2002
2003
ager@chromium.org7c537e22008-10-16 08:43:32 +00002004Address SeqTwoByteString::GetCharsAddress() {
2005 return FIELD_ADDR(this, kHeaderSize);
2006}
2007
2008
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002009uc16* SeqTwoByteString::GetChars() {
2010 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2011}
2012
2013
ager@chromium.org7c537e22008-10-16 08:43:32 +00002014uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002015 ASSERT(index >= 0 && index < length());
2016 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2017}
2018
2019
ager@chromium.org7c537e22008-10-16 08:43:32 +00002020void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002021 ASSERT(index >= 0 && index < length());
2022 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2023}
2024
2025
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002026int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00002027 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002028}
2029
2030
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002031int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00002032 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002033}
2034
2035
ager@chromium.org870a0b62008-11-04 11:43:05 +00002036String* ConsString::first() {
2037 return String::cast(READ_FIELD(this, kFirstOffset));
2038}
2039
2040
2041Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002042 return READ_FIELD(this, kFirstOffset);
2043}
2044
2045
ager@chromium.org870a0b62008-11-04 11:43:05 +00002046void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002047 WRITE_FIELD(this, kFirstOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002048 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002049}
2050
2051
ager@chromium.org870a0b62008-11-04 11:43:05 +00002052String* ConsString::second() {
2053 return String::cast(READ_FIELD(this, kSecondOffset));
2054}
2055
2056
2057Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002058 return READ_FIELD(this, kSecondOffset);
2059}
2060
2061
ager@chromium.org870a0b62008-11-04 11:43:05 +00002062void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002063 WRITE_FIELD(this, kSecondOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002064 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002065}
2066
2067
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002068ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2069 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2070}
2071
2072
2073void ExternalAsciiString::set_resource(
2074 ExternalAsciiString::Resource* resource) {
2075 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
2076}
2077
2078
2079ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2080 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2081}
2082
2083
2084void ExternalTwoByteString::set_resource(
2085 ExternalTwoByteString::Resource* resource) {
2086 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
2087}
2088
2089
ager@chromium.orgac091b72010-05-05 07:34:42 +00002090void JSFunctionResultCache::MakeZeroSize() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002091 set_finger_index(kEntriesIndex);
2092 set_size(kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002093}
2094
2095
2096void JSFunctionResultCache::Clear() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002097 int cache_size = size();
ager@chromium.orgac091b72010-05-05 07:34:42 +00002098 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00002099 MemsetPointer(entries_start,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002100 GetHeap()->the_hole_value(),
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00002101 cache_size - kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002102 MakeZeroSize();
2103}
2104
2105
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002106int JSFunctionResultCache::size() {
2107 return Smi::cast(get(kCacheSizeIndex))->value();
2108}
2109
2110
2111void JSFunctionResultCache::set_size(int size) {
2112 set(kCacheSizeIndex, Smi::FromInt(size));
2113}
2114
2115
2116int JSFunctionResultCache::finger_index() {
2117 return Smi::cast(get(kFingerIndex))->value();
2118}
2119
2120
2121void JSFunctionResultCache::set_finger_index(int finger_index) {
2122 set(kFingerIndex, Smi::FromInt(finger_index));
2123}
2124
2125
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002126byte ByteArray::get(int index) {
2127 ASSERT(index >= 0 && index < this->length());
2128 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2129}
2130
2131
2132void ByteArray::set(int index, byte value) {
2133 ASSERT(index >= 0 && index < this->length());
2134 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2135}
2136
2137
2138int ByteArray::get_int(int index) {
2139 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2140 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2141}
2142
2143
2144ByteArray* ByteArray::FromDataStartAddress(Address address) {
2145 ASSERT_TAG_ALIGNED(address);
2146 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2147}
2148
2149
2150Address ByteArray::GetDataStartAddress() {
2151 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2152}
2153
2154
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002155uint8_t* ExternalPixelArray::external_pixel_pointer() {
2156 return reinterpret_cast<uint8_t*>(external_pointer());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002157}
2158
2159
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002160uint8_t ExternalPixelArray::get(int index) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002161 ASSERT((index >= 0) && (index < this->length()));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002162 uint8_t* ptr = external_pixel_pointer();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002163 return ptr[index];
2164}
2165
2166
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002167void ExternalPixelArray::set(int index, uint8_t value) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002168 ASSERT((index >= 0) && (index < this->length()));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002169 uint8_t* ptr = external_pixel_pointer();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002170 ptr[index] = value;
2171}
2172
2173
ager@chromium.org3811b432009-10-28 14:53:37 +00002174void* ExternalArray::external_pointer() {
2175 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2176 return reinterpret_cast<void*>(ptr);
2177}
2178
2179
2180void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2181 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2182 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2183}
2184
2185
2186int8_t ExternalByteArray::get(int index) {
2187 ASSERT((index >= 0) && (index < this->length()));
2188 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2189 return ptr[index];
2190}
2191
2192
2193void ExternalByteArray::set(int index, int8_t value) {
2194 ASSERT((index >= 0) && (index < this->length()));
2195 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2196 ptr[index] = value;
2197}
2198
2199
2200uint8_t ExternalUnsignedByteArray::get(int index) {
2201 ASSERT((index >= 0) && (index < this->length()));
2202 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2203 return ptr[index];
2204}
2205
2206
2207void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2208 ASSERT((index >= 0) && (index < this->length()));
2209 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2210 ptr[index] = value;
2211}
2212
2213
2214int16_t ExternalShortArray::get(int index) {
2215 ASSERT((index >= 0) && (index < this->length()));
2216 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2217 return ptr[index];
2218}
2219
2220
2221void ExternalShortArray::set(int index, int16_t value) {
2222 ASSERT((index >= 0) && (index < this->length()));
2223 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2224 ptr[index] = value;
2225}
2226
2227
2228uint16_t ExternalUnsignedShortArray::get(int index) {
2229 ASSERT((index >= 0) && (index < this->length()));
2230 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2231 return ptr[index];
2232}
2233
2234
2235void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2236 ASSERT((index >= 0) && (index < this->length()));
2237 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2238 ptr[index] = value;
2239}
2240
2241
2242int32_t ExternalIntArray::get(int index) {
2243 ASSERT((index >= 0) && (index < this->length()));
2244 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2245 return ptr[index];
2246}
2247
2248
2249void ExternalIntArray::set(int index, int32_t value) {
2250 ASSERT((index >= 0) && (index < this->length()));
2251 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2252 ptr[index] = value;
2253}
2254
2255
2256uint32_t ExternalUnsignedIntArray::get(int index) {
2257 ASSERT((index >= 0) && (index < this->length()));
2258 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2259 return ptr[index];
2260}
2261
2262
2263void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2264 ASSERT((index >= 0) && (index < this->length()));
2265 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2266 ptr[index] = value;
2267}
2268
2269
2270float ExternalFloatArray::get(int index) {
2271 ASSERT((index >= 0) && (index < this->length()));
2272 float* ptr = static_cast<float*>(external_pointer());
2273 return ptr[index];
2274}
2275
2276
2277void ExternalFloatArray::set(int index, float value) {
2278 ASSERT((index >= 0) && (index < this->length()));
2279 float* ptr = static_cast<float*>(external_pointer());
2280 ptr[index] = value;
2281}
2282
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002283
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00002284int Map::visitor_id() {
2285 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2286}
2287
2288
2289void Map::set_visitor_id(int id) {
2290 ASSERT(0 <= id && id < 256);
2291 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2292}
2293
ager@chromium.org3811b432009-10-28 14:53:37 +00002294
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002295int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002296 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2297}
2298
2299
2300int Map::inobject_properties() {
2301 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002302}
2303
2304
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002305int Map::pre_allocated_property_fields() {
2306 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2307}
2308
2309
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002310int HeapObject::SizeFromMap(Map* map) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002311 int instance_size = map->instance_size();
2312 if (instance_size != kVariableSizeSentinel) return instance_size;
2313 // We can ignore the "symbol" bit becase it is only set for symbols
2314 // and implies a string type.
2315 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002316 // Only inline the most frequent cases.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002317 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002318 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002319 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002320 if (instance_type == ASCII_STRING_TYPE) {
2321 return SeqAsciiString::SizeFor(
2322 reinterpret_cast<SeqAsciiString*>(this)->length());
2323 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002324 if (instance_type == BYTE_ARRAY_TYPE) {
2325 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2326 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002327 if (instance_type == STRING_TYPE) {
2328 return SeqTwoByteString::SizeFor(
2329 reinterpret_cast<SeqTwoByteString*>(this)->length());
2330 }
2331 ASSERT(instance_type == CODE_TYPE);
2332 return reinterpret_cast<Code*>(this)->CodeSize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002333}
2334
2335
2336void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002337 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002338 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002339 ASSERT(0 <= value && value < 256);
2340 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2341}
2342
2343
ager@chromium.org7c537e22008-10-16 08:43:32 +00002344void Map::set_inobject_properties(int value) {
2345 ASSERT(0 <= value && value < 256);
2346 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2347}
2348
2349
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002350void Map::set_pre_allocated_property_fields(int value) {
2351 ASSERT(0 <= value && value < 256);
2352 WRITE_BYTE_FIELD(this,
2353 kPreAllocatedPropertyFieldsOffset,
2354 static_cast<byte>(value));
2355}
2356
2357
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002358InstanceType Map::instance_type() {
2359 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2360}
2361
2362
2363void Map::set_instance_type(InstanceType value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002364 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2365}
2366
2367
2368int Map::unused_property_fields() {
2369 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2370}
2371
2372
2373void Map::set_unused_property_fields(int value) {
2374 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2375}
2376
2377
2378byte Map::bit_field() {
2379 return READ_BYTE_FIELD(this, kBitFieldOffset);
2380}
2381
2382
2383void Map::set_bit_field(byte value) {
2384 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2385}
2386
2387
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002388byte Map::bit_field2() {
2389 return READ_BYTE_FIELD(this, kBitField2Offset);
2390}
2391
2392
2393void Map::set_bit_field2(byte value) {
2394 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2395}
2396
2397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002398void Map::set_non_instance_prototype(bool value) {
2399 if (value) {
2400 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2401 } else {
2402 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2403 }
2404}
2405
2406
2407bool Map::has_non_instance_prototype() {
2408 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2409}
2410
2411
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002412void Map::set_function_with_prototype(bool value) {
2413 if (value) {
2414 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2415 } else {
2416 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2417 }
2418}
2419
2420
2421bool Map::function_with_prototype() {
2422 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2423}
2424
2425
ager@chromium.org870a0b62008-11-04 11:43:05 +00002426void Map::set_is_access_check_needed(bool access_check_needed) {
2427 if (access_check_needed) {
2428 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2429 } else {
2430 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2431 }
2432}
2433
2434
2435bool Map::is_access_check_needed() {
2436 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2437}
2438
2439
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002440void Map::set_is_extensible(bool value) {
2441 if (value) {
2442 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2443 } else {
2444 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2445 }
2446}
2447
2448bool Map::is_extensible() {
2449 return ((1 << kIsExtensible) & bit_field2()) != 0;
2450}
2451
2452
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002453void Map::set_attached_to_shared_function_info(bool value) {
2454 if (value) {
2455 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2456 } else {
2457 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2458 }
2459}
2460
2461bool Map::attached_to_shared_function_info() {
2462 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2463}
2464
2465
2466void Map::set_is_shared(bool value) {
2467 if (value) {
2468 set_bit_field2(bit_field2() | (1 << kIsShared));
2469 } else {
2470 set_bit_field2(bit_field2() & ~(1 << kIsShared));
2471 }
2472}
2473
2474bool Map::is_shared() {
2475 return ((1 << kIsShared) & bit_field2()) != 0;
2476}
2477
2478
2479JSFunction* Map::unchecked_constructor() {
2480 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2481}
2482
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002483
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002484Code::Flags Code::flags() {
2485 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2486}
2487
2488
2489void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002490 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002491 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002492 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2493 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002494 ExtractArgumentsCountFromFlags(flags) >= 0);
2495 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2496}
2497
2498
2499Code::Kind Code::kind() {
2500 return ExtractKindFromFlags(flags());
2501}
2502
2503
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002504InLoopFlag Code::ic_in_loop() {
2505 return ExtractICInLoopFromFlags(flags());
2506}
2507
2508
kasper.lund7276f142008-07-30 08:49:36 +00002509InlineCacheState Code::ic_state() {
2510 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002511 // Only allow uninitialized or debugger states for non-IC code
2512 // objects. This is used in the debugger to determine whether or not
2513 // a call to code object has been replaced with a debug break call.
2514 ASSERT(is_inline_cache_stub() ||
2515 result == UNINITIALIZED ||
2516 result == DEBUG_BREAK ||
2517 result == DEBUG_PREPARE_STEP_IN);
2518 return result;
2519}
2520
2521
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002522Code::ExtraICState Code::extra_ic_state() {
2523 ASSERT(is_inline_cache_stub());
2524 return ExtractExtraICStateFromFlags(flags());
2525}
2526
2527
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002528PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002529 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002530 return ExtractTypeFromFlags(flags());
2531}
2532
2533
2534int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002535 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002536 return ExtractArgumentsCountFromFlags(flags());
2537}
2538
2539
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002540int Code::major_key() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002541 ASSERT(kind() == STUB ||
2542 kind() == BINARY_OP_IC ||
2543 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2544 kind() == COMPARE_IC);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002545 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
kasper.lund7276f142008-07-30 08:49:36 +00002546}
2547
2548
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002549void Code::set_major_key(int major) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002550 ASSERT(kind() == STUB ||
2551 kind() == BINARY_OP_IC ||
2552 kind() == TYPE_RECORDING_BINARY_OP_IC ||
2553 kind() == COMPARE_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002554 ASSERT(0 <= major && major < 256);
2555 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002556}
2557
2558
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002559bool Code::optimizable() {
2560 ASSERT(kind() == FUNCTION);
2561 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2562}
2563
2564
2565void Code::set_optimizable(bool value) {
2566 ASSERT(kind() == FUNCTION);
2567 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2568}
2569
2570
2571bool Code::has_deoptimization_support() {
2572 ASSERT(kind() == FUNCTION);
2573 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2574}
2575
2576
2577void Code::set_has_deoptimization_support(bool value) {
2578 ASSERT(kind() == FUNCTION);
2579 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2580}
2581
2582
2583int Code::allow_osr_at_loop_nesting_level() {
2584 ASSERT(kind() == FUNCTION);
2585 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2586}
2587
2588
2589void Code::set_allow_osr_at_loop_nesting_level(int level) {
2590 ASSERT(kind() == FUNCTION);
2591 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2592 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2593}
2594
2595
2596unsigned Code::stack_slots() {
2597 ASSERT(kind() == OPTIMIZED_FUNCTION);
2598 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2599}
2600
2601
2602void Code::set_stack_slots(unsigned slots) {
2603 ASSERT(kind() == OPTIMIZED_FUNCTION);
2604 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2605}
2606
2607
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002608unsigned Code::safepoint_table_offset() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002609 ASSERT(kind() == OPTIMIZED_FUNCTION);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002610 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002611}
2612
2613
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002614void Code::set_safepoint_table_offset(unsigned offset) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002615 ASSERT(kind() == OPTIMIZED_FUNCTION);
2616 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002617 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002618}
2619
2620
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002621unsigned Code::stack_check_table_offset() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002622 ASSERT(kind() == FUNCTION);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002623 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002624}
2625
2626
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002627void Code::set_stack_check_table_offset(unsigned offset) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002628 ASSERT(kind() == FUNCTION);
2629 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002630 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002631}
2632
2633
2634CheckType Code::check_type() {
2635 ASSERT(is_call_stub() || is_keyed_call_stub());
2636 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2637 return static_cast<CheckType>(type);
2638}
2639
2640
2641void Code::set_check_type(CheckType value) {
2642 ASSERT(is_call_stub() || is_keyed_call_stub());
2643 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2644}
2645
2646
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002647ExternalArrayType Code::external_array_type() {
2648 ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
2649 byte type = READ_BYTE_FIELD(this, kExternalArrayTypeOffset);
2650 return static_cast<ExternalArrayType>(type);
2651}
2652
2653
2654void Code::set_external_array_type(ExternalArrayType value) {
2655 ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
2656 WRITE_BYTE_FIELD(this, kExternalArrayTypeOffset, value);
2657}
2658
2659
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002660byte Code::binary_op_type() {
2661 ASSERT(is_binary_op_stub());
2662 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2663}
2664
2665
2666void Code::set_binary_op_type(byte value) {
2667 ASSERT(is_binary_op_stub());
2668 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2669}
2670
2671
2672byte Code::type_recording_binary_op_type() {
2673 ASSERT(is_type_recording_binary_op_stub());
2674 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2675}
2676
2677
2678void Code::set_type_recording_binary_op_type(byte value) {
2679 ASSERT(is_type_recording_binary_op_stub());
2680 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2681}
2682
2683
2684byte Code::type_recording_binary_op_result_type() {
2685 ASSERT(is_type_recording_binary_op_stub());
2686 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2687}
2688
2689
2690void Code::set_type_recording_binary_op_result_type(byte value) {
2691 ASSERT(is_type_recording_binary_op_stub());
2692 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2693}
2694
2695
2696byte Code::compare_state() {
2697 ASSERT(is_compare_ic_stub());
2698 return READ_BYTE_FIELD(this, kCompareStateOffset);
2699}
2700
2701
2702void Code::set_compare_state(byte value) {
2703 ASSERT(is_compare_ic_stub());
2704 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2705}
2706
2707
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002708bool Code::is_inline_cache_stub() {
2709 Kind kind = this->kind();
2710 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2711}
2712
2713
2714Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002715 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002716 InlineCacheState ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002717 ExtraICState extra_ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002718 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002719 int argc,
2720 InlineCacheHolderFlag holder) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002721 // Extra IC state is only allowed for monomorphic call IC stubs
2722 // or for store IC stubs.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002723 ASSERT(extra_ic_state == kNoExtraICState ||
2724 (kind == CALL_IC && (ic_state == MONOMORPHIC ||
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002725 ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)) ||
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00002726 (kind == STORE_IC) ||
2727 (kind == KEYED_STORE_IC));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002728 // Compute the bit mask.
2729 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002730 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002731 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002732 bits |= type << kFlagsTypeShift;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002733 bits |= extra_ic_state << kFlagsExtraICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002734 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002735 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002736 // Cast to flags and validate result before returning it.
2737 Flags result = static_cast<Flags>(bits);
2738 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002739 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002740 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002741 ASSERT(ExtractTypeFromFlags(result) == type);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002742 ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002743 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2744 return result;
2745}
2746
2747
2748Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2749 PropertyType type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002750 ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002751 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002752 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002753 int argc) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002754 return ComputeFlags(
2755 kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002756}
2757
2758
2759Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2760 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2761 return static_cast<Kind>(bits);
2762}
2763
2764
kasper.lund7276f142008-07-30 08:49:36 +00002765InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2766 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002767 return static_cast<InlineCacheState>(bits);
2768}
2769
2770
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002771Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
2772 int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
2773 return static_cast<ExtraICState>(bits);
2774}
2775
2776
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002777InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2778 int bits = (flags & kFlagsICInLoopMask);
2779 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2780}
2781
2782
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002783PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2784 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2785 return static_cast<PropertyType>(bits);
2786}
2787
2788
2789int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2790 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2791}
2792
2793
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002794InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2795 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2796 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2797}
2798
2799
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002800Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2801 int bits = flags & ~kFlagsTypeMask;
2802 return static_cast<Flags>(bits);
2803}
2804
2805
ager@chromium.org8bb60582008-12-11 12:02:20 +00002806Code* Code::GetCodeFromTargetAddress(Address address) {
2807 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2808 // GetCodeFromTargetAddress might be called when marking objects during mark
2809 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2810 // Code::cast. Code::cast does not work when the object's map is
2811 // marked.
2812 Code* result = reinterpret_cast<Code*>(code);
2813 return result;
2814}
2815
2816
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002817Isolate* Map::isolate() {
2818 return heap()->isolate();
2819}
2820
2821
2822Heap* Map::heap() {
2823 // NOTE: address() helper is not used to save one instruction.
2824 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
2825 ASSERT(heap != NULL);
2826 ASSERT(heap->isolate() == Isolate::Current());
2827 return heap;
2828}
2829
2830
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002831Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2832 return HeapObject::
2833 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2834}
2835
2836
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002837Object* Map::prototype() {
2838 return READ_FIELD(this, kPrototypeOffset);
2839}
2840
2841
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002842void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002843 ASSERT(value->IsNull() || value->IsJSObject());
2844 WRITE_FIELD(this, kPrototypeOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002845 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002846}
2847
2848
lrn@chromium.org303ada72010-10-27 09:33:13 +00002849MaybeObject* Map::GetFastElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002850 if (has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002851 Object* obj;
2852 { MaybeObject* maybe_obj = CopyDropTransitions();
2853 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2854 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002855 Map* new_map = Map::cast(obj);
2856 new_map->set_has_fast_elements(true);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002857 isolate()->counters()->map_slow_to_fast_elements()->Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002858 return new_map;
2859}
2860
2861
lrn@chromium.org303ada72010-10-27 09:33:13 +00002862MaybeObject* Map::GetSlowElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002863 if (!has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00002864 Object* obj;
2865 { MaybeObject* maybe_obj = CopyDropTransitions();
2866 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2867 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002868 Map* new_map = Map::cast(obj);
2869 new_map->set_has_fast_elements(false);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002870 isolate()->counters()->map_fast_to_slow_elements()->Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002871 return new_map;
2872}
2873
2874
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002875ACCESSORS(Map, instance_descriptors, DescriptorArray,
2876 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002877ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002878ACCESSORS(Map, constructor, Object, kConstructorOffset)
2879
2880ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2881ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002882ACCESSORS_GCSAFE(JSFunction, next_function_link, Object,
2883 kNextFunctionLinkOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002884
2885ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2886ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002887ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002888
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002889ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002890
2891ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2892ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2893ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2894ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2895ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2896
2897ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2898ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2899ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2900
2901ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2902ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2903ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2904ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2905ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2906ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2907
2908ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2909ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2910
2911ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2912ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2913
2914ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2915ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002916ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2917 kPropertyAccessorsOffset)
2918ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2919 kPrototypeTemplateOffset)
2920ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2921ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2922 kNamedPropertyHandlerOffset)
2923ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2924 kIndexedPropertyHandlerOffset)
2925ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2926 kInstanceTemplateOffset)
2927ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2928ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002929ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2930 kInstanceCallHandlerOffset)
2931ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2932 kAccessCheckInfoOffset)
2933ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2934
2935ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002936ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2937 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002938
2939ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2940ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2941
2942ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2943
2944ACCESSORS(Script, source, Object, kSourceOffset)
2945ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002946ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002947ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2948ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002949ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002950ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002951ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2952ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002953ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002954ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002955ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002956ACCESSORS(Script, eval_from_instructions_offset, Smi,
2957 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002958
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002959#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002960ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2961ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2962ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2963ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2964
2965ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2966ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2967ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2968ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002969#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002970
2971ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002972ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2973ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002974ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2975 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002976ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002977ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2978ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002979ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002980ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2981 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002982
2983BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2984 kHiddenPrototypeBit)
2985BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2986BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2987 kNeedsAccessCheckBit)
2988BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2989 kIsExpressionBit)
2990BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2991 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002992BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002993 has_only_simple_this_property_assignments,
2994 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002995BOOL_ACCESSORS(SharedFunctionInfo,
2996 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002997 try_full_codegen,
2998 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002999BOOL_ACCESSORS(SharedFunctionInfo,
3000 compiler_hints,
3001 allows_lazy_compilation,
3002 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003003
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003004
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003005#if V8_HOST_ARCH_32_BIT
3006SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3007SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003008 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003009SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003010 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003011SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3012SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003013 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003014SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3015SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003016 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003017SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003018 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003019SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003020 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003021SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003022#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003023
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003024#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003025 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003026 int holder::name() { \
3027 int value = READ_INT_FIELD(this, offset); \
3028 ASSERT(kHeapObjectTag == 1); \
3029 ASSERT((value & kHeapObjectTag) == 0); \
3030 return value >> 1; \
3031 } \
3032 void holder::set_##name(int value) { \
3033 ASSERT(kHeapObjectTag == 1); \
3034 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3035 (value & 0xC0000000) == 0x000000000); \
3036 WRITE_INT_FIELD(this, \
3037 offset, \
3038 (value << 1) & ~kHeapObjectTag); \
3039 }
3040
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003041#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3042 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003043 INT_ACCESSORS(holder, name, offset)
3044
3045
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003046PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003047PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3048 formal_parameter_count,
3049 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003050
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003051PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3052 expected_nof_properties,
3053 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003054PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3055
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003056PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3057PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3058 start_position_and_type,
3059 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003060
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003061PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3062 function_token_position,
3063 kFunctionTokenPositionOffset)
3064PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3065 compiler_hints,
3066 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003067
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003068PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3069 this_property_assignments_count,
3070 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003071PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003072#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003073
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003074
3075int SharedFunctionInfo::construction_count() {
3076 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3077}
3078
3079
3080void SharedFunctionInfo::set_construction_count(int value) {
3081 ASSERT(0 <= value && value < 256);
3082 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3083}
3084
3085
3086bool SharedFunctionInfo::live_objects_may_exist() {
3087 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
3088}
3089
3090
3091void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
3092 if (value) {
3093 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
3094 } else {
3095 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
3096 }
3097}
3098
3099
3100bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003101 return initial_map() != HEAP->undefined_value();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003102}
3103
3104
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003105bool SharedFunctionInfo::optimization_disabled() {
3106 return BooleanBit::get(compiler_hints(), kOptimizationDisabled);
3107}
3108
3109
3110void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3111 set_compiler_hints(BooleanBit::set(compiler_hints(),
3112 kOptimizationDisabled,
3113 disable));
3114 // If disabling optimizations we reflect that in the code object so
3115 // it will not be counted as optimizable code.
3116 if ((code()->kind() == Code::FUNCTION) && disable) {
3117 code()->set_optimizable(false);
3118 }
3119}
3120
3121
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003122bool SharedFunctionInfo::strict_mode() {
3123 return BooleanBit::get(compiler_hints(), kStrictModeFunction);
3124}
3125
3126
3127void SharedFunctionInfo::set_strict_mode(bool value) {
3128 set_compiler_hints(BooleanBit::set(compiler_hints(),
3129 kStrictModeFunction,
3130 value));
3131}
3132
3133
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003134ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3135ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3136
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00003137bool Script::HasValidSource() {
3138 Object* src = this->source();
3139 if (!src->IsString()) return true;
3140 String* src_str = String::cast(src);
3141 if (!StringShape(src_str).IsExternal()) return true;
3142 if (src_str->IsAsciiRepresentation()) {
3143 return ExternalAsciiString::cast(src)->resource() != NULL;
3144 } else if (src_str->IsTwoByteRepresentation()) {
3145 return ExternalTwoByteString::cast(src)->resource() != NULL;
3146 }
3147 return true;
3148}
3149
3150
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003151void SharedFunctionInfo::DontAdaptArguments() {
3152 ASSERT(code()->kind() == Code::BUILTIN);
3153 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3154}
3155
3156
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003157int SharedFunctionInfo::start_position() {
3158 return start_position_and_type() >> kStartPositionShift;
3159}
3160
3161
3162void SharedFunctionInfo::set_start_position(int start_position) {
3163 set_start_position_and_type((start_position << kStartPositionShift)
3164 | (start_position_and_type() & ~kStartPositionMask));
3165}
3166
3167
3168Code* SharedFunctionInfo::code() {
3169 return Code::cast(READ_FIELD(this, kCodeOffset));
3170}
3171
3172
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003173Code* SharedFunctionInfo::unchecked_code() {
3174 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3175}
3176
3177
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003178void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003179 WRITE_FIELD(this, kCodeOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003180 ASSERT(!Isolate::Current()->heap()->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003181}
3182
3183
ager@chromium.orgb5737492010-07-15 09:29:43 +00003184SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3185 return reinterpret_cast<SerializedScopeInfo*>(
3186 READ_FIELD(this, kScopeInfoOffset));
3187}
3188
3189
3190void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3191 WriteBarrierMode mode) {
3192 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003193 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode);
ager@chromium.orgb5737492010-07-15 09:29:43 +00003194}
3195
3196
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003197Smi* SharedFunctionInfo::deopt_counter() {
3198 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3199}
3200
3201
3202void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3203 WRITE_FIELD(this, kDeoptCounterOffset, value);
3204}
3205
3206
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003207bool SharedFunctionInfo::is_compiled() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003208 return code() !=
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003209 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003210}
3211
3212
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003213bool SharedFunctionInfo::IsApiFunction() {
3214 return function_data()->IsFunctionTemplateInfo();
3215}
3216
3217
3218FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3219 ASSERT(IsApiFunction());
3220 return FunctionTemplateInfo::cast(function_data());
3221}
3222
3223
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003224bool SharedFunctionInfo::HasBuiltinFunctionId() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003225 return function_data()->IsSmi();
3226}
3227
3228
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003229BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3230 ASSERT(HasBuiltinFunctionId());
3231 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003232}
3233
3234
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003235int SharedFunctionInfo::code_age() {
3236 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3237}
3238
3239
3240void SharedFunctionInfo::set_code_age(int code_age) {
3241 set_compiler_hints(compiler_hints() |
3242 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3243}
3244
3245
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003246bool SharedFunctionInfo::has_deoptimization_support() {
3247 Code* code = this->code();
3248 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3249}
3250
3251
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003252bool JSFunction::IsBuiltin() {
3253 return context()->global()->IsJSBuiltinsObject();
3254}
3255
3256
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003257bool JSFunction::NeedsArgumentsAdaption() {
3258 return shared()->formal_parameter_count() !=
3259 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3260}
3261
3262
3263bool JSFunction::IsOptimized() {
3264 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3265}
3266
3267
3268bool JSFunction::IsMarkedForLazyRecompilation() {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003269 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003270}
3271
3272
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003273Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003274 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003275}
3276
3277
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003278Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003279 return reinterpret_cast<Code*>(
3280 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003281}
3282
3283
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003284void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003285 // Skip the write barrier because code is never in new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003286 ASSERT(!HEAP->InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003287 Address entry = value->entry();
3288 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003289}
3290
3291
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003292void JSFunction::ReplaceCode(Code* code) {
3293 bool was_optimized = IsOptimized();
3294 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3295
3296 set_code(code);
3297
3298 // Add/remove the function from the list of optimized functions for this
3299 // context based on the state change.
3300 if (!was_optimized && is_optimized) {
3301 context()->global_context()->AddOptimizedFunction(this);
3302 }
3303 if (was_optimized && !is_optimized) {
3304 context()->global_context()->RemoveOptimizedFunction(this);
3305 }
3306}
3307
3308
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003309Context* JSFunction::context() {
3310 return Context::cast(READ_FIELD(this, kContextOffset));
3311}
3312
3313
3314Object* JSFunction::unchecked_context() {
3315 return READ_FIELD(this, kContextOffset);
3316}
3317
3318
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003319SharedFunctionInfo* JSFunction::unchecked_shared() {
3320 return reinterpret_cast<SharedFunctionInfo*>(
3321 READ_FIELD(this, kSharedFunctionInfoOffset));
3322}
3323
3324
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003325void JSFunction::set_context(Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003326 ASSERT(value->IsUndefined() || value->IsContext());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003327 WRITE_FIELD(this, kContextOffset, value);
3328 WRITE_BARRIER(this, kContextOffset);
3329}
3330
3331ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3332 kPrototypeOrInitialMapOffset)
3333
3334
3335Map* JSFunction::initial_map() {
3336 return Map::cast(prototype_or_initial_map());
3337}
3338
3339
3340void JSFunction::set_initial_map(Map* value) {
3341 set_prototype_or_initial_map(value);
3342}
3343
3344
3345bool JSFunction::has_initial_map() {
3346 return prototype_or_initial_map()->IsMap();
3347}
3348
3349
3350bool JSFunction::has_instance_prototype() {
3351 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3352}
3353
3354
3355bool JSFunction::has_prototype() {
3356 return map()->has_non_instance_prototype() || has_instance_prototype();
3357}
3358
3359
3360Object* JSFunction::instance_prototype() {
3361 ASSERT(has_instance_prototype());
3362 if (has_initial_map()) return initial_map()->prototype();
3363 // When there is no initial map and the prototype is a JSObject, the
3364 // initial map field is used for the prototype field.
3365 return prototype_or_initial_map();
3366}
3367
3368
3369Object* JSFunction::prototype() {
3370 ASSERT(has_prototype());
3371 // If the function's prototype property has been set to a non-JSObject
3372 // value, that value is stored in the constructor field of the map.
3373 if (map()->has_non_instance_prototype()) return map()->constructor();
3374 return instance_prototype();
3375}
3376
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003377bool JSFunction::should_have_prototype() {
3378 return map()->function_with_prototype();
3379}
3380
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003381
3382bool JSFunction::is_compiled() {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003383 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003384}
3385
3386
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003387int JSFunction::NumberOfLiterals() {
3388 return literals()->length();
3389}
3390
3391
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003392Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003393 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003394 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003395}
3396
3397
3398void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3399 Object* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003400 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003401 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3402 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3403}
3404
3405
3406Code* JSBuiltinsObject::javascript_builtin_code(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 Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3409}
3410
3411
3412void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3413 Code* 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, OffsetOfCodeWithId(id), value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003416 ASSERT(!HEAP->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003417}
3418
3419
3420Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00003421 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003422}
3423
3424
3425void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00003426 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003427}
3428
3429
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003430ACCESSORS(JSValue, value, Object, kValueOffset)
3431
3432
3433JSValue* JSValue::cast(Object* obj) {
3434 ASSERT(obj->IsJSValue());
3435 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3436 return reinterpret_cast<JSValue*>(obj);
3437}
3438
3439
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003440ACCESSORS(JSMessageObject, type, String, kTypeOffset)
3441ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
3442ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
3443ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
3444ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
3445SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
3446SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
3447
3448
3449JSMessageObject* JSMessageObject::cast(Object* obj) {
3450 ASSERT(obj->IsJSMessageObject());
3451 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
3452 return reinterpret_cast<JSMessageObject*>(obj);
3453}
3454
3455
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003456INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003457ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003458ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003459
3460
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003461byte* Code::instruction_start() {
3462 return FIELD_ADDR(this, kHeaderSize);
3463}
3464
3465
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003466byte* Code::instruction_end() {
3467 return instruction_start() + instruction_size();
3468}
3469
3470
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003471int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003472 return RoundUp(instruction_size(), kObjectAlignment);
3473}
3474
3475
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003476FixedArray* Code::unchecked_deoptimization_data() {
3477 return reinterpret_cast<FixedArray*>(
3478 READ_FIELD(this, kDeoptimizationDataOffset));
3479}
3480
3481
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003482ByteArray* Code::unchecked_relocation_info() {
3483 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003484}
3485
3486
3487byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003488 return unchecked_relocation_info()->GetDataStartAddress();
3489}
3490
3491
3492int Code::relocation_size() {
3493 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003494}
3495
3496
3497byte* Code::entry() {
3498 return instruction_start();
3499}
3500
3501
3502bool Code::contains(byte* pc) {
3503 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003504 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003505}
3506
3507
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003508ACCESSORS(JSArray, length, Object, kLengthOffset)
3509
3510
ager@chromium.org236ad962008-09-25 09:45:57 +00003511ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003512
3513
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003514JSRegExp::Type JSRegExp::TypeTag() {
3515 Object* data = this->data();
3516 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3517 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3518 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003519}
3520
3521
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003522int JSRegExp::CaptureCount() {
3523 switch (TypeTag()) {
3524 case ATOM:
3525 return 0;
3526 case IRREGEXP:
3527 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3528 default:
3529 UNREACHABLE();
3530 return -1;
3531 }
3532}
3533
3534
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003535JSRegExp::Flags JSRegExp::GetFlags() {
3536 ASSERT(this->data()->IsFixedArray());
3537 Object* data = this->data();
3538 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3539 return Flags(smi->value());
3540}
3541
3542
3543String* JSRegExp::Pattern() {
3544 ASSERT(this->data()->IsFixedArray());
3545 Object* data = this->data();
3546 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3547 return pattern;
3548}
3549
3550
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003551Object* JSRegExp::DataAt(int index) {
3552 ASSERT(TypeTag() != NOT_COMPILED);
3553 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003554}
3555
3556
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003557void JSRegExp::SetDataAt(int index, Object* value) {
3558 ASSERT(TypeTag() != NOT_COMPILED);
3559 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3560 FixedArray::cast(data())->set(index, value);
3561}
3562
3563
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003564JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003565 if (map()->has_fast_elements()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003566 ASSERT(elements()->map() == GetHeap()->fixed_array_map() ||
3567 elements()->map() == GetHeap()->fixed_cow_array_map());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003568 return FAST_ELEMENTS;
3569 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003570 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003571 if (array->IsFixedArray()) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003572 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3573 // FixedArray, but FAST_ELEMENTS is already handled above.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003574 ASSERT(array->IsDictionary());
3575 return DICTIONARY_ELEMENTS;
3576 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003577 ASSERT(!map()->has_fast_elements());
ager@chromium.org3811b432009-10-28 14:53:37 +00003578 if (array->IsExternalArray()) {
3579 switch (array->map()->instance_type()) {
3580 case EXTERNAL_BYTE_ARRAY_TYPE:
3581 return EXTERNAL_BYTE_ELEMENTS;
3582 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3583 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3584 case EXTERNAL_SHORT_ARRAY_TYPE:
3585 return EXTERNAL_SHORT_ELEMENTS;
3586 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3587 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3588 case EXTERNAL_INT_ARRAY_TYPE:
3589 return EXTERNAL_INT_ELEMENTS;
3590 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3591 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003592 case EXTERNAL_PIXEL_ARRAY_TYPE:
3593 return EXTERNAL_PIXEL_ELEMENTS;
ager@chromium.org3811b432009-10-28 14:53:37 +00003594 default:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003595 break;
ager@chromium.org3811b432009-10-28 14:53:37 +00003596 }
3597 }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003598 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3599 return EXTERNAL_FLOAT_ELEMENTS;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003600}
3601
3602
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003603bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003604 return GetElementsKind() == FAST_ELEMENTS;
3605}
3606
3607
3608bool JSObject::HasDictionaryElements() {
3609 return GetElementsKind() == DICTIONARY_ELEMENTS;
3610}
3611
3612
ager@chromium.org3811b432009-10-28 14:53:37 +00003613bool JSObject::HasExternalArrayElements() {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003614 HeapObject* array = elements();
3615 ASSERT(array != NULL);
3616 return array->IsExternalArray();
ager@chromium.org3811b432009-10-28 14:53:37 +00003617}
3618
3619
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003620#define EXTERNAL_ELEMENTS_CHECK(name, type) \
3621bool JSObject::HasExternal##name##Elements() { \
3622 HeapObject* array = elements(); \
3623 ASSERT(array != NULL); \
3624 if (!array->IsHeapObject()) \
3625 return false; \
3626 return array->map()->instance_type() == type; \
ager@chromium.org3811b432009-10-28 14:53:37 +00003627}
3628
3629
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003630EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
3631EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
3632EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
3633EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
3634 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
3635EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
3636EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
3637 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
3638EXTERNAL_ELEMENTS_CHECK(Float,
3639 EXTERNAL_FLOAT_ARRAY_TYPE)
3640EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
ager@chromium.org3811b432009-10-28 14:53:37 +00003641
3642
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003643bool JSObject::HasNamedInterceptor() {
3644 return map()->has_named_interceptor();
3645}
3646
3647
3648bool JSObject::HasIndexedInterceptor() {
3649 return map()->has_indexed_interceptor();
3650}
3651
3652
ager@chromium.org5c838252010-02-19 08:53:10 +00003653bool JSObject::AllowsSetElementsLength() {
3654 bool result = elements()->IsFixedArray();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003655 ASSERT(result == !HasExternalArrayElements());
ager@chromium.org5c838252010-02-19 08:53:10 +00003656 return result;
3657}
3658
3659
lrn@chromium.org303ada72010-10-27 09:33:13 +00003660MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003661 ASSERT(HasFastElements());
3662 FixedArray* elems = FixedArray::cast(elements());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003663 Isolate* isolate = GetIsolate();
3664 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003665 Object* writable_elems;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003666 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
3667 elems, isolate->heap()->fixed_array_map());
lrn@chromium.org303ada72010-10-27 09:33:13 +00003668 if (!maybe_writable_elems->ToObject(&writable_elems)) {
3669 return maybe_writable_elems;
3670 }
3671 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003672 set_elements(FixedArray::cast(writable_elems));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003673 isolate->counters()->cow_arrays_converted()->Increment();
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003674 return writable_elems;
3675}
3676
3677
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003678StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003679 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003680 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003681}
3682
3683
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003684NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003685 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003686 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003687}
3688
3689
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003690bool String::IsHashFieldComputed(uint32_t field) {
3691 return (field & kHashNotComputedMask) == 0;
3692}
3693
3694
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003695bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003696 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003697}
3698
3699
3700uint32_t String::Hash() {
3701 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003702 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003703 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003704 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003705 return ComputeAndSetHash();
3706}
3707
3708
ager@chromium.org7c537e22008-10-16 08:43:32 +00003709StringHasher::StringHasher(int length)
3710 : length_(length),
3711 raw_running_hash_(0),
3712 array_index_(0),
3713 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3714 is_first_char_(true),
3715 is_valid_(true) { }
3716
3717
3718bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003719 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003720}
3721
3722
3723void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003724 // Use the Jenkins one-at-a-time hash function to update the hash
3725 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003726 raw_running_hash_ += c;
3727 raw_running_hash_ += (raw_running_hash_ << 10);
3728 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003729 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003730 if (is_array_index_) {
3731 if (c < '0' || c > '9') {
3732 is_array_index_ = false;
3733 } else {
3734 int d = c - '0';
3735 if (is_first_char_) {
3736 is_first_char_ = false;
3737 if (c == '0' && length_ > 1) {
3738 is_array_index_ = false;
3739 return;
3740 }
3741 }
3742 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3743 is_array_index_ = false;
3744 } else {
3745 array_index_ = array_index_ * 10 + d;
3746 }
3747 }
3748 }
3749}
3750
3751
3752void StringHasher::AddCharacterNoIndex(uc32 c) {
3753 ASSERT(!is_array_index());
3754 raw_running_hash_ += c;
3755 raw_running_hash_ += (raw_running_hash_ << 10);
3756 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3757}
3758
3759
3760uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003761 // Get the calculated raw hash value and do some more bit ops to distribute
3762 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003763 uint32_t result = raw_running_hash_;
3764 result += (result << 3);
3765 result ^= (result >> 11);
3766 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003767 if (result == 0) {
3768 result = 27;
3769 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003770 return result;
3771}
3772
3773
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00003774template <typename schar>
3775uint32_t HashSequentialString(const schar* chars, int length) {
3776 StringHasher hasher(length);
3777 if (!hasher.has_trivial_hash()) {
3778 int i;
3779 for (i = 0; hasher.is_array_index() && (i < length); i++) {
3780 hasher.AddCharacter(chars[i]);
3781 }
3782 for (; i < length; i++) {
3783 hasher.AddCharacterNoIndex(chars[i]);
3784 }
3785 }
3786 return hasher.GetHashField();
3787}
3788
3789
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003790bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003791 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003792 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3793 return false;
3794 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003795 return SlowAsArrayIndex(index);
3796}
3797
3798
3799Object* JSObject::GetPrototype() {
3800 return JSObject::cast(this)->map()->prototype();
3801}
3802
3803
3804PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3805 return GetPropertyAttributeWithReceiver(this, key);
3806}
3807
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003808// TODO(504): this may be useful in other places too where JSGlobalProxy
3809// is used.
3810Object* JSObject::BypassGlobalProxy() {
3811 if (IsJSGlobalProxy()) {
3812 Object* proto = GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003813 if (proto->IsNull()) return GetHeap()->undefined_value();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003814 ASSERT(proto->IsJSGlobalObject());
3815 return proto;
3816 }
3817 return this;
3818}
3819
3820
3821bool JSObject::HasHiddenPropertiesObject() {
3822 ASSERT(!IsJSGlobalProxy());
3823 return GetPropertyAttributePostInterceptor(this,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003824 GetHeap()->hidden_symbol(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003825 false) != ABSENT;
3826}
3827
3828
3829Object* JSObject::GetHiddenPropertiesObject() {
3830 ASSERT(!IsJSGlobalProxy());
3831 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003832 // You can't install a getter on a property indexed by the hidden symbol,
3833 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3834 // object.
3835 Object* result =
3836 GetLocalPropertyPostInterceptor(this,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003837 GetHeap()->hidden_symbol(),
lrn@chromium.org303ada72010-10-27 09:33:13 +00003838 &attributes)->ToObjectUnchecked();
3839 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003840}
3841
3842
lrn@chromium.org303ada72010-10-27 09:33:13 +00003843MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003844 ASSERT(!IsJSGlobalProxy());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003845 return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003846 hidden_obj,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00003847 DONT_ENUM,
3848 kNonStrictMode);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003849}
3850
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003851
3852bool JSObject::HasElement(uint32_t index) {
3853 return HasElementWithReceiver(this, index);
3854}
3855
3856
3857bool AccessorInfo::all_can_read() {
3858 return BooleanBit::get(flag(), kAllCanReadBit);
3859}
3860
3861
3862void AccessorInfo::set_all_can_read(bool value) {
3863 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3864}
3865
3866
3867bool AccessorInfo::all_can_write() {
3868 return BooleanBit::get(flag(), kAllCanWriteBit);
3869}
3870
3871
3872void AccessorInfo::set_all_can_write(bool value) {
3873 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3874}
3875
3876
ager@chromium.org870a0b62008-11-04 11:43:05 +00003877bool AccessorInfo::prohibits_overwriting() {
3878 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3879}
3880
3881
3882void AccessorInfo::set_prohibits_overwriting(bool value) {
3883 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3884}
3885
3886
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003887PropertyAttributes AccessorInfo::property_attributes() {
3888 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3889}
3890
3891
3892void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3893 ASSERT(AttributesField::is_valid(attributes));
3894 int rest_value = flag()->value() & ~AttributesField::mask();
3895 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3896}
3897
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003898template<typename Shape, typename Key>
3899void Dictionary<Shape, Key>::SetEntry(int entry,
3900 Object* key,
3901 Object* value,
3902 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003903 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003904 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003905 AssertNoAllocation no_gc;
3906 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003907 FixedArray::set(index, key, mode);
3908 FixedArray::set(index+1, value, mode);
3909 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003910}
3911
3912
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003913bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
3914 ASSERT(other->IsNumber());
3915 return key == static_cast<uint32_t>(other->Number());
3916}
3917
3918
3919uint32_t NumberDictionaryShape::Hash(uint32_t key) {
3920 return ComputeIntegerHash(key);
3921}
3922
3923
3924uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
3925 ASSERT(other->IsNumber());
3926 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
3927}
3928
3929
3930MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
3931 return Isolate::Current()->heap()->NumberFromUint32(key);
3932}
3933
3934
3935bool StringDictionaryShape::IsMatch(String* key, Object* other) {
3936 // We know that all entries in a hash table had their hash keys created.
3937 // Use that knowledge to have fast failure.
3938 if (key->Hash() != String::cast(other)->Hash()) return false;
3939 return key->Equals(String::cast(other));
3940}
3941
3942
3943uint32_t StringDictionaryShape::Hash(String* key) {
3944 return key->Hash();
3945}
3946
3947
3948uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
3949 return String::cast(other)->Hash();
3950}
3951
3952
3953MaybeObject* StringDictionaryShape::AsObject(String* key) {
3954 return key;
3955}
3956
3957
3958void Map::ClearCodeCache(Heap* heap) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003959 // No write barrier is needed since empty_fixed_array is not in new space.
3960 // Please note this function is used during marking:
3961 // - MarkCompactCollector::MarkUnmarkedObject
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003962 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
3963 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003964}
3965
3966
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003967void JSArray::EnsureSize(int required_size) {
3968 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003969 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003970 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3971 if (elts->length() < required_size) {
3972 // Doubling in size would be overkill, but leave some slack to avoid
3973 // constantly growing.
3974 Expand(required_size + (required_size >> 3));
3975 // It's a performance benefit to keep a frequently used array in new-space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003976 } else if (!GetHeap()->new_space()->Contains(elts) &&
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003977 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3978 // Expand will allocate a new backing store in new space even if the size
3979 // we asked for isn't larger than what we had before.
3980 Expand(required_size);
3981 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003982}
3983
3984
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003985void JSArray::set_length(Smi* length) {
3986 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3987}
3988
3989
ager@chromium.org7c537e22008-10-16 08:43:32 +00003990void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003991 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003992 set_elements(storage);
3993}
3994
3995
lrn@chromium.org303ada72010-10-27 09:33:13 +00003996MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003997 if (length() == 0) return this;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003998 return GetHeap()->CopyFixedArray(this);
3999}
4000
4001
4002Relocatable::Relocatable(Isolate* isolate) {
4003 ASSERT(isolate == Isolate::Current());
4004 isolate_ = isolate;
4005 prev_ = isolate->relocatable_top();
4006 isolate->set_relocatable_top(this);
4007}
4008
4009
4010Relocatable::~Relocatable() {
4011 ASSERT(isolate_ == Isolate::Current());
4012 ASSERT_EQ(isolate_->relocatable_top(), this);
4013 isolate_->set_relocatable_top(prev_);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004014}
4015
4016
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004017int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4018 return map->instance_size();
4019}
4020
4021
4022void Proxy::ProxyIterateBody(ObjectVisitor* v) {
4023 v->VisitExternalReference(
4024 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
4025}
4026
4027
4028template<typename StaticVisitor>
4029void Proxy::ProxyIterateBody() {
4030 StaticVisitor::VisitExternalReference(
4031 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
4032}
4033
4034
4035void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4036 typedef v8::String::ExternalAsciiStringResource Resource;
4037 v->VisitExternalAsciiString(
4038 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4039}
4040
4041
4042template<typename StaticVisitor>
4043void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4044 typedef v8::String::ExternalAsciiStringResource Resource;
4045 StaticVisitor::VisitExternalAsciiString(
4046 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4047}
4048
4049
4050void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4051 typedef v8::String::ExternalStringResource Resource;
4052 v->VisitExternalTwoByteString(
4053 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4054}
4055
4056
4057template<typename StaticVisitor>
4058void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4059 typedef v8::String::ExternalStringResource Resource;
4060 StaticVisitor::VisitExternalTwoByteString(
4061 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4062}
4063
4064#define SLOT_ADDR(obj, offset) \
4065 reinterpret_cast<Object**>((obj)->address() + offset)
4066
4067template<int start_offset, int end_offset, int size>
4068void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4069 HeapObject* obj,
4070 ObjectVisitor* v) {
4071 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4072}
4073
4074
4075template<int start_offset>
4076void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4077 int object_size,
4078 ObjectVisitor* v) {
4079 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4080}
4081
4082#undef SLOT_ADDR
4083
4084
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004085#undef CAST_ACCESSOR
4086#undef INT_ACCESSORS
4087#undef SMI_ACCESSORS
4088#undef ACCESSORS
4089#undef FIELD_ADDR
4090#undef READ_FIELD
4091#undef WRITE_FIELD
4092#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004093#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004094#undef READ_MEMADDR_FIELD
4095#undef WRITE_MEMADDR_FIELD
4096#undef READ_DOUBLE_FIELD
4097#undef WRITE_DOUBLE_FIELD
4098#undef READ_INT_FIELD
4099#undef WRITE_INT_FIELD
4100#undef READ_SHORT_FIELD
4101#undef WRITE_SHORT_FIELD
4102#undef READ_BYTE_FIELD
4103#undef WRITE_BYTE_FIELD
4104
4105
4106} } // namespace v8::internal
4107
4108#endif // V8_OBJECTS_INL_H_