blob: 3003342460aaf9f6aa8c24fb8aeba1972a4a301e [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
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001352WriteBarrierMode HeapObject::GetWriteBarrierMode() {
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());
1370 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1371}
1372
1373
1374void FixedArray::set_undefined(int index) {
1375 ASSERT(index >= 0 && index < this->length());
1376 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1377 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1378 Heap::undefined_value());
1379}
1380
1381
ager@chromium.org236ad962008-09-25 09:45:57 +00001382void FixedArray::set_null(int index) {
1383 ASSERT(index >= 0 && index < this->length());
1384 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1385 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1386}
1387
1388
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389void FixedArray::set_the_hole(int index) {
1390 ASSERT(index >= 0 && index < this->length());
1391 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1392 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1393}
1394
1395
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001396bool DescriptorArray::IsEmpty() {
1397 ASSERT(this == Heap::empty_descriptor_array() ||
1398 this->length() > 2);
1399 return this == Heap::empty_descriptor_array();
1400}
1401
1402
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001403void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1404 Object* tmp = array->get(first);
1405 fast_set(array, first, array->get(second));
1406 fast_set(array, second, tmp);
1407}
1408
1409
1410int DescriptorArray::Search(String* name) {
1411 SLOW_ASSERT(IsSortedNoDuplicates());
1412
1413 // Check for empty descriptor array.
1414 int nof = number_of_descriptors();
1415 if (nof == 0) return kNotFound;
1416
1417 // Fast case: do linear search for small arrays.
1418 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001419 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001420 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001421 }
1422
1423 // Slow case: perform binary search.
1424 return BinarySearch(name, 0, nof - 1);
1425}
1426
1427
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001428String* DescriptorArray::GetKey(int descriptor_number) {
1429 ASSERT(descriptor_number < number_of_descriptors());
1430 return String::cast(get(ToKeyIndex(descriptor_number)));
1431}
1432
1433
1434Object* DescriptorArray::GetValue(int descriptor_number) {
1435 ASSERT(descriptor_number < number_of_descriptors());
1436 return GetContentArray()->get(ToValueIndex(descriptor_number));
1437}
1438
1439
1440Smi* DescriptorArray::GetDetails(int descriptor_number) {
1441 ASSERT(descriptor_number < number_of_descriptors());
1442 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1443}
1444
1445
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001446PropertyType DescriptorArray::GetType(int descriptor_number) {
1447 ASSERT(descriptor_number < number_of_descriptors());
1448 return PropertyDetails(GetDetails(descriptor_number)).type();
1449}
1450
1451
1452int DescriptorArray::GetFieldIndex(int descriptor_number) {
1453 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1454}
1455
1456
1457JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1458 return JSFunction::cast(GetValue(descriptor_number));
1459}
1460
1461
1462Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1463 ASSERT(GetType(descriptor_number) == CALLBACKS);
1464 return GetValue(descriptor_number);
1465}
1466
1467
1468AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1469 ASSERT(GetType(descriptor_number) == CALLBACKS);
1470 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1471 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1472}
1473
1474
1475bool DescriptorArray::IsProperty(int descriptor_number) {
1476 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1477}
1478
1479
1480bool DescriptorArray::IsTransition(int descriptor_number) {
1481 PropertyType t = GetType(descriptor_number);
1482 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1483}
1484
1485
1486bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1487 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1488}
1489
1490
1491bool DescriptorArray::IsDontEnum(int descriptor_number) {
1492 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1493}
1494
1495
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001496void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1497 desc->Init(GetKey(descriptor_number),
1498 GetValue(descriptor_number),
1499 GetDetails(descriptor_number));
1500}
1501
1502
1503void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1504 // Range check.
1505 ASSERT(descriptor_number < number_of_descriptors());
1506
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001507 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001508 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1509 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1510
1511 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1512 FixedArray* content_array = GetContentArray();
1513 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1514 fast_set(content_array, ToDetailsIndex(descriptor_number),
1515 desc->GetDetails().AsSmi());
1516}
1517
1518
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001519void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1520 Descriptor desc;
1521 src->Get(src_index, &desc);
1522 Set(index, &desc);
1523}
1524
1525
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001526void DescriptorArray::Swap(int first, int second) {
1527 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1528 FixedArray* content_array = GetContentArray();
1529 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1530 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1531}
1532
1533
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001534bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001535 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001536 if (!max_index_object->IsSmi()) return false;
1537 return 0 !=
1538 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1539}
1540
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001541uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001542 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001543 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001544 if (!max_index_object->IsSmi()) return 0;
1545 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1546 return value >> kRequiresSlowElementsTagSize;
1547}
1548
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001549void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001550 set(kMaxNumberKeyIndex,
1551 Smi::FromInt(kRequiresSlowElementsMask),
1552 SKIP_WRITE_BARRIER);
1553}
1554
1555
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556// ------------------------------------
1557// Cast operations
1558
1559
1560CAST_ACCESSOR(FixedArray)
1561CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001562CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001563CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001564CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001565CAST_ACCESSOR(String)
1566CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001567CAST_ACCESSOR(SeqAsciiString)
1568CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001569CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570CAST_ACCESSOR(ExternalString)
1571CAST_ACCESSOR(ExternalAsciiString)
1572CAST_ACCESSOR(ExternalTwoByteString)
1573CAST_ACCESSOR(JSObject)
1574CAST_ACCESSOR(Smi)
1575CAST_ACCESSOR(Failure)
1576CAST_ACCESSOR(HeapObject)
1577CAST_ACCESSOR(HeapNumber)
1578CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001579CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580CAST_ACCESSOR(SharedFunctionInfo)
1581CAST_ACCESSOR(Map)
1582CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001583CAST_ACCESSOR(GlobalObject)
1584CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585CAST_ACCESSOR(JSGlobalObject)
1586CAST_ACCESSOR(JSBuiltinsObject)
1587CAST_ACCESSOR(Code)
1588CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001589CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001590CAST_ACCESSOR(Proxy)
1591CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001592CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001593CAST_ACCESSOR(ExternalArray)
1594CAST_ACCESSOR(ExternalByteArray)
1595CAST_ACCESSOR(ExternalUnsignedByteArray)
1596CAST_ACCESSOR(ExternalShortArray)
1597CAST_ACCESSOR(ExternalUnsignedShortArray)
1598CAST_ACCESSOR(ExternalIntArray)
1599CAST_ACCESSOR(ExternalUnsignedIntArray)
1600CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001601CAST_ACCESSOR(Struct)
1602
1603
1604#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1605 STRUCT_LIST(MAKE_STRUCT_CAST)
1606#undef MAKE_STRUCT_CAST
1607
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001608
1609template <typename Shape, typename Key>
1610HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611 ASSERT(obj->IsHashTable());
1612 return reinterpret_cast<HashTable*>(obj);
1613}
1614
1615
1616INT_ACCESSORS(Array, length, kLengthOffset)
1617
1618
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001619INT_ACCESSORS(String, length, kLengthOffset)
1620
1621
1622uint32_t String::hash_field() {
1623 return READ_UINT32_FIELD(this, kHashFieldOffset);
1624}
1625
1626
1627void String::set_hash_field(uint32_t value) {
1628 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1629}
1630
1631
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001632bool String::Equals(String* other) {
1633 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001634 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1635 return false;
1636 }
1637 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638}
1639
1640
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001641Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001642 // We don't need to flatten strings that are already flat. Since this code
1643 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001644 if (!IsFlat()) {
1645 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001646 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001647 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648}
1649
1650
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001651uint16_t String::Get(int index) {
1652 ASSERT(index >= 0 && index < length());
1653 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001654 case kSeqStringTag | kAsciiStringTag:
1655 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1656 case kSeqStringTag | kTwoByteStringTag:
1657 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1658 case kConsStringTag | kAsciiStringTag:
1659 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001660 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001661 case kExternalStringTag | kAsciiStringTag:
1662 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1663 case kExternalStringTag | kTwoByteStringTag:
1664 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001665 default:
1666 break;
1667 }
1668
1669 UNREACHABLE();
1670 return 0;
1671}
1672
1673
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001674void String::Set(int index, uint16_t value) {
1675 ASSERT(index >= 0 && index < length());
1676 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001677
ager@chromium.org5ec48922009-05-05 07:25:34 +00001678 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001679 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1680 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001681}
1682
1683
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001684bool String::IsFlat() {
1685 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001686 case kConsStringTag: {
1687 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001688 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001689 return second->length() == 0;
1690 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001691 default:
1692 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001693 }
1694}
1695
1696
ager@chromium.org7c537e22008-10-16 08:43:32 +00001697uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001698 ASSERT(index >= 0 && index < length());
1699 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1700}
1701
1702
ager@chromium.org7c537e22008-10-16 08:43:32 +00001703void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001704 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1705 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1706 static_cast<byte>(value));
1707}
1708
1709
ager@chromium.org7c537e22008-10-16 08:43:32 +00001710Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001711 return FIELD_ADDR(this, kHeaderSize);
1712}
1713
1714
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001715char* SeqAsciiString::GetChars() {
1716 return reinterpret_cast<char*>(GetCharsAddress());
1717}
1718
1719
ager@chromium.org7c537e22008-10-16 08:43:32 +00001720Address SeqTwoByteString::GetCharsAddress() {
1721 return FIELD_ADDR(this, kHeaderSize);
1722}
1723
1724
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001725uc16* SeqTwoByteString::GetChars() {
1726 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1727}
1728
1729
ager@chromium.org7c537e22008-10-16 08:43:32 +00001730uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001731 ASSERT(index >= 0 && index < length());
1732 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1733}
1734
1735
ager@chromium.org7c537e22008-10-16 08:43:32 +00001736void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001737 ASSERT(index >= 0 && index < length());
1738 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1739}
1740
1741
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001742int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001743 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744 return SizeFor(length);
1745}
1746
1747
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001748int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001750 return SizeFor(length);
1751}
1752
1753
ager@chromium.org870a0b62008-11-04 11:43:05 +00001754String* ConsString::first() {
1755 return String::cast(READ_FIELD(this, kFirstOffset));
1756}
1757
1758
1759Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001760 return READ_FIELD(this, kFirstOffset);
1761}
1762
1763
ager@chromium.org870a0b62008-11-04 11:43:05 +00001764void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001765 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001766 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001767}
1768
1769
ager@chromium.org870a0b62008-11-04 11:43:05 +00001770String* ConsString::second() {
1771 return String::cast(READ_FIELD(this, kSecondOffset));
1772}
1773
1774
1775Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001776 return READ_FIELD(this, kSecondOffset);
1777}
1778
1779
ager@chromium.org870a0b62008-11-04 11:43:05 +00001780void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001781 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001782 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001783}
1784
1785
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001786ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1787 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1788}
1789
1790
1791void ExternalAsciiString::set_resource(
1792 ExternalAsciiString::Resource* resource) {
1793 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1794}
1795
1796
1797ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1798 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1799}
1800
1801
1802void ExternalTwoByteString::set_resource(
1803 ExternalTwoByteString::Resource* resource) {
1804 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1805}
1806
1807
1808byte ByteArray::get(int index) {
1809 ASSERT(index >= 0 && index < this->length());
1810 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1811}
1812
1813
1814void ByteArray::set(int index, byte value) {
1815 ASSERT(index >= 0 && index < this->length());
1816 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1817}
1818
1819
1820int ByteArray::get_int(int index) {
1821 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1822 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1823}
1824
1825
1826ByteArray* ByteArray::FromDataStartAddress(Address address) {
1827 ASSERT_TAG_ALIGNED(address);
1828 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1829}
1830
1831
1832Address ByteArray::GetDataStartAddress() {
1833 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1834}
1835
1836
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001837uint8_t* PixelArray::external_pointer() {
1838 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1839 return reinterpret_cast<uint8_t*>(ptr);
1840}
1841
1842
1843void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1844 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1845 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1846}
1847
1848
1849uint8_t PixelArray::get(int index) {
1850 ASSERT((index >= 0) && (index < this->length()));
1851 uint8_t* ptr = external_pointer();
1852 return ptr[index];
1853}
1854
1855
1856void PixelArray::set(int index, uint8_t value) {
1857 ASSERT((index >= 0) && (index < this->length()));
1858 uint8_t* ptr = external_pointer();
1859 ptr[index] = value;
1860}
1861
1862
ager@chromium.org3811b432009-10-28 14:53:37 +00001863void* ExternalArray::external_pointer() {
1864 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1865 return reinterpret_cast<void*>(ptr);
1866}
1867
1868
1869void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1870 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1871 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1872}
1873
1874
1875int8_t ExternalByteArray::get(int index) {
1876 ASSERT((index >= 0) && (index < this->length()));
1877 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1878 return ptr[index];
1879}
1880
1881
1882void ExternalByteArray::set(int index, int8_t value) {
1883 ASSERT((index >= 0) && (index < this->length()));
1884 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1885 ptr[index] = value;
1886}
1887
1888
1889uint8_t ExternalUnsignedByteArray::get(int index) {
1890 ASSERT((index >= 0) && (index < this->length()));
1891 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1892 return ptr[index];
1893}
1894
1895
1896void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1897 ASSERT((index >= 0) && (index < this->length()));
1898 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1899 ptr[index] = value;
1900}
1901
1902
1903int16_t ExternalShortArray::get(int index) {
1904 ASSERT((index >= 0) && (index < this->length()));
1905 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1906 return ptr[index];
1907}
1908
1909
1910void ExternalShortArray::set(int index, int16_t value) {
1911 ASSERT((index >= 0) && (index < this->length()));
1912 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1913 ptr[index] = value;
1914}
1915
1916
1917uint16_t ExternalUnsignedShortArray::get(int index) {
1918 ASSERT((index >= 0) && (index < this->length()));
1919 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1920 return ptr[index];
1921}
1922
1923
1924void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1925 ASSERT((index >= 0) && (index < this->length()));
1926 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1927 ptr[index] = value;
1928}
1929
1930
1931int32_t ExternalIntArray::get(int index) {
1932 ASSERT((index >= 0) && (index < this->length()));
1933 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1934 return ptr[index];
1935}
1936
1937
1938void ExternalIntArray::set(int index, int32_t value) {
1939 ASSERT((index >= 0) && (index < this->length()));
1940 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1941 ptr[index] = value;
1942}
1943
1944
1945uint32_t ExternalUnsignedIntArray::get(int index) {
1946 ASSERT((index >= 0) && (index < this->length()));
1947 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1948 return ptr[index];
1949}
1950
1951
1952void ExternalUnsignedIntArray::set(int index, uint32_t value) {
1953 ASSERT((index >= 0) && (index < this->length()));
1954 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1955 ptr[index] = value;
1956}
1957
1958
1959float ExternalFloatArray::get(int index) {
1960 ASSERT((index >= 0) && (index < this->length()));
1961 float* ptr = static_cast<float*>(external_pointer());
1962 return ptr[index];
1963}
1964
1965
1966void ExternalFloatArray::set(int index, float value) {
1967 ASSERT((index >= 0) && (index < this->length()));
1968 float* ptr = static_cast<float*>(external_pointer());
1969 ptr[index] = value;
1970}
1971
1972
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001973int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001974 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1975}
1976
1977
1978int Map::inobject_properties() {
1979 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001980}
1981
1982
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001983int Map::pre_allocated_property_fields() {
1984 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1985}
1986
1987
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001988int HeapObject::SizeFromMap(Map* map) {
1989 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001990 // Only inline the most frequent cases.
1991 if (instance_type == JS_OBJECT_TYPE ||
1992 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1993 (kStringTag | kConsStringTag) ||
1994 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995 if (instance_type == FIXED_ARRAY_TYPE) {
1996 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1997 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001998 if (instance_type == BYTE_ARRAY_TYPE) {
1999 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2000 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002001 // Otherwise do the general size computation.
2002 return SlowSizeFromMap(map);
2003}
2004
2005
2006void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002007 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002008 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002009 ASSERT(0 <= value && value < 256);
2010 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2011}
2012
2013
ager@chromium.org7c537e22008-10-16 08:43:32 +00002014void Map::set_inobject_properties(int value) {
2015 ASSERT(0 <= value && value < 256);
2016 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2017}
2018
2019
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002020void Map::set_pre_allocated_property_fields(int value) {
2021 ASSERT(0 <= value && value < 256);
2022 WRITE_BYTE_FIELD(this,
2023 kPreAllocatedPropertyFieldsOffset,
2024 static_cast<byte>(value));
2025}
2026
2027
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002028InstanceType Map::instance_type() {
2029 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2030}
2031
2032
2033void Map::set_instance_type(InstanceType value) {
2034 ASSERT(0 <= value && value < 256);
2035 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2036}
2037
2038
2039int Map::unused_property_fields() {
2040 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2041}
2042
2043
2044void Map::set_unused_property_fields(int value) {
2045 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2046}
2047
2048
2049byte Map::bit_field() {
2050 return READ_BYTE_FIELD(this, kBitFieldOffset);
2051}
2052
2053
2054void Map::set_bit_field(byte value) {
2055 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2056}
2057
2058
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002059byte Map::bit_field2() {
2060 return READ_BYTE_FIELD(this, kBitField2Offset);
2061}
2062
2063
2064void Map::set_bit_field2(byte value) {
2065 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2066}
2067
2068
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002069void Map::set_non_instance_prototype(bool value) {
2070 if (value) {
2071 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2072 } else {
2073 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2074 }
2075}
2076
2077
2078bool Map::has_non_instance_prototype() {
2079 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2080}
2081
2082
ager@chromium.org870a0b62008-11-04 11:43:05 +00002083void Map::set_is_access_check_needed(bool access_check_needed) {
2084 if (access_check_needed) {
2085 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2086 } else {
2087 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2088 }
2089}
2090
2091
2092bool Map::is_access_check_needed() {
2093 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2094}
2095
2096
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002097Code::Flags Code::flags() {
2098 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2099}
2100
2101
2102void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002103 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002104 // Make sure that all call stubs have an arguments count.
2105 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2106 ExtractArgumentsCountFromFlags(flags) >= 0);
2107 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2108}
2109
2110
2111Code::Kind Code::kind() {
2112 return ExtractKindFromFlags(flags());
2113}
2114
2115
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002116InLoopFlag Code::ic_in_loop() {
2117 return ExtractICInLoopFromFlags(flags());
2118}
2119
2120
kasper.lund7276f142008-07-30 08:49:36 +00002121InlineCacheState Code::ic_state() {
2122 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002123 // Only allow uninitialized or debugger states for non-IC code
2124 // objects. This is used in the debugger to determine whether or not
2125 // a call to code object has been replaced with a debug break call.
2126 ASSERT(is_inline_cache_stub() ||
2127 result == UNINITIALIZED ||
2128 result == DEBUG_BREAK ||
2129 result == DEBUG_PREPARE_STEP_IN);
2130 return result;
2131}
2132
2133
2134PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002135 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002136 return ExtractTypeFromFlags(flags());
2137}
2138
2139
2140int Code::arguments_count() {
2141 ASSERT(is_call_stub() || kind() == STUB);
2142 return ExtractArgumentsCountFromFlags(flags());
2143}
2144
2145
2146CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002147 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002148 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2149 kStubMajorKeyOffset));
2150}
2151
2152
2153void Code::set_major_key(CodeStub::Major major) {
2154 ASSERT(kind() == STUB);
2155 ASSERT(0 <= major && major < 256);
2156 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002157}
2158
2159
2160bool Code::is_inline_cache_stub() {
2161 Kind kind = this->kind();
2162 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2163}
2164
2165
2166Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002167 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002168 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002169 PropertyType type,
2170 int argc) {
2171 // Compute the bit mask.
2172 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002173 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002174 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002175 bits |= type << kFlagsTypeShift;
2176 bits |= argc << kFlagsArgumentsCountShift;
2177 // Cast to flags and validate result before returning it.
2178 Flags result = static_cast<Flags>(bits);
2179 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002180 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002181 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002182 ASSERT(ExtractTypeFromFlags(result) == type);
2183 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2184 return result;
2185}
2186
2187
2188Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2189 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002190 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002191 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002192 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002193}
2194
2195
2196Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2197 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2198 return static_cast<Kind>(bits);
2199}
2200
2201
kasper.lund7276f142008-07-30 08:49:36 +00002202InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2203 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002204 return static_cast<InlineCacheState>(bits);
2205}
2206
2207
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002208InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2209 int bits = (flags & kFlagsICInLoopMask);
2210 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2211}
2212
2213
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002214PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2215 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2216 return static_cast<PropertyType>(bits);
2217}
2218
2219
2220int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2221 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2222}
2223
2224
2225Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2226 int bits = flags & ~kFlagsTypeMask;
2227 return static_cast<Flags>(bits);
2228}
2229
2230
ager@chromium.org8bb60582008-12-11 12:02:20 +00002231Code* Code::GetCodeFromTargetAddress(Address address) {
2232 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2233 // GetCodeFromTargetAddress might be called when marking objects during mark
2234 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2235 // Code::cast. Code::cast does not work when the object's map is
2236 // marked.
2237 Code* result = reinterpret_cast<Code*>(code);
2238 return result;
2239}
2240
2241
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002242Object* Map::prototype() {
2243 return READ_FIELD(this, kPrototypeOffset);
2244}
2245
2246
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002247void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002248 ASSERT(value->IsNull() || value->IsJSObject());
2249 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002250 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002251}
2252
2253
2254ACCESSORS(Map, instance_descriptors, DescriptorArray,
2255 kInstanceDescriptorsOffset)
2256ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2257ACCESSORS(Map, constructor, Object, kConstructorOffset)
2258
2259ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2260ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2261
2262ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2263ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002264ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002265
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002266ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002267
2268ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2269ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2270ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2271ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2272ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002273ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002274
2275ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2276ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2277ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2278
2279ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2280ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2281ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2282ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2283ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2284ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2285
2286ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2287ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2288
2289ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2290ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2291
2292ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2293ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002294ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2295 kPropertyAccessorsOffset)
2296ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2297 kPrototypeTemplateOffset)
2298ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2299ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2300 kNamedPropertyHandlerOffset)
2301ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2302 kIndexedPropertyHandlerOffset)
2303ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2304 kInstanceTemplateOffset)
2305ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2306ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002307ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2308 kInstanceCallHandlerOffset)
2309ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2310 kAccessCheckInfoOffset)
2311ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2312
2313ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002314ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2315 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002316
2317ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2318ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2319
2320ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2321
2322ACCESSORS(Script, source, Object, kSourceOffset)
2323ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002324ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002325ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2326ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002327ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002328ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002329ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2330ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002331ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002332ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002333ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002334ACCESSORS(Script, eval_from_instructions_offset, Smi,
2335 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002336
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002337#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002338ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2339ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2340ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2341ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2342
2343ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2344ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2345ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2346ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002347#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002348
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002349ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002350ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2351ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2352 kInstanceClassNameOffset)
2353ACCESSORS(SharedFunctionInfo, function_data, Object,
2354 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002355ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2356ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002357ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002358ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2359 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002360
2361BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2362 kHiddenPrototypeBit)
2363BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2364BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2365 kNeedsAccessCheckBit)
2366BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2367 kIsExpressionBit)
2368BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2369 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002370BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002371 has_only_simple_this_property_assignments,
2372 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002373BOOL_ACCESSORS(SharedFunctionInfo,
2374 compiler_hints,
2375 try_fast_codegen,
2376 kTryFastCodegen)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002377
2378INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2379INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2380 kFormalParameterCountOffset)
2381INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2382 kExpectedNofPropertiesOffset)
2383INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2384 kStartPositionAndTypeOffset)
2385INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2386INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2387 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002388INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2389 kCompilerHintsOffset)
2390INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2391 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002392
2393
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002394bool Script::HasValidSource() {
2395 Object* src = this->source();
2396 if (!src->IsString()) return true;
2397 String* src_str = String::cast(src);
2398 if (!StringShape(src_str).IsExternal()) return true;
2399 if (src_str->IsAsciiRepresentation()) {
2400 return ExternalAsciiString::cast(src)->resource() != NULL;
2401 } else if (src_str->IsTwoByteRepresentation()) {
2402 return ExternalTwoByteString::cast(src)->resource() != NULL;
2403 }
2404 return true;
2405}
2406
2407
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002408void SharedFunctionInfo::DontAdaptArguments() {
2409 ASSERT(code()->kind() == Code::BUILTIN);
2410 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2411}
2412
2413
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002414int SharedFunctionInfo::start_position() {
2415 return start_position_and_type() >> kStartPositionShift;
2416}
2417
2418
2419void SharedFunctionInfo::set_start_position(int start_position) {
2420 set_start_position_and_type((start_position << kStartPositionShift)
2421 | (start_position_and_type() & ~kStartPositionMask));
2422}
2423
2424
2425Code* SharedFunctionInfo::code() {
2426 return Code::cast(READ_FIELD(this, kCodeOffset));
2427}
2428
2429
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002430void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002431 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002432 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002433}
2434
2435
2436bool SharedFunctionInfo::is_compiled() {
2437 // TODO(1242782): Create a code kind for uncompiled code.
2438 return code()->kind() != Code::STUB;
2439}
2440
2441
2442bool JSFunction::IsBoilerplate() {
2443 return map() == Heap::boilerplate_function_map();
2444}
2445
2446
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002447bool JSFunction::IsBuiltin() {
2448 return context()->global()->IsJSBuiltinsObject();
2449}
2450
2451
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002452bool JSObject::IsLoaded() {
2453 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002454}
2455
2456
2457Code* JSFunction::code() {
2458 return shared()->code();
2459}
2460
2461
2462void JSFunction::set_code(Code* value) {
2463 shared()->set_code(value);
2464}
2465
2466
2467Context* JSFunction::context() {
2468 return Context::cast(READ_FIELD(this, kContextOffset));
2469}
2470
2471
2472Object* JSFunction::unchecked_context() {
2473 return READ_FIELD(this, kContextOffset);
2474}
2475
2476
2477void JSFunction::set_context(Object* value) {
2478 ASSERT(value == Heap::undefined_value() || value->IsContext());
2479 WRITE_FIELD(this, kContextOffset, value);
2480 WRITE_BARRIER(this, kContextOffset);
2481}
2482
2483ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2484 kPrototypeOrInitialMapOffset)
2485
2486
2487Map* JSFunction::initial_map() {
2488 return Map::cast(prototype_or_initial_map());
2489}
2490
2491
2492void JSFunction::set_initial_map(Map* value) {
2493 set_prototype_or_initial_map(value);
2494}
2495
2496
2497bool JSFunction::has_initial_map() {
2498 return prototype_or_initial_map()->IsMap();
2499}
2500
2501
2502bool JSFunction::has_instance_prototype() {
2503 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2504}
2505
2506
2507bool JSFunction::has_prototype() {
2508 return map()->has_non_instance_prototype() || has_instance_prototype();
2509}
2510
2511
2512Object* JSFunction::instance_prototype() {
2513 ASSERT(has_instance_prototype());
2514 if (has_initial_map()) return initial_map()->prototype();
2515 // When there is no initial map and the prototype is a JSObject, the
2516 // initial map field is used for the prototype field.
2517 return prototype_or_initial_map();
2518}
2519
2520
2521Object* JSFunction::prototype() {
2522 ASSERT(has_prototype());
2523 // If the function's prototype property has been set to a non-JSObject
2524 // value, that value is stored in the constructor field of the map.
2525 if (map()->has_non_instance_prototype()) return map()->constructor();
2526 return instance_prototype();
2527}
2528
2529
2530bool JSFunction::is_compiled() {
2531 return shared()->is_compiled();
2532}
2533
2534
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002535int JSFunction::NumberOfLiterals() {
2536 return literals()->length();
2537}
2538
2539
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002540Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2541 ASSERT(0 <= id && id < kJSBuiltinsCount);
2542 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2543}
2544
2545
2546void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2547 Object* value) {
2548 ASSERT(0 <= id && id < kJSBuiltinsCount);
2549 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2550 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2551}
2552
2553
2554Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002555 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002556}
2557
2558
2559void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002560 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002561}
2562
2563
2564void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2565 visitor->VisitExternalReference(
2566 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2567}
2568
2569
2570ACCESSORS(JSValue, value, Object, kValueOffset)
2571
2572
2573JSValue* JSValue::cast(Object* obj) {
2574 ASSERT(obj->IsJSValue());
2575 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2576 return reinterpret_cast<JSValue*>(obj);
2577}
2578
2579
2580INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2581INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2582INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2583
2584
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002585byte* Code::instruction_start() {
2586 return FIELD_ADDR(this, kHeaderSize);
2587}
2588
2589
2590int Code::body_size() {
2591 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2592}
2593
2594
2595byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002596 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002597}
2598
2599
2600byte* Code::entry() {
2601 return instruction_start();
2602}
2603
2604
2605bool Code::contains(byte* pc) {
2606 return (instruction_start() <= pc) &&
2607 (pc < instruction_start() + instruction_size());
2608}
2609
2610
2611byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002612 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002613}
2614
2615
2616ACCESSORS(JSArray, length, Object, kLengthOffset)
2617
2618
ager@chromium.org236ad962008-09-25 09:45:57 +00002619ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002620
2621
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002622JSRegExp::Type JSRegExp::TypeTag() {
2623 Object* data = this->data();
2624 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2625 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2626 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002627}
2628
2629
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002630int JSRegExp::CaptureCount() {
2631 switch (TypeTag()) {
2632 case ATOM:
2633 return 0;
2634 case IRREGEXP:
2635 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2636 default:
2637 UNREACHABLE();
2638 return -1;
2639 }
2640}
2641
2642
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002643JSRegExp::Flags JSRegExp::GetFlags() {
2644 ASSERT(this->data()->IsFixedArray());
2645 Object* data = this->data();
2646 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2647 return Flags(smi->value());
2648}
2649
2650
2651String* JSRegExp::Pattern() {
2652 ASSERT(this->data()->IsFixedArray());
2653 Object* data = this->data();
2654 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2655 return pattern;
2656}
2657
2658
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002659Object* JSRegExp::DataAt(int index) {
2660 ASSERT(TypeTag() != NOT_COMPILED);
2661 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002662}
2663
2664
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002665void JSRegExp::SetDataAt(int index, Object* value) {
2666 ASSERT(TypeTag() != NOT_COMPILED);
2667 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2668 FixedArray::cast(data())->set(index, value);
2669}
2670
2671
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002672JSObject::ElementsKind JSObject::GetElementsKind() {
2673 Array* array = elements();
2674 if (array->IsFixedArray()) {
2675 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2676 if (array->map() == Heap::fixed_array_map()) {
2677 return FAST_ELEMENTS;
2678 }
2679 ASSERT(array->IsDictionary());
2680 return DICTIONARY_ELEMENTS;
2681 }
ager@chromium.org3811b432009-10-28 14:53:37 +00002682 if (array->IsExternalArray()) {
2683 switch (array->map()->instance_type()) {
2684 case EXTERNAL_BYTE_ARRAY_TYPE:
2685 return EXTERNAL_BYTE_ELEMENTS;
2686 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2687 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2688 case EXTERNAL_SHORT_ARRAY_TYPE:
2689 return EXTERNAL_SHORT_ELEMENTS;
2690 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2691 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2692 case EXTERNAL_INT_ARRAY_TYPE:
2693 return EXTERNAL_INT_ELEMENTS;
2694 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2695 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2696 default:
2697 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2698 return EXTERNAL_FLOAT_ELEMENTS;
2699 }
2700 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002701 ASSERT(array->IsPixelArray());
2702 return PIXEL_ELEMENTS;
2703}
2704
2705
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002706bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002707 return GetElementsKind() == FAST_ELEMENTS;
2708}
2709
2710
2711bool JSObject::HasDictionaryElements() {
2712 return GetElementsKind() == DICTIONARY_ELEMENTS;
2713}
2714
2715
2716bool JSObject::HasPixelElements() {
2717 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002718}
2719
2720
ager@chromium.org3811b432009-10-28 14:53:37 +00002721bool JSObject::HasExternalArrayElements() {
2722 return (HasExternalByteElements() ||
2723 HasExternalUnsignedByteElements() ||
2724 HasExternalShortElements() ||
2725 HasExternalUnsignedShortElements() ||
2726 HasExternalIntElements() ||
2727 HasExternalUnsignedIntElements() ||
2728 HasExternalFloatElements());
2729}
2730
2731
2732bool JSObject::HasExternalByteElements() {
2733 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2734}
2735
2736
2737bool JSObject::HasExternalUnsignedByteElements() {
2738 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2739}
2740
2741
2742bool JSObject::HasExternalShortElements() {
2743 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2744}
2745
2746
2747bool JSObject::HasExternalUnsignedShortElements() {
2748 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2749}
2750
2751
2752bool JSObject::HasExternalIntElements() {
2753 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2754}
2755
2756
2757bool JSObject::HasExternalUnsignedIntElements() {
2758 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2759}
2760
2761
2762bool JSObject::HasExternalFloatElements() {
2763 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2764}
2765
2766
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002767bool JSObject::HasNamedInterceptor() {
2768 return map()->has_named_interceptor();
2769}
2770
2771
2772bool JSObject::HasIndexedInterceptor() {
2773 return map()->has_indexed_interceptor();
2774}
2775
2776
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002777StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002778 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002779 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002780}
2781
2782
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002783NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002784 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002785 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002786}
2787
2788
2789bool String::HasHashCode() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002790 return (hash_field() & kHashComputedMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002791}
2792
2793
2794uint32_t String::Hash() {
2795 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002796 uint32_t field = hash_field();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002797 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002798 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002799 return ComputeAndSetHash();
2800}
2801
2802
ager@chromium.org7c537e22008-10-16 08:43:32 +00002803StringHasher::StringHasher(int length)
2804 : length_(length),
2805 raw_running_hash_(0),
2806 array_index_(0),
2807 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2808 is_first_char_(true),
2809 is_valid_(true) { }
2810
2811
2812bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002813 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00002814}
2815
2816
2817void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002818 // Use the Jenkins one-at-a-time hash function to update the hash
2819 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002820 raw_running_hash_ += c;
2821 raw_running_hash_ += (raw_running_hash_ << 10);
2822 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002823 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002824 if (is_array_index_) {
2825 if (c < '0' || c > '9') {
2826 is_array_index_ = false;
2827 } else {
2828 int d = c - '0';
2829 if (is_first_char_) {
2830 is_first_char_ = false;
2831 if (c == '0' && length_ > 1) {
2832 is_array_index_ = false;
2833 return;
2834 }
2835 }
2836 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2837 is_array_index_ = false;
2838 } else {
2839 array_index_ = array_index_ * 10 + d;
2840 }
2841 }
2842 }
2843}
2844
2845
2846void StringHasher::AddCharacterNoIndex(uc32 c) {
2847 ASSERT(!is_array_index());
2848 raw_running_hash_ += c;
2849 raw_running_hash_ += (raw_running_hash_ << 10);
2850 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2851}
2852
2853
2854uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002855 // Get the calculated raw hash value and do some more bit ops to distribute
2856 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002857 uint32_t result = raw_running_hash_;
2858 result += (result << 3);
2859 result ^= (result >> 11);
2860 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002861 if (result == 0) {
2862 result = 27;
2863 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002864 return result;
2865}
2866
2867
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002868bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002869 uint32_t field = hash_field();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002870 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002871 return SlowAsArrayIndex(index);
2872}
2873
2874
2875Object* JSObject::GetPrototype() {
2876 return JSObject::cast(this)->map()->prototype();
2877}
2878
2879
2880PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2881 return GetPropertyAttributeWithReceiver(this, key);
2882}
2883
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002884// TODO(504): this may be useful in other places too where JSGlobalProxy
2885// is used.
2886Object* JSObject::BypassGlobalProxy() {
2887 if (IsJSGlobalProxy()) {
2888 Object* proto = GetPrototype();
2889 if (proto->IsNull()) return Heap::undefined_value();
2890 ASSERT(proto->IsJSGlobalObject());
2891 return proto;
2892 }
2893 return this;
2894}
2895
2896
2897bool JSObject::HasHiddenPropertiesObject() {
2898 ASSERT(!IsJSGlobalProxy());
2899 return GetPropertyAttributePostInterceptor(this,
2900 Heap::hidden_symbol(),
2901 false) != ABSENT;
2902}
2903
2904
2905Object* JSObject::GetHiddenPropertiesObject() {
2906 ASSERT(!IsJSGlobalProxy());
2907 PropertyAttributes attributes;
2908 return GetLocalPropertyPostInterceptor(this,
2909 Heap::hidden_symbol(),
2910 &attributes);
2911}
2912
2913
2914Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
2915 ASSERT(!IsJSGlobalProxy());
2916 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
2917 hidden_obj,
2918 DONT_ENUM);
2919}
2920
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002921
2922bool JSObject::HasElement(uint32_t index) {
2923 return HasElementWithReceiver(this, index);
2924}
2925
2926
2927bool AccessorInfo::all_can_read() {
2928 return BooleanBit::get(flag(), kAllCanReadBit);
2929}
2930
2931
2932void AccessorInfo::set_all_can_read(bool value) {
2933 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2934}
2935
2936
2937bool AccessorInfo::all_can_write() {
2938 return BooleanBit::get(flag(), kAllCanWriteBit);
2939}
2940
2941
2942void AccessorInfo::set_all_can_write(bool value) {
2943 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2944}
2945
2946
ager@chromium.org870a0b62008-11-04 11:43:05 +00002947bool AccessorInfo::prohibits_overwriting() {
2948 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2949}
2950
2951
2952void AccessorInfo::set_prohibits_overwriting(bool value) {
2953 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2954}
2955
2956
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002957PropertyAttributes AccessorInfo::property_attributes() {
2958 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2959}
2960
2961
2962void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2963 ASSERT(AttributesField::is_valid(attributes));
2964 int rest_value = flag()->value() & ~AttributesField::mask();
2965 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2966}
2967
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002968template<typename Shape, typename Key>
2969void Dictionary<Shape, Key>::SetEntry(int entry,
2970 Object* key,
2971 Object* value,
2972 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002973 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002974 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2975 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2976 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
ager@chromium.org7c537e22008-10-16 08:43:32 +00003009void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003010 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00003011 set_elements(storage);
3012}
3013
3014
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003015Object* FixedArray::Copy() {
3016 if (length() == 0) return this;
3017 return Heap::CopyFixedArray(this);
3018}
3019
3020
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003021#undef CAST_ACCESSOR
3022#undef INT_ACCESSORS
3023#undef SMI_ACCESSORS
3024#undef ACCESSORS
3025#undef FIELD_ADDR
3026#undef READ_FIELD
3027#undef WRITE_FIELD
3028#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003029#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003030#undef READ_MEMADDR_FIELD
3031#undef WRITE_MEMADDR_FIELD
3032#undef READ_DOUBLE_FIELD
3033#undef WRITE_DOUBLE_FIELD
3034#undef READ_INT_FIELD
3035#undef WRITE_INT_FIELD
3036#undef READ_SHORT_FIELD
3037#undef WRITE_SHORT_FIELD
3038#undef READ_BYTE_FIELD
3039#undef WRITE_BYTE_FIELD
3040
3041
3042} } // namespace v8::internal
3043
3044#endif // V8_OBJECTS_INL_H_