blob: 101096d6c9a21c49fc5b9dde6823853f830c8507 [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 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000241}
242
243
ager@chromium.org5ec48922009-05-05 07:25:34 +0000244bool String::IsTwoByteRepresentation() {
245 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000246 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000247}
248
249
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000250bool String::HasOnlyAsciiChars() {
251 uint32_t type = map()->instance_type();
252 return (type & kStringEncodingMask) == kAsciiStringTag ||
253 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000254}
255
256
ager@chromium.org870a0b62008-11-04 11:43:05 +0000257bool StringShape::IsCons() {
258 return (type_ & kStringRepresentationMask) == kConsStringTag;
259}
260
261
ager@chromium.org870a0b62008-11-04 11:43:05 +0000262bool StringShape::IsExternal() {
263 return (type_ & kStringRepresentationMask) == kExternalStringTag;
264}
265
266
267bool StringShape::IsSequential() {
268 return (type_ & kStringRepresentationMask) == kSeqStringTag;
269}
270
271
272StringRepresentationTag StringShape::representation_tag() {
273 uint32_t tag = (type_ & kStringRepresentationMask);
274 return static_cast<StringRepresentationTag>(tag);
275}
276
277
278uint32_t StringShape::full_representation_tag() {
279 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
280}
281
282
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000283STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
284 Internals::kFullStringRepresentationMask);
285
286
ager@chromium.org870a0b62008-11-04 11:43:05 +0000287bool StringShape::IsSequentialAscii() {
288 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
289}
290
291
292bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000293 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000294}
295
296
297bool StringShape::IsExternalAscii() {
298 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
299}
300
301
302bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000303 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000304}
305
306
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000307STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
308 Internals::kExternalTwoByteRepresentationTag);
309
310
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000311uc32 FlatStringReader::Get(int index) {
312 ASSERT(0 <= index && index <= length_);
313 if (is_ascii_) {
314 return static_cast<const byte*>(start_)[index];
315 } else {
316 return static_cast<const uc16*>(start_)[index];
317 }
318}
319
320
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321bool Object::IsNumber() {
322 return IsSmi() || IsHeapNumber();
323}
324
325
326bool Object::IsByteArray() {
327 return Object::IsHeapObject()
328 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
329}
330
331
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000332bool Object::IsPixelArray() {
333 return Object::IsHeapObject() &&
334 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
335}
336
337
ager@chromium.org3811b432009-10-28 14:53:37 +0000338bool Object::IsExternalArray() {
339 if (!Object::IsHeapObject())
340 return false;
341 InstanceType instance_type =
342 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000343 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
344 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000345}
346
347
348bool Object::IsExternalByteArray() {
349 return Object::IsHeapObject() &&
350 HeapObject::cast(this)->map()->instance_type() ==
351 EXTERNAL_BYTE_ARRAY_TYPE;
352}
353
354
355bool Object::IsExternalUnsignedByteArray() {
356 return Object::IsHeapObject() &&
357 HeapObject::cast(this)->map()->instance_type() ==
358 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
359}
360
361
362bool Object::IsExternalShortArray() {
363 return Object::IsHeapObject() &&
364 HeapObject::cast(this)->map()->instance_type() ==
365 EXTERNAL_SHORT_ARRAY_TYPE;
366}
367
368
369bool Object::IsExternalUnsignedShortArray() {
370 return Object::IsHeapObject() &&
371 HeapObject::cast(this)->map()->instance_type() ==
372 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
373}
374
375
376bool Object::IsExternalIntArray() {
377 return Object::IsHeapObject() &&
378 HeapObject::cast(this)->map()->instance_type() ==
379 EXTERNAL_INT_ARRAY_TYPE;
380}
381
382
383bool Object::IsExternalUnsignedIntArray() {
384 return Object::IsHeapObject() &&
385 HeapObject::cast(this)->map()->instance_type() ==
386 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
387}
388
389
390bool Object::IsExternalFloatArray() {
391 return Object::IsHeapObject() &&
392 HeapObject::cast(this)->map()->instance_type() ==
393 EXTERNAL_FLOAT_ARRAY_TYPE;
394}
395
396
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397bool Object::IsFailure() {
398 return HAS_FAILURE_TAG(this);
399}
400
401
402bool Object::IsRetryAfterGC() {
403 return HAS_FAILURE_TAG(this)
404 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
405}
406
407
ager@chromium.org7c537e22008-10-16 08:43:32 +0000408bool Object::IsOutOfMemoryFailure() {
409 return HAS_FAILURE_TAG(this)
410 && Failure::cast(this)->IsOutOfMemoryException();
411}
412
413
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000414bool Object::IsException() {
415 return this == Failure::Exception();
416}
417
418
419bool Object::IsJSObject() {
420 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000421 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000422}
423
424
ager@chromium.org32912102009-01-16 10:38:43 +0000425bool Object::IsJSContextExtensionObject() {
426 return IsHeapObject()
427 && (HeapObject::cast(this)->map()->instance_type() ==
428 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
429}
430
431
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432bool Object::IsMap() {
433 return Object::IsHeapObject()
434 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
435}
436
437
438bool Object::IsFixedArray() {
439 return Object::IsHeapObject()
440 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
441}
442
443
444bool Object::IsDescriptorArray() {
445 return IsFixedArray();
446}
447
448
449bool Object::IsContext() {
450 return Object::IsHeapObject()
451 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000452 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000453 HeapObject::cast(this)->map() == Heap::global_context_map());
454}
455
456
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000457bool Object::IsCatchContext() {
458 return Object::IsHeapObject()
459 && HeapObject::cast(this)->map() == Heap::catch_context_map();
460}
461
462
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000463bool Object::IsGlobalContext() {
464 return Object::IsHeapObject()
465 && HeapObject::cast(this)->map() == Heap::global_context_map();
466}
467
468
469bool Object::IsJSFunction() {
470 return Object::IsHeapObject()
471 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
472}
473
474
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000475template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000476 return obj->IsJSFunction();
477}
478
479
480bool Object::IsCode() {
481 return Object::IsHeapObject()
482 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
483}
484
485
486bool Object::IsOddball() {
487 return Object::IsHeapObject()
488 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
489}
490
491
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000492bool Object::IsJSGlobalPropertyCell() {
493 return Object::IsHeapObject()
494 && HeapObject::cast(this)->map()->instance_type()
495 == JS_GLOBAL_PROPERTY_CELL_TYPE;
496}
497
498
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499bool Object::IsSharedFunctionInfo() {
500 return Object::IsHeapObject() &&
501 (HeapObject::cast(this)->map()->instance_type() ==
502 SHARED_FUNCTION_INFO_TYPE);
503}
504
505
506bool Object::IsJSValue() {
507 return Object::IsHeapObject()
508 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
509}
510
511
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000512bool Object::IsStringWrapper() {
513 return IsJSValue() && JSValue::cast(this)->value()->IsString();
514}
515
516
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517bool Object::IsProxy() {
518 return Object::IsHeapObject()
519 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
520}
521
522
523bool Object::IsBoolean() {
524 return IsTrue() || IsFalse();
525}
526
527
528bool Object::IsJSArray() {
529 return Object::IsHeapObject()
530 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
531}
532
533
ager@chromium.org236ad962008-09-25 09:45:57 +0000534bool Object::IsJSRegExp() {
535 return Object::IsHeapObject()
536 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
537}
538
539
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000540template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000541 return obj->IsJSArray();
542}
543
544
545bool Object::IsHashTable() {
546 return Object::IsHeapObject()
547 && HeapObject::cast(this)->map() == Heap::hash_table_map();
548}
549
550
551bool Object::IsDictionary() {
552 return IsHashTable() && this != Heap::symbol_table();
553}
554
555
556bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000557 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558}
559
560
ager@chromium.orgac091b72010-05-05 07:34:42 +0000561bool Object::IsJSFunctionResultCache() {
562 if (!IsFixedArray()) return false;
563 FixedArray* self = FixedArray::cast(this);
564 int length = self->length();
565 if (length < JSFunctionResultCache::kEntriesIndex) return false;
566 if ((length - JSFunctionResultCache::kEntriesIndex)
567 % JSFunctionResultCache::kEntrySize != 0) {
568 return false;
569 }
570#ifdef DEBUG
571 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
572#endif
573 return true;
574}
575
576
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000577bool Object::IsCompilationCacheTable() {
578 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000579}
580
581
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000582bool Object::IsCodeCacheHashTable() {
583 return IsHashTable();
584}
585
586
ager@chromium.org236ad962008-09-25 09:45:57 +0000587bool Object::IsMapCache() {
588 return IsHashTable();
589}
590
591
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592bool Object::IsPrimitive() {
593 return IsOddball() || IsNumber() || IsString();
594}
595
596
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000597bool Object::IsJSGlobalProxy() {
598 bool result = IsHeapObject() &&
599 (HeapObject::cast(this)->map()->instance_type() ==
600 JS_GLOBAL_PROXY_TYPE);
601 ASSERT(!result || IsAccessCheckNeeded());
602 return result;
603}
604
605
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000607 if (!IsHeapObject()) return false;
608
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000609 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000610 return type == JS_GLOBAL_OBJECT_TYPE ||
611 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612}
613
614
615bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616 return IsHeapObject() &&
617 (HeapObject::cast(this)->map()->instance_type() ==
618 JS_GLOBAL_OBJECT_TYPE);
619}
620
621
622bool Object::IsJSBuiltinsObject() {
623 return IsHeapObject() &&
624 (HeapObject::cast(this)->map()->instance_type() ==
625 JS_BUILTINS_OBJECT_TYPE);
626}
627
628
629bool Object::IsUndetectableObject() {
630 return IsHeapObject()
631 && HeapObject::cast(this)->map()->is_undetectable();
632}
633
634
635bool Object::IsAccessCheckNeeded() {
636 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000637 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000638}
639
640
641bool Object::IsStruct() {
642 if (!IsHeapObject()) return false;
643 switch (HeapObject::cast(this)->map()->instance_type()) {
644#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
645 STRUCT_LIST(MAKE_STRUCT_CASE)
646#undef MAKE_STRUCT_CASE
647 default: return false;
648 }
649}
650
651
652#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
653 bool Object::Is##Name() { \
654 return Object::IsHeapObject() \
655 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
656 }
657 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
658#undef MAKE_STRUCT_PREDICATE
659
660
661bool Object::IsUndefined() {
662 return this == Heap::undefined_value();
663}
664
665
666bool Object::IsTheHole() {
667 return this == Heap::the_hole_value();
668}
669
670
671bool Object::IsNull() {
672 return this == Heap::null_value();
673}
674
675
676bool Object::IsTrue() {
677 return this == Heap::true_value();
678}
679
680
681bool Object::IsFalse() {
682 return this == Heap::false_value();
683}
684
685
686double Object::Number() {
687 ASSERT(IsNumber());
688 return IsSmi()
689 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
690 : reinterpret_cast<HeapNumber*>(this)->value();
691}
692
693
694
695Object* Object::ToSmi() {
696 if (IsSmi()) return this;
697 if (IsHeapNumber()) {
698 double value = HeapNumber::cast(this)->value();
699 int int_value = FastD2I(value);
700 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
701 return Smi::FromInt(int_value);
702 }
703 }
704 return Failure::Exception();
705}
706
707
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000708bool Object::HasSpecificClassOf(String* name) {
709 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
710}
711
712
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713Object* Object::GetElement(uint32_t index) {
714 return GetElementWithReceiver(this, index);
715}
716
717
718Object* Object::GetProperty(String* key) {
719 PropertyAttributes attributes;
720 return GetPropertyWithReceiver(this, key, &attributes);
721}
722
723
724Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
725 return GetPropertyWithReceiver(this, key, attributes);
726}
727
728
729#define FIELD_ADDR(p, offset) \
730 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
731
732#define READ_FIELD(p, offset) \
733 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
734
735#define WRITE_FIELD(p, offset, value) \
736 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
737
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000738
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739#define WRITE_BARRIER(object, offset) \
740 Heap::RecordWrite(object->address(), offset);
741
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000742// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000743// write due to the assert validating the written value.
744#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
745 if (mode == UPDATE_WRITE_BARRIER) { \
746 Heap::RecordWrite(object->address(), offset); \
747 } else { \
748 ASSERT(mode == SKIP_WRITE_BARRIER); \
749 ASSERT(Heap::InNewSpace(object) || \
kmillikin@chromium.orgb8dc8eb2010-04-01 07:13:38 +0000750 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000751 Page::FromAddress(object->address())-> \
752 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000753 }
754
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755#define READ_DOUBLE_FIELD(p, offset) \
756 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
757
758#define WRITE_DOUBLE_FIELD(p, offset, value) \
759 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
760
761#define READ_INT_FIELD(p, offset) \
762 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
763
764#define WRITE_INT_FIELD(p, offset, value) \
765 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
766
ager@chromium.org3e875802009-06-29 08:26:34 +0000767#define READ_INTPTR_FIELD(p, offset) \
768 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
769
770#define WRITE_INTPTR_FIELD(p, offset, value) \
771 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
772
ager@chromium.org7c537e22008-10-16 08:43:32 +0000773#define READ_UINT32_FIELD(p, offset) \
774 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
775
776#define WRITE_UINT32_FIELD(p, offset, value) \
777 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
778
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000779#define READ_SHORT_FIELD(p, offset) \
780 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
781
782#define WRITE_SHORT_FIELD(p, offset, value) \
783 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
784
785#define READ_BYTE_FIELD(p, offset) \
786 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
787
788#define WRITE_BYTE_FIELD(p, offset, value) \
789 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
790
791
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000792Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
793 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794}
795
796
797int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000798 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799}
800
801
802Smi* Smi::FromInt(int value) {
803 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000804 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000805 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000806 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000807 return reinterpret_cast<Smi*>(tagged_value);
808}
809
810
811Smi* Smi::FromIntptr(intptr_t value) {
812 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000813 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
814 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815}
816
817
818Failure::Type Failure::type() const {
819 return static_cast<Type>(value() & kFailureTypeTagMask);
820}
821
822
823bool Failure::IsInternalError() const {
824 return type() == INTERNAL_ERROR;
825}
826
827
828bool Failure::IsOutOfMemoryException() const {
829 return type() == OUT_OF_MEMORY_EXCEPTION;
830}
831
832
833int Failure::requested() const {
834 const int kShiftBits =
835 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
836 STATIC_ASSERT(kShiftBits >= 0);
837 ASSERT(type() == RETRY_AFTER_GC);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000838 return static_cast<int>(value() >> kShiftBits);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839}
840
841
842AllocationSpace Failure::allocation_space() const {
843 ASSERT_EQ(RETRY_AFTER_GC, type());
844 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
845 & kSpaceTagMask);
846}
847
848
849Failure* Failure::InternalError() {
850 return Construct(INTERNAL_ERROR);
851}
852
853
854Failure* Failure::Exception() {
855 return Construct(EXCEPTION);
856}
857
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000858
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000859Failure* Failure::OutOfMemoryException() {
860 return Construct(OUT_OF_MEMORY_EXCEPTION);
861}
862
863
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000864intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000865 return static_cast<intptr_t>(
866 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867}
868
869
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000870Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000871 // Assert that the space encoding fits in the three bytes allotted for it.
872 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000873 uintptr_t requested =
874 static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
875 int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000876 if (((requested << tag_bits) >> tag_bits) != requested) {
877 // No room for entire requested size in the bits. Round down to
878 // maximally representable size.
879 requested = static_cast<intptr_t>(
880 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
881 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000882 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000883 return Construct(RETRY_AFTER_GC, value);
884}
885
886
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000887Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000888 uintptr_t info =
889 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000890 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000891 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892}
893
894
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000895bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896#ifdef DEBUG
897 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
898#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000899
900#ifdef V8_TARGET_ARCH_X64
901 // To be representable as a long smi, the value must be a 32-bit integer.
902 bool result = (value == static_cast<int32_t>(value));
903#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000904 // To be representable as an tagged small integer, the two
905 // most-significant bits of 'value' must be either 00 or 11 due to
906 // sign-extension. To check this we add 01 to the two
907 // most-significant bits, and check if the most-significant bit is 0
908 //
909 // CAUTION: The original code below:
910 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
911 // may lead to incorrect results according to the C language spec, and
912 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
913 // compiler may produce undefined results in case of signed integer
914 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000915 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000916#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000917 ASSERT(result == in_range);
918 return result;
919}
920
921
kasper.lund7276f142008-07-30 08:49:36 +0000922MapWord MapWord::FromMap(Map* map) {
923 return MapWord(reinterpret_cast<uintptr_t>(map));
924}
925
926
927Map* MapWord::ToMap() {
928 return reinterpret_cast<Map*>(value_);
929}
930
931
932bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000933 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000934}
935
936
937MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000938 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
939 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000940}
941
942
943HeapObject* MapWord::ToForwardingAddress() {
944 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000945 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000946}
947
948
949bool MapWord::IsMarked() {
950 return (value_ & kMarkingMask) == 0;
951}
952
953
954void MapWord::SetMark() {
955 value_ &= ~kMarkingMask;
956}
957
958
959void MapWord::ClearMark() {
960 value_ |= kMarkingMask;
961}
962
963
964bool MapWord::IsOverflowed() {
965 return (value_ & kOverflowMask) != 0;
966}
967
968
969void MapWord::SetOverflow() {
970 value_ |= kOverflowMask;
971}
972
973
974void MapWord::ClearOverflow() {
975 value_ &= ~kOverflowMask;
976}
977
978
979MapWord MapWord::EncodeAddress(Address map_address, int offset) {
980 // Offset is the distance in live bytes from the first live object in the
981 // same page. The offset between two objects in the same page should not
982 // exceed the object area size of a page.
983 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
984
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000985 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +0000986 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
987
988 Page* map_page = Page::FromAddress(map_address);
989 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
990
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000991 uintptr_t map_page_offset =
992 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +0000993
994 uintptr_t encoding =
995 (compact_offset << kForwardingOffsetShift) |
996 (map_page_offset << kMapPageOffsetShift) |
997 (map_page->mc_page_index << kMapPageIndexShift);
998 return MapWord(encoding);
999}
1000
1001
1002Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001003 int map_page_index =
1004 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001005 ASSERT_MAP_PAGE_INDEX(map_page_index);
1006
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001007 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001008 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1009 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001010
1011 return (map_space->PageAddress(map_page_index) + map_page_offset);
1012}
1013
1014
1015int MapWord::DecodeOffset() {
1016 // The offset field is represented in the kForwardingOffsetBits
1017 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001018 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1019 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1020 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001021}
1022
1023
1024MapWord MapWord::FromEncodedAddress(Address address) {
1025 return MapWord(reinterpret_cast<uintptr_t>(address));
1026}
1027
1028
1029Address MapWord::ToEncodedAddress() {
1030 return reinterpret_cast<Address>(value_);
1031}
1032
1033
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034#ifdef DEBUG
1035void HeapObject::VerifyObjectField(int offset) {
1036 VerifyPointer(READ_FIELD(this, offset));
1037}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001038
1039void HeapObject::VerifySmiField(int offset) {
1040 ASSERT(READ_FIELD(this, offset)->IsSmi());
1041}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001042#endif
1043
1044
1045Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001046 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001047}
1048
1049
1050void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001051 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001052}
1053
1054
kasper.lund7276f142008-07-30 08:49:36 +00001055MapWord HeapObject::map_word() {
1056 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1057}
1058
1059
1060void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001061 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001062 // here.
1063 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1064}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001065
1066
1067HeapObject* HeapObject::FromAddress(Address address) {
1068 ASSERT_TAG_ALIGNED(address);
1069 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1070}
1071
1072
1073Address HeapObject::address() {
1074 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1075}
1076
1077
1078int HeapObject::Size() {
1079 return SizeFromMap(map());
1080}
1081
1082
1083void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1084 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1085 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1086}
1087
1088
1089void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1090 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1091}
1092
1093
kasper.lund7276f142008-07-30 08:49:36 +00001094bool HeapObject::IsMarked() {
1095 return map_word().IsMarked();
1096}
1097
1098
1099void HeapObject::SetMark() {
1100 ASSERT(!IsMarked());
1101 MapWord first_word = map_word();
1102 first_word.SetMark();
1103 set_map_word(first_word);
1104}
1105
1106
1107void HeapObject::ClearMark() {
1108 ASSERT(IsMarked());
1109 MapWord first_word = map_word();
1110 first_word.ClearMark();
1111 set_map_word(first_word);
1112}
1113
1114
1115bool HeapObject::IsOverflowed() {
1116 return map_word().IsOverflowed();
1117}
1118
1119
1120void HeapObject::SetOverflow() {
1121 MapWord first_word = map_word();
1122 first_word.SetOverflow();
1123 set_map_word(first_word);
1124}
1125
1126
1127void HeapObject::ClearOverflow() {
1128 ASSERT(IsOverflowed());
1129 MapWord first_word = map_word();
1130 first_word.ClearOverflow();
1131 set_map_word(first_word);
1132}
1133
1134
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135double HeapNumber::value() {
1136 return READ_DOUBLE_FIELD(this, kValueOffset);
1137}
1138
1139
1140void HeapNumber::set_value(double value) {
1141 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1142}
1143
1144
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001145int HeapNumber::get_exponent() {
1146 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1147 kExponentShift) - kExponentBias;
1148}
1149
1150
1151int HeapNumber::get_sign() {
1152 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1153}
1154
1155
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001156ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001157
1158
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001159HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001160 Object* array = READ_FIELD(this, kElementsOffset);
1161 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001162 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1163 array->IsExternalArray());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001164 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001165}
1166
1167
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001168void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001169 ASSERT(map()->has_fast_elements() ==
1170 (value->map() == Heap::fixed_array_map()));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001171 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001172 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1173 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001174 WRITE_FIELD(this, kElementsOffset, value);
1175 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1176}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177
1178
1179void JSObject::initialize_properties() {
1180 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1181 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1182}
1183
1184
1185void JSObject::initialize_elements() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001186 ASSERT(map()->has_fast_elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001187 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1188 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1189}
1190
1191
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001192Object* JSObject::ResetElements() {
1193 Object* obj = map()->GetFastElementsMap();
1194 if (obj->IsFailure()) return obj;
1195 set_map(Map::cast(obj));
1196 initialize_elements();
1197 return this;
1198}
1199
1200
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001201ACCESSORS(Oddball, to_string, String, kToStringOffset)
1202ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1203
1204
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001205Object* JSGlobalPropertyCell::value() {
1206 return READ_FIELD(this, kValueOffset);
1207}
1208
1209
1210void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1211 // The write barrier is not used for global property cells.
1212 ASSERT(!val->IsJSGlobalPropertyCell());
1213 WRITE_FIELD(this, kValueOffset, val);
1214}
1215
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001216
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001217int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001218 InstanceType type = map()->instance_type();
1219 // Check for the most common kind of JavaScript object before
1220 // falling into the generic switch. This speeds up the internal
1221 // field operations considerably on average.
1222 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1223 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001224 case JS_GLOBAL_PROXY_TYPE:
1225 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001226 case JS_GLOBAL_OBJECT_TYPE:
1227 return JSGlobalObject::kSize;
1228 case JS_BUILTINS_OBJECT_TYPE:
1229 return JSBuiltinsObject::kSize;
1230 case JS_FUNCTION_TYPE:
1231 return JSFunction::kSize;
1232 case JS_VALUE_TYPE:
1233 return JSValue::kSize;
1234 case JS_ARRAY_TYPE:
1235 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001236 case JS_REGEXP_TYPE:
1237 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001238 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001239 return JSObject::kHeaderSize;
1240 default:
1241 UNREACHABLE();
1242 return 0;
1243 }
1244}
1245
1246
1247int JSObject::GetInternalFieldCount() {
1248 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001249 // Make sure to adjust for the number of in-object properties. These
1250 // properties do contribute to the size, but are not internal fields.
1251 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1252 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001253}
1254
1255
1256Object* JSObject::GetInternalField(int index) {
1257 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001258 // Internal objects do follow immediately after the header, whereas in-object
1259 // properties are at the end of the object. Therefore there is no need
1260 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001261 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1262}
1263
1264
1265void JSObject::SetInternalField(int index, Object* value) {
1266 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001267 // Internal objects do follow immediately after the header, whereas in-object
1268 // properties are at the end of the object. Therefore there is no need
1269 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 int offset = GetHeaderSize() + (kPointerSize * index);
1271 WRITE_FIELD(this, offset, value);
1272 WRITE_BARRIER(this, offset);
1273}
1274
1275
ager@chromium.org7c537e22008-10-16 08:43:32 +00001276// Access fast-case object properties at index. The use of these routines
1277// is needed to correctly distinguish between properties stored in-object and
1278// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001279Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001280 // Adjust for the number of properties stored in the object.
1281 index -= map()->inobject_properties();
1282 if (index < 0) {
1283 int offset = map()->instance_size() + (index * kPointerSize);
1284 return READ_FIELD(this, offset);
1285 } else {
1286 ASSERT(index < properties()->length());
1287 return properties()->get(index);
1288 }
1289}
1290
1291
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001292Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001293 // Adjust for the number of properties stored in the object.
1294 index -= map()->inobject_properties();
1295 if (index < 0) {
1296 int offset = map()->instance_size() + (index * kPointerSize);
1297 WRITE_FIELD(this, offset, value);
1298 WRITE_BARRIER(this, offset);
1299 } else {
1300 ASSERT(index < properties()->length());
1301 properties()->set(index, value);
1302 }
1303 return value;
1304}
1305
1306
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001307Object* JSObject::InObjectPropertyAt(int index) {
1308 // Adjust for the number of properties stored in the object.
1309 index -= map()->inobject_properties();
1310 ASSERT(index < 0);
1311 int offset = map()->instance_size() + (index * kPointerSize);
1312 return READ_FIELD(this, offset);
1313}
1314
1315
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001316Object* JSObject::InObjectPropertyAtPut(int index,
1317 Object* value,
1318 WriteBarrierMode mode) {
1319 // Adjust for the number of properties stored in the object.
1320 index -= map()->inobject_properties();
1321 ASSERT(index < 0);
1322 int offset = map()->instance_size() + (index * kPointerSize);
1323 WRITE_FIELD(this, offset, value);
1324 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1325 return value;
1326}
1327
1328
1329
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001330void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001331 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001332 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001333 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001334 }
1335}
1336
1337
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001338bool JSObject::HasFastProperties() {
1339 return !properties()->IsDictionary();
1340}
1341
1342
1343int JSObject::MaxFastProperties() {
1344 // Allow extra fast properties if the object has more than
1345 // kMaxFastProperties in-object properties. When this is the case,
1346 // it is very unlikely that the object is being used as a dictionary
1347 // and there is a good chance that allowing more map transitions
1348 // will be worth it.
1349 return Max(map()->inobject_properties(), kMaxFastProperties);
1350}
1351
1352
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001354 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001355 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001356 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001357 }
1358}
1359
1360
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001361bool Object::ToArrayIndex(uint32_t* index) {
1362 if (IsSmi()) {
1363 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001364 if (value < 0) return false;
1365 *index = value;
1366 return true;
1367 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001368 if (IsHeapNumber()) {
1369 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001370 uint32_t uint_value = static_cast<uint32_t>(value);
1371 if (value == static_cast<double>(uint_value)) {
1372 *index = uint_value;
1373 return true;
1374 }
1375 }
1376 return false;
1377}
1378
1379
1380bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1381 if (!this->IsJSValue()) return false;
1382
1383 JSValue* js_value = JSValue::cast(this);
1384 if (!js_value->value()->IsString()) return false;
1385
1386 String* str = String::cast(js_value->value());
1387 if (index >= (uint32_t)str->length()) return false;
1388
1389 return true;
1390}
1391
1392
1393Object* FixedArray::get(int index) {
1394 ASSERT(index >= 0 && index < this->length());
1395 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1396}
1397
1398
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001399void FixedArray::set(int index, Smi* value) {
1400 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1401 int offset = kHeaderSize + index * kPointerSize;
1402 WRITE_FIELD(this, offset, value);
1403}
1404
1405
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001406void FixedArray::set(int index, Object* value) {
1407 ASSERT(index >= 0 && index < this->length());
1408 int offset = kHeaderSize + index * kPointerSize;
1409 WRITE_FIELD(this, offset, value);
1410 WRITE_BARRIER(this, offset);
1411}
1412
1413
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001414WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001415 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1416 return UPDATE_WRITE_BARRIER;
1417}
1418
1419
1420void FixedArray::set(int index,
1421 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001422 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423 ASSERT(index >= 0 && index < this->length());
1424 int offset = kHeaderSize + index * kPointerSize;
1425 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001426 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001427}
1428
1429
1430void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1431 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001432 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1434}
1435
1436
1437void FixedArray::set_undefined(int index) {
1438 ASSERT(index >= 0 && index < this->length());
1439 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1440 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1441 Heap::undefined_value());
1442}
1443
1444
ager@chromium.org236ad962008-09-25 09:45:57 +00001445void FixedArray::set_null(int index) {
1446 ASSERT(index >= 0 && index < this->length());
1447 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1448 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1449}
1450
1451
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001452void FixedArray::set_the_hole(int index) {
1453 ASSERT(index >= 0 && index < this->length());
1454 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1455 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1456}
1457
1458
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001459Object** FixedArray::data_start() {
1460 return HeapObject::RawField(this, kHeaderSize);
1461}
1462
1463
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001464bool DescriptorArray::IsEmpty() {
1465 ASSERT(this == Heap::empty_descriptor_array() ||
1466 this->length() > 2);
1467 return this == Heap::empty_descriptor_array();
1468}
1469
1470
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001471void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1472 Object* tmp = array->get(first);
1473 fast_set(array, first, array->get(second));
1474 fast_set(array, second, tmp);
1475}
1476
1477
1478int DescriptorArray::Search(String* name) {
1479 SLOW_ASSERT(IsSortedNoDuplicates());
1480
1481 // Check for empty descriptor array.
1482 int nof = number_of_descriptors();
1483 if (nof == 0) return kNotFound;
1484
1485 // Fast case: do linear search for small arrays.
1486 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001487 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001488 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001489 }
1490
1491 // Slow case: perform binary search.
1492 return BinarySearch(name, 0, nof - 1);
1493}
1494
1495
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001496String* DescriptorArray::GetKey(int descriptor_number) {
1497 ASSERT(descriptor_number < number_of_descriptors());
1498 return String::cast(get(ToKeyIndex(descriptor_number)));
1499}
1500
1501
1502Object* DescriptorArray::GetValue(int descriptor_number) {
1503 ASSERT(descriptor_number < number_of_descriptors());
1504 return GetContentArray()->get(ToValueIndex(descriptor_number));
1505}
1506
1507
1508Smi* DescriptorArray::GetDetails(int descriptor_number) {
1509 ASSERT(descriptor_number < number_of_descriptors());
1510 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1511}
1512
1513
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001514PropertyType DescriptorArray::GetType(int descriptor_number) {
1515 ASSERT(descriptor_number < number_of_descriptors());
1516 return PropertyDetails(GetDetails(descriptor_number)).type();
1517}
1518
1519
1520int DescriptorArray::GetFieldIndex(int descriptor_number) {
1521 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1522}
1523
1524
1525JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1526 return JSFunction::cast(GetValue(descriptor_number));
1527}
1528
1529
1530Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1531 ASSERT(GetType(descriptor_number) == CALLBACKS);
1532 return GetValue(descriptor_number);
1533}
1534
1535
1536AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1537 ASSERT(GetType(descriptor_number) == CALLBACKS);
1538 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1539 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1540}
1541
1542
1543bool DescriptorArray::IsProperty(int descriptor_number) {
1544 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1545}
1546
1547
1548bool DescriptorArray::IsTransition(int descriptor_number) {
1549 PropertyType t = GetType(descriptor_number);
1550 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1551}
1552
1553
1554bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1555 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1556}
1557
1558
1559bool DescriptorArray::IsDontEnum(int descriptor_number) {
1560 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1561}
1562
1563
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001564void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1565 desc->Init(GetKey(descriptor_number),
1566 GetValue(descriptor_number),
1567 GetDetails(descriptor_number));
1568}
1569
1570
1571void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1572 // Range check.
1573 ASSERT(descriptor_number < number_of_descriptors());
1574
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001575 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001576 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1577 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1578
1579 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1580 FixedArray* content_array = GetContentArray();
1581 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1582 fast_set(content_array, ToDetailsIndex(descriptor_number),
1583 desc->GetDetails().AsSmi());
1584}
1585
1586
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001587void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1588 Descriptor desc;
1589 src->Get(src_index, &desc);
1590 Set(index, &desc);
1591}
1592
1593
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001594void DescriptorArray::Swap(int first, int second) {
1595 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1596 FixedArray* content_array = GetContentArray();
1597 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1598 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1599}
1600
1601
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001602bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001603 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001604 if (!max_index_object->IsSmi()) return false;
1605 return 0 !=
1606 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1607}
1608
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001609uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001610 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001611 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612 if (!max_index_object->IsSmi()) return 0;
1613 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1614 return value >> kRequiresSlowElementsTagSize;
1615}
1616
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001617void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001618 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001619}
1620
1621
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001622// ------------------------------------
1623// Cast operations
1624
1625
1626CAST_ACCESSOR(FixedArray)
1627CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001629CAST_ACCESSOR(JSFunctionResultCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001630CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001631CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001632CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633CAST_ACCESSOR(String)
1634CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001635CAST_ACCESSOR(SeqAsciiString)
1636CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001637CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638CAST_ACCESSOR(ExternalString)
1639CAST_ACCESSOR(ExternalAsciiString)
1640CAST_ACCESSOR(ExternalTwoByteString)
1641CAST_ACCESSOR(JSObject)
1642CAST_ACCESSOR(Smi)
1643CAST_ACCESSOR(Failure)
1644CAST_ACCESSOR(HeapObject)
1645CAST_ACCESSOR(HeapNumber)
1646CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001647CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648CAST_ACCESSOR(SharedFunctionInfo)
1649CAST_ACCESSOR(Map)
1650CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001651CAST_ACCESSOR(GlobalObject)
1652CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001653CAST_ACCESSOR(JSGlobalObject)
1654CAST_ACCESSOR(JSBuiltinsObject)
1655CAST_ACCESSOR(Code)
1656CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001657CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001658CAST_ACCESSOR(Proxy)
1659CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001660CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001661CAST_ACCESSOR(ExternalArray)
1662CAST_ACCESSOR(ExternalByteArray)
1663CAST_ACCESSOR(ExternalUnsignedByteArray)
1664CAST_ACCESSOR(ExternalShortArray)
1665CAST_ACCESSOR(ExternalUnsignedShortArray)
1666CAST_ACCESSOR(ExternalIntArray)
1667CAST_ACCESSOR(ExternalUnsignedIntArray)
1668CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001669CAST_ACCESSOR(Struct)
1670
1671
1672#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1673 STRUCT_LIST(MAKE_STRUCT_CAST)
1674#undef MAKE_STRUCT_CAST
1675
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001676
1677template <typename Shape, typename Key>
1678HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001679 ASSERT(obj->IsHashTable());
1680 return reinterpret_cast<HashTable*>(obj);
1681}
1682
1683
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001684SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1685SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1686
1687INT_ACCESSORS(PixelArray, length, kLengthOffset)
1688INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001689
1690
ager@chromium.orgac091b72010-05-05 07:34:42 +00001691SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001692
1693
1694uint32_t String::hash_field() {
1695 return READ_UINT32_FIELD(this, kHashFieldOffset);
1696}
1697
1698
1699void String::set_hash_field(uint32_t value) {
1700 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001701#if V8_HOST_ARCH_64_BIT
1702 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1703#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001704}
1705
1706
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001707bool String::Equals(String* other) {
1708 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001709 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1710 return false;
1711 }
1712 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001713}
1714
1715
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001716Object* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001717 if (!StringShape(this).IsCons()) return this;
1718 ConsString* cons = ConsString::cast(this);
1719 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001720 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001721}
1722
1723
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001724String* String::TryFlattenGetString(PretenureFlag pretenure) {
1725 Object* flat = TryFlatten(pretenure);
1726 return flat->IsFailure() ? this : String::cast(flat);
1727}
1728
1729
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001730uint16_t String::Get(int index) {
1731 ASSERT(index >= 0 && index < length());
1732 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001733 case kSeqStringTag | kAsciiStringTag:
1734 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1735 case kSeqStringTag | kTwoByteStringTag:
1736 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1737 case kConsStringTag | kAsciiStringTag:
1738 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001740 case kExternalStringTag | kAsciiStringTag:
1741 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1742 case kExternalStringTag | kTwoByteStringTag:
1743 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744 default:
1745 break;
1746 }
1747
1748 UNREACHABLE();
1749 return 0;
1750}
1751
1752
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001753void String::Set(int index, uint16_t value) {
1754 ASSERT(index >= 0 && index < length());
1755 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756
ager@chromium.org5ec48922009-05-05 07:25:34 +00001757 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001758 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1759 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001760}
1761
1762
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001763bool String::IsFlat() {
1764 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001765 case kConsStringTag: {
1766 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001767 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001768 return second->length() == 0;
1769 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001770 default:
1771 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001772 }
1773}
1774
1775
ager@chromium.org7c537e22008-10-16 08:43:32 +00001776uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001777 ASSERT(index >= 0 && index < length());
1778 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1779}
1780
1781
ager@chromium.org7c537e22008-10-16 08:43:32 +00001782void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001783 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1784 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1785 static_cast<byte>(value));
1786}
1787
1788
ager@chromium.org7c537e22008-10-16 08:43:32 +00001789Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001790 return FIELD_ADDR(this, kHeaderSize);
1791}
1792
1793
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001794char* SeqAsciiString::GetChars() {
1795 return reinterpret_cast<char*>(GetCharsAddress());
1796}
1797
1798
ager@chromium.org7c537e22008-10-16 08:43:32 +00001799Address SeqTwoByteString::GetCharsAddress() {
1800 return FIELD_ADDR(this, kHeaderSize);
1801}
1802
1803
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001804uc16* SeqTwoByteString::GetChars() {
1805 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1806}
1807
1808
ager@chromium.org7c537e22008-10-16 08:43:32 +00001809uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001810 ASSERT(index >= 0 && index < length());
1811 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1812}
1813
1814
ager@chromium.org7c537e22008-10-16 08:43:32 +00001815void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001816 ASSERT(index >= 0 && index < length());
1817 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1818}
1819
1820
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001821int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001822 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001823}
1824
1825
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001826int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001827 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001828}
1829
1830
ager@chromium.org870a0b62008-11-04 11:43:05 +00001831String* ConsString::first() {
1832 return String::cast(READ_FIELD(this, kFirstOffset));
1833}
1834
1835
1836Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001837 return READ_FIELD(this, kFirstOffset);
1838}
1839
1840
ager@chromium.org870a0b62008-11-04 11:43:05 +00001841void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001842 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001843 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001844}
1845
1846
ager@chromium.org870a0b62008-11-04 11:43:05 +00001847String* ConsString::second() {
1848 return String::cast(READ_FIELD(this, kSecondOffset));
1849}
1850
1851
1852Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001853 return READ_FIELD(this, kSecondOffset);
1854}
1855
1856
ager@chromium.org870a0b62008-11-04 11:43:05 +00001857void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001858 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001859 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001860}
1861
1862
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001863ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1864 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1865}
1866
1867
1868void ExternalAsciiString::set_resource(
1869 ExternalAsciiString::Resource* resource) {
1870 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1871}
1872
1873
1874ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1875 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1876}
1877
1878
1879void ExternalTwoByteString::set_resource(
1880 ExternalTwoByteString::Resource* resource) {
1881 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1882}
1883
1884
ager@chromium.orgac091b72010-05-05 07:34:42 +00001885void JSFunctionResultCache::MakeZeroSize() {
1886 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1887 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1888}
1889
1890
1891void JSFunctionResultCache::Clear() {
1892 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1893 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1894 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1895 MakeZeroSize();
1896}
1897
1898
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001899byte ByteArray::get(int index) {
1900 ASSERT(index >= 0 && index < this->length());
1901 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1902}
1903
1904
1905void ByteArray::set(int index, byte value) {
1906 ASSERT(index >= 0 && index < this->length());
1907 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1908}
1909
1910
1911int ByteArray::get_int(int index) {
1912 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1913 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1914}
1915
1916
1917ByteArray* ByteArray::FromDataStartAddress(Address address) {
1918 ASSERT_TAG_ALIGNED(address);
1919 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1920}
1921
1922
1923Address ByteArray::GetDataStartAddress() {
1924 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1925}
1926
1927
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001928uint8_t* PixelArray::external_pointer() {
1929 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1930 return reinterpret_cast<uint8_t*>(ptr);
1931}
1932
1933
1934void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1935 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1936 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1937}
1938
1939
1940uint8_t PixelArray::get(int index) {
1941 ASSERT((index >= 0) && (index < this->length()));
1942 uint8_t* ptr = external_pointer();
1943 return ptr[index];
1944}
1945
1946
1947void PixelArray::set(int index, uint8_t value) {
1948 ASSERT((index >= 0) && (index < this->length()));
1949 uint8_t* ptr = external_pointer();
1950 ptr[index] = value;
1951}
1952
1953
ager@chromium.org3811b432009-10-28 14:53:37 +00001954void* ExternalArray::external_pointer() {
1955 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1956 return reinterpret_cast<void*>(ptr);
1957}
1958
1959
1960void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1961 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1962 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1963}
1964
1965
1966int8_t ExternalByteArray::get(int index) {
1967 ASSERT((index >= 0) && (index < this->length()));
1968 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1969 return ptr[index];
1970}
1971
1972
1973void ExternalByteArray::set(int index, int8_t value) {
1974 ASSERT((index >= 0) && (index < this->length()));
1975 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1976 ptr[index] = value;
1977}
1978
1979
1980uint8_t ExternalUnsignedByteArray::get(int index) {
1981 ASSERT((index >= 0) && (index < this->length()));
1982 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1983 return ptr[index];
1984}
1985
1986
1987void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1988 ASSERT((index >= 0) && (index < this->length()));
1989 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1990 ptr[index] = value;
1991}
1992
1993
1994int16_t ExternalShortArray::get(int index) {
1995 ASSERT((index >= 0) && (index < this->length()));
1996 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1997 return ptr[index];
1998}
1999
2000
2001void ExternalShortArray::set(int index, int16_t value) {
2002 ASSERT((index >= 0) && (index < this->length()));
2003 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2004 ptr[index] = value;
2005}
2006
2007
2008uint16_t ExternalUnsignedShortArray::get(int index) {
2009 ASSERT((index >= 0) && (index < this->length()));
2010 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2011 return ptr[index];
2012}
2013
2014
2015void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2016 ASSERT((index >= 0) && (index < this->length()));
2017 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2018 ptr[index] = value;
2019}
2020
2021
2022int32_t ExternalIntArray::get(int index) {
2023 ASSERT((index >= 0) && (index < this->length()));
2024 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2025 return ptr[index];
2026}
2027
2028
2029void ExternalIntArray::set(int index, int32_t value) {
2030 ASSERT((index >= 0) && (index < this->length()));
2031 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2032 ptr[index] = value;
2033}
2034
2035
2036uint32_t ExternalUnsignedIntArray::get(int index) {
2037 ASSERT((index >= 0) && (index < this->length()));
2038 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2039 return ptr[index];
2040}
2041
2042
2043void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2044 ASSERT((index >= 0) && (index < this->length()));
2045 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2046 ptr[index] = value;
2047}
2048
2049
2050float ExternalFloatArray::get(int index) {
2051 ASSERT((index >= 0) && (index < this->length()));
2052 float* ptr = static_cast<float*>(external_pointer());
2053 return ptr[index];
2054}
2055
2056
2057void ExternalFloatArray::set(int index, float value) {
2058 ASSERT((index >= 0) && (index < this->length()));
2059 float* ptr = static_cast<float*>(external_pointer());
2060 ptr[index] = value;
2061}
2062
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002063inline Scavenger Map::scavenger() {
2064 Scavenger callback = reinterpret_cast<Scavenger>(
2065 READ_INTPTR_FIELD(this, kScavengerCallbackOffset));
2066
2067 ASSERT(callback == Heap::GetScavenger(instance_type(),
2068 instance_size()));
2069
2070 return callback;
2071}
2072
2073inline void Map::set_scavenger(Scavenger callback) {
2074 WRITE_INTPTR_FIELD(this,
2075 kScavengerCallbackOffset,
2076 reinterpret_cast<intptr_t>(callback));
2077}
ager@chromium.org3811b432009-10-28 14:53:37 +00002078
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002079int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002080 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2081}
2082
2083
2084int Map::inobject_properties() {
2085 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002086}
2087
2088
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002089int Map::pre_allocated_property_fields() {
2090 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2091}
2092
2093
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002094int HeapObject::SizeFromMap(Map* map) {
2095 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002096 // Only inline the most frequent cases.
2097 if (instance_type == JS_OBJECT_TYPE ||
2098 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
2099 (kStringTag | kConsStringTag) ||
2100 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002101 if (instance_type == FIXED_ARRAY_TYPE) {
2102 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
2103 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002104 if (instance_type == BYTE_ARRAY_TYPE) {
2105 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2106 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002107 // Otherwise do the general size computation.
2108 return SlowSizeFromMap(map);
2109}
2110
2111
2112void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002113 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002114 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002115 ASSERT(0 <= value && value < 256);
2116 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2117}
2118
2119
ager@chromium.org7c537e22008-10-16 08:43:32 +00002120void Map::set_inobject_properties(int value) {
2121 ASSERT(0 <= value && value < 256);
2122 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2123}
2124
2125
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002126void Map::set_pre_allocated_property_fields(int value) {
2127 ASSERT(0 <= value && value < 256);
2128 WRITE_BYTE_FIELD(this,
2129 kPreAllocatedPropertyFieldsOffset,
2130 static_cast<byte>(value));
2131}
2132
2133
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002134InstanceType Map::instance_type() {
2135 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2136}
2137
2138
2139void Map::set_instance_type(InstanceType value) {
2140 ASSERT(0 <= value && value < 256);
2141 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2142}
2143
2144
2145int Map::unused_property_fields() {
2146 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2147}
2148
2149
2150void Map::set_unused_property_fields(int value) {
2151 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2152}
2153
2154
2155byte Map::bit_field() {
2156 return READ_BYTE_FIELD(this, kBitFieldOffset);
2157}
2158
2159
2160void Map::set_bit_field(byte value) {
2161 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2162}
2163
2164
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002165byte Map::bit_field2() {
2166 return READ_BYTE_FIELD(this, kBitField2Offset);
2167}
2168
2169
2170void Map::set_bit_field2(byte value) {
2171 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2172}
2173
2174
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002175void Map::set_non_instance_prototype(bool value) {
2176 if (value) {
2177 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2178 } else {
2179 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2180 }
2181}
2182
2183
2184bool Map::has_non_instance_prototype() {
2185 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2186}
2187
2188
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002189void Map::set_function_with_prototype(bool value) {
2190 if (value) {
2191 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2192 } else {
2193 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2194 }
2195}
2196
2197
2198bool Map::function_with_prototype() {
2199 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2200}
2201
2202
ager@chromium.org870a0b62008-11-04 11:43:05 +00002203void Map::set_is_access_check_needed(bool access_check_needed) {
2204 if (access_check_needed) {
2205 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2206 } else {
2207 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2208 }
2209}
2210
2211
2212bool Map::is_access_check_needed() {
2213 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2214}
2215
2216
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002217void Map::set_is_extensible(bool value) {
2218 if (value) {
2219 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2220 } else {
2221 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2222 }
2223}
2224
2225bool Map::is_extensible() {
2226 return ((1 << kIsExtensible) & bit_field2()) != 0;
2227}
2228
2229
2230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002231Code::Flags Code::flags() {
2232 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2233}
2234
2235
2236void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002237 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002238 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002239 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2240 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002241 ExtractArgumentsCountFromFlags(flags) >= 0);
2242 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2243}
2244
2245
2246Code::Kind Code::kind() {
2247 return ExtractKindFromFlags(flags());
2248}
2249
2250
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002251InLoopFlag Code::ic_in_loop() {
2252 return ExtractICInLoopFromFlags(flags());
2253}
2254
2255
kasper.lund7276f142008-07-30 08:49:36 +00002256InlineCacheState Code::ic_state() {
2257 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002258 // Only allow uninitialized or debugger states for non-IC code
2259 // objects. This is used in the debugger to determine whether or not
2260 // a call to code object has been replaced with a debug break call.
2261 ASSERT(is_inline_cache_stub() ||
2262 result == UNINITIALIZED ||
2263 result == DEBUG_BREAK ||
2264 result == DEBUG_PREPARE_STEP_IN);
2265 return result;
2266}
2267
2268
2269PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002270 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002271 return ExtractTypeFromFlags(flags());
2272}
2273
2274
2275int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002276 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002277 return ExtractArgumentsCountFromFlags(flags());
2278}
2279
2280
2281CodeStub::Major Code::major_key() {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002282 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002283 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2284 kStubMajorKeyOffset));
2285}
2286
2287
2288void Code::set_major_key(CodeStub::Major major) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002289 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002290 ASSERT(0 <= major && major < 256);
2291 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002292}
2293
2294
2295bool Code::is_inline_cache_stub() {
2296 Kind kind = this->kind();
2297 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2298}
2299
2300
2301Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002302 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002303 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002304 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002305 int argc,
2306 InlineCacheHolderFlag holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002307 // Compute the bit mask.
2308 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002309 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002310 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311 bits |= type << kFlagsTypeShift;
2312 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002313 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002314 // Cast to flags and validate result before returning it.
2315 Flags result = static_cast<Flags>(bits);
2316 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002317 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002318 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002319 ASSERT(ExtractTypeFromFlags(result) == type);
2320 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2321 return result;
2322}
2323
2324
2325Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2326 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002327 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002328 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002329 int argc) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002330 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002331}
2332
2333
2334Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2335 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2336 return static_cast<Kind>(bits);
2337}
2338
2339
kasper.lund7276f142008-07-30 08:49:36 +00002340InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2341 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002342 return static_cast<InlineCacheState>(bits);
2343}
2344
2345
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002346InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2347 int bits = (flags & kFlagsICInLoopMask);
2348 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2349}
2350
2351
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002352PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2353 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2354 return static_cast<PropertyType>(bits);
2355}
2356
2357
2358int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2359 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2360}
2361
2362
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002363InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2364 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2365 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2366}
2367
2368
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002369Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2370 int bits = flags & ~kFlagsTypeMask;
2371 return static_cast<Flags>(bits);
2372}
2373
2374
ager@chromium.org8bb60582008-12-11 12:02:20 +00002375Code* Code::GetCodeFromTargetAddress(Address address) {
2376 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2377 // GetCodeFromTargetAddress might be called when marking objects during mark
2378 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2379 // Code::cast. Code::cast does not work when the object's map is
2380 // marked.
2381 Code* result = reinterpret_cast<Code*>(code);
2382 return result;
2383}
2384
2385
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002386Object* Map::prototype() {
2387 return READ_FIELD(this, kPrototypeOffset);
2388}
2389
2390
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002391void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002392 ASSERT(value->IsNull() || value->IsJSObject());
2393 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002394 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002395}
2396
2397
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002398Object* Map::GetFastElementsMap() {
2399 if (has_fast_elements()) return this;
2400 Object* obj = CopyDropTransitions();
2401 if (obj->IsFailure()) return obj;
2402 Map* new_map = Map::cast(obj);
2403 new_map->set_has_fast_elements(true);
2404 return new_map;
2405}
2406
2407
2408Object* Map::GetSlowElementsMap() {
2409 if (!has_fast_elements()) return this;
2410 Object* obj = CopyDropTransitions();
2411 if (obj->IsFailure()) return obj;
2412 Map* new_map = Map::cast(obj);
2413 new_map->set_has_fast_elements(false);
2414 return new_map;
2415}
2416
2417
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002418ACCESSORS(Map, instance_descriptors, DescriptorArray,
2419 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002420ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002421ACCESSORS(Map, constructor, Object, kConstructorOffset)
2422
2423ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2424ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2425
2426ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2427ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002428ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002429
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002430ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002431
2432ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2433ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2434ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2435ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2436ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002437ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002438
2439ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2440ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2441ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2442
2443ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2444ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2445ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2446ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2447ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2448ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2449
2450ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2451ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2452
2453ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2454ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2455
2456ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2457ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002458ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2459 kPropertyAccessorsOffset)
2460ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2461 kPrototypeTemplateOffset)
2462ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2463ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2464 kNamedPropertyHandlerOffset)
2465ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2466 kIndexedPropertyHandlerOffset)
2467ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2468 kInstanceTemplateOffset)
2469ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2470ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002471ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2472 kInstanceCallHandlerOffset)
2473ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2474 kAccessCheckInfoOffset)
2475ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2476
2477ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002478ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2479 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002480
2481ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2482ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2483
2484ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2485
2486ACCESSORS(Script, source, Object, kSourceOffset)
2487ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002488ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002489ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2490ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002491ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002492ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002493ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2494ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002495ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002496ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002497ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002498ACCESSORS(Script, eval_from_instructions_offset, Smi,
2499 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002500
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002501#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002502ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2503ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2504ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2505ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2506
2507ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2508ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2509ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2510ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002511#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002512
2513ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002514ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002515ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2516 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002517ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002518ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2519ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002520ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002521ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2522 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002523
2524BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2525 kHiddenPrototypeBit)
2526BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2527BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2528 kNeedsAccessCheckBit)
2529BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2530 kIsExpressionBit)
2531BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2532 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002533BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002534 has_only_simple_this_property_assignments,
2535 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002536BOOL_ACCESSORS(SharedFunctionInfo,
2537 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002538 try_full_codegen,
2539 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002540BOOL_ACCESSORS(SharedFunctionInfo,
2541 compiler_hints,
2542 allows_lazy_compilation,
2543 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002544
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002545#if V8_HOST_ARCH_32_BIT
2546SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2547SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002548 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002549SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002550 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002551SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2552SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002553 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002554SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2555SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002556 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002557SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002558 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002559SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002560 kThisPropertyAssignmentsCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002561#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002562
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002563#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2564 int holder::name() { \
2565 int value = READ_INT_FIELD(this, offset); \
2566 ASSERT(kHeapObjectTag == 1); \
2567 ASSERT((value & kHeapObjectTag) == 0); \
2568 return value >> 1; \
2569 } \
2570 void holder::set_##name(int value) { \
2571 ASSERT(kHeapObjectTag == 1); \
2572 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2573 (value & 0xC0000000) == 0x000000000); \
2574 WRITE_INT_FIELD(this, \
2575 offset, \
2576 (value << 1) & ~kHeapObjectTag); \
2577 }
2578
2579#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2580 INT_ACCESSORS(holder, name, offset)
2581
2582
2583
2584PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2585PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2586 kFormalParameterCountOffset)
2587
2588PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2589 kExpectedNofPropertiesOffset)
2590PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2591
2592PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2593 kStartPositionAndTypeOffset)
2594PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2595
2596PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2597 kFunctionTokenPositionOffset)
2598PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2599 kCompilerHintsOffset)
2600
2601PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2602 kThisPropertyAssignmentsCountOffset)
2603#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002604
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002605ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2606ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2607
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002608bool Script::HasValidSource() {
2609 Object* src = this->source();
2610 if (!src->IsString()) return true;
2611 String* src_str = String::cast(src);
2612 if (!StringShape(src_str).IsExternal()) return true;
2613 if (src_str->IsAsciiRepresentation()) {
2614 return ExternalAsciiString::cast(src)->resource() != NULL;
2615 } else if (src_str->IsTwoByteRepresentation()) {
2616 return ExternalTwoByteString::cast(src)->resource() != NULL;
2617 }
2618 return true;
2619}
2620
2621
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002622void SharedFunctionInfo::DontAdaptArguments() {
2623 ASSERT(code()->kind() == Code::BUILTIN);
2624 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2625}
2626
2627
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002628int SharedFunctionInfo::start_position() {
2629 return start_position_and_type() >> kStartPositionShift;
2630}
2631
2632
2633void SharedFunctionInfo::set_start_position(int start_position) {
2634 set_start_position_and_type((start_position << kStartPositionShift)
2635 | (start_position_and_type() & ~kStartPositionMask));
2636}
2637
2638
2639Code* SharedFunctionInfo::code() {
2640 return Code::cast(READ_FIELD(this, kCodeOffset));
2641}
2642
2643
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002644void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002645 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002646 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002647}
2648
2649
ager@chromium.orgb5737492010-07-15 09:29:43 +00002650SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2651 return reinterpret_cast<SerializedScopeInfo*>(
2652 READ_FIELD(this, kScopeInfoOffset));
2653}
2654
2655
2656void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2657 WriteBarrierMode mode) {
2658 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2659 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2660}
2661
2662
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002663bool SharedFunctionInfo::is_compiled() {
2664 // TODO(1242782): Create a code kind for uncompiled code.
2665 return code()->kind() != Code::STUB;
2666}
2667
2668
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002669bool SharedFunctionInfo::IsApiFunction() {
2670 return function_data()->IsFunctionTemplateInfo();
2671}
2672
2673
2674FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2675 ASSERT(IsApiFunction());
2676 return FunctionTemplateInfo::cast(function_data());
2677}
2678
2679
2680bool SharedFunctionInfo::HasCustomCallGenerator() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00002681 return function_data()->IsSmi();
2682}
2683
2684
2685int SharedFunctionInfo::custom_call_generator_id() {
2686 ASSERT(HasCustomCallGenerator());
2687 return Smi::cast(function_data())->value();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002688}
2689
2690
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002691bool JSFunction::IsBuiltin() {
2692 return context()->global()->IsJSBuiltinsObject();
2693}
2694
2695
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002696Code* JSFunction::code() {
2697 return shared()->code();
2698}
2699
2700
2701void JSFunction::set_code(Code* value) {
2702 shared()->set_code(value);
2703}
2704
2705
2706Context* JSFunction::context() {
2707 return Context::cast(READ_FIELD(this, kContextOffset));
2708}
2709
2710
2711Object* JSFunction::unchecked_context() {
2712 return READ_FIELD(this, kContextOffset);
2713}
2714
2715
2716void JSFunction::set_context(Object* value) {
2717 ASSERT(value == Heap::undefined_value() || value->IsContext());
2718 WRITE_FIELD(this, kContextOffset, value);
2719 WRITE_BARRIER(this, kContextOffset);
2720}
2721
2722ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2723 kPrototypeOrInitialMapOffset)
2724
2725
2726Map* JSFunction::initial_map() {
2727 return Map::cast(prototype_or_initial_map());
2728}
2729
2730
2731void JSFunction::set_initial_map(Map* value) {
2732 set_prototype_or_initial_map(value);
2733}
2734
2735
2736bool JSFunction::has_initial_map() {
2737 return prototype_or_initial_map()->IsMap();
2738}
2739
2740
2741bool JSFunction::has_instance_prototype() {
2742 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2743}
2744
2745
2746bool JSFunction::has_prototype() {
2747 return map()->has_non_instance_prototype() || has_instance_prototype();
2748}
2749
2750
2751Object* JSFunction::instance_prototype() {
2752 ASSERT(has_instance_prototype());
2753 if (has_initial_map()) return initial_map()->prototype();
2754 // When there is no initial map and the prototype is a JSObject, the
2755 // initial map field is used for the prototype field.
2756 return prototype_or_initial_map();
2757}
2758
2759
2760Object* JSFunction::prototype() {
2761 ASSERT(has_prototype());
2762 // If the function's prototype property has been set to a non-JSObject
2763 // value, that value is stored in the constructor field of the map.
2764 if (map()->has_non_instance_prototype()) return map()->constructor();
2765 return instance_prototype();
2766}
2767
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002768bool JSFunction::should_have_prototype() {
2769 return map()->function_with_prototype();
2770}
2771
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002772
2773bool JSFunction::is_compiled() {
2774 return shared()->is_compiled();
2775}
2776
2777
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002778int JSFunction::NumberOfLiterals() {
2779 return literals()->length();
2780}
2781
2782
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002783Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2784 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002785 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002786}
2787
2788
2789void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2790 Object* value) {
2791 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002792 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2793 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2794}
2795
2796
2797Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2798 ASSERT(0 <= id && id < kJSBuiltinsCount);
2799 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2800}
2801
2802
2803void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2804 Code* value) {
2805 ASSERT(0 <= id && id < kJSBuiltinsCount);
2806 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2807 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002808}
2809
2810
2811Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002812 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002813}
2814
2815
2816void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002817 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002818}
2819
2820
2821void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2822 visitor->VisitExternalReference(
2823 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2824}
2825
2826
2827ACCESSORS(JSValue, value, Object, kValueOffset)
2828
2829
2830JSValue* JSValue::cast(Object* obj) {
2831 ASSERT(obj->IsJSValue());
2832 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2833 return reinterpret_cast<JSValue*>(obj);
2834}
2835
2836
2837INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002838ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002839
2840
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002841byte* Code::instruction_start() {
2842 return FIELD_ADDR(this, kHeaderSize);
2843}
2844
2845
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002846byte* Code::instruction_end() {
2847 return instruction_start() + instruction_size();
2848}
2849
2850
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002851int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002852 return RoundUp(instruction_size(), kObjectAlignment);
2853}
2854
2855
2856ByteArray* Code::unchecked_relocation_info() {
2857 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002858}
2859
2860
2861byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002862 return unchecked_relocation_info()->GetDataStartAddress();
2863}
2864
2865
2866int Code::relocation_size() {
2867 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002868}
2869
2870
2871byte* Code::entry() {
2872 return instruction_start();
2873}
2874
2875
2876bool Code::contains(byte* pc) {
2877 return (instruction_start() <= pc) &&
2878 (pc < instruction_start() + instruction_size());
2879}
2880
2881
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002882ACCESSORS(JSArray, length, Object, kLengthOffset)
2883
2884
ager@chromium.org236ad962008-09-25 09:45:57 +00002885ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002886
2887
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002888JSRegExp::Type JSRegExp::TypeTag() {
2889 Object* data = this->data();
2890 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2891 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2892 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002893}
2894
2895
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002896int JSRegExp::CaptureCount() {
2897 switch (TypeTag()) {
2898 case ATOM:
2899 return 0;
2900 case IRREGEXP:
2901 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2902 default:
2903 UNREACHABLE();
2904 return -1;
2905 }
2906}
2907
2908
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002909JSRegExp::Flags JSRegExp::GetFlags() {
2910 ASSERT(this->data()->IsFixedArray());
2911 Object* data = this->data();
2912 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2913 return Flags(smi->value());
2914}
2915
2916
2917String* JSRegExp::Pattern() {
2918 ASSERT(this->data()->IsFixedArray());
2919 Object* data = this->data();
2920 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2921 return pattern;
2922}
2923
2924
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002925Object* JSRegExp::DataAt(int index) {
2926 ASSERT(TypeTag() != NOT_COMPILED);
2927 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002928}
2929
2930
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002931void JSRegExp::SetDataAt(int index, Object* value) {
2932 ASSERT(TypeTag() != NOT_COMPILED);
2933 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2934 FixedArray::cast(data())->set(index, value);
2935}
2936
2937
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002938JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002939 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002940 if (array->IsFixedArray()) {
2941 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2942 if (array->map() == Heap::fixed_array_map()) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002943 ASSERT(map()->has_fast_elements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002944 return FAST_ELEMENTS;
2945 }
2946 ASSERT(array->IsDictionary());
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002947 ASSERT(!map()->has_fast_elements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002948 return DICTIONARY_ELEMENTS;
2949 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002950 ASSERT(!map()->has_fast_elements());
ager@chromium.org3811b432009-10-28 14:53:37 +00002951 if (array->IsExternalArray()) {
2952 switch (array->map()->instance_type()) {
2953 case EXTERNAL_BYTE_ARRAY_TYPE:
2954 return EXTERNAL_BYTE_ELEMENTS;
2955 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2956 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2957 case EXTERNAL_SHORT_ARRAY_TYPE:
2958 return EXTERNAL_SHORT_ELEMENTS;
2959 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2960 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2961 case EXTERNAL_INT_ARRAY_TYPE:
2962 return EXTERNAL_INT_ELEMENTS;
2963 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2964 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2965 default:
2966 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2967 return EXTERNAL_FLOAT_ELEMENTS;
2968 }
2969 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002970 ASSERT(array->IsPixelArray());
2971 return PIXEL_ELEMENTS;
2972}
2973
2974
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002975bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002976 return GetElementsKind() == FAST_ELEMENTS;
2977}
2978
2979
2980bool JSObject::HasDictionaryElements() {
2981 return GetElementsKind() == DICTIONARY_ELEMENTS;
2982}
2983
2984
2985bool JSObject::HasPixelElements() {
2986 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002987}
2988
2989
ager@chromium.org3811b432009-10-28 14:53:37 +00002990bool JSObject::HasExternalArrayElements() {
2991 return (HasExternalByteElements() ||
2992 HasExternalUnsignedByteElements() ||
2993 HasExternalShortElements() ||
2994 HasExternalUnsignedShortElements() ||
2995 HasExternalIntElements() ||
2996 HasExternalUnsignedIntElements() ||
2997 HasExternalFloatElements());
2998}
2999
3000
3001bool JSObject::HasExternalByteElements() {
3002 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3003}
3004
3005
3006bool JSObject::HasExternalUnsignedByteElements() {
3007 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3008}
3009
3010
3011bool JSObject::HasExternalShortElements() {
3012 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3013}
3014
3015
3016bool JSObject::HasExternalUnsignedShortElements() {
3017 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3018}
3019
3020
3021bool JSObject::HasExternalIntElements() {
3022 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3023}
3024
3025
3026bool JSObject::HasExternalUnsignedIntElements() {
3027 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3028}
3029
3030
3031bool JSObject::HasExternalFloatElements() {
3032 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3033}
3034
3035
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003036bool JSObject::HasNamedInterceptor() {
3037 return map()->has_named_interceptor();
3038}
3039
3040
3041bool JSObject::HasIndexedInterceptor() {
3042 return map()->has_indexed_interceptor();
3043}
3044
3045
ager@chromium.org5c838252010-02-19 08:53:10 +00003046bool JSObject::AllowsSetElementsLength() {
3047 bool result = elements()->IsFixedArray();
3048 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3049 return result;
3050}
3051
3052
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003053StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003054 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003055 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003056}
3057
3058
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003059NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003060 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003061 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003062}
3063
3064
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003065bool String::IsHashFieldComputed(uint32_t field) {
3066 return (field & kHashNotComputedMask) == 0;
3067}
3068
3069
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003070bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003071 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003072}
3073
3074
3075uint32_t String::Hash() {
3076 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003077 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003078 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003079 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003080 return ComputeAndSetHash();
3081}
3082
3083
ager@chromium.org7c537e22008-10-16 08:43:32 +00003084StringHasher::StringHasher(int length)
3085 : length_(length),
3086 raw_running_hash_(0),
3087 array_index_(0),
3088 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3089 is_first_char_(true),
3090 is_valid_(true) { }
3091
3092
3093bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003094 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003095}
3096
3097
3098void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003099 // Use the Jenkins one-at-a-time hash function to update the hash
3100 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003101 raw_running_hash_ += c;
3102 raw_running_hash_ += (raw_running_hash_ << 10);
3103 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003104 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003105 if (is_array_index_) {
3106 if (c < '0' || c > '9') {
3107 is_array_index_ = false;
3108 } else {
3109 int d = c - '0';
3110 if (is_first_char_) {
3111 is_first_char_ = false;
3112 if (c == '0' && length_ > 1) {
3113 is_array_index_ = false;
3114 return;
3115 }
3116 }
3117 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3118 is_array_index_ = false;
3119 } else {
3120 array_index_ = array_index_ * 10 + d;
3121 }
3122 }
3123 }
3124}
3125
3126
3127void StringHasher::AddCharacterNoIndex(uc32 c) {
3128 ASSERT(!is_array_index());
3129 raw_running_hash_ += c;
3130 raw_running_hash_ += (raw_running_hash_ << 10);
3131 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3132}
3133
3134
3135uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003136 // Get the calculated raw hash value and do some more bit ops to distribute
3137 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003138 uint32_t result = raw_running_hash_;
3139 result += (result << 3);
3140 result ^= (result >> 11);
3141 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003142 if (result == 0) {
3143 result = 27;
3144 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003145 return result;
3146}
3147
3148
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003149bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003150 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003151 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3152 return false;
3153 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003154 return SlowAsArrayIndex(index);
3155}
3156
3157
3158Object* JSObject::GetPrototype() {
3159 return JSObject::cast(this)->map()->prototype();
3160}
3161
3162
3163PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3164 return GetPropertyAttributeWithReceiver(this, key);
3165}
3166
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003167// TODO(504): this may be useful in other places too where JSGlobalProxy
3168// is used.
3169Object* JSObject::BypassGlobalProxy() {
3170 if (IsJSGlobalProxy()) {
3171 Object* proto = GetPrototype();
3172 if (proto->IsNull()) return Heap::undefined_value();
3173 ASSERT(proto->IsJSGlobalObject());
3174 return proto;
3175 }
3176 return this;
3177}
3178
3179
3180bool JSObject::HasHiddenPropertiesObject() {
3181 ASSERT(!IsJSGlobalProxy());
3182 return GetPropertyAttributePostInterceptor(this,
3183 Heap::hidden_symbol(),
3184 false) != ABSENT;
3185}
3186
3187
3188Object* JSObject::GetHiddenPropertiesObject() {
3189 ASSERT(!IsJSGlobalProxy());
3190 PropertyAttributes attributes;
3191 return GetLocalPropertyPostInterceptor(this,
3192 Heap::hidden_symbol(),
3193 &attributes);
3194}
3195
3196
3197Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3198 ASSERT(!IsJSGlobalProxy());
3199 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3200 hidden_obj,
3201 DONT_ENUM);
3202}
3203
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003204
3205bool JSObject::HasElement(uint32_t index) {
3206 return HasElementWithReceiver(this, index);
3207}
3208
3209
3210bool AccessorInfo::all_can_read() {
3211 return BooleanBit::get(flag(), kAllCanReadBit);
3212}
3213
3214
3215void AccessorInfo::set_all_can_read(bool value) {
3216 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3217}
3218
3219
3220bool AccessorInfo::all_can_write() {
3221 return BooleanBit::get(flag(), kAllCanWriteBit);
3222}
3223
3224
3225void AccessorInfo::set_all_can_write(bool value) {
3226 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3227}
3228
3229
ager@chromium.org870a0b62008-11-04 11:43:05 +00003230bool AccessorInfo::prohibits_overwriting() {
3231 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3232}
3233
3234
3235void AccessorInfo::set_prohibits_overwriting(bool value) {
3236 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3237}
3238
3239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003240PropertyAttributes AccessorInfo::property_attributes() {
3241 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3242}
3243
3244
3245void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3246 ASSERT(AttributesField::is_valid(attributes));
3247 int rest_value = flag()->value() & ~AttributesField::mask();
3248 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3249}
3250
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003251template<typename Shape, typename Key>
3252void Dictionary<Shape, Key>::SetEntry(int entry,
3253 Object* key,
3254 Object* value,
3255 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003256 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003257 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003258 AssertNoAllocation no_gc;
3259 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003260 FixedArray::set(index, key, mode);
3261 FixedArray::set(index+1, value, mode);
3262 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003263}
3264
3265
3266void Map::ClearCodeCache() {
3267 // No write barrier is needed since empty_fixed_array is not in new space.
3268 // Please note this function is used during marking:
3269 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003270 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3271 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003272}
3273
3274
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003275void JSArray::EnsureSize(int required_size) {
3276 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003277 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003278 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3279 if (elts->length() < required_size) {
3280 // Doubling in size would be overkill, but leave some slack to avoid
3281 // constantly growing.
3282 Expand(required_size + (required_size >> 3));
3283 // It's a performance benefit to keep a frequently used array in new-space.
3284 } else if (!Heap::new_space()->Contains(elts) &&
3285 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3286 // Expand will allocate a new backing store in new space even if the size
3287 // we asked for isn't larger than what we had before.
3288 Expand(required_size);
3289 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003290}
3291
3292
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003293void JSArray::set_length(Smi* length) {
3294 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3295}
3296
3297
ager@chromium.org7c537e22008-10-16 08:43:32 +00003298void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003299 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003300 set_elements(storage);
3301}
3302
3303
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003304Object* FixedArray::Copy() {
3305 if (length() == 0) return this;
3306 return Heap::CopyFixedArray(this);
3307}
3308
3309
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003310#undef CAST_ACCESSOR
3311#undef INT_ACCESSORS
3312#undef SMI_ACCESSORS
3313#undef ACCESSORS
3314#undef FIELD_ADDR
3315#undef READ_FIELD
3316#undef WRITE_FIELD
3317#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003318#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003319#undef READ_MEMADDR_FIELD
3320#undef WRITE_MEMADDR_FIELD
3321#undef READ_DOUBLE_FIELD
3322#undef WRITE_DOUBLE_FIELD
3323#undef READ_INT_FIELD
3324#undef WRITE_INT_FIELD
3325#undef READ_SHORT_FIELD
3326#undef WRITE_SHORT_FIELD
3327#undef READ_BYTE_FIELD
3328#undef WRITE_BYTE_FIELD
3329
3330
3331} } // namespace v8::internal
3332
3333#endif // V8_OBJECTS_INL_H_