blob: f9def82d23f707ec4c9e6f2145672c931092ee34 [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
1338void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001339 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001340 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001341 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001342 }
1343}
1344
1345
1346bool JSObject::HasFastProperties() {
1347 return !properties()->IsDictionary();
1348}
1349
1350
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001351bool Object::ToArrayIndex(uint32_t* index) {
1352 if (IsSmi()) {
1353 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354 if (value < 0) return false;
1355 *index = value;
1356 return true;
1357 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001358 if (IsHeapNumber()) {
1359 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001360 uint32_t uint_value = static_cast<uint32_t>(value);
1361 if (value == static_cast<double>(uint_value)) {
1362 *index = uint_value;
1363 return true;
1364 }
1365 }
1366 return false;
1367}
1368
1369
1370bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1371 if (!this->IsJSValue()) return false;
1372
1373 JSValue* js_value = JSValue::cast(this);
1374 if (!js_value->value()->IsString()) return false;
1375
1376 String* str = String::cast(js_value->value());
1377 if (index >= (uint32_t)str->length()) return false;
1378
1379 return true;
1380}
1381
1382
1383Object* FixedArray::get(int index) {
1384 ASSERT(index >= 0 && index < this->length());
1385 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1386}
1387
1388
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001389void FixedArray::set(int index, Smi* value) {
1390 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1391 int offset = kHeaderSize + index * kPointerSize;
1392 WRITE_FIELD(this, offset, value);
1393}
1394
1395
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001396void FixedArray::set(int index, Object* value) {
1397 ASSERT(index >= 0 && index < this->length());
1398 int offset = kHeaderSize + index * kPointerSize;
1399 WRITE_FIELD(this, offset, value);
1400 WRITE_BARRIER(this, offset);
1401}
1402
1403
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001404WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1406 return UPDATE_WRITE_BARRIER;
1407}
1408
1409
1410void FixedArray::set(int index,
1411 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001412 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001413 ASSERT(index >= 0 && index < this->length());
1414 int offset = kHeaderSize + index * kPointerSize;
1415 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001416 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417}
1418
1419
1420void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1421 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001422 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1424}
1425
1426
1427void FixedArray::set_undefined(int index) {
1428 ASSERT(index >= 0 && index < this->length());
1429 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1430 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1431 Heap::undefined_value());
1432}
1433
1434
ager@chromium.org236ad962008-09-25 09:45:57 +00001435void FixedArray::set_null(int index) {
1436 ASSERT(index >= 0 && index < this->length());
1437 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1438 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1439}
1440
1441
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001442void FixedArray::set_the_hole(int index) {
1443 ASSERT(index >= 0 && index < this->length());
1444 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1445 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1446}
1447
1448
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001449Object** FixedArray::data_start() {
1450 return HeapObject::RawField(this, kHeaderSize);
1451}
1452
1453
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001454bool DescriptorArray::IsEmpty() {
1455 ASSERT(this == Heap::empty_descriptor_array() ||
1456 this->length() > 2);
1457 return this == Heap::empty_descriptor_array();
1458}
1459
1460
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1462 Object* tmp = array->get(first);
1463 fast_set(array, first, array->get(second));
1464 fast_set(array, second, tmp);
1465}
1466
1467
1468int DescriptorArray::Search(String* name) {
1469 SLOW_ASSERT(IsSortedNoDuplicates());
1470
1471 // Check for empty descriptor array.
1472 int nof = number_of_descriptors();
1473 if (nof == 0) return kNotFound;
1474
1475 // Fast case: do linear search for small arrays.
1476 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001477 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001478 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001479 }
1480
1481 // Slow case: perform binary search.
1482 return BinarySearch(name, 0, nof - 1);
1483}
1484
1485
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001486String* DescriptorArray::GetKey(int descriptor_number) {
1487 ASSERT(descriptor_number < number_of_descriptors());
1488 return String::cast(get(ToKeyIndex(descriptor_number)));
1489}
1490
1491
1492Object* DescriptorArray::GetValue(int descriptor_number) {
1493 ASSERT(descriptor_number < number_of_descriptors());
1494 return GetContentArray()->get(ToValueIndex(descriptor_number));
1495}
1496
1497
1498Smi* DescriptorArray::GetDetails(int descriptor_number) {
1499 ASSERT(descriptor_number < number_of_descriptors());
1500 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1501}
1502
1503
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001504PropertyType DescriptorArray::GetType(int descriptor_number) {
1505 ASSERT(descriptor_number < number_of_descriptors());
1506 return PropertyDetails(GetDetails(descriptor_number)).type();
1507}
1508
1509
1510int DescriptorArray::GetFieldIndex(int descriptor_number) {
1511 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1512}
1513
1514
1515JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1516 return JSFunction::cast(GetValue(descriptor_number));
1517}
1518
1519
1520Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1521 ASSERT(GetType(descriptor_number) == CALLBACKS);
1522 return GetValue(descriptor_number);
1523}
1524
1525
1526AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1527 ASSERT(GetType(descriptor_number) == CALLBACKS);
1528 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1529 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1530}
1531
1532
1533bool DescriptorArray::IsProperty(int descriptor_number) {
1534 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1535}
1536
1537
1538bool DescriptorArray::IsTransition(int descriptor_number) {
1539 PropertyType t = GetType(descriptor_number);
1540 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1541}
1542
1543
1544bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1545 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1546}
1547
1548
1549bool DescriptorArray::IsDontEnum(int descriptor_number) {
1550 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1551}
1552
1553
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001554void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1555 desc->Init(GetKey(descriptor_number),
1556 GetValue(descriptor_number),
1557 GetDetails(descriptor_number));
1558}
1559
1560
1561void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1562 // Range check.
1563 ASSERT(descriptor_number < number_of_descriptors());
1564
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001565 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001566 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1567 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1568
1569 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1570 FixedArray* content_array = GetContentArray();
1571 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1572 fast_set(content_array, ToDetailsIndex(descriptor_number),
1573 desc->GetDetails().AsSmi());
1574}
1575
1576
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001577void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1578 Descriptor desc;
1579 src->Get(src_index, &desc);
1580 Set(index, &desc);
1581}
1582
1583
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001584void DescriptorArray::Swap(int first, int second) {
1585 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1586 FixedArray* content_array = GetContentArray();
1587 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1588 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1589}
1590
1591
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001592bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001593 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001594 if (!max_index_object->IsSmi()) return false;
1595 return 0 !=
1596 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1597}
1598
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001599uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001601 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001602 if (!max_index_object->IsSmi()) return 0;
1603 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1604 return value >> kRequiresSlowElementsTagSize;
1605}
1606
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001607void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001608 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001609}
1610
1611
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612// ------------------------------------
1613// Cast operations
1614
1615
1616CAST_ACCESSOR(FixedArray)
1617CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001618CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001619CAST_ACCESSOR(JSFunctionResultCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001620CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001621CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001622CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623CAST_ACCESSOR(String)
1624CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001625CAST_ACCESSOR(SeqAsciiString)
1626CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628CAST_ACCESSOR(ExternalString)
1629CAST_ACCESSOR(ExternalAsciiString)
1630CAST_ACCESSOR(ExternalTwoByteString)
1631CAST_ACCESSOR(JSObject)
1632CAST_ACCESSOR(Smi)
1633CAST_ACCESSOR(Failure)
1634CAST_ACCESSOR(HeapObject)
1635CAST_ACCESSOR(HeapNumber)
1636CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001637CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638CAST_ACCESSOR(SharedFunctionInfo)
1639CAST_ACCESSOR(Map)
1640CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001641CAST_ACCESSOR(GlobalObject)
1642CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643CAST_ACCESSOR(JSGlobalObject)
1644CAST_ACCESSOR(JSBuiltinsObject)
1645CAST_ACCESSOR(Code)
1646CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001647CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648CAST_ACCESSOR(Proxy)
1649CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001650CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001651CAST_ACCESSOR(ExternalArray)
1652CAST_ACCESSOR(ExternalByteArray)
1653CAST_ACCESSOR(ExternalUnsignedByteArray)
1654CAST_ACCESSOR(ExternalShortArray)
1655CAST_ACCESSOR(ExternalUnsignedShortArray)
1656CAST_ACCESSOR(ExternalIntArray)
1657CAST_ACCESSOR(ExternalUnsignedIntArray)
1658CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001659CAST_ACCESSOR(Struct)
1660
1661
1662#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1663 STRUCT_LIST(MAKE_STRUCT_CAST)
1664#undef MAKE_STRUCT_CAST
1665
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001666
1667template <typename Shape, typename Key>
1668HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001669 ASSERT(obj->IsHashTable());
1670 return reinterpret_cast<HashTable*>(obj);
1671}
1672
1673
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001674SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1675SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1676
1677INT_ACCESSORS(PixelArray, length, kLengthOffset)
1678INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001679
1680
ager@chromium.orgac091b72010-05-05 07:34:42 +00001681SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001682
1683
1684uint32_t String::hash_field() {
1685 return READ_UINT32_FIELD(this, kHashFieldOffset);
1686}
1687
1688
1689void String::set_hash_field(uint32_t value) {
1690 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001691#if V8_HOST_ARCH_64_BIT
1692 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1693#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001694}
1695
1696
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001697bool String::Equals(String* other) {
1698 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001699 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1700 return false;
1701 }
1702 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703}
1704
1705
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001706Object* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001707 if (!StringShape(this).IsCons()) return this;
1708 ConsString* cons = ConsString::cast(this);
1709 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001710 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001711}
1712
1713
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001714String* String::TryFlattenGetString(PretenureFlag pretenure) {
1715 Object* flat = TryFlatten(pretenure);
1716 return flat->IsFailure() ? this : String::cast(flat);
1717}
1718
1719
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001720uint16_t String::Get(int index) {
1721 ASSERT(index >= 0 && index < length());
1722 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001723 case kSeqStringTag | kAsciiStringTag:
1724 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1725 case kSeqStringTag | kTwoByteStringTag:
1726 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1727 case kConsStringTag | kAsciiStringTag:
1728 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001729 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001730 case kExternalStringTag | kAsciiStringTag:
1731 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1732 case kExternalStringTag | kTwoByteStringTag:
1733 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001734 default:
1735 break;
1736 }
1737
1738 UNREACHABLE();
1739 return 0;
1740}
1741
1742
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001743void String::Set(int index, uint16_t value) {
1744 ASSERT(index >= 0 && index < length());
1745 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001746
ager@chromium.org5ec48922009-05-05 07:25:34 +00001747 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001748 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1749 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001750}
1751
1752
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001753bool String::IsFlat() {
1754 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001755 case kConsStringTag: {
1756 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001757 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001758 return second->length() == 0;
1759 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001760 default:
1761 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001762 }
1763}
1764
1765
ager@chromium.org7c537e22008-10-16 08:43:32 +00001766uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001767 ASSERT(index >= 0 && index < length());
1768 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1769}
1770
1771
ager@chromium.org7c537e22008-10-16 08:43:32 +00001772void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001773 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1774 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1775 static_cast<byte>(value));
1776}
1777
1778
ager@chromium.org7c537e22008-10-16 08:43:32 +00001779Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001780 return FIELD_ADDR(this, kHeaderSize);
1781}
1782
1783
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001784char* SeqAsciiString::GetChars() {
1785 return reinterpret_cast<char*>(GetCharsAddress());
1786}
1787
1788
ager@chromium.org7c537e22008-10-16 08:43:32 +00001789Address SeqTwoByteString::GetCharsAddress() {
1790 return FIELD_ADDR(this, kHeaderSize);
1791}
1792
1793
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001794uc16* SeqTwoByteString::GetChars() {
1795 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1796}
1797
1798
ager@chromium.org7c537e22008-10-16 08:43:32 +00001799uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001800 ASSERT(index >= 0 && index < length());
1801 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1802}
1803
1804
ager@chromium.org7c537e22008-10-16 08:43:32 +00001805void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001806 ASSERT(index >= 0 && index < length());
1807 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1808}
1809
1810
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001811int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001812 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001813}
1814
1815
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001816int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001817 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001818}
1819
1820
ager@chromium.org870a0b62008-11-04 11:43:05 +00001821String* ConsString::first() {
1822 return String::cast(READ_FIELD(this, kFirstOffset));
1823}
1824
1825
1826Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001827 return READ_FIELD(this, kFirstOffset);
1828}
1829
1830
ager@chromium.org870a0b62008-11-04 11:43:05 +00001831void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001832 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001833 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001834}
1835
1836
ager@chromium.org870a0b62008-11-04 11:43:05 +00001837String* ConsString::second() {
1838 return String::cast(READ_FIELD(this, kSecondOffset));
1839}
1840
1841
1842Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001843 return READ_FIELD(this, kSecondOffset);
1844}
1845
1846
ager@chromium.org870a0b62008-11-04 11:43:05 +00001847void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001848 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001849 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001850}
1851
1852
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001853ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1854 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1855}
1856
1857
1858void ExternalAsciiString::set_resource(
1859 ExternalAsciiString::Resource* resource) {
1860 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1861}
1862
1863
1864ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1865 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1866}
1867
1868
1869void ExternalTwoByteString::set_resource(
1870 ExternalTwoByteString::Resource* resource) {
1871 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1872}
1873
1874
ager@chromium.orgac091b72010-05-05 07:34:42 +00001875void JSFunctionResultCache::MakeZeroSize() {
1876 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1877 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1878}
1879
1880
1881void JSFunctionResultCache::Clear() {
1882 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1883 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1884 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1885 MakeZeroSize();
1886}
1887
1888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889byte ByteArray::get(int index) {
1890 ASSERT(index >= 0 && index < this->length());
1891 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1892}
1893
1894
1895void ByteArray::set(int index, byte value) {
1896 ASSERT(index >= 0 && index < this->length());
1897 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1898}
1899
1900
1901int ByteArray::get_int(int index) {
1902 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1903 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1904}
1905
1906
1907ByteArray* ByteArray::FromDataStartAddress(Address address) {
1908 ASSERT_TAG_ALIGNED(address);
1909 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1910}
1911
1912
1913Address ByteArray::GetDataStartAddress() {
1914 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1915}
1916
1917
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001918uint8_t* PixelArray::external_pointer() {
1919 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1920 return reinterpret_cast<uint8_t*>(ptr);
1921}
1922
1923
1924void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1925 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1926 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1927}
1928
1929
1930uint8_t PixelArray::get(int index) {
1931 ASSERT((index >= 0) && (index < this->length()));
1932 uint8_t* ptr = external_pointer();
1933 return ptr[index];
1934}
1935
1936
1937void PixelArray::set(int index, uint8_t value) {
1938 ASSERT((index >= 0) && (index < this->length()));
1939 uint8_t* ptr = external_pointer();
1940 ptr[index] = value;
1941}
1942
1943
ager@chromium.org3811b432009-10-28 14:53:37 +00001944void* ExternalArray::external_pointer() {
1945 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1946 return reinterpret_cast<void*>(ptr);
1947}
1948
1949
1950void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1951 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1952 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1953}
1954
1955
1956int8_t ExternalByteArray::get(int index) {
1957 ASSERT((index >= 0) && (index < this->length()));
1958 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1959 return ptr[index];
1960}
1961
1962
1963void ExternalByteArray::set(int index, int8_t value) {
1964 ASSERT((index >= 0) && (index < this->length()));
1965 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1966 ptr[index] = value;
1967}
1968
1969
1970uint8_t ExternalUnsignedByteArray::get(int index) {
1971 ASSERT((index >= 0) && (index < this->length()));
1972 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1973 return ptr[index];
1974}
1975
1976
1977void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1978 ASSERT((index >= 0) && (index < this->length()));
1979 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1980 ptr[index] = value;
1981}
1982
1983
1984int16_t ExternalShortArray::get(int index) {
1985 ASSERT((index >= 0) && (index < this->length()));
1986 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1987 return ptr[index];
1988}
1989
1990
1991void ExternalShortArray::set(int index, int16_t value) {
1992 ASSERT((index >= 0) && (index < this->length()));
1993 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1994 ptr[index] = value;
1995}
1996
1997
1998uint16_t ExternalUnsignedShortArray::get(int index) {
1999 ASSERT((index >= 0) && (index < this->length()));
2000 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2001 return ptr[index];
2002}
2003
2004
2005void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2006 ASSERT((index >= 0) && (index < this->length()));
2007 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2008 ptr[index] = value;
2009}
2010
2011
2012int32_t ExternalIntArray::get(int index) {
2013 ASSERT((index >= 0) && (index < this->length()));
2014 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2015 return ptr[index];
2016}
2017
2018
2019void ExternalIntArray::set(int index, int32_t value) {
2020 ASSERT((index >= 0) && (index < this->length()));
2021 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2022 ptr[index] = value;
2023}
2024
2025
2026uint32_t ExternalUnsignedIntArray::get(int index) {
2027 ASSERT((index >= 0) && (index < this->length()));
2028 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2029 return ptr[index];
2030}
2031
2032
2033void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2034 ASSERT((index >= 0) && (index < this->length()));
2035 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2036 ptr[index] = value;
2037}
2038
2039
2040float ExternalFloatArray::get(int index) {
2041 ASSERT((index >= 0) && (index < this->length()));
2042 float* ptr = static_cast<float*>(external_pointer());
2043 return ptr[index];
2044}
2045
2046
2047void ExternalFloatArray::set(int index, float value) {
2048 ASSERT((index >= 0) && (index < this->length()));
2049 float* ptr = static_cast<float*>(external_pointer());
2050 ptr[index] = value;
2051}
2052
2053
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002054int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002055 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2056}
2057
2058
2059int Map::inobject_properties() {
2060 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002061}
2062
2063
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002064int Map::pre_allocated_property_fields() {
2065 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2066}
2067
2068
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002069int HeapObject::SizeFromMap(Map* map) {
2070 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002071 // Only inline the most frequent cases.
2072 if (instance_type == JS_OBJECT_TYPE ||
2073 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
2074 (kStringTag | kConsStringTag) ||
2075 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002076 if (instance_type == FIXED_ARRAY_TYPE) {
2077 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
2078 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002079 if (instance_type == BYTE_ARRAY_TYPE) {
2080 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2081 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002082 // Otherwise do the general size computation.
2083 return SlowSizeFromMap(map);
2084}
2085
2086
2087void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002088 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002089 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002090 ASSERT(0 <= value && value < 256);
2091 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2092}
2093
2094
ager@chromium.org7c537e22008-10-16 08:43:32 +00002095void Map::set_inobject_properties(int value) {
2096 ASSERT(0 <= value && value < 256);
2097 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2098}
2099
2100
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002101void Map::set_pre_allocated_property_fields(int value) {
2102 ASSERT(0 <= value && value < 256);
2103 WRITE_BYTE_FIELD(this,
2104 kPreAllocatedPropertyFieldsOffset,
2105 static_cast<byte>(value));
2106}
2107
2108
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002109InstanceType Map::instance_type() {
2110 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2111}
2112
2113
2114void Map::set_instance_type(InstanceType value) {
2115 ASSERT(0 <= value && value < 256);
2116 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2117}
2118
2119
2120int Map::unused_property_fields() {
2121 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2122}
2123
2124
2125void Map::set_unused_property_fields(int value) {
2126 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2127}
2128
2129
2130byte Map::bit_field() {
2131 return READ_BYTE_FIELD(this, kBitFieldOffset);
2132}
2133
2134
2135void Map::set_bit_field(byte value) {
2136 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2137}
2138
2139
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002140byte Map::bit_field2() {
2141 return READ_BYTE_FIELD(this, kBitField2Offset);
2142}
2143
2144
2145void Map::set_bit_field2(byte value) {
2146 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2147}
2148
2149
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002150void Map::set_non_instance_prototype(bool value) {
2151 if (value) {
2152 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2153 } else {
2154 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2155 }
2156}
2157
2158
2159bool Map::has_non_instance_prototype() {
2160 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2161}
2162
2163
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002164void Map::set_function_with_prototype(bool value) {
2165 if (value) {
2166 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2167 } else {
2168 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2169 }
2170}
2171
2172
2173bool Map::function_with_prototype() {
2174 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2175}
2176
2177
ager@chromium.org870a0b62008-11-04 11:43:05 +00002178void Map::set_is_access_check_needed(bool access_check_needed) {
2179 if (access_check_needed) {
2180 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2181 } else {
2182 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2183 }
2184}
2185
2186
2187bool Map::is_access_check_needed() {
2188 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2189}
2190
2191
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192Code::Flags Code::flags() {
2193 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2194}
2195
2196
2197void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002198 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002199 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002200 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2201 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002202 ExtractArgumentsCountFromFlags(flags) >= 0);
2203 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2204}
2205
2206
2207Code::Kind Code::kind() {
2208 return ExtractKindFromFlags(flags());
2209}
2210
2211
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002212InLoopFlag Code::ic_in_loop() {
2213 return ExtractICInLoopFromFlags(flags());
2214}
2215
2216
kasper.lund7276f142008-07-30 08:49:36 +00002217InlineCacheState Code::ic_state() {
2218 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002219 // Only allow uninitialized or debugger states for non-IC code
2220 // objects. This is used in the debugger to determine whether or not
2221 // a call to code object has been replaced with a debug break call.
2222 ASSERT(is_inline_cache_stub() ||
2223 result == UNINITIALIZED ||
2224 result == DEBUG_BREAK ||
2225 result == DEBUG_PREPARE_STEP_IN);
2226 return result;
2227}
2228
2229
2230PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002231 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002232 return ExtractTypeFromFlags(flags());
2233}
2234
2235
2236int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002237 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002238 return ExtractArgumentsCountFromFlags(flags());
2239}
2240
2241
2242CodeStub::Major Code::major_key() {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002243 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002244 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2245 kStubMajorKeyOffset));
2246}
2247
2248
2249void Code::set_major_key(CodeStub::Major major) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002250 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002251 ASSERT(0 <= major && major < 256);
2252 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002253}
2254
2255
2256bool Code::is_inline_cache_stub() {
2257 Kind kind = this->kind();
2258 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2259}
2260
2261
2262Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002263 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002264 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002265 PropertyType type,
2266 int argc) {
2267 // Compute the bit mask.
2268 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002269 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002270 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002271 bits |= type << kFlagsTypeShift;
2272 bits |= argc << kFlagsArgumentsCountShift;
2273 // Cast to flags and validate result before returning it.
2274 Flags result = static_cast<Flags>(bits);
2275 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002276 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002277 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002278 ASSERT(ExtractTypeFromFlags(result) == type);
2279 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2280 return result;
2281}
2282
2283
2284Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2285 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002286 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002287 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002288 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002289}
2290
2291
2292Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2293 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2294 return static_cast<Kind>(bits);
2295}
2296
2297
kasper.lund7276f142008-07-30 08:49:36 +00002298InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2299 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002300 return static_cast<InlineCacheState>(bits);
2301}
2302
2303
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002304InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2305 int bits = (flags & kFlagsICInLoopMask);
2306 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2307}
2308
2309
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002310PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2311 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2312 return static_cast<PropertyType>(bits);
2313}
2314
2315
2316int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2317 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2318}
2319
2320
2321Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2322 int bits = flags & ~kFlagsTypeMask;
2323 return static_cast<Flags>(bits);
2324}
2325
2326
ager@chromium.org8bb60582008-12-11 12:02:20 +00002327Code* Code::GetCodeFromTargetAddress(Address address) {
2328 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2329 // GetCodeFromTargetAddress might be called when marking objects during mark
2330 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2331 // Code::cast. Code::cast does not work when the object's map is
2332 // marked.
2333 Code* result = reinterpret_cast<Code*>(code);
2334 return result;
2335}
2336
2337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002338Object* Map::prototype() {
2339 return READ_FIELD(this, kPrototypeOffset);
2340}
2341
2342
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002343void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002344 ASSERT(value->IsNull() || value->IsJSObject());
2345 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002346 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002347}
2348
2349
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002350Object* Map::GetFastElementsMap() {
2351 if (has_fast_elements()) return this;
2352 Object* obj = CopyDropTransitions();
2353 if (obj->IsFailure()) return obj;
2354 Map* new_map = Map::cast(obj);
2355 new_map->set_has_fast_elements(true);
2356 return new_map;
2357}
2358
2359
2360Object* Map::GetSlowElementsMap() {
2361 if (!has_fast_elements()) return this;
2362 Object* obj = CopyDropTransitions();
2363 if (obj->IsFailure()) return obj;
2364 Map* new_map = Map::cast(obj);
2365 new_map->set_has_fast_elements(false);
2366 return new_map;
2367}
2368
2369
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002370ACCESSORS(Map, instance_descriptors, DescriptorArray,
2371 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002372ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002373ACCESSORS(Map, constructor, Object, kConstructorOffset)
2374
2375ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2376ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2377
2378ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2379ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002380ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002381
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002382ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002383
2384ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2385ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2386ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2387ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2388ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002389ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002390
2391ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2392ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2393ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2394
2395ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2396ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2397ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2398ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2399ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2400ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2401
2402ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2403ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2404
2405ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2406ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2407
2408ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2409ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002410ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2411 kPropertyAccessorsOffset)
2412ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2413 kPrototypeTemplateOffset)
2414ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2415ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2416 kNamedPropertyHandlerOffset)
2417ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2418 kIndexedPropertyHandlerOffset)
2419ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2420 kInstanceTemplateOffset)
2421ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2422ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002423ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2424 kInstanceCallHandlerOffset)
2425ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2426 kAccessCheckInfoOffset)
2427ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2428
2429ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002430ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2431 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002432
2433ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2434ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2435
2436ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2437
2438ACCESSORS(Script, source, Object, kSourceOffset)
2439ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002440ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002441ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2442ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002443ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002444ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002445ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2446ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002447ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002448ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002449ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002450ACCESSORS(Script, eval_from_instructions_offset, Smi,
2451 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002452
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002453#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002454ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2455ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2456ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2457ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2458
2459ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2460ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2461ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2462ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002463#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002464
2465ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002466ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002467ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2468 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002469ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002470ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2471ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002472ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002473ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2474 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002475
2476BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2477 kHiddenPrototypeBit)
2478BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2479BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2480 kNeedsAccessCheckBit)
2481BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2482 kIsExpressionBit)
2483BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2484 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002485BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002486 has_only_simple_this_property_assignments,
2487 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002488BOOL_ACCESSORS(SharedFunctionInfo,
2489 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002490 try_full_codegen,
2491 kTryFullCodegen)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00002492BOOL_ACCESSORS(SharedFunctionInfo,
2493 compiler_hints,
2494 allows_lazy_compilation,
2495 kAllowLazyCompilation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002496
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002497#if V8_HOST_ARCH_32_BIT
2498SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2499SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002500 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002501SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002502 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002503SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2504SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002505 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002506SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2507SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002508 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002509SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002510 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002511SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002512 kThisPropertyAssignmentsCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002513#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002514
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002515#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2516 int holder::name() { \
2517 int value = READ_INT_FIELD(this, offset); \
2518 ASSERT(kHeapObjectTag == 1); \
2519 ASSERT((value & kHeapObjectTag) == 0); \
2520 return value >> 1; \
2521 } \
2522 void holder::set_##name(int value) { \
2523 ASSERT(kHeapObjectTag == 1); \
2524 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2525 (value & 0xC0000000) == 0x000000000); \
2526 WRITE_INT_FIELD(this, \
2527 offset, \
2528 (value << 1) & ~kHeapObjectTag); \
2529 }
2530
2531#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2532 INT_ACCESSORS(holder, name, offset)
2533
2534
2535
2536PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2537PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2538 kFormalParameterCountOffset)
2539
2540PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2541 kExpectedNofPropertiesOffset)
2542PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2543
2544PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2545 kStartPositionAndTypeOffset)
2546PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2547
2548PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2549 kFunctionTokenPositionOffset)
2550PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2551 kCompilerHintsOffset)
2552
2553PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2554 kThisPropertyAssignmentsCountOffset)
2555#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002556
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002557ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2558ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2559
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002560bool Script::HasValidSource() {
2561 Object* src = this->source();
2562 if (!src->IsString()) return true;
2563 String* src_str = String::cast(src);
2564 if (!StringShape(src_str).IsExternal()) return true;
2565 if (src_str->IsAsciiRepresentation()) {
2566 return ExternalAsciiString::cast(src)->resource() != NULL;
2567 } else if (src_str->IsTwoByteRepresentation()) {
2568 return ExternalTwoByteString::cast(src)->resource() != NULL;
2569 }
2570 return true;
2571}
2572
2573
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002574void SharedFunctionInfo::DontAdaptArguments() {
2575 ASSERT(code()->kind() == Code::BUILTIN);
2576 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2577}
2578
2579
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002580int SharedFunctionInfo::start_position() {
2581 return start_position_and_type() >> kStartPositionShift;
2582}
2583
2584
2585void SharedFunctionInfo::set_start_position(int start_position) {
2586 set_start_position_and_type((start_position << kStartPositionShift)
2587 | (start_position_and_type() & ~kStartPositionMask));
2588}
2589
2590
2591Code* SharedFunctionInfo::code() {
2592 return Code::cast(READ_FIELD(this, kCodeOffset));
2593}
2594
2595
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002596void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002597 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002598 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002599}
2600
2601
2602bool SharedFunctionInfo::is_compiled() {
2603 // TODO(1242782): Create a code kind for uncompiled code.
2604 return code()->kind() != Code::STUB;
2605}
2606
2607
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002608bool SharedFunctionInfo::IsApiFunction() {
2609 return function_data()->IsFunctionTemplateInfo();
2610}
2611
2612
2613FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2614 ASSERT(IsApiFunction());
2615 return FunctionTemplateInfo::cast(function_data());
2616}
2617
2618
2619bool SharedFunctionInfo::HasCustomCallGenerator() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00002620 return function_data()->IsSmi();
2621}
2622
2623
2624int SharedFunctionInfo::custom_call_generator_id() {
2625 ASSERT(HasCustomCallGenerator());
2626 return Smi::cast(function_data())->value();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002627}
2628
2629
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002630bool JSFunction::IsBuiltin() {
2631 return context()->global()->IsJSBuiltinsObject();
2632}
2633
2634
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002635Code* JSFunction::code() {
2636 return shared()->code();
2637}
2638
2639
2640void JSFunction::set_code(Code* value) {
2641 shared()->set_code(value);
2642}
2643
2644
2645Context* JSFunction::context() {
2646 return Context::cast(READ_FIELD(this, kContextOffset));
2647}
2648
2649
2650Object* JSFunction::unchecked_context() {
2651 return READ_FIELD(this, kContextOffset);
2652}
2653
2654
2655void JSFunction::set_context(Object* value) {
2656 ASSERT(value == Heap::undefined_value() || value->IsContext());
2657 WRITE_FIELD(this, kContextOffset, value);
2658 WRITE_BARRIER(this, kContextOffset);
2659}
2660
2661ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2662 kPrototypeOrInitialMapOffset)
2663
2664
2665Map* JSFunction::initial_map() {
2666 return Map::cast(prototype_or_initial_map());
2667}
2668
2669
2670void JSFunction::set_initial_map(Map* value) {
2671 set_prototype_or_initial_map(value);
2672}
2673
2674
2675bool JSFunction::has_initial_map() {
2676 return prototype_or_initial_map()->IsMap();
2677}
2678
2679
2680bool JSFunction::has_instance_prototype() {
2681 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2682}
2683
2684
2685bool JSFunction::has_prototype() {
2686 return map()->has_non_instance_prototype() || has_instance_prototype();
2687}
2688
2689
2690Object* JSFunction::instance_prototype() {
2691 ASSERT(has_instance_prototype());
2692 if (has_initial_map()) return initial_map()->prototype();
2693 // When there is no initial map and the prototype is a JSObject, the
2694 // initial map field is used for the prototype field.
2695 return prototype_or_initial_map();
2696}
2697
2698
2699Object* JSFunction::prototype() {
2700 ASSERT(has_prototype());
2701 // If the function's prototype property has been set to a non-JSObject
2702 // value, that value is stored in the constructor field of the map.
2703 if (map()->has_non_instance_prototype()) return map()->constructor();
2704 return instance_prototype();
2705}
2706
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002707bool JSFunction::should_have_prototype() {
2708 return map()->function_with_prototype();
2709}
2710
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002711
2712bool JSFunction::is_compiled() {
2713 return shared()->is_compiled();
2714}
2715
2716
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002717int JSFunction::NumberOfLiterals() {
2718 return literals()->length();
2719}
2720
2721
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002722Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2723 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002724 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002725}
2726
2727
2728void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2729 Object* value) {
2730 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002731 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2732 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2733}
2734
2735
2736Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2737 ASSERT(0 <= id && id < kJSBuiltinsCount);
2738 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2739}
2740
2741
2742void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2743 Code* value) {
2744 ASSERT(0 <= id && id < kJSBuiltinsCount);
2745 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2746 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002747}
2748
2749
2750Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002751 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002752}
2753
2754
2755void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002756 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002757}
2758
2759
2760void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2761 visitor->VisitExternalReference(
2762 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2763}
2764
2765
2766ACCESSORS(JSValue, value, Object, kValueOffset)
2767
2768
2769JSValue* JSValue::cast(Object* obj) {
2770 ASSERT(obj->IsJSValue());
2771 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2772 return reinterpret_cast<JSValue*>(obj);
2773}
2774
2775
2776INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2777INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2778INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2779
2780
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781byte* Code::instruction_start() {
2782 return FIELD_ADDR(this, kHeaderSize);
2783}
2784
2785
2786int Code::body_size() {
2787 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2788}
2789
2790
2791byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002792 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002793}
2794
2795
2796byte* Code::entry() {
2797 return instruction_start();
2798}
2799
2800
2801bool Code::contains(byte* pc) {
2802 return (instruction_start() <= pc) &&
2803 (pc < instruction_start() + instruction_size());
2804}
2805
2806
2807byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002808 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002809}
2810
2811
2812ACCESSORS(JSArray, length, Object, kLengthOffset)
2813
2814
ager@chromium.org236ad962008-09-25 09:45:57 +00002815ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002816
2817
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002818JSRegExp::Type JSRegExp::TypeTag() {
2819 Object* data = this->data();
2820 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2821 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2822 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002823}
2824
2825
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002826int JSRegExp::CaptureCount() {
2827 switch (TypeTag()) {
2828 case ATOM:
2829 return 0;
2830 case IRREGEXP:
2831 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2832 default:
2833 UNREACHABLE();
2834 return -1;
2835 }
2836}
2837
2838
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002839JSRegExp::Flags JSRegExp::GetFlags() {
2840 ASSERT(this->data()->IsFixedArray());
2841 Object* data = this->data();
2842 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2843 return Flags(smi->value());
2844}
2845
2846
2847String* JSRegExp::Pattern() {
2848 ASSERT(this->data()->IsFixedArray());
2849 Object* data = this->data();
2850 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2851 return pattern;
2852}
2853
2854
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002855Object* JSRegExp::DataAt(int index) {
2856 ASSERT(TypeTag() != NOT_COMPILED);
2857 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002858}
2859
2860
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002861void JSRegExp::SetDataAt(int index, Object* value) {
2862 ASSERT(TypeTag() != NOT_COMPILED);
2863 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2864 FixedArray::cast(data())->set(index, value);
2865}
2866
2867
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002868JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002869 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002870 if (array->IsFixedArray()) {
2871 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2872 if (array->map() == Heap::fixed_array_map()) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002873 ASSERT(map()->has_fast_elements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002874 return FAST_ELEMENTS;
2875 }
2876 ASSERT(array->IsDictionary());
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002877 ASSERT(!map()->has_fast_elements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002878 return DICTIONARY_ELEMENTS;
2879 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00002880 ASSERT(!map()->has_fast_elements());
ager@chromium.org3811b432009-10-28 14:53:37 +00002881 if (array->IsExternalArray()) {
2882 switch (array->map()->instance_type()) {
2883 case EXTERNAL_BYTE_ARRAY_TYPE:
2884 return EXTERNAL_BYTE_ELEMENTS;
2885 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2886 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2887 case EXTERNAL_SHORT_ARRAY_TYPE:
2888 return EXTERNAL_SHORT_ELEMENTS;
2889 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2890 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2891 case EXTERNAL_INT_ARRAY_TYPE:
2892 return EXTERNAL_INT_ELEMENTS;
2893 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2894 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2895 default:
2896 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2897 return EXTERNAL_FLOAT_ELEMENTS;
2898 }
2899 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002900 ASSERT(array->IsPixelArray());
2901 return PIXEL_ELEMENTS;
2902}
2903
2904
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002905bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002906 return GetElementsKind() == FAST_ELEMENTS;
2907}
2908
2909
2910bool JSObject::HasDictionaryElements() {
2911 return GetElementsKind() == DICTIONARY_ELEMENTS;
2912}
2913
2914
2915bool JSObject::HasPixelElements() {
2916 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002917}
2918
2919
ager@chromium.org3811b432009-10-28 14:53:37 +00002920bool JSObject::HasExternalArrayElements() {
2921 return (HasExternalByteElements() ||
2922 HasExternalUnsignedByteElements() ||
2923 HasExternalShortElements() ||
2924 HasExternalUnsignedShortElements() ||
2925 HasExternalIntElements() ||
2926 HasExternalUnsignedIntElements() ||
2927 HasExternalFloatElements());
2928}
2929
2930
2931bool JSObject::HasExternalByteElements() {
2932 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2933}
2934
2935
2936bool JSObject::HasExternalUnsignedByteElements() {
2937 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2938}
2939
2940
2941bool JSObject::HasExternalShortElements() {
2942 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2943}
2944
2945
2946bool JSObject::HasExternalUnsignedShortElements() {
2947 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2948}
2949
2950
2951bool JSObject::HasExternalIntElements() {
2952 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2953}
2954
2955
2956bool JSObject::HasExternalUnsignedIntElements() {
2957 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2958}
2959
2960
2961bool JSObject::HasExternalFloatElements() {
2962 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2963}
2964
2965
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002966bool JSObject::HasNamedInterceptor() {
2967 return map()->has_named_interceptor();
2968}
2969
2970
2971bool JSObject::HasIndexedInterceptor() {
2972 return map()->has_indexed_interceptor();
2973}
2974
2975
ager@chromium.org5c838252010-02-19 08:53:10 +00002976bool JSObject::AllowsSetElementsLength() {
2977 bool result = elements()->IsFixedArray();
2978 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
2979 return result;
2980}
2981
2982
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002983StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002984 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002985 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002986}
2987
2988
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002989NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002990 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002991 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002992}
2993
2994
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002995bool String::IsHashFieldComputed(uint32_t field) {
2996 return (field & kHashNotComputedMask) == 0;
2997}
2998
2999
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003000bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003001 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003002}
3003
3004
3005uint32_t String::Hash() {
3006 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003007 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003008 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003009 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003010 return ComputeAndSetHash();
3011}
3012
3013
ager@chromium.org7c537e22008-10-16 08:43:32 +00003014StringHasher::StringHasher(int length)
3015 : length_(length),
3016 raw_running_hash_(0),
3017 array_index_(0),
3018 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3019 is_first_char_(true),
3020 is_valid_(true) { }
3021
3022
3023bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003024 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00003025}
3026
3027
3028void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003029 // Use the Jenkins one-at-a-time hash function to update the hash
3030 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003031 raw_running_hash_ += c;
3032 raw_running_hash_ += (raw_running_hash_ << 10);
3033 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003034 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003035 if (is_array_index_) {
3036 if (c < '0' || c > '9') {
3037 is_array_index_ = false;
3038 } else {
3039 int d = c - '0';
3040 if (is_first_char_) {
3041 is_first_char_ = false;
3042 if (c == '0' && length_ > 1) {
3043 is_array_index_ = false;
3044 return;
3045 }
3046 }
3047 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3048 is_array_index_ = false;
3049 } else {
3050 array_index_ = array_index_ * 10 + d;
3051 }
3052 }
3053 }
3054}
3055
3056
3057void StringHasher::AddCharacterNoIndex(uc32 c) {
3058 ASSERT(!is_array_index());
3059 raw_running_hash_ += c;
3060 raw_running_hash_ += (raw_running_hash_ << 10);
3061 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3062}
3063
3064
3065uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003066 // Get the calculated raw hash value and do some more bit ops to distribute
3067 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003068 uint32_t result = raw_running_hash_;
3069 result += (result << 3);
3070 result ^= (result >> 11);
3071 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003072 if (result == 0) {
3073 result = 27;
3074 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003075 return result;
3076}
3077
3078
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003079bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003080 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003081 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3082 return false;
3083 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003084 return SlowAsArrayIndex(index);
3085}
3086
3087
3088Object* JSObject::GetPrototype() {
3089 return JSObject::cast(this)->map()->prototype();
3090}
3091
3092
3093PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3094 return GetPropertyAttributeWithReceiver(this, key);
3095}
3096
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003097// TODO(504): this may be useful in other places too where JSGlobalProxy
3098// is used.
3099Object* JSObject::BypassGlobalProxy() {
3100 if (IsJSGlobalProxy()) {
3101 Object* proto = GetPrototype();
3102 if (proto->IsNull()) return Heap::undefined_value();
3103 ASSERT(proto->IsJSGlobalObject());
3104 return proto;
3105 }
3106 return this;
3107}
3108
3109
3110bool JSObject::HasHiddenPropertiesObject() {
3111 ASSERT(!IsJSGlobalProxy());
3112 return GetPropertyAttributePostInterceptor(this,
3113 Heap::hidden_symbol(),
3114 false) != ABSENT;
3115}
3116
3117
3118Object* JSObject::GetHiddenPropertiesObject() {
3119 ASSERT(!IsJSGlobalProxy());
3120 PropertyAttributes attributes;
3121 return GetLocalPropertyPostInterceptor(this,
3122 Heap::hidden_symbol(),
3123 &attributes);
3124}
3125
3126
3127Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3128 ASSERT(!IsJSGlobalProxy());
3129 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3130 hidden_obj,
3131 DONT_ENUM);
3132}
3133
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003134
3135bool JSObject::HasElement(uint32_t index) {
3136 return HasElementWithReceiver(this, index);
3137}
3138
3139
3140bool AccessorInfo::all_can_read() {
3141 return BooleanBit::get(flag(), kAllCanReadBit);
3142}
3143
3144
3145void AccessorInfo::set_all_can_read(bool value) {
3146 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3147}
3148
3149
3150bool AccessorInfo::all_can_write() {
3151 return BooleanBit::get(flag(), kAllCanWriteBit);
3152}
3153
3154
3155void AccessorInfo::set_all_can_write(bool value) {
3156 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3157}
3158
3159
ager@chromium.org870a0b62008-11-04 11:43:05 +00003160bool AccessorInfo::prohibits_overwriting() {
3161 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3162}
3163
3164
3165void AccessorInfo::set_prohibits_overwriting(bool value) {
3166 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3167}
3168
3169
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003170PropertyAttributes AccessorInfo::property_attributes() {
3171 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3172}
3173
3174
3175void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3176 ASSERT(AttributesField::is_valid(attributes));
3177 int rest_value = flag()->value() & ~AttributesField::mask();
3178 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3179}
3180
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003181template<typename Shape, typename Key>
3182void Dictionary<Shape, Key>::SetEntry(int entry,
3183 Object* key,
3184 Object* value,
3185 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003186 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003187 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003188 AssertNoAllocation no_gc;
3189 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003190 FixedArray::set(index, key, mode);
3191 FixedArray::set(index+1, value, mode);
3192 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003193}
3194
3195
3196void Map::ClearCodeCache() {
3197 // No write barrier is needed since empty_fixed_array is not in new space.
3198 // Please note this function is used during marking:
3199 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003200 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3201 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003202}
3203
3204
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003205void JSArray::EnsureSize(int required_size) {
3206 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003207 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003208 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3209 if (elts->length() < required_size) {
3210 // Doubling in size would be overkill, but leave some slack to avoid
3211 // constantly growing.
3212 Expand(required_size + (required_size >> 3));
3213 // It's a performance benefit to keep a frequently used array in new-space.
3214 } else if (!Heap::new_space()->Contains(elts) &&
3215 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3216 // Expand will allocate a new backing store in new space even if the size
3217 // we asked for isn't larger than what we had before.
3218 Expand(required_size);
3219 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003220}
3221
3222
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003223void JSArray::set_length(Smi* length) {
3224 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3225}
3226
3227
ager@chromium.org7c537e22008-10-16 08:43:32 +00003228void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003229 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003230 set_elements(storage);
3231}
3232
3233
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003234Object* FixedArray::Copy() {
3235 if (length() == 0) return this;
3236 return Heap::CopyFixedArray(this);
3237}
3238
3239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003240#undef CAST_ACCESSOR
3241#undef INT_ACCESSORS
3242#undef SMI_ACCESSORS
3243#undef ACCESSORS
3244#undef FIELD_ADDR
3245#undef READ_FIELD
3246#undef WRITE_FIELD
3247#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003248#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003249#undef READ_MEMADDR_FIELD
3250#undef WRITE_MEMADDR_FIELD
3251#undef READ_DOUBLE_FIELD
3252#undef WRITE_DOUBLE_FIELD
3253#undef READ_INT_FIELD
3254#undef WRITE_INT_FIELD
3255#undef READ_SHORT_FIELD
3256#undef WRITE_SHORT_FIELD
3257#undef READ_BYTE_FIELD
3258#undef WRITE_BYTE_FIELD
3259
3260
3261} } // namespace v8::internal
3262
3263#endif // V8_OBJECTS_INL_H_