blob: 5e8022e51fde445b2c717ad93ea4655be5ebb164 [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
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001496int DescriptorArray::SearchWithCache(String* name) {
1497 int number = DescriptorLookupCache::Lookup(this, name);
1498 if (number == DescriptorLookupCache::kAbsent) {
1499 number = Search(name);
1500 DescriptorLookupCache::Update(this, name, number);
1501 }
1502 return number;
1503}
1504
1505
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001506String* DescriptorArray::GetKey(int descriptor_number) {
1507 ASSERT(descriptor_number < number_of_descriptors());
1508 return String::cast(get(ToKeyIndex(descriptor_number)));
1509}
1510
1511
1512Object* DescriptorArray::GetValue(int descriptor_number) {
1513 ASSERT(descriptor_number < number_of_descriptors());
1514 return GetContentArray()->get(ToValueIndex(descriptor_number));
1515}
1516
1517
1518Smi* DescriptorArray::GetDetails(int descriptor_number) {
1519 ASSERT(descriptor_number < number_of_descriptors());
1520 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1521}
1522
1523
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001524PropertyType DescriptorArray::GetType(int descriptor_number) {
1525 ASSERT(descriptor_number < number_of_descriptors());
1526 return PropertyDetails(GetDetails(descriptor_number)).type();
1527}
1528
1529
1530int DescriptorArray::GetFieldIndex(int descriptor_number) {
1531 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1532}
1533
1534
1535JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1536 return JSFunction::cast(GetValue(descriptor_number));
1537}
1538
1539
1540Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1541 ASSERT(GetType(descriptor_number) == CALLBACKS);
1542 return GetValue(descriptor_number);
1543}
1544
1545
1546AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1547 ASSERT(GetType(descriptor_number) == CALLBACKS);
1548 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1549 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1550}
1551
1552
1553bool DescriptorArray::IsProperty(int descriptor_number) {
1554 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1555}
1556
1557
1558bool DescriptorArray::IsTransition(int descriptor_number) {
1559 PropertyType t = GetType(descriptor_number);
1560 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1561}
1562
1563
1564bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1565 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1566}
1567
1568
1569bool DescriptorArray::IsDontEnum(int descriptor_number) {
1570 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1571}
1572
1573
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001574void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1575 desc->Init(GetKey(descriptor_number),
1576 GetValue(descriptor_number),
1577 GetDetails(descriptor_number));
1578}
1579
1580
1581void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1582 // Range check.
1583 ASSERT(descriptor_number < number_of_descriptors());
1584
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001585 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001586 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1587 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1588
1589 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1590 FixedArray* content_array = GetContentArray();
1591 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1592 fast_set(content_array, ToDetailsIndex(descriptor_number),
1593 desc->GetDetails().AsSmi());
1594}
1595
1596
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001597void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1598 Descriptor desc;
1599 src->Get(src_index, &desc);
1600 Set(index, &desc);
1601}
1602
1603
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001604void DescriptorArray::Swap(int first, int second) {
1605 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1606 FixedArray* content_array = GetContentArray();
1607 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1608 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1609}
1610
1611
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001612bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001613 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001614 if (!max_index_object->IsSmi()) return false;
1615 return 0 !=
1616 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1617}
1618
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001619uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001620 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001621 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001622 if (!max_index_object->IsSmi()) return 0;
1623 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1624 return value >> kRequiresSlowElementsTagSize;
1625}
1626
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001627void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001628 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001629}
1630
1631
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001632// ------------------------------------
1633// Cast operations
1634
1635
1636CAST_ACCESSOR(FixedArray)
1637CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001639CAST_ACCESSOR(JSFunctionResultCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001640CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001641CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001642CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643CAST_ACCESSOR(String)
1644CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001645CAST_ACCESSOR(SeqAsciiString)
1646CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001647CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648CAST_ACCESSOR(ExternalString)
1649CAST_ACCESSOR(ExternalAsciiString)
1650CAST_ACCESSOR(ExternalTwoByteString)
1651CAST_ACCESSOR(JSObject)
1652CAST_ACCESSOR(Smi)
1653CAST_ACCESSOR(Failure)
1654CAST_ACCESSOR(HeapObject)
1655CAST_ACCESSOR(HeapNumber)
1656CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001657CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001658CAST_ACCESSOR(SharedFunctionInfo)
1659CAST_ACCESSOR(Map)
1660CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001661CAST_ACCESSOR(GlobalObject)
1662CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001663CAST_ACCESSOR(JSGlobalObject)
1664CAST_ACCESSOR(JSBuiltinsObject)
1665CAST_ACCESSOR(Code)
1666CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001667CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668CAST_ACCESSOR(Proxy)
1669CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001670CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001671CAST_ACCESSOR(ExternalArray)
1672CAST_ACCESSOR(ExternalByteArray)
1673CAST_ACCESSOR(ExternalUnsignedByteArray)
1674CAST_ACCESSOR(ExternalShortArray)
1675CAST_ACCESSOR(ExternalUnsignedShortArray)
1676CAST_ACCESSOR(ExternalIntArray)
1677CAST_ACCESSOR(ExternalUnsignedIntArray)
1678CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001679CAST_ACCESSOR(Struct)
1680
1681
1682#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1683 STRUCT_LIST(MAKE_STRUCT_CAST)
1684#undef MAKE_STRUCT_CAST
1685
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001686
1687template <typename Shape, typename Key>
1688HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001689 ASSERT(obj->IsHashTable());
1690 return reinterpret_cast<HashTable*>(obj);
1691}
1692
1693
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001694SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1695SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1696
1697INT_ACCESSORS(PixelArray, length, kLengthOffset)
1698INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001699
1700
ager@chromium.orgac091b72010-05-05 07:34:42 +00001701SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001702
1703
1704uint32_t String::hash_field() {
1705 return READ_UINT32_FIELD(this, kHashFieldOffset);
1706}
1707
1708
1709void String::set_hash_field(uint32_t value) {
1710 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001711#if V8_HOST_ARCH_64_BIT
1712 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1713#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001714}
1715
1716
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001717bool String::Equals(String* other) {
1718 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001719 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1720 return false;
1721 }
1722 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001723}
1724
1725
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001726Object* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001727 if (!StringShape(this).IsCons()) return this;
1728 ConsString* cons = ConsString::cast(this);
1729 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001730 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001731}
1732
1733
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001734String* String::TryFlattenGetString(PretenureFlag pretenure) {
1735 Object* flat = TryFlatten(pretenure);
1736 return flat->IsFailure() ? this : String::cast(flat);
1737}
1738
1739
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001740uint16_t String::Get(int index) {
1741 ASSERT(index >= 0 && index < length());
1742 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001743 case kSeqStringTag | kAsciiStringTag:
1744 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1745 case kSeqStringTag | kTwoByteStringTag:
1746 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1747 case kConsStringTag | kAsciiStringTag:
1748 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001750 case kExternalStringTag | kAsciiStringTag:
1751 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1752 case kExternalStringTag | kTwoByteStringTag:
1753 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001754 default:
1755 break;
1756 }
1757
1758 UNREACHABLE();
1759 return 0;
1760}
1761
1762
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001763void String::Set(int index, uint16_t value) {
1764 ASSERT(index >= 0 && index < length());
1765 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001766
ager@chromium.org5ec48922009-05-05 07:25:34 +00001767 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001768 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1769 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001770}
1771
1772
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001773bool String::IsFlat() {
1774 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001775 case kConsStringTag: {
1776 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001777 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001778 return second->length() == 0;
1779 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001780 default:
1781 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001782 }
1783}
1784
1785
ager@chromium.org7c537e22008-10-16 08:43:32 +00001786uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001787 ASSERT(index >= 0 && index < length());
1788 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1789}
1790
1791
ager@chromium.org7c537e22008-10-16 08:43:32 +00001792void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001793 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1794 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1795 static_cast<byte>(value));
1796}
1797
1798
ager@chromium.org7c537e22008-10-16 08:43:32 +00001799Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001800 return FIELD_ADDR(this, kHeaderSize);
1801}
1802
1803
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001804char* SeqAsciiString::GetChars() {
1805 return reinterpret_cast<char*>(GetCharsAddress());
1806}
1807
1808
ager@chromium.org7c537e22008-10-16 08:43:32 +00001809Address SeqTwoByteString::GetCharsAddress() {
1810 return FIELD_ADDR(this, kHeaderSize);
1811}
1812
1813
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001814uc16* SeqTwoByteString::GetChars() {
1815 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1816}
1817
1818
ager@chromium.org7c537e22008-10-16 08:43:32 +00001819uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001820 ASSERT(index >= 0 && index < length());
1821 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1822}
1823
1824
ager@chromium.org7c537e22008-10-16 08:43:32 +00001825void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001826 ASSERT(index >= 0 && index < length());
1827 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1828}
1829
1830
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001831int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001832 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001833}
1834
1835
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001836int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001837 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001838}
1839
1840
ager@chromium.org870a0b62008-11-04 11:43:05 +00001841String* ConsString::first() {
1842 return String::cast(READ_FIELD(this, kFirstOffset));
1843}
1844
1845
1846Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001847 return READ_FIELD(this, kFirstOffset);
1848}
1849
1850
ager@chromium.org870a0b62008-11-04 11:43:05 +00001851void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001852 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001853 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001854}
1855
1856
ager@chromium.org870a0b62008-11-04 11:43:05 +00001857String* ConsString::second() {
1858 return String::cast(READ_FIELD(this, kSecondOffset));
1859}
1860
1861
1862Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001863 return READ_FIELD(this, kSecondOffset);
1864}
1865
1866
ager@chromium.org870a0b62008-11-04 11:43:05 +00001867void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001868 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001869 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001870}
1871
1872
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001873ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1874 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1875}
1876
1877
1878void ExternalAsciiString::set_resource(
1879 ExternalAsciiString::Resource* resource) {
1880 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1881}
1882
1883
1884ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1885 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1886}
1887
1888
1889void ExternalTwoByteString::set_resource(
1890 ExternalTwoByteString::Resource* resource) {
1891 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1892}
1893
1894
ager@chromium.orgac091b72010-05-05 07:34:42 +00001895void JSFunctionResultCache::MakeZeroSize() {
1896 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1897 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1898}
1899
1900
1901void JSFunctionResultCache::Clear() {
1902 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1903 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1904 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1905 MakeZeroSize();
1906}
1907
1908
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001909byte ByteArray::get(int index) {
1910 ASSERT(index >= 0 && index < this->length());
1911 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1912}
1913
1914
1915void ByteArray::set(int index, byte value) {
1916 ASSERT(index >= 0 && index < this->length());
1917 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1918}
1919
1920
1921int ByteArray::get_int(int index) {
1922 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1923 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1924}
1925
1926
1927ByteArray* ByteArray::FromDataStartAddress(Address address) {
1928 ASSERT_TAG_ALIGNED(address);
1929 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1930}
1931
1932
1933Address ByteArray::GetDataStartAddress() {
1934 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1935}
1936
1937
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001938uint8_t* PixelArray::external_pointer() {
1939 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1940 return reinterpret_cast<uint8_t*>(ptr);
1941}
1942
1943
1944void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1945 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1946 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1947}
1948
1949
1950uint8_t PixelArray::get(int index) {
1951 ASSERT((index >= 0) && (index < this->length()));
1952 uint8_t* ptr = external_pointer();
1953 return ptr[index];
1954}
1955
1956
1957void PixelArray::set(int index, uint8_t value) {
1958 ASSERT((index >= 0) && (index < this->length()));
1959 uint8_t* ptr = external_pointer();
1960 ptr[index] = value;
1961}
1962
1963
ager@chromium.org3811b432009-10-28 14:53:37 +00001964void* ExternalArray::external_pointer() {
1965 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1966 return reinterpret_cast<void*>(ptr);
1967}
1968
1969
1970void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1971 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1972 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1973}
1974
1975
1976int8_t ExternalByteArray::get(int index) {
1977 ASSERT((index >= 0) && (index < this->length()));
1978 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1979 return ptr[index];
1980}
1981
1982
1983void ExternalByteArray::set(int index, int8_t value) {
1984 ASSERT((index >= 0) && (index < this->length()));
1985 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1986 ptr[index] = value;
1987}
1988
1989
1990uint8_t ExternalUnsignedByteArray::get(int index) {
1991 ASSERT((index >= 0) && (index < this->length()));
1992 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1993 return ptr[index];
1994}
1995
1996
1997void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1998 ASSERT((index >= 0) && (index < this->length()));
1999 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2000 ptr[index] = value;
2001}
2002
2003
2004int16_t ExternalShortArray::get(int index) {
2005 ASSERT((index >= 0) && (index < this->length()));
2006 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2007 return ptr[index];
2008}
2009
2010
2011void ExternalShortArray::set(int index, int16_t value) {
2012 ASSERT((index >= 0) && (index < this->length()));
2013 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2014 ptr[index] = value;
2015}
2016
2017
2018uint16_t ExternalUnsignedShortArray::get(int index) {
2019 ASSERT((index >= 0) && (index < this->length()));
2020 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2021 return ptr[index];
2022}
2023
2024
2025void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2026 ASSERT((index >= 0) && (index < this->length()));
2027 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2028 ptr[index] = value;
2029}
2030
2031
2032int32_t ExternalIntArray::get(int index) {
2033 ASSERT((index >= 0) && (index < this->length()));
2034 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2035 return ptr[index];
2036}
2037
2038
2039void ExternalIntArray::set(int index, int32_t value) {
2040 ASSERT((index >= 0) && (index < this->length()));
2041 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2042 ptr[index] = value;
2043}
2044
2045
2046uint32_t ExternalUnsignedIntArray::get(int index) {
2047 ASSERT((index >= 0) && (index < this->length()));
2048 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2049 return ptr[index];
2050}
2051
2052
2053void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2054 ASSERT((index >= 0) && (index < this->length()));
2055 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2056 ptr[index] = value;
2057}
2058
2059
2060float ExternalFloatArray::get(int index) {
2061 ASSERT((index >= 0) && (index < this->length()));
2062 float* ptr = static_cast<float*>(external_pointer());
2063 return ptr[index];
2064}
2065
2066
2067void ExternalFloatArray::set(int index, float value) {
2068 ASSERT((index >= 0) && (index < this->length()));
2069 float* ptr = static_cast<float*>(external_pointer());
2070 ptr[index] = value;
2071}
2072
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002073
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002074INT_ACCESSORS(Map, visitor_id, kScavengerCallbackOffset)
ager@chromium.org3811b432009-10-28 14:53:37 +00002075
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002076int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002077 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2078}
2079
2080
2081int Map::inobject_properties() {
2082 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002083}
2084
2085
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002086int Map::pre_allocated_property_fields() {
2087 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2088}
2089
2090
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091int HeapObject::SizeFromMap(Map* map) {
2092 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002093 // Only inline the most frequent cases.
2094 if (instance_type == JS_OBJECT_TYPE ||
2095 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
2096 (kStringTag | kConsStringTag) ||
2097 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002098 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002099 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002100 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002101 if (instance_type == BYTE_ARRAY_TYPE) {
2102 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2103 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002104 // Otherwise do the general size computation.
2105 return SlowSizeFromMap(map);
2106}
2107
2108
2109void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002110 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002111 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002112 ASSERT(0 <= value && value < 256);
2113 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2114}
2115
2116
ager@chromium.org7c537e22008-10-16 08:43:32 +00002117void Map::set_inobject_properties(int value) {
2118 ASSERT(0 <= value && value < 256);
2119 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2120}
2121
2122
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002123void Map::set_pre_allocated_property_fields(int value) {
2124 ASSERT(0 <= value && value < 256);
2125 WRITE_BYTE_FIELD(this,
2126 kPreAllocatedPropertyFieldsOffset,
2127 static_cast<byte>(value));
2128}
2129
2130
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002131InstanceType Map::instance_type() {
2132 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2133}
2134
2135
2136void Map::set_instance_type(InstanceType value) {
2137 ASSERT(0 <= value && value < 256);
2138 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2139}
2140
2141
2142int Map::unused_property_fields() {
2143 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2144}
2145
2146
2147void Map::set_unused_property_fields(int value) {
2148 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2149}
2150
2151
2152byte Map::bit_field() {
2153 return READ_BYTE_FIELD(this, kBitFieldOffset);
2154}
2155
2156
2157void Map::set_bit_field(byte value) {
2158 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2159}
2160
2161
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002162byte Map::bit_field2() {
2163 return READ_BYTE_FIELD(this, kBitField2Offset);
2164}
2165
2166
2167void Map::set_bit_field2(byte value) {
2168 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2169}
2170
2171
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002172void Map::set_non_instance_prototype(bool value) {
2173 if (value) {
2174 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2175 } else {
2176 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2177 }
2178}
2179
2180
2181bool Map::has_non_instance_prototype() {
2182 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2183}
2184
2185
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002186void Map::set_function_with_prototype(bool value) {
2187 if (value) {
2188 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2189 } else {
2190 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2191 }
2192}
2193
2194
2195bool Map::function_with_prototype() {
2196 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2197}
2198
2199
ager@chromium.org870a0b62008-11-04 11:43:05 +00002200void Map::set_is_access_check_needed(bool access_check_needed) {
2201 if (access_check_needed) {
2202 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2203 } else {
2204 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2205 }
2206}
2207
2208
2209bool Map::is_access_check_needed() {
2210 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2211}
2212
2213
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002214void Map::set_is_extensible(bool value) {
2215 if (value) {
2216 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2217 } else {
2218 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2219 }
2220}
2221
2222bool Map::is_extensible() {
2223 return ((1 << kIsExtensible) & bit_field2()) != 0;
2224}
2225
2226
2227
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002228Code::Flags Code::flags() {
2229 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2230}
2231
2232
2233void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002234 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002235 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002236 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2237 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002238 ExtractArgumentsCountFromFlags(flags) >= 0);
2239 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2240}
2241
2242
2243Code::Kind Code::kind() {
2244 return ExtractKindFromFlags(flags());
2245}
2246
2247
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002248InLoopFlag Code::ic_in_loop() {
2249 return ExtractICInLoopFromFlags(flags());
2250}
2251
2252
kasper.lund7276f142008-07-30 08:49:36 +00002253InlineCacheState Code::ic_state() {
2254 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002255 // Only allow uninitialized or debugger states for non-IC code
2256 // objects. This is used in the debugger to determine whether or not
2257 // a call to code object has been replaced with a debug break call.
2258 ASSERT(is_inline_cache_stub() ||
2259 result == UNINITIALIZED ||
2260 result == DEBUG_BREAK ||
2261 result == DEBUG_PREPARE_STEP_IN);
2262 return result;
2263}
2264
2265
2266PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002267 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002268 return ExtractTypeFromFlags(flags());
2269}
2270
2271
2272int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002273 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002274 return ExtractArgumentsCountFromFlags(flags());
2275}
2276
2277
2278CodeStub::Major Code::major_key() {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002279 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002280 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2281 kStubMajorKeyOffset));
2282}
2283
2284
2285void Code::set_major_key(CodeStub::Major major) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002286 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002287 ASSERT(0 <= major && major < 256);
2288 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002289}
2290
2291
2292bool Code::is_inline_cache_stub() {
2293 Kind kind = this->kind();
2294 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2295}
2296
2297
2298Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002299 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002300 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002301 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002302 int argc,
2303 InlineCacheHolderFlag holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002304 // Compute the bit mask.
2305 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002306 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002307 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002308 bits |= type << kFlagsTypeShift;
2309 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002310 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311 // Cast to flags and validate result before returning it.
2312 Flags result = static_cast<Flags>(bits);
2313 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002314 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002315 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002316 ASSERT(ExtractTypeFromFlags(result) == type);
2317 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2318 return result;
2319}
2320
2321
2322Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2323 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002324 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002325 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002326 int argc) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002327 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002328}
2329
2330
2331Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2332 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2333 return static_cast<Kind>(bits);
2334}
2335
2336
kasper.lund7276f142008-07-30 08:49:36 +00002337InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2338 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002339 return static_cast<InlineCacheState>(bits);
2340}
2341
2342
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002343InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2344 int bits = (flags & kFlagsICInLoopMask);
2345 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2346}
2347
2348
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002349PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2350 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2351 return static_cast<PropertyType>(bits);
2352}
2353
2354
2355int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2356 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2357}
2358
2359
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002360InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2361 int bits = (flags & kFlagsCacheInPrototypeMapMask);
2362 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2363}
2364
2365
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002366Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2367 int bits = flags & ~kFlagsTypeMask;
2368 return static_cast<Flags>(bits);
2369}
2370
2371
ager@chromium.org8bb60582008-12-11 12:02:20 +00002372Code* Code::GetCodeFromTargetAddress(Address address) {
2373 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2374 // GetCodeFromTargetAddress might be called when marking objects during mark
2375 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2376 // Code::cast. Code::cast does not work when the object's map is
2377 // marked.
2378 Code* result = reinterpret_cast<Code*>(code);
2379 return result;
2380}
2381
2382
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002383Object* Map::prototype() {
2384 return READ_FIELD(this, kPrototypeOffset);
2385}
2386
2387
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002388void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002389 ASSERT(value->IsNull() || value->IsJSObject());
2390 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002391 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002392}
2393
2394
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002395Object* Map::GetFastElementsMap() {
2396 if (has_fast_elements()) return this;
2397 Object* obj = CopyDropTransitions();
2398 if (obj->IsFailure()) return obj;
2399 Map* new_map = Map::cast(obj);
2400 new_map->set_has_fast_elements(true);
2401 return new_map;
2402}
2403
2404
2405Object* Map::GetSlowElementsMap() {
2406 if (!has_fast_elements()) return this;
2407 Object* obj = CopyDropTransitions();
2408 if (obj->IsFailure()) return obj;
2409 Map* new_map = Map::cast(obj);
2410 new_map->set_has_fast_elements(false);
2411 return new_map;
2412}
2413
2414
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002415ACCESSORS(Map, instance_descriptors, DescriptorArray,
2416 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002417ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002418ACCESSORS(Map, constructor, Object, kConstructorOffset)
2419
2420ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2421ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2422
2423ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2424ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002425ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002426
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002427ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002428
2429ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2430ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2431ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2432ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2433ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002434ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002435
2436ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2437ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2438ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2439
2440ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2441ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2442ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2443ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2444ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2445ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2446
2447ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2448ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2449
2450ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2451ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2452
2453ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2454ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002455ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2456 kPropertyAccessorsOffset)
2457ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2458 kPrototypeTemplateOffset)
2459ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2460ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2461 kNamedPropertyHandlerOffset)
2462ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2463 kIndexedPropertyHandlerOffset)
2464ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2465 kInstanceTemplateOffset)
2466ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2467ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002468ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2469 kInstanceCallHandlerOffset)
2470ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2471 kAccessCheckInfoOffset)
2472ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2473
2474ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002475ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2476 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002477
2478ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2479ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2480
2481ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2482
2483ACCESSORS(Script, source, Object, kSourceOffset)
2484ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002485ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002486ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2487ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002488ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002489ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002490ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2491ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002492ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002493ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002494ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002495ACCESSORS(Script, eval_from_instructions_offset, Smi,
2496 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002497
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002498#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002499ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2500ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2501ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2502ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2503
2504ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2505ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2506ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2507ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002508#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002509
2510ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002511ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002512ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2513 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002514ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002515ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2516ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002517ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002518ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2519 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002520
2521BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2522 kHiddenPrototypeBit)
2523BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2524BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2525 kNeedsAccessCheckBit)
2526BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2527 kIsExpressionBit)
2528BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2529 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002530BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002531 has_only_simple_this_property_assignments,
2532 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002533BOOL_ACCESSORS(SharedFunctionInfo,
2534 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002535 try_full_codegen,
2536 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002537BOOL_ACCESSORS(SharedFunctionInfo,
2538 compiler_hints,
2539 allows_lazy_compilation,
2540 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002541
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002542#if V8_HOST_ARCH_32_BIT
2543SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2544SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002545 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002546SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002547 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002548SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2549SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002550 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002551SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2552SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002553 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002554SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002555 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002556SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002557 kThisPropertyAssignmentsCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002558#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002559
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002560#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2561 int holder::name() { \
2562 int value = READ_INT_FIELD(this, offset); \
2563 ASSERT(kHeapObjectTag == 1); \
2564 ASSERT((value & kHeapObjectTag) == 0); \
2565 return value >> 1; \
2566 } \
2567 void holder::set_##name(int value) { \
2568 ASSERT(kHeapObjectTag == 1); \
2569 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2570 (value & 0xC0000000) == 0x000000000); \
2571 WRITE_INT_FIELD(this, \
2572 offset, \
2573 (value << 1) & ~kHeapObjectTag); \
2574 }
2575
2576#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2577 INT_ACCESSORS(holder, name, offset)
2578
2579
2580
2581PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2582PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2583 kFormalParameterCountOffset)
2584
2585PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2586 kExpectedNofPropertiesOffset)
2587PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2588
2589PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2590 kStartPositionAndTypeOffset)
2591PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2592
2593PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2594 kFunctionTokenPositionOffset)
2595PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2596 kCompilerHintsOffset)
2597
2598PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2599 kThisPropertyAssignmentsCountOffset)
2600#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002601
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002602ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2603ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2604
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002605bool Script::HasValidSource() {
2606 Object* src = this->source();
2607 if (!src->IsString()) return true;
2608 String* src_str = String::cast(src);
2609 if (!StringShape(src_str).IsExternal()) return true;
2610 if (src_str->IsAsciiRepresentation()) {
2611 return ExternalAsciiString::cast(src)->resource() != NULL;
2612 } else if (src_str->IsTwoByteRepresentation()) {
2613 return ExternalTwoByteString::cast(src)->resource() != NULL;
2614 }
2615 return true;
2616}
2617
2618
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002619void SharedFunctionInfo::DontAdaptArguments() {
2620 ASSERT(code()->kind() == Code::BUILTIN);
2621 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2622}
2623
2624
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002625int SharedFunctionInfo::start_position() {
2626 return start_position_and_type() >> kStartPositionShift;
2627}
2628
2629
2630void SharedFunctionInfo::set_start_position(int start_position) {
2631 set_start_position_and_type((start_position << kStartPositionShift)
2632 | (start_position_and_type() & ~kStartPositionMask));
2633}
2634
2635
2636Code* SharedFunctionInfo::code() {
2637 return Code::cast(READ_FIELD(this, kCodeOffset));
2638}
2639
2640
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002641void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002642 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002643 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002644}
2645
2646
ager@chromium.orgb5737492010-07-15 09:29:43 +00002647SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2648 return reinterpret_cast<SerializedScopeInfo*>(
2649 READ_FIELD(this, kScopeInfoOffset));
2650}
2651
2652
2653void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2654 WriteBarrierMode mode) {
2655 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2656 CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2657}
2658
2659
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002660bool SharedFunctionInfo::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002661 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002662}
2663
2664
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002665bool SharedFunctionInfo::IsApiFunction() {
2666 return function_data()->IsFunctionTemplateInfo();
2667}
2668
2669
2670FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2671 ASSERT(IsApiFunction());
2672 return FunctionTemplateInfo::cast(function_data());
2673}
2674
2675
2676bool SharedFunctionInfo::HasCustomCallGenerator() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00002677 return function_data()->IsSmi();
2678}
2679
2680
2681int SharedFunctionInfo::custom_call_generator_id() {
2682 ASSERT(HasCustomCallGenerator());
2683 return Smi::cast(function_data())->value();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002684}
2685
2686
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002687bool JSFunction::IsBuiltin() {
2688 return context()->global()->IsJSBuiltinsObject();
2689}
2690
2691
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002692Code* JSFunction::code() {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00002693 return Code::cast(READ_FIELD(this, kCodeOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002694}
2695
2696
2697void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00002698 // Skip the write barrier because code is never in new space.
2699 ASSERT(!Heap::InNewSpace(value));
2700 WRITE_FIELD(this, kCodeOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002701}
2702
2703
2704Context* JSFunction::context() {
2705 return Context::cast(READ_FIELD(this, kContextOffset));
2706}
2707
2708
2709Object* JSFunction::unchecked_context() {
2710 return READ_FIELD(this, kContextOffset);
2711}
2712
2713
2714void JSFunction::set_context(Object* value) {
2715 ASSERT(value == Heap::undefined_value() || value->IsContext());
2716 WRITE_FIELD(this, kContextOffset, value);
2717 WRITE_BARRIER(this, kContextOffset);
2718}
2719
2720ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2721 kPrototypeOrInitialMapOffset)
2722
2723
2724Map* JSFunction::initial_map() {
2725 return Map::cast(prototype_or_initial_map());
2726}
2727
2728
2729void JSFunction::set_initial_map(Map* value) {
2730 set_prototype_or_initial_map(value);
2731}
2732
2733
2734bool JSFunction::has_initial_map() {
2735 return prototype_or_initial_map()->IsMap();
2736}
2737
2738
2739bool JSFunction::has_instance_prototype() {
2740 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2741}
2742
2743
2744bool JSFunction::has_prototype() {
2745 return map()->has_non_instance_prototype() || has_instance_prototype();
2746}
2747
2748
2749Object* JSFunction::instance_prototype() {
2750 ASSERT(has_instance_prototype());
2751 if (has_initial_map()) return initial_map()->prototype();
2752 // When there is no initial map and the prototype is a JSObject, the
2753 // initial map field is used for the prototype field.
2754 return prototype_or_initial_map();
2755}
2756
2757
2758Object* JSFunction::prototype() {
2759 ASSERT(has_prototype());
2760 // If the function's prototype property has been set to a non-JSObject
2761 // value, that value is stored in the constructor field of the map.
2762 if (map()->has_non_instance_prototype()) return map()->constructor();
2763 return instance_prototype();
2764}
2765
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002766bool JSFunction::should_have_prototype() {
2767 return map()->function_with_prototype();
2768}
2769
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002770
2771bool JSFunction::is_compiled() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002772 return code() != Builtins::builtin(Builtins::LazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002773}
2774
2775
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002776int JSFunction::NumberOfLiterals() {
2777 return literals()->length();
2778}
2779
2780
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2782 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002783 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002784}
2785
2786
2787void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2788 Object* value) {
2789 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002790 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2791 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2792}
2793
2794
2795Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2796 ASSERT(0 <= id && id < kJSBuiltinsCount);
2797 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2798}
2799
2800
2801void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2802 Code* value) {
2803 ASSERT(0 <= id && id < kJSBuiltinsCount);
2804 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2805 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002806}
2807
2808
2809Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002810 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002811}
2812
2813
2814void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002815 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002816}
2817
2818
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002819ACCESSORS(JSValue, value, Object, kValueOffset)
2820
2821
2822JSValue* JSValue::cast(Object* obj) {
2823 ASSERT(obj->IsJSValue());
2824 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2825 return reinterpret_cast<JSValue*>(obj);
2826}
2827
2828
2829INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002830ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002831
2832
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002833byte* Code::instruction_start() {
2834 return FIELD_ADDR(this, kHeaderSize);
2835}
2836
2837
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002838byte* Code::instruction_end() {
2839 return instruction_start() + instruction_size();
2840}
2841
2842
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002843int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002844 return RoundUp(instruction_size(), kObjectAlignment);
2845}
2846
2847
2848ByteArray* Code::unchecked_relocation_info() {
2849 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002850}
2851
2852
2853byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00002854 return unchecked_relocation_info()->GetDataStartAddress();
2855}
2856
2857
2858int Code::relocation_size() {
2859 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002860}
2861
2862
2863byte* Code::entry() {
2864 return instruction_start();
2865}
2866
2867
2868bool Code::contains(byte* pc) {
2869 return (instruction_start() <= pc) &&
2870 (pc < instruction_start() + instruction_size());
2871}
2872
2873
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002874ACCESSORS(JSArray, length, Object, kLengthOffset)
2875
2876
ager@chromium.org236ad962008-09-25 09:45:57 +00002877ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002878
2879
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002880JSRegExp::Type JSRegExp::TypeTag() {
2881 Object* data = this->data();
2882 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2883 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2884 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002885}
2886
2887
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002888int JSRegExp::CaptureCount() {
2889 switch (TypeTag()) {
2890 case ATOM:
2891 return 0;
2892 case IRREGEXP:
2893 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2894 default:
2895 UNREACHABLE();
2896 return -1;
2897 }
2898}
2899
2900
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002901JSRegExp::Flags JSRegExp::GetFlags() {
2902 ASSERT(this->data()->IsFixedArray());
2903 Object* data = this->data();
2904 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2905 return Flags(smi->value());
2906}
2907
2908
2909String* JSRegExp::Pattern() {
2910 ASSERT(this->data()->IsFixedArray());
2911 Object* data = this->data();
2912 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2913 return pattern;
2914}
2915
2916
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002917Object* JSRegExp::DataAt(int index) {
2918 ASSERT(TypeTag() != NOT_COMPILED);
2919 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002920}
2921
2922
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002923void JSRegExp::SetDataAt(int index, Object* value) {
2924 ASSERT(TypeTag() != NOT_COMPILED);
2925 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2926 FixedArray::cast(data())->set(index, value);
2927}
2928
2929
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002930JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002931 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002932 if (array->IsFixedArray()) {
2933 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2934 if (array->map() == Heap::fixed_array_map()) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002935 ASSERT(map()->has_fast_elements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002936 return FAST_ELEMENTS;
2937 }
2938 ASSERT(array->IsDictionary());
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002939 ASSERT(!map()->has_fast_elements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002940 return DICTIONARY_ELEMENTS;
2941 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002942 ASSERT(!map()->has_fast_elements());
ager@chromium.org3811b432009-10-28 14:53:37 +00002943 if (array->IsExternalArray()) {
2944 switch (array->map()->instance_type()) {
2945 case EXTERNAL_BYTE_ARRAY_TYPE:
2946 return EXTERNAL_BYTE_ELEMENTS;
2947 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2948 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2949 case EXTERNAL_SHORT_ARRAY_TYPE:
2950 return EXTERNAL_SHORT_ELEMENTS;
2951 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2952 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2953 case EXTERNAL_INT_ARRAY_TYPE:
2954 return EXTERNAL_INT_ELEMENTS;
2955 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2956 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2957 default:
2958 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2959 return EXTERNAL_FLOAT_ELEMENTS;
2960 }
2961 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002962 ASSERT(array->IsPixelArray());
2963 return PIXEL_ELEMENTS;
2964}
2965
2966
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002967bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002968 return GetElementsKind() == FAST_ELEMENTS;
2969}
2970
2971
2972bool JSObject::HasDictionaryElements() {
2973 return GetElementsKind() == DICTIONARY_ELEMENTS;
2974}
2975
2976
2977bool JSObject::HasPixelElements() {
2978 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002979}
2980
2981
ager@chromium.org3811b432009-10-28 14:53:37 +00002982bool JSObject::HasExternalArrayElements() {
2983 return (HasExternalByteElements() ||
2984 HasExternalUnsignedByteElements() ||
2985 HasExternalShortElements() ||
2986 HasExternalUnsignedShortElements() ||
2987 HasExternalIntElements() ||
2988 HasExternalUnsignedIntElements() ||
2989 HasExternalFloatElements());
2990}
2991
2992
2993bool JSObject::HasExternalByteElements() {
2994 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2995}
2996
2997
2998bool JSObject::HasExternalUnsignedByteElements() {
2999 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3000}
3001
3002
3003bool JSObject::HasExternalShortElements() {
3004 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3005}
3006
3007
3008bool JSObject::HasExternalUnsignedShortElements() {
3009 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3010}
3011
3012
3013bool JSObject::HasExternalIntElements() {
3014 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3015}
3016
3017
3018bool JSObject::HasExternalUnsignedIntElements() {
3019 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3020}
3021
3022
3023bool JSObject::HasExternalFloatElements() {
3024 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3025}
3026
3027
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003028bool JSObject::HasNamedInterceptor() {
3029 return map()->has_named_interceptor();
3030}
3031
3032
3033bool JSObject::HasIndexedInterceptor() {
3034 return map()->has_indexed_interceptor();
3035}
3036
3037
ager@chromium.org5c838252010-02-19 08:53:10 +00003038bool JSObject::AllowsSetElementsLength() {
3039 bool result = elements()->IsFixedArray();
3040 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3041 return result;
3042}
3043
3044
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003045StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003046 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003047 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003048}
3049
3050
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003051NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003052 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003053 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003054}
3055
3056
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003057bool String::IsHashFieldComputed(uint32_t field) {
3058 return (field & kHashNotComputedMask) == 0;
3059}
3060
3061
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003062bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003063 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003064}
3065
3066
3067uint32_t String::Hash() {
3068 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003069 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003070 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003071 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003072 return ComputeAndSetHash();
3073}
3074
3075
ager@chromium.org7c537e22008-10-16 08:43:32 +00003076StringHasher::StringHasher(int length)
3077 : length_(length),
3078 raw_running_hash_(0),
3079 array_index_(0),
3080 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3081 is_first_char_(true),
3082 is_valid_(true) { }
3083
3084
3085bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003086 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003087}
3088
3089
3090void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003091 // Use the Jenkins one-at-a-time hash function to update the hash
3092 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003093 raw_running_hash_ += c;
3094 raw_running_hash_ += (raw_running_hash_ << 10);
3095 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003096 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003097 if (is_array_index_) {
3098 if (c < '0' || c > '9') {
3099 is_array_index_ = false;
3100 } else {
3101 int d = c - '0';
3102 if (is_first_char_) {
3103 is_first_char_ = false;
3104 if (c == '0' && length_ > 1) {
3105 is_array_index_ = false;
3106 return;
3107 }
3108 }
3109 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3110 is_array_index_ = false;
3111 } else {
3112 array_index_ = array_index_ * 10 + d;
3113 }
3114 }
3115 }
3116}
3117
3118
3119void StringHasher::AddCharacterNoIndex(uc32 c) {
3120 ASSERT(!is_array_index());
3121 raw_running_hash_ += c;
3122 raw_running_hash_ += (raw_running_hash_ << 10);
3123 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3124}
3125
3126
3127uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003128 // Get the calculated raw hash value and do some more bit ops to distribute
3129 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003130 uint32_t result = raw_running_hash_;
3131 result += (result << 3);
3132 result ^= (result >> 11);
3133 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003134 if (result == 0) {
3135 result = 27;
3136 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003137 return result;
3138}
3139
3140
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003141bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003142 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003143 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3144 return false;
3145 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003146 return SlowAsArrayIndex(index);
3147}
3148
3149
3150Object* JSObject::GetPrototype() {
3151 return JSObject::cast(this)->map()->prototype();
3152}
3153
3154
3155PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3156 return GetPropertyAttributeWithReceiver(this, key);
3157}
3158
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003159// TODO(504): this may be useful in other places too where JSGlobalProxy
3160// is used.
3161Object* JSObject::BypassGlobalProxy() {
3162 if (IsJSGlobalProxy()) {
3163 Object* proto = GetPrototype();
3164 if (proto->IsNull()) return Heap::undefined_value();
3165 ASSERT(proto->IsJSGlobalObject());
3166 return proto;
3167 }
3168 return this;
3169}
3170
3171
3172bool JSObject::HasHiddenPropertiesObject() {
3173 ASSERT(!IsJSGlobalProxy());
3174 return GetPropertyAttributePostInterceptor(this,
3175 Heap::hidden_symbol(),
3176 false) != ABSENT;
3177}
3178
3179
3180Object* JSObject::GetHiddenPropertiesObject() {
3181 ASSERT(!IsJSGlobalProxy());
3182 PropertyAttributes attributes;
3183 return GetLocalPropertyPostInterceptor(this,
3184 Heap::hidden_symbol(),
3185 &attributes);
3186}
3187
3188
3189Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3190 ASSERT(!IsJSGlobalProxy());
3191 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3192 hidden_obj,
3193 DONT_ENUM);
3194}
3195
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003196
3197bool JSObject::HasElement(uint32_t index) {
3198 return HasElementWithReceiver(this, index);
3199}
3200
3201
3202bool AccessorInfo::all_can_read() {
3203 return BooleanBit::get(flag(), kAllCanReadBit);
3204}
3205
3206
3207void AccessorInfo::set_all_can_read(bool value) {
3208 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3209}
3210
3211
3212bool AccessorInfo::all_can_write() {
3213 return BooleanBit::get(flag(), kAllCanWriteBit);
3214}
3215
3216
3217void AccessorInfo::set_all_can_write(bool value) {
3218 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3219}
3220
3221
ager@chromium.org870a0b62008-11-04 11:43:05 +00003222bool AccessorInfo::prohibits_overwriting() {
3223 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3224}
3225
3226
3227void AccessorInfo::set_prohibits_overwriting(bool value) {
3228 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3229}
3230
3231
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003232PropertyAttributes AccessorInfo::property_attributes() {
3233 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3234}
3235
3236
3237void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3238 ASSERT(AttributesField::is_valid(attributes));
3239 int rest_value = flag()->value() & ~AttributesField::mask();
3240 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3241}
3242
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003243template<typename Shape, typename Key>
3244void Dictionary<Shape, Key>::SetEntry(int entry,
3245 Object* key,
3246 Object* value,
3247 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003248 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003249 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003250 AssertNoAllocation no_gc;
3251 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003252 FixedArray::set(index, key, mode);
3253 FixedArray::set(index+1, value, mode);
3254 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003255}
3256
3257
3258void Map::ClearCodeCache() {
3259 // No write barrier is needed since empty_fixed_array is not in new space.
3260 // Please note this function is used during marking:
3261 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003262 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3263 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003264}
3265
3266
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003267void JSArray::EnsureSize(int required_size) {
3268 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003269 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003270 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3271 if (elts->length() < required_size) {
3272 // Doubling in size would be overkill, but leave some slack to avoid
3273 // constantly growing.
3274 Expand(required_size + (required_size >> 3));
3275 // It's a performance benefit to keep a frequently used array in new-space.
3276 } else if (!Heap::new_space()->Contains(elts) &&
3277 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3278 // Expand will allocate a new backing store in new space even if the size
3279 // we asked for isn't larger than what we had before.
3280 Expand(required_size);
3281 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003282}
3283
3284
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003285void JSArray::set_length(Smi* length) {
3286 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3287}
3288
3289
ager@chromium.org7c537e22008-10-16 08:43:32 +00003290void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003291 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003292 set_elements(storage);
3293}
3294
3295
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003296Object* FixedArray::Copy() {
3297 if (length() == 0) return this;
3298 return Heap::CopyFixedArray(this);
3299}
3300
3301
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003302int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3303 return map->instance_size();
3304}
3305
3306
3307void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3308 v->VisitExternalReference(
3309 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3310}
3311
3312
3313template<typename StaticVisitor>
3314void Proxy::ProxyIterateBody() {
3315 StaticVisitor::VisitExternalReference(
3316 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3317}
3318
3319
3320void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3321 typedef v8::String::ExternalAsciiStringResource Resource;
3322 v->VisitExternalAsciiString(
3323 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3324}
3325
3326
3327template<typename StaticVisitor>
3328void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3329 typedef v8::String::ExternalAsciiStringResource Resource;
3330 StaticVisitor::VisitExternalAsciiString(
3331 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3332}
3333
3334
3335void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3336 typedef v8::String::ExternalStringResource Resource;
3337 v->VisitExternalTwoByteString(
3338 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3339}
3340
3341
3342template<typename StaticVisitor>
3343void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3344 typedef v8::String::ExternalStringResource Resource;
3345 StaticVisitor::VisitExternalTwoByteString(
3346 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3347}
3348
3349#define SLOT_ADDR(obj, offset) \
3350 reinterpret_cast<Object**>((obj)->address() + offset)
3351
3352template<int start_offset, int end_offset, int size>
3353void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3354 HeapObject* obj,
3355 ObjectVisitor* v) {
3356 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3357}
3358
3359
3360template<int start_offset>
3361void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3362 int object_size,
3363 ObjectVisitor* v) {
3364 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3365}
3366
3367#undef SLOT_ADDR
3368
3369
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003370#undef CAST_ACCESSOR
3371#undef INT_ACCESSORS
3372#undef SMI_ACCESSORS
3373#undef ACCESSORS
3374#undef FIELD_ADDR
3375#undef READ_FIELD
3376#undef WRITE_FIELD
3377#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003378#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003379#undef READ_MEMADDR_FIELD
3380#undef WRITE_MEMADDR_FIELD
3381#undef READ_DOUBLE_FIELD
3382#undef WRITE_DOUBLE_FIELD
3383#undef READ_INT_FIELD
3384#undef WRITE_INT_FIELD
3385#undef READ_SHORT_FIELD
3386#undef WRITE_SHORT_FIELD
3387#undef READ_BYTE_FIELD
3388#undef WRITE_BYTE_FIELD
3389
3390
3391} } // namespace v8::internal
3392
3393#endif // V8_OBJECTS_INL_H_