blob: 4355fe9e1fb6b72db3400b1b227ee32d0301b0e0 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 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
38#include "objects.h"
39#include "contexts.h"
40#include "conversions-inl.h"
41#include "property.h"
42
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48}
49
50
51Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53}
54
55
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000056PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60}
61
62
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063#define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70#define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75#define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000077 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000079 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 }
81
82
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000083
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084#define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000094#define BOOL_GETTER(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98
99
100#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101 bool holder::name() { \
102 return BooleanBit::get(field(), offset); \
103 } \
104 void holder::set_##name(bool value) { \
105 set_##field(BooleanBit::set(field(), offset, value)); \
106 }
107
108
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000109bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110 // There is a constraint on the object; check.
111 if (!this->IsJSObject()) return false;
112 // Fetch the constructor function of the object.
113 Object* cons_obj = JSObject::cast(this)->map()->constructor();
114 if (!cons_obj->IsJSFunction()) return false;
115 JSFunction* fun = JSFunction::cast(cons_obj);
116 // Iterate through the chain of inheriting function templates to
117 // see if the required one occurs.
118 for (Object* type = fun->shared()->function_data();
119 type->IsFunctionTemplateInfo();
120 type = FunctionTemplateInfo::cast(type)->parent_template()) {
121 if (type == expected) return true;
122 }
123 // Didn't find the required type in the inheritance chain.
124 return false;
125}
126
127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128bool Object::IsSmi() {
129 return HAS_SMI_TAG(this);
130}
131
132
133bool Object::IsHeapObject() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000134 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135}
136
137
138bool Object::IsHeapNumber() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141}
142
143
144bool Object::IsString() {
145 return Object::IsHeapObject()
146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147}
148
149
ager@chromium.org870a0b62008-11-04 11:43:05 +0000150bool Object::IsSymbol() {
151 if (!this->IsHeapObject()) return false;
152 uint32_t type = HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000153 // Because the symbol tag is non-zero and no non-string types have the
154 // symbol bit set we can test for symbols with a very simple test
155 // operation.
156 ASSERT(kSymbolTag != 0);
157 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
158 return (type & kIsSymbolMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000159}
160
161
162bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000163 if (!this->IsHeapObject()) return false;
164 uint32_t type = HeapObject::cast(this)->map()->instance_type();
165 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
166 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000167}
168
169
ager@chromium.org870a0b62008-11-04 11:43:05 +0000170bool Object::IsSeqString() {
171 if (!IsString()) return false;
172 return StringShape(String::cast(this)).IsSequential();
173}
174
175
176bool Object::IsSeqAsciiString() {
177 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000178 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000179 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000180}
181
182
183bool Object::IsSeqTwoByteString() {
184 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000185 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000186 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187}
188
189
190bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000191 if (!IsString()) return false;
192 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193}
194
195
196bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000197 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000198 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000199 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200}
201
202
203bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000204 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000205 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000206 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207}
208
209
ager@chromium.org870a0b62008-11-04 11:43:05 +0000210StringShape::StringShape(String* str)
211 : type_(str->map()->instance_type()) {
212 set_valid();
213 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214}
215
216
ager@chromium.org870a0b62008-11-04 11:43:05 +0000217StringShape::StringShape(Map* map)
218 : type_(map->instance_type()) {
219 set_valid();
220 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221}
222
223
ager@chromium.org870a0b62008-11-04 11:43:05 +0000224StringShape::StringShape(InstanceType t)
225 : type_(static_cast<uint32_t>(t)) {
226 set_valid();
227 ASSERT((type_ & kIsNotStringMask) == kStringTag);
228}
229
230
231bool StringShape::IsSymbol() {
232 ASSERT(valid());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000233 ASSERT(kSymbolTag != 0);
234 return (type_ & kIsSymbolMask) != 0;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000235}
236
237
ager@chromium.org5ec48922009-05-05 07:25:34 +0000238bool String::IsAsciiRepresentation() {
239 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000240 if ((type & kStringRepresentationMask) == kConsStringTag &&
241 ConsString::cast(this)->second()->length() == 0) {
242 return ConsString::cast(this)->first()->IsAsciiRepresentation();
243 }
244 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000245}
246
247
ager@chromium.org5ec48922009-05-05 07:25:34 +0000248bool String::IsTwoByteRepresentation() {
249 uint32_t type = map()->instance_type();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000250 if ((type & kStringRepresentationMask) == kConsStringTag &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000251 ConsString::cast(this)->second()->length() == 0) {
252 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
253 }
254 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000255}
256
257
258bool StringShape::IsCons() {
259 return (type_ & kStringRepresentationMask) == kConsStringTag;
260}
261
262
ager@chromium.org870a0b62008-11-04 11:43:05 +0000263bool StringShape::IsExternal() {
264 return (type_ & kStringRepresentationMask) == kExternalStringTag;
265}
266
267
268bool StringShape::IsSequential() {
269 return (type_ & kStringRepresentationMask) == kSeqStringTag;
270}
271
272
273StringRepresentationTag StringShape::representation_tag() {
274 uint32_t tag = (type_ & kStringRepresentationMask);
275 return static_cast<StringRepresentationTag>(tag);
276}
277
278
279uint32_t StringShape::full_representation_tag() {
280 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
281}
282
283
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000284STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
285 Internals::kFullStringRepresentationMask);
286
287
ager@chromium.org870a0b62008-11-04 11:43:05 +0000288bool StringShape::IsSequentialAscii() {
289 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
290}
291
292
293bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000294 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000295}
296
297
298bool StringShape::IsExternalAscii() {
299 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
300}
301
302
303bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000304 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305}
306
307
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000308STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
309 Internals::kExternalTwoByteRepresentationTag);
310
311
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000312uc32 FlatStringReader::Get(int index) {
313 ASSERT(0 <= index && index <= length_);
314 if (is_ascii_) {
315 return static_cast<const byte*>(start_)[index];
316 } else {
317 return static_cast<const uc16*>(start_)[index];
318 }
319}
320
321
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322bool Object::IsNumber() {
323 return IsSmi() || IsHeapNumber();
324}
325
326
327bool Object::IsByteArray() {
328 return Object::IsHeapObject()
329 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
330}
331
332
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000333bool Object::IsPixelArray() {
334 return Object::IsHeapObject() &&
335 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
336}
337
338
ager@chromium.org3811b432009-10-28 14:53:37 +0000339bool Object::IsExternalArray() {
340 if (!Object::IsHeapObject())
341 return false;
342 InstanceType instance_type =
343 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000344 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
345 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000346}
347
348
349bool Object::IsExternalByteArray() {
350 return Object::IsHeapObject() &&
351 HeapObject::cast(this)->map()->instance_type() ==
352 EXTERNAL_BYTE_ARRAY_TYPE;
353}
354
355
356bool Object::IsExternalUnsignedByteArray() {
357 return Object::IsHeapObject() &&
358 HeapObject::cast(this)->map()->instance_type() ==
359 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
360}
361
362
363bool Object::IsExternalShortArray() {
364 return Object::IsHeapObject() &&
365 HeapObject::cast(this)->map()->instance_type() ==
366 EXTERNAL_SHORT_ARRAY_TYPE;
367}
368
369
370bool Object::IsExternalUnsignedShortArray() {
371 return Object::IsHeapObject() &&
372 HeapObject::cast(this)->map()->instance_type() ==
373 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
374}
375
376
377bool Object::IsExternalIntArray() {
378 return Object::IsHeapObject() &&
379 HeapObject::cast(this)->map()->instance_type() ==
380 EXTERNAL_INT_ARRAY_TYPE;
381}
382
383
384bool Object::IsExternalUnsignedIntArray() {
385 return Object::IsHeapObject() &&
386 HeapObject::cast(this)->map()->instance_type() ==
387 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
388}
389
390
391bool Object::IsExternalFloatArray() {
392 return Object::IsHeapObject() &&
393 HeapObject::cast(this)->map()->instance_type() ==
394 EXTERNAL_FLOAT_ARRAY_TYPE;
395}
396
397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398bool Object::IsFailure() {
399 return HAS_FAILURE_TAG(this);
400}
401
402
403bool Object::IsRetryAfterGC() {
404 return HAS_FAILURE_TAG(this)
405 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
406}
407
408
ager@chromium.org7c537e22008-10-16 08:43:32 +0000409bool Object::IsOutOfMemoryFailure() {
410 return HAS_FAILURE_TAG(this)
411 && Failure::cast(this)->IsOutOfMemoryException();
412}
413
414
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415bool Object::IsException() {
416 return this == Failure::Exception();
417}
418
419
420bool Object::IsJSObject() {
421 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000422 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423}
424
425
ager@chromium.org32912102009-01-16 10:38:43 +0000426bool Object::IsJSContextExtensionObject() {
427 return IsHeapObject()
428 && (HeapObject::cast(this)->map()->instance_type() ==
429 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
430}
431
432
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433bool Object::IsMap() {
434 return Object::IsHeapObject()
435 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
436}
437
438
439bool Object::IsFixedArray() {
440 return Object::IsHeapObject()
441 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
442}
443
444
445bool Object::IsDescriptorArray() {
446 return IsFixedArray();
447}
448
449
450bool Object::IsContext() {
451 return Object::IsHeapObject()
452 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000453 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000454 HeapObject::cast(this)->map() == Heap::global_context_map());
455}
456
457
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000458bool Object::IsCatchContext() {
459 return Object::IsHeapObject()
460 && HeapObject::cast(this)->map() == Heap::catch_context_map();
461}
462
463
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464bool Object::IsGlobalContext() {
465 return Object::IsHeapObject()
466 && HeapObject::cast(this)->map() == Heap::global_context_map();
467}
468
469
470bool Object::IsJSFunction() {
471 return Object::IsHeapObject()
472 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
473}
474
475
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000476template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477 return obj->IsJSFunction();
478}
479
480
481bool Object::IsCode() {
482 return Object::IsHeapObject()
483 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
484}
485
486
487bool Object::IsOddball() {
488 return Object::IsHeapObject()
489 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
490}
491
492
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000493bool Object::IsJSGlobalPropertyCell() {
494 return Object::IsHeapObject()
495 && HeapObject::cast(this)->map()->instance_type()
496 == JS_GLOBAL_PROPERTY_CELL_TYPE;
497}
498
499
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000500bool Object::IsSharedFunctionInfo() {
501 return Object::IsHeapObject() &&
502 (HeapObject::cast(this)->map()->instance_type() ==
503 SHARED_FUNCTION_INFO_TYPE);
504}
505
506
507bool Object::IsJSValue() {
508 return Object::IsHeapObject()
509 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
510}
511
512
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000513bool Object::IsStringWrapper() {
514 return IsJSValue() && JSValue::cast(this)->value()->IsString();
515}
516
517
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518bool Object::IsProxy() {
519 return Object::IsHeapObject()
520 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
521}
522
523
524bool Object::IsBoolean() {
525 return IsTrue() || IsFalse();
526}
527
528
529bool Object::IsJSArray() {
530 return Object::IsHeapObject()
531 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
532}
533
534
ager@chromium.org236ad962008-09-25 09:45:57 +0000535bool Object::IsJSRegExp() {
536 return Object::IsHeapObject()
537 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
538}
539
540
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000541template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542 return obj->IsJSArray();
543}
544
545
546bool Object::IsHashTable() {
547 return Object::IsHeapObject()
548 && HeapObject::cast(this)->map() == Heap::hash_table_map();
549}
550
551
552bool Object::IsDictionary() {
553 return IsHashTable() && this != Heap::symbol_table();
554}
555
556
557bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000558 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559}
560
561
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000562bool Object::IsCompilationCacheTable() {
563 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000564}
565
566
ager@chromium.org236ad962008-09-25 09:45:57 +0000567bool Object::IsMapCache() {
568 return IsHashTable();
569}
570
571
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572bool Object::IsPrimitive() {
573 return IsOddball() || IsNumber() || IsString();
574}
575
576
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000577bool Object::IsJSGlobalProxy() {
578 bool result = IsHeapObject() &&
579 (HeapObject::cast(this)->map()->instance_type() ==
580 JS_GLOBAL_PROXY_TYPE);
581 ASSERT(!result || IsAccessCheckNeeded());
582 return result;
583}
584
585
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000587 if (!IsHeapObject()) return false;
588
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000589 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000590 return type == JS_GLOBAL_OBJECT_TYPE ||
591 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592}
593
594
595bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596 return IsHeapObject() &&
597 (HeapObject::cast(this)->map()->instance_type() ==
598 JS_GLOBAL_OBJECT_TYPE);
599}
600
601
602bool Object::IsJSBuiltinsObject() {
603 return IsHeapObject() &&
604 (HeapObject::cast(this)->map()->instance_type() ==
605 JS_BUILTINS_OBJECT_TYPE);
606}
607
608
609bool Object::IsUndetectableObject() {
610 return IsHeapObject()
611 && HeapObject::cast(this)->map()->is_undetectable();
612}
613
614
615bool Object::IsAccessCheckNeeded() {
616 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000617 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618}
619
620
621bool Object::IsStruct() {
622 if (!IsHeapObject()) return false;
623 switch (HeapObject::cast(this)->map()->instance_type()) {
624#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
625 STRUCT_LIST(MAKE_STRUCT_CASE)
626#undef MAKE_STRUCT_CASE
627 default: return false;
628 }
629}
630
631
632#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
633 bool Object::Is##Name() { \
634 return Object::IsHeapObject() \
635 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
636 }
637 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
638#undef MAKE_STRUCT_PREDICATE
639
640
641bool Object::IsUndefined() {
642 return this == Heap::undefined_value();
643}
644
645
646bool Object::IsTheHole() {
647 return this == Heap::the_hole_value();
648}
649
650
651bool Object::IsNull() {
652 return this == Heap::null_value();
653}
654
655
656bool Object::IsTrue() {
657 return this == Heap::true_value();
658}
659
660
661bool Object::IsFalse() {
662 return this == Heap::false_value();
663}
664
665
666double Object::Number() {
667 ASSERT(IsNumber());
668 return IsSmi()
669 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
670 : reinterpret_cast<HeapNumber*>(this)->value();
671}
672
673
674
675Object* Object::ToSmi() {
676 if (IsSmi()) return this;
677 if (IsHeapNumber()) {
678 double value = HeapNumber::cast(this)->value();
679 int int_value = FastD2I(value);
680 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
681 return Smi::FromInt(int_value);
682 }
683 }
684 return Failure::Exception();
685}
686
687
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000688bool Object::HasSpecificClassOf(String* name) {
689 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
690}
691
692
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000693Object* Object::GetElement(uint32_t index) {
694 return GetElementWithReceiver(this, index);
695}
696
697
698Object* Object::GetProperty(String* key) {
699 PropertyAttributes attributes;
700 return GetPropertyWithReceiver(this, key, &attributes);
701}
702
703
704Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
705 return GetPropertyWithReceiver(this, key, attributes);
706}
707
708
709#define FIELD_ADDR(p, offset) \
710 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
711
712#define READ_FIELD(p, offset) \
713 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
714
715#define WRITE_FIELD(p, offset, value) \
716 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
717
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000718
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000719#define WRITE_BARRIER(object, offset) \
720 Heap::RecordWrite(object->address(), offset);
721
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000722// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000723// write due to the assert validating the written value.
724#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
725 if (mode == UPDATE_WRITE_BARRIER) { \
726 Heap::RecordWrite(object->address(), offset); \
727 } else { \
728 ASSERT(mode == SKIP_WRITE_BARRIER); \
729 ASSERT(Heap::InNewSpace(object) || \
730 !Heap::InNewSpace(READ_FIELD(object, offset))); \
731 }
732
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000733#define READ_DOUBLE_FIELD(p, offset) \
734 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
735
736#define WRITE_DOUBLE_FIELD(p, offset, value) \
737 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
738
739#define READ_INT_FIELD(p, offset) \
740 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
741
742#define WRITE_INT_FIELD(p, offset, value) \
743 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
744
ager@chromium.org3e875802009-06-29 08:26:34 +0000745#define READ_INTPTR_FIELD(p, offset) \
746 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
747
748#define WRITE_INTPTR_FIELD(p, offset, value) \
749 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
750
ager@chromium.org7c537e22008-10-16 08:43:32 +0000751#define READ_UINT32_FIELD(p, offset) \
752 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
753
754#define WRITE_UINT32_FIELD(p, offset, value) \
755 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
756
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757#define READ_SHORT_FIELD(p, offset) \
758 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
759
760#define WRITE_SHORT_FIELD(p, offset, value) \
761 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
762
763#define READ_BYTE_FIELD(p, offset) \
764 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
765
766#define WRITE_BYTE_FIELD(p, offset, value) \
767 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
768
769
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000770Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
771 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772}
773
774
775int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000776 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000777}
778
779
780Smi* Smi::FromInt(int value) {
781 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000782 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000783 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000784 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000785 return reinterpret_cast<Smi*>(tagged_value);
786}
787
788
789Smi* Smi::FromIntptr(intptr_t value) {
790 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000791 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
792 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793}
794
795
796Failure::Type Failure::type() const {
797 return static_cast<Type>(value() & kFailureTypeTagMask);
798}
799
800
801bool Failure::IsInternalError() const {
802 return type() == INTERNAL_ERROR;
803}
804
805
806bool Failure::IsOutOfMemoryException() const {
807 return type() == OUT_OF_MEMORY_EXCEPTION;
808}
809
810
811int Failure::requested() const {
812 const int kShiftBits =
813 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
814 STATIC_ASSERT(kShiftBits >= 0);
815 ASSERT(type() == RETRY_AFTER_GC);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000816 return static_cast<int>(value() >> kShiftBits);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000817}
818
819
820AllocationSpace Failure::allocation_space() const {
821 ASSERT_EQ(RETRY_AFTER_GC, type());
822 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
823 & kSpaceTagMask);
824}
825
826
827Failure* Failure::InternalError() {
828 return Construct(INTERNAL_ERROR);
829}
830
831
832Failure* Failure::Exception() {
833 return Construct(EXCEPTION);
834}
835
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000836
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000837Failure* Failure::OutOfMemoryException() {
838 return Construct(OUT_OF_MEMORY_EXCEPTION);
839}
840
841
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000842intptr_t Failure::value() const {
843 return reinterpret_cast<intptr_t>(this) >> kFailureTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844}
845
846
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000847Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000848 // Assert that the space encoding fits in the three bytes allotted for it.
849 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000850 intptr_t requested = requested_bytes >> kObjectAlignmentBits;
851 int tag_bits = kSpaceTagSize + kFailureTypeTagSize;
852 if (((requested << tag_bits) >> tag_bits) != requested) {
853 // No room for entire requested size in the bits. Round down to
854 // maximally representable size.
855 requested = static_cast<intptr_t>(
856 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
857 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000858 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000859 return Construct(RETRY_AFTER_GC, value);
860}
861
862
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000863Failure* Failure::Construct(Type type, intptr_t value) {
864 intptr_t info = (static_cast<intptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000865 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000866 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867}
868
869
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000870bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871#ifdef DEBUG
872 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
873#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000874
875#ifdef V8_TARGET_ARCH_X64
876 // To be representable as a long smi, the value must be a 32-bit integer.
877 bool result = (value == static_cast<int32_t>(value));
878#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879 // To be representable as an tagged small integer, the two
880 // most-significant bits of 'value' must be either 00 or 11 due to
881 // sign-extension. To check this we add 01 to the two
882 // most-significant bits, and check if the most-significant bit is 0
883 //
884 // CAUTION: The original code below:
885 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
886 // may lead to incorrect results according to the C language spec, and
887 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
888 // compiler may produce undefined results in case of signed integer
889 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000890 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000891#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000892 ASSERT(result == in_range);
893 return result;
894}
895
896
kasper.lund7276f142008-07-30 08:49:36 +0000897MapWord MapWord::FromMap(Map* map) {
898 return MapWord(reinterpret_cast<uintptr_t>(map));
899}
900
901
902Map* MapWord::ToMap() {
903 return reinterpret_cast<Map*>(value_);
904}
905
906
907bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000908 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000909}
910
911
912MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000913 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
914 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000915}
916
917
918HeapObject* MapWord::ToForwardingAddress() {
919 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000920 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000921}
922
923
924bool MapWord::IsMarked() {
925 return (value_ & kMarkingMask) == 0;
926}
927
928
929void MapWord::SetMark() {
930 value_ &= ~kMarkingMask;
931}
932
933
934void MapWord::ClearMark() {
935 value_ |= kMarkingMask;
936}
937
938
939bool MapWord::IsOverflowed() {
940 return (value_ & kOverflowMask) != 0;
941}
942
943
944void MapWord::SetOverflow() {
945 value_ |= kOverflowMask;
946}
947
948
949void MapWord::ClearOverflow() {
950 value_ &= ~kOverflowMask;
951}
952
953
954MapWord MapWord::EncodeAddress(Address map_address, int offset) {
955 // Offset is the distance in live bytes from the first live object in the
956 // same page. The offset between two objects in the same page should not
957 // exceed the object area size of a page.
958 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
959
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000960 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +0000961 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
962
963 Page* map_page = Page::FromAddress(map_address);
964 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
965
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000966 uintptr_t map_page_offset =
967 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +0000968
969 uintptr_t encoding =
970 (compact_offset << kForwardingOffsetShift) |
971 (map_page_offset << kMapPageOffsetShift) |
972 (map_page->mc_page_index << kMapPageIndexShift);
973 return MapWord(encoding);
974}
975
976
977Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000978 int map_page_index =
979 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +0000980 ASSERT_MAP_PAGE_INDEX(map_page_index);
981
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000982 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000983 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
984 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +0000985
986 return (map_space->PageAddress(map_page_index) + map_page_offset);
987}
988
989
990int MapWord::DecodeOffset() {
991 // The offset field is represented in the kForwardingOffsetBits
992 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000993 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
994 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
995 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +0000996}
997
998
999MapWord MapWord::FromEncodedAddress(Address address) {
1000 return MapWord(reinterpret_cast<uintptr_t>(address));
1001}
1002
1003
1004Address MapWord::ToEncodedAddress() {
1005 return reinterpret_cast<Address>(value_);
1006}
1007
1008
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001009#ifdef DEBUG
1010void HeapObject::VerifyObjectField(int offset) {
1011 VerifyPointer(READ_FIELD(this, offset));
1012}
1013#endif
1014
1015
1016Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001017 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018}
1019
1020
1021void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001022 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001023}
1024
1025
kasper.lund7276f142008-07-30 08:49:36 +00001026MapWord HeapObject::map_word() {
1027 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1028}
1029
1030
1031void HeapObject::set_map_word(MapWord map_word) {
1032 // WRITE_FIELD does not update the remembered set, but there is no need
1033 // here.
1034 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1035}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001036
1037
1038HeapObject* HeapObject::FromAddress(Address address) {
1039 ASSERT_TAG_ALIGNED(address);
1040 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1041}
1042
1043
1044Address HeapObject::address() {
1045 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1046}
1047
1048
1049int HeapObject::Size() {
1050 return SizeFromMap(map());
1051}
1052
1053
1054void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1055 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1056 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1057}
1058
1059
1060void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1061 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1062}
1063
1064
kasper.lund7276f142008-07-30 08:49:36 +00001065bool HeapObject::IsMarked() {
1066 return map_word().IsMarked();
1067}
1068
1069
1070void HeapObject::SetMark() {
1071 ASSERT(!IsMarked());
1072 MapWord first_word = map_word();
1073 first_word.SetMark();
1074 set_map_word(first_word);
1075}
1076
1077
1078void HeapObject::ClearMark() {
1079 ASSERT(IsMarked());
1080 MapWord first_word = map_word();
1081 first_word.ClearMark();
1082 set_map_word(first_word);
1083}
1084
1085
1086bool HeapObject::IsOverflowed() {
1087 return map_word().IsOverflowed();
1088}
1089
1090
1091void HeapObject::SetOverflow() {
1092 MapWord first_word = map_word();
1093 first_word.SetOverflow();
1094 set_map_word(first_word);
1095}
1096
1097
1098void HeapObject::ClearOverflow() {
1099 ASSERT(IsOverflowed());
1100 MapWord first_word = map_word();
1101 first_word.ClearOverflow();
1102 set_map_word(first_word);
1103}
1104
1105
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106double HeapNumber::value() {
1107 return READ_DOUBLE_FIELD(this, kValueOffset);
1108}
1109
1110
1111void HeapNumber::set_value(double value) {
1112 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1113}
1114
1115
1116ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001117
1118
1119Array* JSObject::elements() {
1120 Object* array = READ_FIELD(this, kElementsOffset);
1121 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001122 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1123 array->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001124 return reinterpret_cast<Array*>(array);
1125}
1126
1127
1128void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1129 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001130 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1131 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001132 WRITE_FIELD(this, kElementsOffset, value);
1133 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1134}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135
1136
1137void JSObject::initialize_properties() {
1138 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1139 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1140}
1141
1142
1143void JSObject::initialize_elements() {
1144 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1145 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1146}
1147
1148
1149ACCESSORS(Oddball, to_string, String, kToStringOffset)
1150ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1151
1152
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001153Object* JSGlobalPropertyCell::value() {
1154 return READ_FIELD(this, kValueOffset);
1155}
1156
1157
1158void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1159 // The write barrier is not used for global property cells.
1160 ASSERT(!val->IsJSGlobalPropertyCell());
1161 WRITE_FIELD(this, kValueOffset, val);
1162}
1163
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001164
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001165int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001166 InstanceType type = map()->instance_type();
1167 // Check for the most common kind of JavaScript object before
1168 // falling into the generic switch. This speeds up the internal
1169 // field operations considerably on average.
1170 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1171 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001172 case JS_GLOBAL_PROXY_TYPE:
1173 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001174 case JS_GLOBAL_OBJECT_TYPE:
1175 return JSGlobalObject::kSize;
1176 case JS_BUILTINS_OBJECT_TYPE:
1177 return JSBuiltinsObject::kSize;
1178 case JS_FUNCTION_TYPE:
1179 return JSFunction::kSize;
1180 case JS_VALUE_TYPE:
1181 return JSValue::kSize;
1182 case JS_ARRAY_TYPE:
1183 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001184 case JS_REGEXP_TYPE:
1185 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001186 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001187 return JSObject::kHeaderSize;
1188 default:
1189 UNREACHABLE();
1190 return 0;
1191 }
1192}
1193
1194
1195int JSObject::GetInternalFieldCount() {
1196 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001197 // Make sure to adjust for the number of in-object properties. These
1198 // properties do contribute to the size, but are not internal fields.
1199 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1200 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001201}
1202
1203
1204Object* JSObject::GetInternalField(int index) {
1205 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001206 // Internal objects do follow immediately after the header, whereas in-object
1207 // properties are at the end of the object. Therefore there is no need
1208 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001209 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1210}
1211
1212
1213void JSObject::SetInternalField(int index, Object* value) {
1214 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001215 // Internal objects do follow immediately after the header, whereas in-object
1216 // properties are at the end of the object. Therefore there is no need
1217 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001218 int offset = GetHeaderSize() + (kPointerSize * index);
1219 WRITE_FIELD(this, offset, value);
1220 WRITE_BARRIER(this, offset);
1221}
1222
1223
ager@chromium.org7c537e22008-10-16 08:43:32 +00001224// Access fast-case object properties at index. The use of these routines
1225// is needed to correctly distinguish between properties stored in-object and
1226// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001227Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001228 // Adjust for the number of properties stored in the object.
1229 index -= map()->inobject_properties();
1230 if (index < 0) {
1231 int offset = map()->instance_size() + (index * kPointerSize);
1232 return READ_FIELD(this, offset);
1233 } else {
1234 ASSERT(index < properties()->length());
1235 return properties()->get(index);
1236 }
1237}
1238
1239
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001240Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001241 // Adjust for the number of properties stored in the object.
1242 index -= map()->inobject_properties();
1243 if (index < 0) {
1244 int offset = map()->instance_size() + (index * kPointerSize);
1245 WRITE_FIELD(this, offset, value);
1246 WRITE_BARRIER(this, offset);
1247 } else {
1248 ASSERT(index < properties()->length());
1249 properties()->set(index, value);
1250 }
1251 return value;
1252}
1253
1254
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001255Object* JSObject::InObjectPropertyAt(int index) {
1256 // Adjust for the number of properties stored in the object.
1257 index -= map()->inobject_properties();
1258 ASSERT(index < 0);
1259 int offset = map()->instance_size() + (index * kPointerSize);
1260 return READ_FIELD(this, offset);
1261}
1262
1263
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001264Object* JSObject::InObjectPropertyAtPut(int index,
1265 Object* value,
1266 WriteBarrierMode mode) {
1267 // Adjust for the number of properties stored in the object.
1268 index -= map()->inobject_properties();
1269 ASSERT(index < 0);
1270 int offset = map()->instance_size() + (index * kPointerSize);
1271 WRITE_FIELD(this, offset, value);
1272 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1273 return value;
1274}
1275
1276
1277
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001278void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001279 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001280 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001281 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282 }
1283}
1284
1285
1286void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001287 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001288 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001289 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001290 }
1291}
1292
1293
1294bool JSObject::HasFastProperties() {
1295 return !properties()->IsDictionary();
1296}
1297
1298
1299bool Array::IndexFromObject(Object* object, uint32_t* index) {
1300 if (object->IsSmi()) {
1301 int value = Smi::cast(object)->value();
1302 if (value < 0) return false;
1303 *index = value;
1304 return true;
1305 }
1306 if (object->IsHeapNumber()) {
1307 double value = HeapNumber::cast(object)->value();
1308 uint32_t uint_value = static_cast<uint32_t>(value);
1309 if (value == static_cast<double>(uint_value)) {
1310 *index = uint_value;
1311 return true;
1312 }
1313 }
1314 return false;
1315}
1316
1317
1318bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1319 if (!this->IsJSValue()) return false;
1320
1321 JSValue* js_value = JSValue::cast(this);
1322 if (!js_value->value()->IsString()) return false;
1323
1324 String* str = String::cast(js_value->value());
1325 if (index >= (uint32_t)str->length()) return false;
1326
1327 return true;
1328}
1329
1330
1331Object* FixedArray::get(int index) {
1332 ASSERT(index >= 0 && index < this->length());
1333 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1334}
1335
1336
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001337void FixedArray::set(int index, Smi* value) {
1338 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1339 int offset = kHeaderSize + index * kPointerSize;
1340 WRITE_FIELD(this, offset, value);
1341}
1342
1343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001344void FixedArray::set(int index, Object* value) {
1345 ASSERT(index >= 0 && index < this->length());
1346 int offset = kHeaderSize + index * kPointerSize;
1347 WRITE_FIELD(this, offset, value);
1348 WRITE_BARRIER(this, offset);
1349}
1350
1351
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001352WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1354 return UPDATE_WRITE_BARRIER;
1355}
1356
1357
1358void FixedArray::set(int index,
1359 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001360 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361 ASSERT(index >= 0 && index < this->length());
1362 int offset = kHeaderSize + index * kPointerSize;
1363 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001364 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365}
1366
1367
1368void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1369 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001370 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001371 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1372}
1373
1374
1375void FixedArray::set_undefined(int index) {
1376 ASSERT(index >= 0 && index < this->length());
1377 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1378 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1379 Heap::undefined_value());
1380}
1381
1382
ager@chromium.org236ad962008-09-25 09:45:57 +00001383void FixedArray::set_null(int index) {
1384 ASSERT(index >= 0 && index < this->length());
1385 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1386 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1387}
1388
1389
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001390void FixedArray::set_the_hole(int index) {
1391 ASSERT(index >= 0 && index < this->length());
1392 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1393 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1394}
1395
1396
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001397bool DescriptorArray::IsEmpty() {
1398 ASSERT(this == Heap::empty_descriptor_array() ||
1399 this->length() > 2);
1400 return this == Heap::empty_descriptor_array();
1401}
1402
1403
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001404void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1405 Object* tmp = array->get(first);
1406 fast_set(array, first, array->get(second));
1407 fast_set(array, second, tmp);
1408}
1409
1410
1411int DescriptorArray::Search(String* name) {
1412 SLOW_ASSERT(IsSortedNoDuplicates());
1413
1414 // Check for empty descriptor array.
1415 int nof = number_of_descriptors();
1416 if (nof == 0) return kNotFound;
1417
1418 // Fast case: do linear search for small arrays.
1419 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001420 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001421 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001422 }
1423
1424 // Slow case: perform binary search.
1425 return BinarySearch(name, 0, nof - 1);
1426}
1427
1428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001429String* DescriptorArray::GetKey(int descriptor_number) {
1430 ASSERT(descriptor_number < number_of_descriptors());
1431 return String::cast(get(ToKeyIndex(descriptor_number)));
1432}
1433
1434
1435Object* DescriptorArray::GetValue(int descriptor_number) {
1436 ASSERT(descriptor_number < number_of_descriptors());
1437 return GetContentArray()->get(ToValueIndex(descriptor_number));
1438}
1439
1440
1441Smi* DescriptorArray::GetDetails(int descriptor_number) {
1442 ASSERT(descriptor_number < number_of_descriptors());
1443 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1444}
1445
1446
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001447PropertyType DescriptorArray::GetType(int descriptor_number) {
1448 ASSERT(descriptor_number < number_of_descriptors());
1449 return PropertyDetails(GetDetails(descriptor_number)).type();
1450}
1451
1452
1453int DescriptorArray::GetFieldIndex(int descriptor_number) {
1454 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1455}
1456
1457
1458JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1459 return JSFunction::cast(GetValue(descriptor_number));
1460}
1461
1462
1463Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1464 ASSERT(GetType(descriptor_number) == CALLBACKS);
1465 return GetValue(descriptor_number);
1466}
1467
1468
1469AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1470 ASSERT(GetType(descriptor_number) == CALLBACKS);
1471 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1472 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1473}
1474
1475
1476bool DescriptorArray::IsProperty(int descriptor_number) {
1477 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1478}
1479
1480
1481bool DescriptorArray::IsTransition(int descriptor_number) {
1482 PropertyType t = GetType(descriptor_number);
1483 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1484}
1485
1486
1487bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1488 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1489}
1490
1491
1492bool DescriptorArray::IsDontEnum(int descriptor_number) {
1493 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1494}
1495
1496
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001497void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1498 desc->Init(GetKey(descriptor_number),
1499 GetValue(descriptor_number),
1500 GetDetails(descriptor_number));
1501}
1502
1503
1504void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1505 // Range check.
1506 ASSERT(descriptor_number < number_of_descriptors());
1507
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001508 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001509 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1510 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1511
1512 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1513 FixedArray* content_array = GetContentArray();
1514 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1515 fast_set(content_array, ToDetailsIndex(descriptor_number),
1516 desc->GetDetails().AsSmi());
1517}
1518
1519
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001520void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1521 Descriptor desc;
1522 src->Get(src_index, &desc);
1523 Set(index, &desc);
1524}
1525
1526
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001527void DescriptorArray::Swap(int first, int second) {
1528 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1529 FixedArray* content_array = GetContentArray();
1530 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1531 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1532}
1533
1534
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001535bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001536 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 if (!max_index_object->IsSmi()) return false;
1538 return 0 !=
1539 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1540}
1541
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001542uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001544 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545 if (!max_index_object->IsSmi()) return 0;
1546 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1547 return value >> kRequiresSlowElementsTagSize;
1548}
1549
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001550void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001551 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001552}
1553
1554
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001555// ------------------------------------
1556// Cast operations
1557
1558
1559CAST_ACCESSOR(FixedArray)
1560CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001561CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001562CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001563CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001564CAST_ACCESSOR(String)
1565CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001566CAST_ACCESSOR(SeqAsciiString)
1567CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001568CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001569CAST_ACCESSOR(ExternalString)
1570CAST_ACCESSOR(ExternalAsciiString)
1571CAST_ACCESSOR(ExternalTwoByteString)
1572CAST_ACCESSOR(JSObject)
1573CAST_ACCESSOR(Smi)
1574CAST_ACCESSOR(Failure)
1575CAST_ACCESSOR(HeapObject)
1576CAST_ACCESSOR(HeapNumber)
1577CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001578CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579CAST_ACCESSOR(SharedFunctionInfo)
1580CAST_ACCESSOR(Map)
1581CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001582CAST_ACCESSOR(GlobalObject)
1583CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001584CAST_ACCESSOR(JSGlobalObject)
1585CAST_ACCESSOR(JSBuiltinsObject)
1586CAST_ACCESSOR(Code)
1587CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001588CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589CAST_ACCESSOR(Proxy)
1590CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001591CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001592CAST_ACCESSOR(ExternalArray)
1593CAST_ACCESSOR(ExternalByteArray)
1594CAST_ACCESSOR(ExternalUnsignedByteArray)
1595CAST_ACCESSOR(ExternalShortArray)
1596CAST_ACCESSOR(ExternalUnsignedShortArray)
1597CAST_ACCESSOR(ExternalIntArray)
1598CAST_ACCESSOR(ExternalUnsignedIntArray)
1599CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600CAST_ACCESSOR(Struct)
1601
1602
1603#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1604 STRUCT_LIST(MAKE_STRUCT_CAST)
1605#undef MAKE_STRUCT_CAST
1606
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001607
1608template <typename Shape, typename Key>
1609HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001610 ASSERT(obj->IsHashTable());
1611 return reinterpret_cast<HashTable*>(obj);
1612}
1613
1614
1615INT_ACCESSORS(Array, length, kLengthOffset)
1616
1617
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001618INT_ACCESSORS(String, length, kLengthOffset)
1619
1620
1621uint32_t String::hash_field() {
1622 return READ_UINT32_FIELD(this, kHashFieldOffset);
1623}
1624
1625
1626void String::set_hash_field(uint32_t value) {
1627 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1628}
1629
1630
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001631bool String::Equals(String* other) {
1632 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001633 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1634 return false;
1635 }
1636 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001637}
1638
1639
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001640Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001641 // We don't need to flatten strings that are already flat. Since this code
1642 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001643 if (!IsFlat()) {
1644 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001645 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001646 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001647}
1648
1649
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001650uint16_t String::Get(int index) {
1651 ASSERT(index >= 0 && index < length());
1652 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001653 case kSeqStringTag | kAsciiStringTag:
1654 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1655 case kSeqStringTag | kTwoByteStringTag:
1656 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1657 case kConsStringTag | kAsciiStringTag:
1658 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001659 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001660 case kExternalStringTag | kAsciiStringTag:
1661 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1662 case kExternalStringTag | kTwoByteStringTag:
1663 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664 default:
1665 break;
1666 }
1667
1668 UNREACHABLE();
1669 return 0;
1670}
1671
1672
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001673void String::Set(int index, uint16_t value) {
1674 ASSERT(index >= 0 && index < length());
1675 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676
ager@chromium.org5ec48922009-05-05 07:25:34 +00001677 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001678 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1679 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001680}
1681
1682
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001683bool String::IsFlat() {
1684 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001685 case kConsStringTag: {
1686 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001687 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001688 return second->length() == 0;
1689 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001690 default:
1691 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001692 }
1693}
1694
1695
ager@chromium.org7c537e22008-10-16 08:43:32 +00001696uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001697 ASSERT(index >= 0 && index < length());
1698 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1699}
1700
1701
ager@chromium.org7c537e22008-10-16 08:43:32 +00001702void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1704 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1705 static_cast<byte>(value));
1706}
1707
1708
ager@chromium.org7c537e22008-10-16 08:43:32 +00001709Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001710 return FIELD_ADDR(this, kHeaderSize);
1711}
1712
1713
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001714char* SeqAsciiString::GetChars() {
1715 return reinterpret_cast<char*>(GetCharsAddress());
1716}
1717
1718
ager@chromium.org7c537e22008-10-16 08:43:32 +00001719Address SeqTwoByteString::GetCharsAddress() {
1720 return FIELD_ADDR(this, kHeaderSize);
1721}
1722
1723
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001724uc16* SeqTwoByteString::GetChars() {
1725 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1726}
1727
1728
ager@chromium.org7c537e22008-10-16 08:43:32 +00001729uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730 ASSERT(index >= 0 && index < length());
1731 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1732}
1733
1734
ager@chromium.org7c537e22008-10-16 08:43:32 +00001735void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001736 ASSERT(index >= 0 && index < length());
1737 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1738}
1739
1740
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001741int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001742 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001743 return SizeFor(length);
1744}
1745
1746
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001747int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001748 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749 return SizeFor(length);
1750}
1751
1752
ager@chromium.org870a0b62008-11-04 11:43:05 +00001753String* ConsString::first() {
1754 return String::cast(READ_FIELD(this, kFirstOffset));
1755}
1756
1757
1758Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001759 return READ_FIELD(this, kFirstOffset);
1760}
1761
1762
ager@chromium.org870a0b62008-11-04 11:43:05 +00001763void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001764 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001765 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001766}
1767
1768
ager@chromium.org870a0b62008-11-04 11:43:05 +00001769String* ConsString::second() {
1770 return String::cast(READ_FIELD(this, kSecondOffset));
1771}
1772
1773
1774Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001775 return READ_FIELD(this, kSecondOffset);
1776}
1777
1778
ager@chromium.org870a0b62008-11-04 11:43:05 +00001779void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001780 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001781 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001782}
1783
1784
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001785ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1786 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1787}
1788
1789
1790void ExternalAsciiString::set_resource(
1791 ExternalAsciiString::Resource* resource) {
1792 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1793}
1794
1795
1796ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1797 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1798}
1799
1800
1801void ExternalTwoByteString::set_resource(
1802 ExternalTwoByteString::Resource* resource) {
1803 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1804}
1805
1806
1807byte ByteArray::get(int index) {
1808 ASSERT(index >= 0 && index < this->length());
1809 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1810}
1811
1812
1813void ByteArray::set(int index, byte value) {
1814 ASSERT(index >= 0 && index < this->length());
1815 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1816}
1817
1818
1819int ByteArray::get_int(int index) {
1820 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1821 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1822}
1823
1824
1825ByteArray* ByteArray::FromDataStartAddress(Address address) {
1826 ASSERT_TAG_ALIGNED(address);
1827 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1828}
1829
1830
1831Address ByteArray::GetDataStartAddress() {
1832 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1833}
1834
1835
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001836uint8_t* PixelArray::external_pointer() {
1837 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1838 return reinterpret_cast<uint8_t*>(ptr);
1839}
1840
1841
1842void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1843 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1844 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1845}
1846
1847
1848uint8_t PixelArray::get(int index) {
1849 ASSERT((index >= 0) && (index < this->length()));
1850 uint8_t* ptr = external_pointer();
1851 return ptr[index];
1852}
1853
1854
1855void PixelArray::set(int index, uint8_t value) {
1856 ASSERT((index >= 0) && (index < this->length()));
1857 uint8_t* ptr = external_pointer();
1858 ptr[index] = value;
1859}
1860
1861
ager@chromium.org3811b432009-10-28 14:53:37 +00001862void* ExternalArray::external_pointer() {
1863 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1864 return reinterpret_cast<void*>(ptr);
1865}
1866
1867
1868void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1869 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1870 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1871}
1872
1873
1874int8_t ExternalByteArray::get(int index) {
1875 ASSERT((index >= 0) && (index < this->length()));
1876 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1877 return ptr[index];
1878}
1879
1880
1881void ExternalByteArray::set(int index, int8_t value) {
1882 ASSERT((index >= 0) && (index < this->length()));
1883 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1884 ptr[index] = value;
1885}
1886
1887
1888uint8_t ExternalUnsignedByteArray::get(int index) {
1889 ASSERT((index >= 0) && (index < this->length()));
1890 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1891 return ptr[index];
1892}
1893
1894
1895void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1896 ASSERT((index >= 0) && (index < this->length()));
1897 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1898 ptr[index] = value;
1899}
1900
1901
1902int16_t ExternalShortArray::get(int index) {
1903 ASSERT((index >= 0) && (index < this->length()));
1904 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1905 return ptr[index];
1906}
1907
1908
1909void ExternalShortArray::set(int index, int16_t value) {
1910 ASSERT((index >= 0) && (index < this->length()));
1911 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1912 ptr[index] = value;
1913}
1914
1915
1916uint16_t ExternalUnsignedShortArray::get(int index) {
1917 ASSERT((index >= 0) && (index < this->length()));
1918 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1919 return ptr[index];
1920}
1921
1922
1923void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1924 ASSERT((index >= 0) && (index < this->length()));
1925 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1926 ptr[index] = value;
1927}
1928
1929
1930int32_t ExternalIntArray::get(int index) {
1931 ASSERT((index >= 0) && (index < this->length()));
1932 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1933 return ptr[index];
1934}
1935
1936
1937void ExternalIntArray::set(int index, int32_t value) {
1938 ASSERT((index >= 0) && (index < this->length()));
1939 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1940 ptr[index] = value;
1941}
1942
1943
1944uint32_t ExternalUnsignedIntArray::get(int index) {
1945 ASSERT((index >= 0) && (index < this->length()));
1946 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1947 return ptr[index];
1948}
1949
1950
1951void ExternalUnsignedIntArray::set(int index, uint32_t value) {
1952 ASSERT((index >= 0) && (index < this->length()));
1953 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1954 ptr[index] = value;
1955}
1956
1957
1958float ExternalFloatArray::get(int index) {
1959 ASSERT((index >= 0) && (index < this->length()));
1960 float* ptr = static_cast<float*>(external_pointer());
1961 return ptr[index];
1962}
1963
1964
1965void ExternalFloatArray::set(int index, float value) {
1966 ASSERT((index >= 0) && (index < this->length()));
1967 float* ptr = static_cast<float*>(external_pointer());
1968 ptr[index] = value;
1969}
1970
1971
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001972int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001973 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1974}
1975
1976
1977int Map::inobject_properties() {
1978 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001979}
1980
1981
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001982int Map::pre_allocated_property_fields() {
1983 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1984}
1985
1986
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001987int HeapObject::SizeFromMap(Map* map) {
1988 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001989 // Only inline the most frequent cases.
1990 if (instance_type == JS_OBJECT_TYPE ||
1991 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1992 (kStringTag | kConsStringTag) ||
1993 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001994 if (instance_type == FIXED_ARRAY_TYPE) {
1995 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1996 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001997 if (instance_type == BYTE_ARRAY_TYPE) {
1998 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1999 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002000 // Otherwise do the general size computation.
2001 return SlowSizeFromMap(map);
2002}
2003
2004
2005void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002006 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002007 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002008 ASSERT(0 <= value && value < 256);
2009 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2010}
2011
2012
ager@chromium.org7c537e22008-10-16 08:43:32 +00002013void Map::set_inobject_properties(int value) {
2014 ASSERT(0 <= value && value < 256);
2015 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2016}
2017
2018
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002019void Map::set_pre_allocated_property_fields(int value) {
2020 ASSERT(0 <= value && value < 256);
2021 WRITE_BYTE_FIELD(this,
2022 kPreAllocatedPropertyFieldsOffset,
2023 static_cast<byte>(value));
2024}
2025
2026
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002027InstanceType Map::instance_type() {
2028 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2029}
2030
2031
2032void Map::set_instance_type(InstanceType value) {
2033 ASSERT(0 <= value && value < 256);
2034 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2035}
2036
2037
2038int Map::unused_property_fields() {
2039 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2040}
2041
2042
2043void Map::set_unused_property_fields(int value) {
2044 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2045}
2046
2047
2048byte Map::bit_field() {
2049 return READ_BYTE_FIELD(this, kBitFieldOffset);
2050}
2051
2052
2053void Map::set_bit_field(byte value) {
2054 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2055}
2056
2057
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002058byte Map::bit_field2() {
2059 return READ_BYTE_FIELD(this, kBitField2Offset);
2060}
2061
2062
2063void Map::set_bit_field2(byte value) {
2064 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2065}
2066
2067
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002068void Map::set_non_instance_prototype(bool value) {
2069 if (value) {
2070 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2071 } else {
2072 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2073 }
2074}
2075
2076
2077bool Map::has_non_instance_prototype() {
2078 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2079}
2080
2081
ager@chromium.org870a0b62008-11-04 11:43:05 +00002082void Map::set_is_access_check_needed(bool access_check_needed) {
2083 if (access_check_needed) {
2084 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2085 } else {
2086 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2087 }
2088}
2089
2090
2091bool Map::is_access_check_needed() {
2092 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2093}
2094
2095
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002096Code::Flags Code::flags() {
2097 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2098}
2099
2100
2101void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002102 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002103 // Make sure that all call stubs have an arguments count.
2104 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2105 ExtractArgumentsCountFromFlags(flags) >= 0);
2106 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2107}
2108
2109
2110Code::Kind Code::kind() {
2111 return ExtractKindFromFlags(flags());
2112}
2113
2114
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002115InLoopFlag Code::ic_in_loop() {
2116 return ExtractICInLoopFromFlags(flags());
2117}
2118
2119
kasper.lund7276f142008-07-30 08:49:36 +00002120InlineCacheState Code::ic_state() {
2121 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002122 // Only allow uninitialized or debugger states for non-IC code
2123 // objects. This is used in the debugger to determine whether or not
2124 // a call to code object has been replaced with a debug break call.
2125 ASSERT(is_inline_cache_stub() ||
2126 result == UNINITIALIZED ||
2127 result == DEBUG_BREAK ||
2128 result == DEBUG_PREPARE_STEP_IN);
2129 return result;
2130}
2131
2132
2133PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002134 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002135 return ExtractTypeFromFlags(flags());
2136}
2137
2138
2139int Code::arguments_count() {
2140 ASSERT(is_call_stub() || kind() == STUB);
2141 return ExtractArgumentsCountFromFlags(flags());
2142}
2143
2144
2145CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002146 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002147 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2148 kStubMajorKeyOffset));
2149}
2150
2151
2152void Code::set_major_key(CodeStub::Major major) {
2153 ASSERT(kind() == STUB);
2154 ASSERT(0 <= major && major < 256);
2155 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002156}
2157
2158
2159bool Code::is_inline_cache_stub() {
2160 Kind kind = this->kind();
2161 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2162}
2163
2164
2165Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002166 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002167 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002168 PropertyType type,
2169 int argc) {
2170 // Compute the bit mask.
2171 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002172 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002173 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002174 bits |= type << kFlagsTypeShift;
2175 bits |= argc << kFlagsArgumentsCountShift;
2176 // Cast to flags and validate result before returning it.
2177 Flags result = static_cast<Flags>(bits);
2178 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002179 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002180 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002181 ASSERT(ExtractTypeFromFlags(result) == type);
2182 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2183 return result;
2184}
2185
2186
2187Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2188 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002189 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002190 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002191 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192}
2193
2194
2195Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2196 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2197 return static_cast<Kind>(bits);
2198}
2199
2200
kasper.lund7276f142008-07-30 08:49:36 +00002201InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2202 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002203 return static_cast<InlineCacheState>(bits);
2204}
2205
2206
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002207InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2208 int bits = (flags & kFlagsICInLoopMask);
2209 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2210}
2211
2212
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002213PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2214 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2215 return static_cast<PropertyType>(bits);
2216}
2217
2218
2219int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2220 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2221}
2222
2223
2224Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2225 int bits = flags & ~kFlagsTypeMask;
2226 return static_cast<Flags>(bits);
2227}
2228
2229
ager@chromium.org8bb60582008-12-11 12:02:20 +00002230Code* Code::GetCodeFromTargetAddress(Address address) {
2231 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2232 // GetCodeFromTargetAddress might be called when marking objects during mark
2233 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2234 // Code::cast. Code::cast does not work when the object's map is
2235 // marked.
2236 Code* result = reinterpret_cast<Code*>(code);
2237 return result;
2238}
2239
2240
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002241Object* Map::prototype() {
2242 return READ_FIELD(this, kPrototypeOffset);
2243}
2244
2245
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002246void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002247 ASSERT(value->IsNull() || value->IsJSObject());
2248 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002249 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002250}
2251
2252
2253ACCESSORS(Map, instance_descriptors, DescriptorArray,
2254 kInstanceDescriptorsOffset)
2255ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2256ACCESSORS(Map, constructor, Object, kConstructorOffset)
2257
2258ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2259ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2260
2261ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2262ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002263ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002264
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002265ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002266
2267ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2268ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2269ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2270ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2271ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002272ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002273
2274ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2275ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2276ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2277
2278ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2279ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2280ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2281ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2282ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2283ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2284
2285ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2286ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2287
2288ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2289ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2290
2291ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2292ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002293ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2294 kPropertyAccessorsOffset)
2295ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2296 kPrototypeTemplateOffset)
2297ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2298ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2299 kNamedPropertyHandlerOffset)
2300ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2301 kIndexedPropertyHandlerOffset)
2302ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2303 kInstanceTemplateOffset)
2304ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2305ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002306ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2307 kInstanceCallHandlerOffset)
2308ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2309 kAccessCheckInfoOffset)
2310ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2311
2312ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002313ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2314 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002315
2316ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2317ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2318
2319ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2320
2321ACCESSORS(Script, source, Object, kSourceOffset)
2322ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002323ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002324ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2325ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002326ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002327ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002328ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2329ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002330ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002331ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002332ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002333ACCESSORS(Script, eval_from_instructions_offset, Smi,
2334 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002335
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002336#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002337ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2338ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2339ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2340ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2341
2342ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2343ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2344ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2345ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002346#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002347
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002348ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002349ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2350ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2351 kInstanceClassNameOffset)
2352ACCESSORS(SharedFunctionInfo, function_data, Object,
2353 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002354ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2355ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002356ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002357ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2358 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002359
2360BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2361 kHiddenPrototypeBit)
2362BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2363BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2364 kNeedsAccessCheckBit)
2365BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2366 kIsExpressionBit)
2367BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2368 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002369BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002370 has_only_simple_this_property_assignments,
2371 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002372BOOL_ACCESSORS(SharedFunctionInfo,
2373 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002374 try_full_codegen,
2375 kTryFullCodegen)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002376
2377INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2378INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2379 kFormalParameterCountOffset)
2380INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2381 kExpectedNofPropertiesOffset)
2382INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2383 kStartPositionAndTypeOffset)
2384INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2385INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2386 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002387INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2388 kCompilerHintsOffset)
2389INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2390 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002391
2392
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002393bool Script::HasValidSource() {
2394 Object* src = this->source();
2395 if (!src->IsString()) return true;
2396 String* src_str = String::cast(src);
2397 if (!StringShape(src_str).IsExternal()) return true;
2398 if (src_str->IsAsciiRepresentation()) {
2399 return ExternalAsciiString::cast(src)->resource() != NULL;
2400 } else if (src_str->IsTwoByteRepresentation()) {
2401 return ExternalTwoByteString::cast(src)->resource() != NULL;
2402 }
2403 return true;
2404}
2405
2406
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002407void SharedFunctionInfo::DontAdaptArguments() {
2408 ASSERT(code()->kind() == Code::BUILTIN);
2409 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2410}
2411
2412
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002413int SharedFunctionInfo::start_position() {
2414 return start_position_and_type() >> kStartPositionShift;
2415}
2416
2417
2418void SharedFunctionInfo::set_start_position(int start_position) {
2419 set_start_position_and_type((start_position << kStartPositionShift)
2420 | (start_position_and_type() & ~kStartPositionMask));
2421}
2422
2423
2424Code* SharedFunctionInfo::code() {
2425 return Code::cast(READ_FIELD(this, kCodeOffset));
2426}
2427
2428
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002429void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002430 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002431 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002432}
2433
2434
2435bool SharedFunctionInfo::is_compiled() {
2436 // TODO(1242782): Create a code kind for uncompiled code.
2437 return code()->kind() != Code::STUB;
2438}
2439
2440
2441bool JSFunction::IsBoilerplate() {
2442 return map() == Heap::boilerplate_function_map();
2443}
2444
2445
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002446bool JSFunction::IsBuiltin() {
2447 return context()->global()->IsJSBuiltinsObject();
2448}
2449
2450
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002451bool JSObject::IsLoaded() {
2452 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002453}
2454
2455
2456Code* JSFunction::code() {
2457 return shared()->code();
2458}
2459
2460
2461void JSFunction::set_code(Code* value) {
2462 shared()->set_code(value);
2463}
2464
2465
2466Context* JSFunction::context() {
2467 return Context::cast(READ_FIELD(this, kContextOffset));
2468}
2469
2470
2471Object* JSFunction::unchecked_context() {
2472 return READ_FIELD(this, kContextOffset);
2473}
2474
2475
2476void JSFunction::set_context(Object* value) {
2477 ASSERT(value == Heap::undefined_value() || value->IsContext());
2478 WRITE_FIELD(this, kContextOffset, value);
2479 WRITE_BARRIER(this, kContextOffset);
2480}
2481
2482ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2483 kPrototypeOrInitialMapOffset)
2484
2485
2486Map* JSFunction::initial_map() {
2487 return Map::cast(prototype_or_initial_map());
2488}
2489
2490
2491void JSFunction::set_initial_map(Map* value) {
2492 set_prototype_or_initial_map(value);
2493}
2494
2495
2496bool JSFunction::has_initial_map() {
2497 return prototype_or_initial_map()->IsMap();
2498}
2499
2500
2501bool JSFunction::has_instance_prototype() {
2502 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2503}
2504
2505
2506bool JSFunction::has_prototype() {
2507 return map()->has_non_instance_prototype() || has_instance_prototype();
2508}
2509
2510
2511Object* JSFunction::instance_prototype() {
2512 ASSERT(has_instance_prototype());
2513 if (has_initial_map()) return initial_map()->prototype();
2514 // When there is no initial map and the prototype is a JSObject, the
2515 // initial map field is used for the prototype field.
2516 return prototype_or_initial_map();
2517}
2518
2519
2520Object* JSFunction::prototype() {
2521 ASSERT(has_prototype());
2522 // If the function's prototype property has been set to a non-JSObject
2523 // value, that value is stored in the constructor field of the map.
2524 if (map()->has_non_instance_prototype()) return map()->constructor();
2525 return instance_prototype();
2526}
2527
2528
2529bool JSFunction::is_compiled() {
2530 return shared()->is_compiled();
2531}
2532
2533
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002534int JSFunction::NumberOfLiterals() {
2535 return literals()->length();
2536}
2537
2538
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002539Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2540 ASSERT(0 <= id && id < kJSBuiltinsCount);
2541 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2542}
2543
2544
2545void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2546 Object* value) {
2547 ASSERT(0 <= id && id < kJSBuiltinsCount);
2548 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2549 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2550}
2551
2552
2553Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002554 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002555}
2556
2557
2558void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002559 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002560}
2561
2562
2563void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2564 visitor->VisitExternalReference(
2565 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2566}
2567
2568
2569ACCESSORS(JSValue, value, Object, kValueOffset)
2570
2571
2572JSValue* JSValue::cast(Object* obj) {
2573 ASSERT(obj->IsJSValue());
2574 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2575 return reinterpret_cast<JSValue*>(obj);
2576}
2577
2578
2579INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2580INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2581INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2582
2583
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002584byte* Code::instruction_start() {
2585 return FIELD_ADDR(this, kHeaderSize);
2586}
2587
2588
2589int Code::body_size() {
2590 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2591}
2592
2593
2594byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002595 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002596}
2597
2598
2599byte* Code::entry() {
2600 return instruction_start();
2601}
2602
2603
2604bool Code::contains(byte* pc) {
2605 return (instruction_start() <= pc) &&
2606 (pc < instruction_start() + instruction_size());
2607}
2608
2609
2610byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002611 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002612}
2613
2614
2615ACCESSORS(JSArray, length, Object, kLengthOffset)
2616
2617
ager@chromium.org236ad962008-09-25 09:45:57 +00002618ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002619
2620
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002621JSRegExp::Type JSRegExp::TypeTag() {
2622 Object* data = this->data();
2623 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2624 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2625 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002626}
2627
2628
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002629int JSRegExp::CaptureCount() {
2630 switch (TypeTag()) {
2631 case ATOM:
2632 return 0;
2633 case IRREGEXP:
2634 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2635 default:
2636 UNREACHABLE();
2637 return -1;
2638 }
2639}
2640
2641
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002642JSRegExp::Flags JSRegExp::GetFlags() {
2643 ASSERT(this->data()->IsFixedArray());
2644 Object* data = this->data();
2645 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2646 return Flags(smi->value());
2647}
2648
2649
2650String* JSRegExp::Pattern() {
2651 ASSERT(this->data()->IsFixedArray());
2652 Object* data = this->data();
2653 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2654 return pattern;
2655}
2656
2657
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002658Object* JSRegExp::DataAt(int index) {
2659 ASSERT(TypeTag() != NOT_COMPILED);
2660 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002661}
2662
2663
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002664void JSRegExp::SetDataAt(int index, Object* value) {
2665 ASSERT(TypeTag() != NOT_COMPILED);
2666 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2667 FixedArray::cast(data())->set(index, value);
2668}
2669
2670
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002671JSObject::ElementsKind JSObject::GetElementsKind() {
2672 Array* array = elements();
2673 if (array->IsFixedArray()) {
2674 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2675 if (array->map() == Heap::fixed_array_map()) {
2676 return FAST_ELEMENTS;
2677 }
2678 ASSERT(array->IsDictionary());
2679 return DICTIONARY_ELEMENTS;
2680 }
ager@chromium.org3811b432009-10-28 14:53:37 +00002681 if (array->IsExternalArray()) {
2682 switch (array->map()->instance_type()) {
2683 case EXTERNAL_BYTE_ARRAY_TYPE:
2684 return EXTERNAL_BYTE_ELEMENTS;
2685 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2686 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2687 case EXTERNAL_SHORT_ARRAY_TYPE:
2688 return EXTERNAL_SHORT_ELEMENTS;
2689 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2690 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2691 case EXTERNAL_INT_ARRAY_TYPE:
2692 return EXTERNAL_INT_ELEMENTS;
2693 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2694 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2695 default:
2696 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2697 return EXTERNAL_FLOAT_ELEMENTS;
2698 }
2699 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002700 ASSERT(array->IsPixelArray());
2701 return PIXEL_ELEMENTS;
2702}
2703
2704
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002705bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002706 return GetElementsKind() == FAST_ELEMENTS;
2707}
2708
2709
2710bool JSObject::HasDictionaryElements() {
2711 return GetElementsKind() == DICTIONARY_ELEMENTS;
2712}
2713
2714
2715bool JSObject::HasPixelElements() {
2716 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002717}
2718
2719
ager@chromium.org3811b432009-10-28 14:53:37 +00002720bool JSObject::HasExternalArrayElements() {
2721 return (HasExternalByteElements() ||
2722 HasExternalUnsignedByteElements() ||
2723 HasExternalShortElements() ||
2724 HasExternalUnsignedShortElements() ||
2725 HasExternalIntElements() ||
2726 HasExternalUnsignedIntElements() ||
2727 HasExternalFloatElements());
2728}
2729
2730
2731bool JSObject::HasExternalByteElements() {
2732 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2733}
2734
2735
2736bool JSObject::HasExternalUnsignedByteElements() {
2737 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2738}
2739
2740
2741bool JSObject::HasExternalShortElements() {
2742 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2743}
2744
2745
2746bool JSObject::HasExternalUnsignedShortElements() {
2747 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2748}
2749
2750
2751bool JSObject::HasExternalIntElements() {
2752 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2753}
2754
2755
2756bool JSObject::HasExternalUnsignedIntElements() {
2757 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2758}
2759
2760
2761bool JSObject::HasExternalFloatElements() {
2762 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2763}
2764
2765
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002766bool JSObject::HasNamedInterceptor() {
2767 return map()->has_named_interceptor();
2768}
2769
2770
2771bool JSObject::HasIndexedInterceptor() {
2772 return map()->has_indexed_interceptor();
2773}
2774
2775
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002776StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002777 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002778 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002779}
2780
2781
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002782NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002783 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002784 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002785}
2786
2787
2788bool String::HasHashCode() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002789 return (hash_field() & kHashComputedMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002790}
2791
2792
2793uint32_t String::Hash() {
2794 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002795 uint32_t field = hash_field();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002796 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002797 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002798 return ComputeAndSetHash();
2799}
2800
2801
ager@chromium.org7c537e22008-10-16 08:43:32 +00002802StringHasher::StringHasher(int length)
2803 : length_(length),
2804 raw_running_hash_(0),
2805 array_index_(0),
2806 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2807 is_first_char_(true),
2808 is_valid_(true) { }
2809
2810
2811bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002812 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00002813}
2814
2815
2816void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002817 // Use the Jenkins one-at-a-time hash function to update the hash
2818 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002819 raw_running_hash_ += c;
2820 raw_running_hash_ += (raw_running_hash_ << 10);
2821 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002822 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002823 if (is_array_index_) {
2824 if (c < '0' || c > '9') {
2825 is_array_index_ = false;
2826 } else {
2827 int d = c - '0';
2828 if (is_first_char_) {
2829 is_first_char_ = false;
2830 if (c == '0' && length_ > 1) {
2831 is_array_index_ = false;
2832 return;
2833 }
2834 }
2835 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2836 is_array_index_ = false;
2837 } else {
2838 array_index_ = array_index_ * 10 + d;
2839 }
2840 }
2841 }
2842}
2843
2844
2845void StringHasher::AddCharacterNoIndex(uc32 c) {
2846 ASSERT(!is_array_index());
2847 raw_running_hash_ += c;
2848 raw_running_hash_ += (raw_running_hash_ << 10);
2849 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2850}
2851
2852
2853uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002854 // Get the calculated raw hash value and do some more bit ops to distribute
2855 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002856 uint32_t result = raw_running_hash_;
2857 result += (result << 3);
2858 result ^= (result >> 11);
2859 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002860 if (result == 0) {
2861 result = 27;
2862 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002863 return result;
2864}
2865
2866
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002867bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002868 uint32_t field = hash_field();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002869 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002870 return SlowAsArrayIndex(index);
2871}
2872
2873
2874Object* JSObject::GetPrototype() {
2875 return JSObject::cast(this)->map()->prototype();
2876}
2877
2878
2879PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2880 return GetPropertyAttributeWithReceiver(this, key);
2881}
2882
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002883// TODO(504): this may be useful in other places too where JSGlobalProxy
2884// is used.
2885Object* JSObject::BypassGlobalProxy() {
2886 if (IsJSGlobalProxy()) {
2887 Object* proto = GetPrototype();
2888 if (proto->IsNull()) return Heap::undefined_value();
2889 ASSERT(proto->IsJSGlobalObject());
2890 return proto;
2891 }
2892 return this;
2893}
2894
2895
2896bool JSObject::HasHiddenPropertiesObject() {
2897 ASSERT(!IsJSGlobalProxy());
2898 return GetPropertyAttributePostInterceptor(this,
2899 Heap::hidden_symbol(),
2900 false) != ABSENT;
2901}
2902
2903
2904Object* JSObject::GetHiddenPropertiesObject() {
2905 ASSERT(!IsJSGlobalProxy());
2906 PropertyAttributes attributes;
2907 return GetLocalPropertyPostInterceptor(this,
2908 Heap::hidden_symbol(),
2909 &attributes);
2910}
2911
2912
2913Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
2914 ASSERT(!IsJSGlobalProxy());
2915 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
2916 hidden_obj,
2917 DONT_ENUM);
2918}
2919
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002920
2921bool JSObject::HasElement(uint32_t index) {
2922 return HasElementWithReceiver(this, index);
2923}
2924
2925
2926bool AccessorInfo::all_can_read() {
2927 return BooleanBit::get(flag(), kAllCanReadBit);
2928}
2929
2930
2931void AccessorInfo::set_all_can_read(bool value) {
2932 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2933}
2934
2935
2936bool AccessorInfo::all_can_write() {
2937 return BooleanBit::get(flag(), kAllCanWriteBit);
2938}
2939
2940
2941void AccessorInfo::set_all_can_write(bool value) {
2942 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2943}
2944
2945
ager@chromium.org870a0b62008-11-04 11:43:05 +00002946bool AccessorInfo::prohibits_overwriting() {
2947 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2948}
2949
2950
2951void AccessorInfo::set_prohibits_overwriting(bool value) {
2952 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2953}
2954
2955
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002956PropertyAttributes AccessorInfo::property_attributes() {
2957 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2958}
2959
2960
2961void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2962 ASSERT(AttributesField::is_valid(attributes));
2963 int rest_value = flag()->value() & ~AttributesField::mask();
2964 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2965}
2966
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002967template<typename Shape, typename Key>
2968void Dictionary<Shape, Key>::SetEntry(int entry,
2969 Object* key,
2970 Object* value,
2971 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002972 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002973 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002974 AssertNoAllocation no_gc;
2975 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002976 FixedArray::set(index, key, mode);
2977 FixedArray::set(index+1, value, mode);
2978 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002979}
2980
2981
2982void Map::ClearCodeCache() {
2983 // No write barrier is needed since empty_fixed_array is not in new space.
2984 // Please note this function is used during marking:
2985 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002986 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2987 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002988}
2989
2990
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002991void JSArray::EnsureSize(int required_size) {
2992 ASSERT(HasFastElements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00002993 Array* elts = elements();
2994 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
2995 if (elts->length() < required_size) {
2996 // Doubling in size would be overkill, but leave some slack to avoid
2997 // constantly growing.
2998 Expand(required_size + (required_size >> 3));
2999 // It's a performance benefit to keep a frequently used array in new-space.
3000 } else if (!Heap::new_space()->Contains(elts) &&
3001 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3002 // Expand will allocate a new backing store in new space even if the size
3003 // we asked for isn't larger than what we had before.
3004 Expand(required_size);
3005 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003006}
3007
3008
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003009void JSArray::set_length(Smi* length) {
3010 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3011}
3012
3013
ager@chromium.org7c537e22008-10-16 08:43:32 +00003014void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003015 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003016 set_elements(storage);
3017}
3018
3019
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003020Object* FixedArray::Copy() {
3021 if (length() == 0) return this;
3022 return Heap::CopyFixedArray(this);
3023}
3024
3025
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003026#undef CAST_ACCESSOR
3027#undef INT_ACCESSORS
3028#undef SMI_ACCESSORS
3029#undef ACCESSORS
3030#undef FIELD_ADDR
3031#undef READ_FIELD
3032#undef WRITE_FIELD
3033#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003034#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003035#undef READ_MEMADDR_FIELD
3036#undef WRITE_MEMADDR_FIELD
3037#undef READ_DOUBLE_FIELD
3038#undef WRITE_DOUBLE_FIELD
3039#undef READ_INT_FIELD
3040#undef WRITE_INT_FIELD
3041#undef READ_SHORT_FIELD
3042#undef WRITE_SHORT_FIELD
3043#undef READ_BYTE_FIELD
3044#undef WRITE_BYTE_FIELD
3045
3046
3047} } // namespace v8::internal
3048
3049#endif // V8_OBJECTS_INL_H_