blob: fceb76f1894ac6100994cdeefad8558b7bfa9457 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27//
28// Review notes:
29//
ager@chromium.org32912102009-01-16 10:38:43 +000030// - The use of macros in these inline functions may seem superfluous
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000031// but it is absolutely needed to make sure gcc generates optimal
32// code. gcc is not happy when attempting to inline too deep.
33//
34
35#ifndef V8_OBJECTS_INL_H_
36#define V8_OBJECTS_INL_H_
37
38#include "objects.h"
39#include "contexts.h"
40#include "conversions-inl.h"
41#include "property.h"
42
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48}
49
50
51Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53}
54
55
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000056PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60}
61
62
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063#define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70#define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75#define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000077 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000079 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 }
81
82
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000083
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084#define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000094#define BOOL_GETTER(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98
99
100#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101 bool holder::name() { \
102 return BooleanBit::get(field(), offset); \
103 } \
104 void holder::set_##name(bool value) { \
105 set_##field(BooleanBit::set(field(), offset, value)); \
106 }
107
108
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000109bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110 // There is a constraint on the object; check.
111 if (!this->IsJSObject()) return false;
112 // Fetch the constructor function of the object.
113 Object* cons_obj = JSObject::cast(this)->map()->constructor();
114 if (!cons_obj->IsJSFunction()) return false;
115 JSFunction* fun = JSFunction::cast(cons_obj);
116 // Iterate through the chain of inheriting function templates to
117 // see if the required one occurs.
118 for (Object* type = fun->shared()->function_data();
119 type->IsFunctionTemplateInfo();
120 type = FunctionTemplateInfo::cast(type)->parent_template()) {
121 if (type == expected) return true;
122 }
123 // Didn't find the required type in the inheritance chain.
124 return false;
125}
126
127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128bool Object::IsSmi() {
129 return HAS_SMI_TAG(this);
130}
131
132
133bool Object::IsHeapObject() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000134 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135}
136
137
138bool Object::IsHeapNumber() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141}
142
143
144bool Object::IsString() {
145 return Object::IsHeapObject()
146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147}
148
149
ager@chromium.org870a0b62008-11-04 11:43:05 +0000150bool Object::IsSymbol() {
151 if (!this->IsHeapObject()) return false;
152 uint32_t type = HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000153 // Because the symbol tag is non-zero and no non-string types have the
154 // symbol bit set we can test for symbols with a very simple test
155 // operation.
156 ASSERT(kSymbolTag != 0);
157 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
158 return (type & kIsSymbolMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000159}
160
161
162bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000163 if (!this->IsHeapObject()) return false;
164 uint32_t type = HeapObject::cast(this)->map()->instance_type();
165 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
166 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000167}
168
169
ager@chromium.org870a0b62008-11-04 11:43:05 +0000170bool Object::IsSeqString() {
171 if (!IsString()) return false;
172 return StringShape(String::cast(this)).IsSequential();
173}
174
175
176bool Object::IsSeqAsciiString() {
177 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000178 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000179 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000180}
181
182
183bool Object::IsSeqTwoByteString() {
184 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000185 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000186 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187}
188
189
190bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000191 if (!IsString()) return false;
192 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193}
194
195
196bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000197 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000198 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000199 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200}
201
202
203bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000204 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000205 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000206 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207}
208
209
ager@chromium.org870a0b62008-11-04 11:43:05 +0000210StringShape::StringShape(String* str)
211 : type_(str->map()->instance_type()) {
212 set_valid();
213 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214}
215
216
ager@chromium.org870a0b62008-11-04 11:43:05 +0000217StringShape::StringShape(Map* map)
218 : type_(map->instance_type()) {
219 set_valid();
220 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221}
222
223
ager@chromium.org870a0b62008-11-04 11:43:05 +0000224StringShape::StringShape(InstanceType t)
225 : type_(static_cast<uint32_t>(t)) {
226 set_valid();
227 ASSERT((type_ & kIsNotStringMask) == kStringTag);
228}
229
230
231bool StringShape::IsSymbol() {
232 ASSERT(valid());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000233 ASSERT(kSymbolTag != 0);
234 return (type_ & kIsSymbolMask) != 0;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000235}
236
237
ager@chromium.org5ec48922009-05-05 07:25:34 +0000238bool String::IsAsciiRepresentation() {
239 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000240 if ((type & kStringRepresentationMask) == kConsStringTag &&
241 ConsString::cast(this)->second()->length() == 0) {
242 return ConsString::cast(this)->first()->IsAsciiRepresentation();
243 }
244 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000245}
246
247
ager@chromium.org5ec48922009-05-05 07:25:34 +0000248bool String::IsTwoByteRepresentation() {
249 uint32_t type = map()->instance_type();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000250 if ((type & kStringRepresentationMask) == kConsStringTag &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000251 ConsString::cast(this)->second()->length() == 0) {
252 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
253 }
254 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000255}
256
257
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000258bool String::IsExternalTwoByteStringWithAsciiChars() {
259 if (!IsExternalTwoByteString()) return false;
260 const uc16* data = ExternalTwoByteString::cast(this)->resource()->data();
261 for (int i = 0, len = length(); i < len; i++) {
262 if (data[i] > kMaxAsciiCharCode) return false;
263 }
264 return true;
265}
266
267
ager@chromium.org870a0b62008-11-04 11:43:05 +0000268bool StringShape::IsCons() {
269 return (type_ & kStringRepresentationMask) == kConsStringTag;
270}
271
272
ager@chromium.org870a0b62008-11-04 11:43:05 +0000273bool StringShape::IsExternal() {
274 return (type_ & kStringRepresentationMask) == kExternalStringTag;
275}
276
277
278bool StringShape::IsSequential() {
279 return (type_ & kStringRepresentationMask) == kSeqStringTag;
280}
281
282
283StringRepresentationTag StringShape::representation_tag() {
284 uint32_t tag = (type_ & kStringRepresentationMask);
285 return static_cast<StringRepresentationTag>(tag);
286}
287
288
289uint32_t StringShape::full_representation_tag() {
290 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
291}
292
293
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000294STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
295 Internals::kFullStringRepresentationMask);
296
297
ager@chromium.org870a0b62008-11-04 11:43:05 +0000298bool StringShape::IsSequentialAscii() {
299 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
300}
301
302
303bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000304 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000305}
306
307
308bool StringShape::IsExternalAscii() {
309 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
310}
311
312
313bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000314 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315}
316
317
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000318STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
319 Internals::kExternalTwoByteRepresentationTag);
320
321
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000322uc32 FlatStringReader::Get(int index) {
323 ASSERT(0 <= index && index <= length_);
324 if (is_ascii_) {
325 return static_cast<const byte*>(start_)[index];
326 } else {
327 return static_cast<const uc16*>(start_)[index];
328 }
329}
330
331
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332bool Object::IsNumber() {
333 return IsSmi() || IsHeapNumber();
334}
335
336
337bool Object::IsByteArray() {
338 return Object::IsHeapObject()
339 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
340}
341
342
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000343bool Object::IsPixelArray() {
344 return Object::IsHeapObject() &&
345 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
346}
347
348
ager@chromium.org3811b432009-10-28 14:53:37 +0000349bool Object::IsExternalArray() {
350 if (!Object::IsHeapObject())
351 return false;
352 InstanceType instance_type =
353 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000354 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
355 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000356}
357
358
359bool Object::IsExternalByteArray() {
360 return Object::IsHeapObject() &&
361 HeapObject::cast(this)->map()->instance_type() ==
362 EXTERNAL_BYTE_ARRAY_TYPE;
363}
364
365
366bool Object::IsExternalUnsignedByteArray() {
367 return Object::IsHeapObject() &&
368 HeapObject::cast(this)->map()->instance_type() ==
369 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
370}
371
372
373bool Object::IsExternalShortArray() {
374 return Object::IsHeapObject() &&
375 HeapObject::cast(this)->map()->instance_type() ==
376 EXTERNAL_SHORT_ARRAY_TYPE;
377}
378
379
380bool Object::IsExternalUnsignedShortArray() {
381 return Object::IsHeapObject() &&
382 HeapObject::cast(this)->map()->instance_type() ==
383 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
384}
385
386
387bool Object::IsExternalIntArray() {
388 return Object::IsHeapObject() &&
389 HeapObject::cast(this)->map()->instance_type() ==
390 EXTERNAL_INT_ARRAY_TYPE;
391}
392
393
394bool Object::IsExternalUnsignedIntArray() {
395 return Object::IsHeapObject() &&
396 HeapObject::cast(this)->map()->instance_type() ==
397 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
398}
399
400
401bool Object::IsExternalFloatArray() {
402 return Object::IsHeapObject() &&
403 HeapObject::cast(this)->map()->instance_type() ==
404 EXTERNAL_FLOAT_ARRAY_TYPE;
405}
406
407
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000408bool Object::IsFailure() {
409 return HAS_FAILURE_TAG(this);
410}
411
412
413bool Object::IsRetryAfterGC() {
414 return HAS_FAILURE_TAG(this)
415 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
416}
417
418
ager@chromium.org7c537e22008-10-16 08:43:32 +0000419bool Object::IsOutOfMemoryFailure() {
420 return HAS_FAILURE_TAG(this)
421 && Failure::cast(this)->IsOutOfMemoryException();
422}
423
424
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000425bool Object::IsException() {
426 return this == Failure::Exception();
427}
428
429
430bool Object::IsJSObject() {
431 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000432 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433}
434
435
ager@chromium.org32912102009-01-16 10:38:43 +0000436bool Object::IsJSContextExtensionObject() {
437 return IsHeapObject()
438 && (HeapObject::cast(this)->map()->instance_type() ==
439 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
440}
441
442
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000443bool Object::IsMap() {
444 return Object::IsHeapObject()
445 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
446}
447
448
449bool Object::IsFixedArray() {
450 return Object::IsHeapObject()
451 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
452}
453
454
455bool Object::IsDescriptorArray() {
456 return IsFixedArray();
457}
458
459
460bool Object::IsContext() {
461 return Object::IsHeapObject()
462 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000463 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464 HeapObject::cast(this)->map() == Heap::global_context_map());
465}
466
467
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000468bool Object::IsCatchContext() {
469 return Object::IsHeapObject()
470 && HeapObject::cast(this)->map() == Heap::catch_context_map();
471}
472
473
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000474bool Object::IsGlobalContext() {
475 return Object::IsHeapObject()
476 && HeapObject::cast(this)->map() == Heap::global_context_map();
477}
478
479
480bool Object::IsJSFunction() {
481 return Object::IsHeapObject()
482 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
483}
484
485
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000486template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487 return obj->IsJSFunction();
488}
489
490
491bool Object::IsCode() {
492 return Object::IsHeapObject()
493 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
494}
495
496
497bool Object::IsOddball() {
498 return Object::IsHeapObject()
499 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
500}
501
502
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000503bool Object::IsJSGlobalPropertyCell() {
504 return Object::IsHeapObject()
505 && HeapObject::cast(this)->map()->instance_type()
506 == JS_GLOBAL_PROPERTY_CELL_TYPE;
507}
508
509
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510bool Object::IsSharedFunctionInfo() {
511 return Object::IsHeapObject() &&
512 (HeapObject::cast(this)->map()->instance_type() ==
513 SHARED_FUNCTION_INFO_TYPE);
514}
515
516
517bool Object::IsJSValue() {
518 return Object::IsHeapObject()
519 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
520}
521
522
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000523bool Object::IsStringWrapper() {
524 return IsJSValue() && JSValue::cast(this)->value()->IsString();
525}
526
527
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528bool Object::IsProxy() {
529 return Object::IsHeapObject()
530 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
531}
532
533
534bool Object::IsBoolean() {
535 return IsTrue() || IsFalse();
536}
537
538
539bool Object::IsJSArray() {
540 return Object::IsHeapObject()
541 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
542}
543
544
ager@chromium.org236ad962008-09-25 09:45:57 +0000545bool Object::IsJSRegExp() {
546 return Object::IsHeapObject()
547 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
548}
549
550
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000551template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 return obj->IsJSArray();
553}
554
555
556bool Object::IsHashTable() {
557 return Object::IsHeapObject()
558 && HeapObject::cast(this)->map() == Heap::hash_table_map();
559}
560
561
562bool Object::IsDictionary() {
563 return IsHashTable() && this != Heap::symbol_table();
564}
565
566
567bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000568 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000569}
570
571
ager@chromium.orgac091b72010-05-05 07:34:42 +0000572bool Object::IsJSFunctionResultCache() {
573 if (!IsFixedArray()) return false;
574 FixedArray* self = FixedArray::cast(this);
575 int length = self->length();
576 if (length < JSFunctionResultCache::kEntriesIndex) return false;
577 if ((length - JSFunctionResultCache::kEntriesIndex)
578 % JSFunctionResultCache::kEntrySize != 0) {
579 return false;
580 }
581#ifdef DEBUG
582 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
583#endif
584 return true;
585}
586
587
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000588bool Object::IsCompilationCacheTable() {
589 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000590}
591
592
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000593bool Object::IsCodeCacheHashTable() {
594 return IsHashTable();
595}
596
597
ager@chromium.org236ad962008-09-25 09:45:57 +0000598bool Object::IsMapCache() {
599 return IsHashTable();
600}
601
602
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603bool Object::IsPrimitive() {
604 return IsOddball() || IsNumber() || IsString();
605}
606
607
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000608bool Object::IsJSGlobalProxy() {
609 bool result = IsHeapObject() &&
610 (HeapObject::cast(this)->map()->instance_type() ==
611 JS_GLOBAL_PROXY_TYPE);
612 ASSERT(!result || IsAccessCheckNeeded());
613 return result;
614}
615
616
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000618 if (!IsHeapObject()) return false;
619
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000620 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000621 return type == JS_GLOBAL_OBJECT_TYPE ||
622 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000623}
624
625
626bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627 return IsHeapObject() &&
628 (HeapObject::cast(this)->map()->instance_type() ==
629 JS_GLOBAL_OBJECT_TYPE);
630}
631
632
633bool Object::IsJSBuiltinsObject() {
634 return IsHeapObject() &&
635 (HeapObject::cast(this)->map()->instance_type() ==
636 JS_BUILTINS_OBJECT_TYPE);
637}
638
639
640bool Object::IsUndetectableObject() {
641 return IsHeapObject()
642 && HeapObject::cast(this)->map()->is_undetectable();
643}
644
645
646bool Object::IsAccessCheckNeeded() {
647 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000648 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649}
650
651
652bool Object::IsStruct() {
653 if (!IsHeapObject()) return false;
654 switch (HeapObject::cast(this)->map()->instance_type()) {
655#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
656 STRUCT_LIST(MAKE_STRUCT_CASE)
657#undef MAKE_STRUCT_CASE
658 default: return false;
659 }
660}
661
662
663#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
664 bool Object::Is##Name() { \
665 return Object::IsHeapObject() \
666 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
667 }
668 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
669#undef MAKE_STRUCT_PREDICATE
670
671
672bool Object::IsUndefined() {
673 return this == Heap::undefined_value();
674}
675
676
677bool Object::IsTheHole() {
678 return this == Heap::the_hole_value();
679}
680
681
682bool Object::IsNull() {
683 return this == Heap::null_value();
684}
685
686
687bool Object::IsTrue() {
688 return this == Heap::true_value();
689}
690
691
692bool Object::IsFalse() {
693 return this == Heap::false_value();
694}
695
696
697double Object::Number() {
698 ASSERT(IsNumber());
699 return IsSmi()
700 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
701 : reinterpret_cast<HeapNumber*>(this)->value();
702}
703
704
705
706Object* Object::ToSmi() {
707 if (IsSmi()) return this;
708 if (IsHeapNumber()) {
709 double value = HeapNumber::cast(this)->value();
710 int int_value = FastD2I(value);
711 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
712 return Smi::FromInt(int_value);
713 }
714 }
715 return Failure::Exception();
716}
717
718
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000719bool Object::HasSpecificClassOf(String* name) {
720 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
721}
722
723
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000724Object* Object::GetElement(uint32_t index) {
725 return GetElementWithReceiver(this, index);
726}
727
728
729Object* Object::GetProperty(String* key) {
730 PropertyAttributes attributes;
731 return GetPropertyWithReceiver(this, key, &attributes);
732}
733
734
735Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
736 return GetPropertyWithReceiver(this, key, attributes);
737}
738
739
740#define FIELD_ADDR(p, offset) \
741 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
742
743#define READ_FIELD(p, offset) \
744 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
745
746#define WRITE_FIELD(p, offset, value) \
747 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
748
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000749
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750#define WRITE_BARRIER(object, offset) \
751 Heap::RecordWrite(object->address(), offset);
752
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000753// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000754// write due to the assert validating the written value.
755#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
756 if (mode == UPDATE_WRITE_BARRIER) { \
757 Heap::RecordWrite(object->address(), offset); \
758 } else { \
759 ASSERT(mode == SKIP_WRITE_BARRIER); \
760 ASSERT(Heap::InNewSpace(object) || \
kmillikin@chromium.orgb8dc8eb2010-04-01 07:13:38 +0000761 !Heap::InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000762 Page::FromAddress(object->address())-> \
763 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000764 }
765
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766#define READ_DOUBLE_FIELD(p, offset) \
767 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
768
769#define WRITE_DOUBLE_FIELD(p, offset, value) \
770 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
771
772#define READ_INT_FIELD(p, offset) \
773 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
774
775#define WRITE_INT_FIELD(p, offset, value) \
776 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
777
ager@chromium.org3e875802009-06-29 08:26:34 +0000778#define READ_INTPTR_FIELD(p, offset) \
779 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
780
781#define WRITE_INTPTR_FIELD(p, offset, value) \
782 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
783
ager@chromium.org7c537e22008-10-16 08:43:32 +0000784#define READ_UINT32_FIELD(p, offset) \
785 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
786
787#define WRITE_UINT32_FIELD(p, offset, value) \
788 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
789
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000790#define READ_SHORT_FIELD(p, offset) \
791 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
792
793#define WRITE_SHORT_FIELD(p, offset, value) \
794 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
795
796#define READ_BYTE_FIELD(p, offset) \
797 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
798
799#define WRITE_BYTE_FIELD(p, offset, value) \
800 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
801
802
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000803Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
804 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805}
806
807
808int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000809 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000810}
811
812
813Smi* Smi::FromInt(int value) {
814 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000815 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000816 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000817 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000818 return reinterpret_cast<Smi*>(tagged_value);
819}
820
821
822Smi* Smi::FromIntptr(intptr_t value) {
823 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000824 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
825 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000826}
827
828
829Failure::Type Failure::type() const {
830 return static_cast<Type>(value() & kFailureTypeTagMask);
831}
832
833
834bool Failure::IsInternalError() const {
835 return type() == INTERNAL_ERROR;
836}
837
838
839bool Failure::IsOutOfMemoryException() const {
840 return type() == OUT_OF_MEMORY_EXCEPTION;
841}
842
843
844int Failure::requested() const {
845 const int kShiftBits =
846 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
847 STATIC_ASSERT(kShiftBits >= 0);
848 ASSERT(type() == RETRY_AFTER_GC);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000849 return static_cast<int>(value() >> kShiftBits);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850}
851
852
853AllocationSpace Failure::allocation_space() const {
854 ASSERT_EQ(RETRY_AFTER_GC, type());
855 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
856 & kSpaceTagMask);
857}
858
859
860Failure* Failure::InternalError() {
861 return Construct(INTERNAL_ERROR);
862}
863
864
865Failure* Failure::Exception() {
866 return Construct(EXCEPTION);
867}
868
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000869
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870Failure* Failure::OutOfMemoryException() {
871 return Construct(OUT_OF_MEMORY_EXCEPTION);
872}
873
874
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000875intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000876 return static_cast<intptr_t>(
877 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878}
879
880
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000881Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000882 // Assert that the space encoding fits in the three bytes allotted for it.
883 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000884 uintptr_t requested =
885 static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
886 int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000887 if (((requested << tag_bits) >> tag_bits) != requested) {
888 // No room for entire requested size in the bits. Round down to
889 // maximally representable size.
890 requested = static_cast<intptr_t>(
891 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
892 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000893 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000894 return Construct(RETRY_AFTER_GC, value);
895}
896
897
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000898Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000899 uintptr_t info =
900 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000901 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000902 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000903}
904
905
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000906bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907#ifdef DEBUG
908 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
909#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000910
911#ifdef V8_TARGET_ARCH_X64
912 // To be representable as a long smi, the value must be a 32-bit integer.
913 bool result = (value == static_cast<int32_t>(value));
914#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915 // To be representable as an tagged small integer, the two
916 // most-significant bits of 'value' must be either 00 or 11 due to
917 // sign-extension. To check this we add 01 to the two
918 // most-significant bits, and check if the most-significant bit is 0
919 //
920 // CAUTION: The original code below:
921 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
922 // may lead to incorrect results according to the C language spec, and
923 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
924 // compiler may produce undefined results in case of signed integer
925 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000926 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000927#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000928 ASSERT(result == in_range);
929 return result;
930}
931
932
kasper.lund7276f142008-07-30 08:49:36 +0000933MapWord MapWord::FromMap(Map* map) {
934 return MapWord(reinterpret_cast<uintptr_t>(map));
935}
936
937
938Map* MapWord::ToMap() {
939 return reinterpret_cast<Map*>(value_);
940}
941
942
943bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000944 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000945}
946
947
948MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000949 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
950 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000951}
952
953
954HeapObject* MapWord::ToForwardingAddress() {
955 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000956 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000957}
958
959
960bool MapWord::IsMarked() {
961 return (value_ & kMarkingMask) == 0;
962}
963
964
965void MapWord::SetMark() {
966 value_ &= ~kMarkingMask;
967}
968
969
970void MapWord::ClearMark() {
971 value_ |= kMarkingMask;
972}
973
974
975bool MapWord::IsOverflowed() {
976 return (value_ & kOverflowMask) != 0;
977}
978
979
980void MapWord::SetOverflow() {
981 value_ |= kOverflowMask;
982}
983
984
985void MapWord::ClearOverflow() {
986 value_ &= ~kOverflowMask;
987}
988
989
990MapWord MapWord::EncodeAddress(Address map_address, int offset) {
991 // Offset is the distance in live bytes from the first live object in the
992 // same page. The offset between two objects in the same page should not
993 // exceed the object area size of a page.
994 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
995
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000996 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +0000997 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
998
999 Page* map_page = Page::FromAddress(map_address);
1000 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1001
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001002 uintptr_t map_page_offset =
1003 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001004
1005 uintptr_t encoding =
1006 (compact_offset << kForwardingOffsetShift) |
1007 (map_page_offset << kMapPageOffsetShift) |
1008 (map_page->mc_page_index << kMapPageIndexShift);
1009 return MapWord(encoding);
1010}
1011
1012
1013Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001014 int map_page_index =
1015 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001016 ASSERT_MAP_PAGE_INDEX(map_page_index);
1017
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001018 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001019 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1020 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001021
1022 return (map_space->PageAddress(map_page_index) + map_page_offset);
1023}
1024
1025
1026int MapWord::DecodeOffset() {
1027 // The offset field is represented in the kForwardingOffsetBits
1028 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001029 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1030 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1031 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001032}
1033
1034
1035MapWord MapWord::FromEncodedAddress(Address address) {
1036 return MapWord(reinterpret_cast<uintptr_t>(address));
1037}
1038
1039
1040Address MapWord::ToEncodedAddress() {
1041 return reinterpret_cast<Address>(value_);
1042}
1043
1044
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045#ifdef DEBUG
1046void HeapObject::VerifyObjectField(int offset) {
1047 VerifyPointer(READ_FIELD(this, offset));
1048}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001049
1050void HeapObject::VerifySmiField(int offset) {
1051 ASSERT(READ_FIELD(this, offset)->IsSmi());
1052}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001053#endif
1054
1055
1056Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001057 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058}
1059
1060
1061void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001062 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001063}
1064
1065
kasper.lund7276f142008-07-30 08:49:36 +00001066MapWord HeapObject::map_word() {
1067 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1068}
1069
1070
1071void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001072 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001073 // here.
1074 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1075}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001076
1077
1078HeapObject* HeapObject::FromAddress(Address address) {
1079 ASSERT_TAG_ALIGNED(address);
1080 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1081}
1082
1083
1084Address HeapObject::address() {
1085 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1086}
1087
1088
1089int HeapObject::Size() {
1090 return SizeFromMap(map());
1091}
1092
1093
1094void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1095 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1096 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1097}
1098
1099
1100void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1101 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1102}
1103
1104
kasper.lund7276f142008-07-30 08:49:36 +00001105bool HeapObject::IsMarked() {
1106 return map_word().IsMarked();
1107}
1108
1109
1110void HeapObject::SetMark() {
1111 ASSERT(!IsMarked());
1112 MapWord first_word = map_word();
1113 first_word.SetMark();
1114 set_map_word(first_word);
1115}
1116
1117
1118void HeapObject::ClearMark() {
1119 ASSERT(IsMarked());
1120 MapWord first_word = map_word();
1121 first_word.ClearMark();
1122 set_map_word(first_word);
1123}
1124
1125
1126bool HeapObject::IsOverflowed() {
1127 return map_word().IsOverflowed();
1128}
1129
1130
1131void HeapObject::SetOverflow() {
1132 MapWord first_word = map_word();
1133 first_word.SetOverflow();
1134 set_map_word(first_word);
1135}
1136
1137
1138void HeapObject::ClearOverflow() {
1139 ASSERT(IsOverflowed());
1140 MapWord first_word = map_word();
1141 first_word.ClearOverflow();
1142 set_map_word(first_word);
1143}
1144
1145
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146double HeapNumber::value() {
1147 return READ_DOUBLE_FIELD(this, kValueOffset);
1148}
1149
1150
1151void HeapNumber::set_value(double value) {
1152 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1153}
1154
1155
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001156int HeapNumber::get_exponent() {
1157 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1158 kExponentShift) - kExponentBias;
1159}
1160
1161
1162int HeapNumber::get_sign() {
1163 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1164}
1165
1166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001167ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001168
1169
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001170HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001171 Object* array = READ_FIELD(this, kElementsOffset);
1172 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001173 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1174 array->IsExternalArray());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001175 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001176}
1177
1178
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001179void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001180 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001181 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1182 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001183 WRITE_FIELD(this, kElementsOffset, value);
1184 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1185}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186
1187
1188void JSObject::initialize_properties() {
1189 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1190 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1191}
1192
1193
1194void JSObject::initialize_elements() {
1195 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1196 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1197}
1198
1199
1200ACCESSORS(Oddball, to_string, String, kToStringOffset)
1201ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1202
1203
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001204Object* JSGlobalPropertyCell::value() {
1205 return READ_FIELD(this, kValueOffset);
1206}
1207
1208
1209void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1210 // The write barrier is not used for global property cells.
1211 ASSERT(!val->IsJSGlobalPropertyCell());
1212 WRITE_FIELD(this, kValueOffset, val);
1213}
1214
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001215
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001216int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001217 InstanceType type = map()->instance_type();
1218 // Check for the most common kind of JavaScript object before
1219 // falling into the generic switch. This speeds up the internal
1220 // field operations considerably on average.
1221 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1222 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001223 case JS_GLOBAL_PROXY_TYPE:
1224 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001225 case JS_GLOBAL_OBJECT_TYPE:
1226 return JSGlobalObject::kSize;
1227 case JS_BUILTINS_OBJECT_TYPE:
1228 return JSBuiltinsObject::kSize;
1229 case JS_FUNCTION_TYPE:
1230 return JSFunction::kSize;
1231 case JS_VALUE_TYPE:
1232 return JSValue::kSize;
1233 case JS_ARRAY_TYPE:
1234 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001235 case JS_REGEXP_TYPE:
1236 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001237 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001238 return JSObject::kHeaderSize;
1239 default:
1240 UNREACHABLE();
1241 return 0;
1242 }
1243}
1244
1245
1246int JSObject::GetInternalFieldCount() {
1247 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001248 // Make sure to adjust for the number of in-object properties. These
1249 // properties do contribute to the size, but are not internal fields.
1250 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1251 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252}
1253
1254
1255Object* JSObject::GetInternalField(int index) {
1256 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001257 // Internal objects do follow immediately after the header, whereas in-object
1258 // properties are at the end of the object. Therefore there is no need
1259 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001260 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1261}
1262
1263
1264void JSObject::SetInternalField(int index, Object* value) {
1265 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001266 // Internal objects do follow immediately after the header, whereas in-object
1267 // properties are at the end of the object. Therefore there is no need
1268 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001269 int offset = GetHeaderSize() + (kPointerSize * index);
1270 WRITE_FIELD(this, offset, value);
1271 WRITE_BARRIER(this, offset);
1272}
1273
1274
ager@chromium.org7c537e22008-10-16 08:43:32 +00001275// Access fast-case object properties at index. The use of these routines
1276// is needed to correctly distinguish between properties stored in-object and
1277// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001278Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001279 // Adjust for the number of properties stored in the object.
1280 index -= map()->inobject_properties();
1281 if (index < 0) {
1282 int offset = map()->instance_size() + (index * kPointerSize);
1283 return READ_FIELD(this, offset);
1284 } else {
1285 ASSERT(index < properties()->length());
1286 return properties()->get(index);
1287 }
1288}
1289
1290
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001291Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001292 // Adjust for the number of properties stored in the object.
1293 index -= map()->inobject_properties();
1294 if (index < 0) {
1295 int offset = map()->instance_size() + (index * kPointerSize);
1296 WRITE_FIELD(this, offset, value);
1297 WRITE_BARRIER(this, offset);
1298 } else {
1299 ASSERT(index < properties()->length());
1300 properties()->set(index, value);
1301 }
1302 return value;
1303}
1304
1305
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001306Object* JSObject::InObjectPropertyAt(int index) {
1307 // Adjust for the number of properties stored in the object.
1308 index -= map()->inobject_properties();
1309 ASSERT(index < 0);
1310 int offset = map()->instance_size() + (index * kPointerSize);
1311 return READ_FIELD(this, offset);
1312}
1313
1314
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001315Object* JSObject::InObjectPropertyAtPut(int index,
1316 Object* value,
1317 WriteBarrierMode mode) {
1318 // Adjust for the number of properties stored in the object.
1319 index -= map()->inobject_properties();
1320 ASSERT(index < 0);
1321 int offset = map()->instance_size() + (index * kPointerSize);
1322 WRITE_FIELD(this, offset, value);
1323 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1324 return value;
1325}
1326
1327
1328
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001330 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001332 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001333 }
1334}
1335
1336
1337void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001338 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001339 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001340 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001341 }
1342}
1343
1344
1345bool JSObject::HasFastProperties() {
1346 return !properties()->IsDictionary();
1347}
1348
1349
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001350bool Object::ToArrayIndex(uint32_t* index) {
1351 if (IsSmi()) {
1352 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353 if (value < 0) return false;
1354 *index = value;
1355 return true;
1356 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001357 if (IsHeapNumber()) {
1358 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359 uint32_t uint_value = static_cast<uint32_t>(value);
1360 if (value == static_cast<double>(uint_value)) {
1361 *index = uint_value;
1362 return true;
1363 }
1364 }
1365 return false;
1366}
1367
1368
1369bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1370 if (!this->IsJSValue()) return false;
1371
1372 JSValue* js_value = JSValue::cast(this);
1373 if (!js_value->value()->IsString()) return false;
1374
1375 String* str = String::cast(js_value->value());
1376 if (index >= (uint32_t)str->length()) return false;
1377
1378 return true;
1379}
1380
1381
1382Object* FixedArray::get(int index) {
1383 ASSERT(index >= 0 && index < this->length());
1384 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1385}
1386
1387
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001388void FixedArray::set(int index, Smi* value) {
1389 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1390 int offset = kHeaderSize + index * kPointerSize;
1391 WRITE_FIELD(this, offset, value);
1392}
1393
1394
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001395void FixedArray::set(int index, Object* value) {
1396 ASSERT(index >= 0 && index < this->length());
1397 int offset = kHeaderSize + index * kPointerSize;
1398 WRITE_FIELD(this, offset, value);
1399 WRITE_BARRIER(this, offset);
1400}
1401
1402
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001403WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001404 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1405 return UPDATE_WRITE_BARRIER;
1406}
1407
1408
1409void FixedArray::set(int index,
1410 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001411 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001412 ASSERT(index >= 0 && index < this->length());
1413 int offset = kHeaderSize + index * kPointerSize;
1414 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001415 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001416}
1417
1418
1419void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1420 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001421 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001422 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1423}
1424
1425
1426void FixedArray::set_undefined(int index) {
1427 ASSERT(index >= 0 && index < this->length());
1428 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1429 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1430 Heap::undefined_value());
1431}
1432
1433
ager@chromium.org236ad962008-09-25 09:45:57 +00001434void FixedArray::set_null(int index) {
1435 ASSERT(index >= 0 && index < this->length());
1436 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1437 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1438}
1439
1440
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001441void FixedArray::set_the_hole(int index) {
1442 ASSERT(index >= 0 && index < this->length());
1443 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1444 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1445}
1446
1447
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001448Object** FixedArray::data_start() {
1449 return HeapObject::RawField(this, kHeaderSize);
1450}
1451
1452
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001453bool DescriptorArray::IsEmpty() {
1454 ASSERT(this == Heap::empty_descriptor_array() ||
1455 this->length() > 2);
1456 return this == Heap::empty_descriptor_array();
1457}
1458
1459
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001460void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1461 Object* tmp = array->get(first);
1462 fast_set(array, first, array->get(second));
1463 fast_set(array, second, tmp);
1464}
1465
1466
1467int DescriptorArray::Search(String* name) {
1468 SLOW_ASSERT(IsSortedNoDuplicates());
1469
1470 // Check for empty descriptor array.
1471 int nof = number_of_descriptors();
1472 if (nof == 0) return kNotFound;
1473
1474 // Fast case: do linear search for small arrays.
1475 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001476 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001477 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001478 }
1479
1480 // Slow case: perform binary search.
1481 return BinarySearch(name, 0, nof - 1);
1482}
1483
1484
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001485String* DescriptorArray::GetKey(int descriptor_number) {
1486 ASSERT(descriptor_number < number_of_descriptors());
1487 return String::cast(get(ToKeyIndex(descriptor_number)));
1488}
1489
1490
1491Object* DescriptorArray::GetValue(int descriptor_number) {
1492 ASSERT(descriptor_number < number_of_descriptors());
1493 return GetContentArray()->get(ToValueIndex(descriptor_number));
1494}
1495
1496
1497Smi* DescriptorArray::GetDetails(int descriptor_number) {
1498 ASSERT(descriptor_number < number_of_descriptors());
1499 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1500}
1501
1502
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001503PropertyType DescriptorArray::GetType(int descriptor_number) {
1504 ASSERT(descriptor_number < number_of_descriptors());
1505 return PropertyDetails(GetDetails(descriptor_number)).type();
1506}
1507
1508
1509int DescriptorArray::GetFieldIndex(int descriptor_number) {
1510 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1511}
1512
1513
1514JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1515 return JSFunction::cast(GetValue(descriptor_number));
1516}
1517
1518
1519Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1520 ASSERT(GetType(descriptor_number) == CALLBACKS);
1521 return GetValue(descriptor_number);
1522}
1523
1524
1525AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1526 ASSERT(GetType(descriptor_number) == CALLBACKS);
1527 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1528 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1529}
1530
1531
1532bool DescriptorArray::IsProperty(int descriptor_number) {
1533 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1534}
1535
1536
1537bool DescriptorArray::IsTransition(int descriptor_number) {
1538 PropertyType t = GetType(descriptor_number);
1539 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1540}
1541
1542
1543bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1544 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1545}
1546
1547
1548bool DescriptorArray::IsDontEnum(int descriptor_number) {
1549 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1550}
1551
1552
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001553void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1554 desc->Init(GetKey(descriptor_number),
1555 GetValue(descriptor_number),
1556 GetDetails(descriptor_number));
1557}
1558
1559
1560void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1561 // Range check.
1562 ASSERT(descriptor_number < number_of_descriptors());
1563
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001564 // Make sure none of the elements in desc are in new space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001565 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1566 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1567
1568 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1569 FixedArray* content_array = GetContentArray();
1570 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1571 fast_set(content_array, ToDetailsIndex(descriptor_number),
1572 desc->GetDetails().AsSmi());
1573}
1574
1575
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001576void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1577 Descriptor desc;
1578 src->Get(src_index, &desc);
1579 Set(index, &desc);
1580}
1581
1582
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583void DescriptorArray::Swap(int first, int second) {
1584 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1585 FixedArray* content_array = GetContentArray();
1586 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1587 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1588}
1589
1590
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001591bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001592 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001593 if (!max_index_object->IsSmi()) return false;
1594 return 0 !=
1595 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1596}
1597
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001598uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001600 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001601 if (!max_index_object->IsSmi()) return 0;
1602 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1603 return value >> kRequiresSlowElementsTagSize;
1604}
1605
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001606void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001607 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001608}
1609
1610
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611// ------------------------------------
1612// Cast operations
1613
1614
1615CAST_ACCESSOR(FixedArray)
1616CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001617CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00001618CAST_ACCESSOR(JSFunctionResultCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001619CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001620CAST_ACCESSOR(CodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001621CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001622CAST_ACCESSOR(String)
1623CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001624CAST_ACCESSOR(SeqAsciiString)
1625CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001626CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627CAST_ACCESSOR(ExternalString)
1628CAST_ACCESSOR(ExternalAsciiString)
1629CAST_ACCESSOR(ExternalTwoByteString)
1630CAST_ACCESSOR(JSObject)
1631CAST_ACCESSOR(Smi)
1632CAST_ACCESSOR(Failure)
1633CAST_ACCESSOR(HeapObject)
1634CAST_ACCESSOR(HeapNumber)
1635CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001636CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001637CAST_ACCESSOR(SharedFunctionInfo)
1638CAST_ACCESSOR(Map)
1639CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001640CAST_ACCESSOR(GlobalObject)
1641CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001642CAST_ACCESSOR(JSGlobalObject)
1643CAST_ACCESSOR(JSBuiltinsObject)
1644CAST_ACCESSOR(Code)
1645CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001646CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001647CAST_ACCESSOR(Proxy)
1648CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001649CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001650CAST_ACCESSOR(ExternalArray)
1651CAST_ACCESSOR(ExternalByteArray)
1652CAST_ACCESSOR(ExternalUnsignedByteArray)
1653CAST_ACCESSOR(ExternalShortArray)
1654CAST_ACCESSOR(ExternalUnsignedShortArray)
1655CAST_ACCESSOR(ExternalIntArray)
1656CAST_ACCESSOR(ExternalUnsignedIntArray)
1657CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001658CAST_ACCESSOR(Struct)
1659
1660
1661#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1662 STRUCT_LIST(MAKE_STRUCT_CAST)
1663#undef MAKE_STRUCT_CAST
1664
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001665
1666template <typename Shape, typename Key>
1667HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668 ASSERT(obj->IsHashTable());
1669 return reinterpret_cast<HashTable*>(obj);
1670}
1671
1672
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001673SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1674SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1675
1676INT_ACCESSORS(PixelArray, length, kLengthOffset)
1677INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001678
1679
ager@chromium.orgac091b72010-05-05 07:34:42 +00001680SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001681
1682
1683uint32_t String::hash_field() {
1684 return READ_UINT32_FIELD(this, kHashFieldOffset);
1685}
1686
1687
1688void String::set_hash_field(uint32_t value) {
1689 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001690#if V8_HOST_ARCH_64_BIT
1691 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1692#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001693}
1694
1695
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001696bool String::Equals(String* other) {
1697 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001698 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1699 return false;
1700 }
1701 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001702}
1703
1704
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001705Object* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001706 if (!StringShape(this).IsCons()) return this;
1707 ConsString* cons = ConsString::cast(this);
1708 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001709 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001710}
1711
1712
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001713String* String::TryFlattenGetString(PretenureFlag pretenure) {
1714 Object* flat = TryFlatten(pretenure);
1715 return flat->IsFailure() ? this : String::cast(flat);
1716}
1717
1718
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001719uint16_t String::Get(int index) {
1720 ASSERT(index >= 0 && index < length());
1721 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001722 case kSeqStringTag | kAsciiStringTag:
1723 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1724 case kSeqStringTag | kTwoByteStringTag:
1725 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1726 case kConsStringTag | kAsciiStringTag:
1727 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001728 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001729 case kExternalStringTag | kAsciiStringTag:
1730 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1731 case kExternalStringTag | kTwoByteStringTag:
1732 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001733 default:
1734 break;
1735 }
1736
1737 UNREACHABLE();
1738 return 0;
1739}
1740
1741
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001742void String::Set(int index, uint16_t value) {
1743 ASSERT(index >= 0 && index < length());
1744 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745
ager@chromium.org5ec48922009-05-05 07:25:34 +00001746 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001747 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1748 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749}
1750
1751
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001752bool String::IsFlat() {
1753 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001754 case kConsStringTag: {
1755 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001756 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001757 return second->length() == 0;
1758 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001759 default:
1760 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761 }
1762}
1763
1764
ager@chromium.org7c537e22008-10-16 08:43:32 +00001765uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001766 ASSERT(index >= 0 && index < length());
1767 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1768}
1769
1770
ager@chromium.org7c537e22008-10-16 08:43:32 +00001771void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001772 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1773 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1774 static_cast<byte>(value));
1775}
1776
1777
ager@chromium.org7c537e22008-10-16 08:43:32 +00001778Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001779 return FIELD_ADDR(this, kHeaderSize);
1780}
1781
1782
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001783char* SeqAsciiString::GetChars() {
1784 return reinterpret_cast<char*>(GetCharsAddress());
1785}
1786
1787
ager@chromium.org7c537e22008-10-16 08:43:32 +00001788Address SeqTwoByteString::GetCharsAddress() {
1789 return FIELD_ADDR(this, kHeaderSize);
1790}
1791
1792
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001793uc16* SeqTwoByteString::GetChars() {
1794 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1795}
1796
1797
ager@chromium.org7c537e22008-10-16 08:43:32 +00001798uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001799 ASSERT(index >= 0 && index < length());
1800 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1801}
1802
1803
ager@chromium.org7c537e22008-10-16 08:43:32 +00001804void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001805 ASSERT(index >= 0 && index < length());
1806 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1807}
1808
1809
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001810int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001811 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001812}
1813
1814
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001815int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00001816 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001817}
1818
1819
ager@chromium.org870a0b62008-11-04 11:43:05 +00001820String* ConsString::first() {
1821 return String::cast(READ_FIELD(this, kFirstOffset));
1822}
1823
1824
1825Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001826 return READ_FIELD(this, kFirstOffset);
1827}
1828
1829
ager@chromium.org870a0b62008-11-04 11:43:05 +00001830void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001831 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001832 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001833}
1834
1835
ager@chromium.org870a0b62008-11-04 11:43:05 +00001836String* ConsString::second() {
1837 return String::cast(READ_FIELD(this, kSecondOffset));
1838}
1839
1840
1841Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001842 return READ_FIELD(this, kSecondOffset);
1843}
1844
1845
ager@chromium.org870a0b62008-11-04 11:43:05 +00001846void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001847 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001848 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001849}
1850
1851
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001852ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1853 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1854}
1855
1856
1857void ExternalAsciiString::set_resource(
1858 ExternalAsciiString::Resource* resource) {
1859 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1860}
1861
1862
1863ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1864 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1865}
1866
1867
1868void ExternalTwoByteString::set_resource(
1869 ExternalTwoByteString::Resource* resource) {
1870 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1871}
1872
1873
ager@chromium.orgac091b72010-05-05 07:34:42 +00001874void JSFunctionResultCache::MakeZeroSize() {
1875 set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1876 set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1877}
1878
1879
1880void JSFunctionResultCache::Clear() {
1881 int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1882 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1883 MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1884 MakeZeroSize();
1885}
1886
1887
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001888byte ByteArray::get(int index) {
1889 ASSERT(index >= 0 && index < this->length());
1890 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1891}
1892
1893
1894void ByteArray::set(int index, byte value) {
1895 ASSERT(index >= 0 && index < this->length());
1896 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1897}
1898
1899
1900int ByteArray::get_int(int index) {
1901 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1902 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1903}
1904
1905
1906ByteArray* ByteArray::FromDataStartAddress(Address address) {
1907 ASSERT_TAG_ALIGNED(address);
1908 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1909}
1910
1911
1912Address ByteArray::GetDataStartAddress() {
1913 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1914}
1915
1916
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001917uint8_t* PixelArray::external_pointer() {
1918 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1919 return reinterpret_cast<uint8_t*>(ptr);
1920}
1921
1922
1923void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1924 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1925 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1926}
1927
1928
1929uint8_t PixelArray::get(int index) {
1930 ASSERT((index >= 0) && (index < this->length()));
1931 uint8_t* ptr = external_pointer();
1932 return ptr[index];
1933}
1934
1935
1936void PixelArray::set(int index, uint8_t value) {
1937 ASSERT((index >= 0) && (index < this->length()));
1938 uint8_t* ptr = external_pointer();
1939 ptr[index] = value;
1940}
1941
1942
ager@chromium.org3811b432009-10-28 14:53:37 +00001943void* ExternalArray::external_pointer() {
1944 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1945 return reinterpret_cast<void*>(ptr);
1946}
1947
1948
1949void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1950 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1951 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1952}
1953
1954
1955int8_t ExternalByteArray::get(int index) {
1956 ASSERT((index >= 0) && (index < this->length()));
1957 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1958 return ptr[index];
1959}
1960
1961
1962void ExternalByteArray::set(int index, int8_t value) {
1963 ASSERT((index >= 0) && (index < this->length()));
1964 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1965 ptr[index] = value;
1966}
1967
1968
1969uint8_t ExternalUnsignedByteArray::get(int index) {
1970 ASSERT((index >= 0) && (index < this->length()));
1971 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1972 return ptr[index];
1973}
1974
1975
1976void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1977 ASSERT((index >= 0) && (index < this->length()));
1978 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1979 ptr[index] = value;
1980}
1981
1982
1983int16_t ExternalShortArray::get(int index) {
1984 ASSERT((index >= 0) && (index < this->length()));
1985 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1986 return ptr[index];
1987}
1988
1989
1990void ExternalShortArray::set(int index, int16_t value) {
1991 ASSERT((index >= 0) && (index < this->length()));
1992 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1993 ptr[index] = value;
1994}
1995
1996
1997uint16_t ExternalUnsignedShortArray::get(int index) {
1998 ASSERT((index >= 0) && (index < this->length()));
1999 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2000 return ptr[index];
2001}
2002
2003
2004void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2005 ASSERT((index >= 0) && (index < this->length()));
2006 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2007 ptr[index] = value;
2008}
2009
2010
2011int32_t ExternalIntArray::get(int index) {
2012 ASSERT((index >= 0) && (index < this->length()));
2013 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2014 return ptr[index];
2015}
2016
2017
2018void ExternalIntArray::set(int index, int32_t value) {
2019 ASSERT((index >= 0) && (index < this->length()));
2020 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2021 ptr[index] = value;
2022}
2023
2024
2025uint32_t ExternalUnsignedIntArray::get(int index) {
2026 ASSERT((index >= 0) && (index < this->length()));
2027 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2028 return ptr[index];
2029}
2030
2031
2032void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2033 ASSERT((index >= 0) && (index < this->length()));
2034 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2035 ptr[index] = value;
2036}
2037
2038
2039float ExternalFloatArray::get(int index) {
2040 ASSERT((index >= 0) && (index < this->length()));
2041 float* ptr = static_cast<float*>(external_pointer());
2042 return ptr[index];
2043}
2044
2045
2046void ExternalFloatArray::set(int index, float value) {
2047 ASSERT((index >= 0) && (index < this->length()));
2048 float* ptr = static_cast<float*>(external_pointer());
2049 ptr[index] = value;
2050}
2051
2052
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002053int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002054 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2055}
2056
2057
2058int Map::inobject_properties() {
2059 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002060}
2061
2062
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002063int Map::pre_allocated_property_fields() {
2064 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2065}
2066
2067
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002068int HeapObject::SizeFromMap(Map* map) {
2069 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002070 // Only inline the most frequent cases.
2071 if (instance_type == JS_OBJECT_TYPE ||
2072 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
2073 (kStringTag | kConsStringTag) ||
2074 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002075 if (instance_type == FIXED_ARRAY_TYPE) {
2076 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
2077 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002078 if (instance_type == BYTE_ARRAY_TYPE) {
2079 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2080 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002081 // Otherwise do the general size computation.
2082 return SlowSizeFromMap(map);
2083}
2084
2085
2086void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002087 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002088 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002089 ASSERT(0 <= value && value < 256);
2090 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2091}
2092
2093
ager@chromium.org7c537e22008-10-16 08:43:32 +00002094void Map::set_inobject_properties(int value) {
2095 ASSERT(0 <= value && value < 256);
2096 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2097}
2098
2099
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002100void Map::set_pre_allocated_property_fields(int value) {
2101 ASSERT(0 <= value && value < 256);
2102 WRITE_BYTE_FIELD(this,
2103 kPreAllocatedPropertyFieldsOffset,
2104 static_cast<byte>(value));
2105}
2106
2107
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002108InstanceType Map::instance_type() {
2109 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2110}
2111
2112
2113void Map::set_instance_type(InstanceType value) {
2114 ASSERT(0 <= value && value < 256);
2115 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2116}
2117
2118
2119int Map::unused_property_fields() {
2120 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2121}
2122
2123
2124void Map::set_unused_property_fields(int value) {
2125 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2126}
2127
2128
2129byte Map::bit_field() {
2130 return READ_BYTE_FIELD(this, kBitFieldOffset);
2131}
2132
2133
2134void Map::set_bit_field(byte value) {
2135 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2136}
2137
2138
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002139byte Map::bit_field2() {
2140 return READ_BYTE_FIELD(this, kBitField2Offset);
2141}
2142
2143
2144void Map::set_bit_field2(byte value) {
2145 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2146}
2147
2148
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002149void Map::set_non_instance_prototype(bool value) {
2150 if (value) {
2151 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2152 } else {
2153 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2154 }
2155}
2156
2157
2158bool Map::has_non_instance_prototype() {
2159 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2160}
2161
2162
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002163void Map::set_function_with_prototype(bool value) {
2164 if (value) {
2165 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2166 } else {
2167 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2168 }
2169}
2170
2171
2172bool Map::function_with_prototype() {
2173 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2174}
2175
2176
ager@chromium.org870a0b62008-11-04 11:43:05 +00002177void Map::set_is_access_check_needed(bool access_check_needed) {
2178 if (access_check_needed) {
2179 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2180 } else {
2181 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2182 }
2183}
2184
2185
2186bool Map::is_access_check_needed() {
2187 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2188}
2189
2190
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002191Code::Flags Code::flags() {
2192 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2193}
2194
2195
2196void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002197 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002198 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002199 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2200 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002201 ExtractArgumentsCountFromFlags(flags) >= 0);
2202 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2203}
2204
2205
2206Code::Kind Code::kind() {
2207 return ExtractKindFromFlags(flags());
2208}
2209
2210
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002211InLoopFlag Code::ic_in_loop() {
2212 return ExtractICInLoopFromFlags(flags());
2213}
2214
2215
kasper.lund7276f142008-07-30 08:49:36 +00002216InlineCacheState Code::ic_state() {
2217 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002218 // Only allow uninitialized or debugger states for non-IC code
2219 // objects. This is used in the debugger to determine whether or not
2220 // a call to code object has been replaced with a debug break call.
2221 ASSERT(is_inline_cache_stub() ||
2222 result == UNINITIALIZED ||
2223 result == DEBUG_BREAK ||
2224 result == DEBUG_PREPARE_STEP_IN);
2225 return result;
2226}
2227
2228
2229PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002230 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002231 return ExtractTypeFromFlags(flags());
2232}
2233
2234
2235int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002236 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002237 return ExtractArgumentsCountFromFlags(flags());
2238}
2239
2240
2241CodeStub::Major Code::major_key() {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002242 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002243 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2244 kStubMajorKeyOffset));
2245}
2246
2247
2248void Code::set_major_key(CodeStub::Major major) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002249 ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002250 ASSERT(0 <= major && major < 256);
2251 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002252}
2253
2254
2255bool Code::is_inline_cache_stub() {
2256 Kind kind = this->kind();
2257 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2258}
2259
2260
2261Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002262 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002263 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002264 PropertyType type,
2265 int argc) {
2266 // Compute the bit mask.
2267 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002268 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002269 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002270 bits |= type << kFlagsTypeShift;
2271 bits |= argc << kFlagsArgumentsCountShift;
2272 // Cast to flags and validate result before returning it.
2273 Flags result = static_cast<Flags>(bits);
2274 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002275 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002276 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002277 ASSERT(ExtractTypeFromFlags(result) == type);
2278 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2279 return result;
2280}
2281
2282
2283Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2284 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002285 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002286 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002287 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002288}
2289
2290
2291Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2292 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2293 return static_cast<Kind>(bits);
2294}
2295
2296
kasper.lund7276f142008-07-30 08:49:36 +00002297InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2298 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002299 return static_cast<InlineCacheState>(bits);
2300}
2301
2302
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002303InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2304 int bits = (flags & kFlagsICInLoopMask);
2305 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2306}
2307
2308
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002309PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2310 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2311 return static_cast<PropertyType>(bits);
2312}
2313
2314
2315int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2316 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2317}
2318
2319
2320Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2321 int bits = flags & ~kFlagsTypeMask;
2322 return static_cast<Flags>(bits);
2323}
2324
2325
ager@chromium.org8bb60582008-12-11 12:02:20 +00002326Code* Code::GetCodeFromTargetAddress(Address address) {
2327 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2328 // GetCodeFromTargetAddress might be called when marking objects during mark
2329 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2330 // Code::cast. Code::cast does not work when the object's map is
2331 // marked.
2332 Code* result = reinterpret_cast<Code*>(code);
2333 return result;
2334}
2335
2336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002337Object* Map::prototype() {
2338 return READ_FIELD(this, kPrototypeOffset);
2339}
2340
2341
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002342void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002343 ASSERT(value->IsNull() || value->IsJSObject());
2344 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002345 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002346}
2347
2348
2349ACCESSORS(Map, instance_descriptors, DescriptorArray,
2350 kInstanceDescriptorsOffset)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002351ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002352ACCESSORS(Map, constructor, Object, kConstructorOffset)
2353
2354ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2355ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2356
2357ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2358ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002359ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002360
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002361ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002362
2363ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2364ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2365ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2366ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2367ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002368ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002369
2370ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2371ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2372ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2373
2374ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2375ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2376ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2377ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2378ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2379ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2380
2381ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2382ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2383
2384ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2385ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2386
2387ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2388ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002389ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2390 kPropertyAccessorsOffset)
2391ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2392 kPrototypeTemplateOffset)
2393ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2394ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2395 kNamedPropertyHandlerOffset)
2396ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2397 kIndexedPropertyHandlerOffset)
2398ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2399 kInstanceTemplateOffset)
2400ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2401ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002402ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2403 kInstanceCallHandlerOffset)
2404ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2405 kAccessCheckInfoOffset)
2406ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2407
2408ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002409ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2410 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002411
2412ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2413ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2414
2415ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2416
2417ACCESSORS(Script, source, Object, kSourceOffset)
2418ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002419ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002420ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2421ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002422ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002423ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002424ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2425ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002426ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002427ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002428ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002429ACCESSORS(Script, eval_from_instructions_offset, Smi,
2430 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002431
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002432#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002433ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2434ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2435ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2436ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2437
2438ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2439ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2440ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2441ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002442#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002443
2444ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00002445ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002446ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2447 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002448ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002449ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2450ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002451ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002452ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2453 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002454
2455BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2456 kHiddenPrototypeBit)
2457BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2458BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2459 kNeedsAccessCheckBit)
2460BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2461 kIsExpressionBit)
2462BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2463 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002464BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002465 has_only_simple_this_property_assignments,
2466 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002467BOOL_ACCESSORS(SharedFunctionInfo,
2468 compiler_hints,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002469 try_full_codegen,
2470 kTryFullCodegen)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002471
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002472#if V8_HOST_ARCH_32_BIT
2473SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2474SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002475 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002476SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002477 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002478SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2479SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002480 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002481SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2482SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002483 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002484SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002485 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002486SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002487 kThisPropertyAssignmentsCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002488#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002489
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002490#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
2491 int holder::name() { \
2492 int value = READ_INT_FIELD(this, offset); \
2493 ASSERT(kHeapObjectTag == 1); \
2494 ASSERT((value & kHeapObjectTag) == 0); \
2495 return value >> 1; \
2496 } \
2497 void holder::set_##name(int value) { \
2498 ASSERT(kHeapObjectTag == 1); \
2499 ASSERT((value & 0xC0000000) == 0xC0000000 || \
2500 (value & 0xC0000000) == 0x000000000); \
2501 WRITE_INT_FIELD(this, \
2502 offset, \
2503 (value << 1) & ~kHeapObjectTag); \
2504 }
2505
2506#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2507 INT_ACCESSORS(holder, name, offset)
2508
2509
2510
2511PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2512PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2513 kFormalParameterCountOffset)
2514
2515PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2516 kExpectedNofPropertiesOffset)
2517PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2518
2519PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2520 kStartPositionAndTypeOffset)
2521PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2522
2523PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2524 kFunctionTokenPositionOffset)
2525PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2526 kCompilerHintsOffset)
2527
2528PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2529 kThisPropertyAssignmentsCountOffset)
2530#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002531
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002532ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2533ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2534
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002535bool Script::HasValidSource() {
2536 Object* src = this->source();
2537 if (!src->IsString()) return true;
2538 String* src_str = String::cast(src);
2539 if (!StringShape(src_str).IsExternal()) return true;
2540 if (src_str->IsAsciiRepresentation()) {
2541 return ExternalAsciiString::cast(src)->resource() != NULL;
2542 } else if (src_str->IsTwoByteRepresentation()) {
2543 return ExternalTwoByteString::cast(src)->resource() != NULL;
2544 }
2545 return true;
2546}
2547
2548
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002549void SharedFunctionInfo::DontAdaptArguments() {
2550 ASSERT(code()->kind() == Code::BUILTIN);
2551 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2552}
2553
2554
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002555int SharedFunctionInfo::start_position() {
2556 return start_position_and_type() >> kStartPositionShift;
2557}
2558
2559
2560void SharedFunctionInfo::set_start_position(int start_position) {
2561 set_start_position_and_type((start_position << kStartPositionShift)
2562 | (start_position_and_type() & ~kStartPositionMask));
2563}
2564
2565
2566Code* SharedFunctionInfo::code() {
2567 return Code::cast(READ_FIELD(this, kCodeOffset));
2568}
2569
2570
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002571void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002572 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002573 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002574}
2575
2576
2577bool SharedFunctionInfo::is_compiled() {
2578 // TODO(1242782): Create a code kind for uncompiled code.
2579 return code()->kind() != Code::STUB;
2580}
2581
2582
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002583bool SharedFunctionInfo::IsApiFunction() {
2584 return function_data()->IsFunctionTemplateInfo();
2585}
2586
2587
2588FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2589 ASSERT(IsApiFunction());
2590 return FunctionTemplateInfo::cast(function_data());
2591}
2592
2593
2594bool SharedFunctionInfo::HasCustomCallGenerator() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00002595 return function_data()->IsSmi();
2596}
2597
2598
2599int SharedFunctionInfo::custom_call_generator_id() {
2600 ASSERT(HasCustomCallGenerator());
2601 return Smi::cast(function_data())->value();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002602}
2603
2604
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002605bool JSFunction::IsBuiltin() {
2606 return context()->global()->IsJSBuiltinsObject();
2607}
2608
2609
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002610Code* JSFunction::code() {
2611 return shared()->code();
2612}
2613
2614
2615void JSFunction::set_code(Code* value) {
2616 shared()->set_code(value);
2617}
2618
2619
2620Context* JSFunction::context() {
2621 return Context::cast(READ_FIELD(this, kContextOffset));
2622}
2623
2624
2625Object* JSFunction::unchecked_context() {
2626 return READ_FIELD(this, kContextOffset);
2627}
2628
2629
2630void JSFunction::set_context(Object* value) {
2631 ASSERT(value == Heap::undefined_value() || value->IsContext());
2632 WRITE_FIELD(this, kContextOffset, value);
2633 WRITE_BARRIER(this, kContextOffset);
2634}
2635
2636ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2637 kPrototypeOrInitialMapOffset)
2638
2639
2640Map* JSFunction::initial_map() {
2641 return Map::cast(prototype_or_initial_map());
2642}
2643
2644
2645void JSFunction::set_initial_map(Map* value) {
2646 set_prototype_or_initial_map(value);
2647}
2648
2649
2650bool JSFunction::has_initial_map() {
2651 return prototype_or_initial_map()->IsMap();
2652}
2653
2654
2655bool JSFunction::has_instance_prototype() {
2656 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2657}
2658
2659
2660bool JSFunction::has_prototype() {
2661 return map()->has_non_instance_prototype() || has_instance_prototype();
2662}
2663
2664
2665Object* JSFunction::instance_prototype() {
2666 ASSERT(has_instance_prototype());
2667 if (has_initial_map()) return initial_map()->prototype();
2668 // When there is no initial map and the prototype is a JSObject, the
2669 // initial map field is used for the prototype field.
2670 return prototype_or_initial_map();
2671}
2672
2673
2674Object* JSFunction::prototype() {
2675 ASSERT(has_prototype());
2676 // If the function's prototype property has been set to a non-JSObject
2677 // value, that value is stored in the constructor field of the map.
2678 if (map()->has_non_instance_prototype()) return map()->constructor();
2679 return instance_prototype();
2680}
2681
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002682bool JSFunction::should_have_prototype() {
2683 return map()->function_with_prototype();
2684}
2685
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002686
2687bool JSFunction::is_compiled() {
2688 return shared()->is_compiled();
2689}
2690
2691
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002692int JSFunction::NumberOfLiterals() {
2693 return literals()->length();
2694}
2695
2696
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002697Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2698 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002699 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002700}
2701
2702
2703void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2704 Object* value) {
2705 ASSERT(0 <= id && id < kJSBuiltinsCount);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002706 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2707 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2708}
2709
2710
2711Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2712 ASSERT(0 <= id && id < kJSBuiltinsCount);
2713 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2714}
2715
2716
2717void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2718 Code* value) {
2719 ASSERT(0 <= id && id < kJSBuiltinsCount);
2720 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2721 ASSERT(!Heap::InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002722}
2723
2724
2725Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002726 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002727}
2728
2729
2730void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002731 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002732}
2733
2734
2735void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2736 visitor->VisitExternalReference(
2737 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2738}
2739
2740
2741ACCESSORS(JSValue, value, Object, kValueOffset)
2742
2743
2744JSValue* JSValue::cast(Object* obj) {
2745 ASSERT(obj->IsJSValue());
2746 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2747 return reinterpret_cast<JSValue*>(obj);
2748}
2749
2750
2751INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2752INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2753INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2754
2755
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002756byte* Code::instruction_start() {
2757 return FIELD_ADDR(this, kHeaderSize);
2758}
2759
2760
2761int Code::body_size() {
2762 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2763}
2764
2765
2766byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002767 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002768}
2769
2770
2771byte* Code::entry() {
2772 return instruction_start();
2773}
2774
2775
2776bool Code::contains(byte* pc) {
2777 return (instruction_start() <= pc) &&
2778 (pc < instruction_start() + instruction_size());
2779}
2780
2781
2782byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002783 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002784}
2785
2786
2787ACCESSORS(JSArray, length, Object, kLengthOffset)
2788
2789
ager@chromium.org236ad962008-09-25 09:45:57 +00002790ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002791
2792
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002793JSRegExp::Type JSRegExp::TypeTag() {
2794 Object* data = this->data();
2795 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2796 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2797 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002798}
2799
2800
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002801int JSRegExp::CaptureCount() {
2802 switch (TypeTag()) {
2803 case ATOM:
2804 return 0;
2805 case IRREGEXP:
2806 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2807 default:
2808 UNREACHABLE();
2809 return -1;
2810 }
2811}
2812
2813
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002814JSRegExp::Flags JSRegExp::GetFlags() {
2815 ASSERT(this->data()->IsFixedArray());
2816 Object* data = this->data();
2817 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2818 return Flags(smi->value());
2819}
2820
2821
2822String* JSRegExp::Pattern() {
2823 ASSERT(this->data()->IsFixedArray());
2824 Object* data = this->data();
2825 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2826 return pattern;
2827}
2828
2829
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002830Object* JSRegExp::DataAt(int index) {
2831 ASSERT(TypeTag() != NOT_COMPILED);
2832 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002833}
2834
2835
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002836void JSRegExp::SetDataAt(int index, Object* value) {
2837 ASSERT(TypeTag() != NOT_COMPILED);
2838 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2839 FixedArray::cast(data())->set(index, value);
2840}
2841
2842
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002843JSObject::ElementsKind JSObject::GetElementsKind() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002844 HeapObject* array = elements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002845 if (array->IsFixedArray()) {
2846 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2847 if (array->map() == Heap::fixed_array_map()) {
2848 return FAST_ELEMENTS;
2849 }
2850 ASSERT(array->IsDictionary());
2851 return DICTIONARY_ELEMENTS;
2852 }
ager@chromium.org3811b432009-10-28 14:53:37 +00002853 if (array->IsExternalArray()) {
2854 switch (array->map()->instance_type()) {
2855 case EXTERNAL_BYTE_ARRAY_TYPE:
2856 return EXTERNAL_BYTE_ELEMENTS;
2857 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2858 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2859 case EXTERNAL_SHORT_ARRAY_TYPE:
2860 return EXTERNAL_SHORT_ELEMENTS;
2861 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2862 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2863 case EXTERNAL_INT_ARRAY_TYPE:
2864 return EXTERNAL_INT_ELEMENTS;
2865 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2866 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2867 default:
2868 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2869 return EXTERNAL_FLOAT_ELEMENTS;
2870 }
2871 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002872 ASSERT(array->IsPixelArray());
2873 return PIXEL_ELEMENTS;
2874}
2875
2876
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002877bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002878 return GetElementsKind() == FAST_ELEMENTS;
2879}
2880
2881
2882bool JSObject::HasDictionaryElements() {
2883 return GetElementsKind() == DICTIONARY_ELEMENTS;
2884}
2885
2886
2887bool JSObject::HasPixelElements() {
2888 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002889}
2890
2891
ager@chromium.org3811b432009-10-28 14:53:37 +00002892bool JSObject::HasExternalArrayElements() {
2893 return (HasExternalByteElements() ||
2894 HasExternalUnsignedByteElements() ||
2895 HasExternalShortElements() ||
2896 HasExternalUnsignedShortElements() ||
2897 HasExternalIntElements() ||
2898 HasExternalUnsignedIntElements() ||
2899 HasExternalFloatElements());
2900}
2901
2902
2903bool JSObject::HasExternalByteElements() {
2904 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2905}
2906
2907
2908bool JSObject::HasExternalUnsignedByteElements() {
2909 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2910}
2911
2912
2913bool JSObject::HasExternalShortElements() {
2914 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2915}
2916
2917
2918bool JSObject::HasExternalUnsignedShortElements() {
2919 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2920}
2921
2922
2923bool JSObject::HasExternalIntElements() {
2924 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2925}
2926
2927
2928bool JSObject::HasExternalUnsignedIntElements() {
2929 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2930}
2931
2932
2933bool JSObject::HasExternalFloatElements() {
2934 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2935}
2936
2937
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002938bool JSObject::HasNamedInterceptor() {
2939 return map()->has_named_interceptor();
2940}
2941
2942
2943bool JSObject::HasIndexedInterceptor() {
2944 return map()->has_indexed_interceptor();
2945}
2946
2947
ager@chromium.org5c838252010-02-19 08:53:10 +00002948bool JSObject::AllowsSetElementsLength() {
2949 bool result = elements()->IsFixedArray();
2950 ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
2951 return result;
2952}
2953
2954
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002955StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002956 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002957 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002958}
2959
2960
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002961NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002962 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002963 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002964}
2965
2966
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002967bool String::IsHashFieldComputed(uint32_t field) {
2968 return (field & kHashNotComputedMask) == 0;
2969}
2970
2971
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002972bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002973 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002974}
2975
2976
2977uint32_t String::Hash() {
2978 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002979 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002980 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002981 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002982 return ComputeAndSetHash();
2983}
2984
2985
ager@chromium.org7c537e22008-10-16 08:43:32 +00002986StringHasher::StringHasher(int length)
2987 : length_(length),
2988 raw_running_hash_(0),
2989 array_index_(0),
2990 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2991 is_first_char_(true),
2992 is_valid_(true) { }
2993
2994
2995bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002996 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00002997}
2998
2999
3000void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003001 // Use the Jenkins one-at-a-time hash function to update the hash
3002 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003003 raw_running_hash_ += c;
3004 raw_running_hash_ += (raw_running_hash_ << 10);
3005 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003006 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003007 if (is_array_index_) {
3008 if (c < '0' || c > '9') {
3009 is_array_index_ = false;
3010 } else {
3011 int d = c - '0';
3012 if (is_first_char_) {
3013 is_first_char_ = false;
3014 if (c == '0' && length_ > 1) {
3015 is_array_index_ = false;
3016 return;
3017 }
3018 }
3019 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3020 is_array_index_ = false;
3021 } else {
3022 array_index_ = array_index_ * 10 + d;
3023 }
3024 }
3025 }
3026}
3027
3028
3029void StringHasher::AddCharacterNoIndex(uc32 c) {
3030 ASSERT(!is_array_index());
3031 raw_running_hash_ += c;
3032 raw_running_hash_ += (raw_running_hash_ << 10);
3033 raw_running_hash_ ^= (raw_running_hash_ >> 6);
3034}
3035
3036
3037uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003038 // Get the calculated raw hash value and do some more bit ops to distribute
3039 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00003040 uint32_t result = raw_running_hash_;
3041 result += (result << 3);
3042 result ^= (result >> 11);
3043 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003044 if (result == 0) {
3045 result = 27;
3046 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00003047 return result;
3048}
3049
3050
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003051bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00003052 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003053 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3054 return false;
3055 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003056 return SlowAsArrayIndex(index);
3057}
3058
3059
3060Object* JSObject::GetPrototype() {
3061 return JSObject::cast(this)->map()->prototype();
3062}
3063
3064
3065PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3066 return GetPropertyAttributeWithReceiver(this, key);
3067}
3068
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003069// TODO(504): this may be useful in other places too where JSGlobalProxy
3070// is used.
3071Object* JSObject::BypassGlobalProxy() {
3072 if (IsJSGlobalProxy()) {
3073 Object* proto = GetPrototype();
3074 if (proto->IsNull()) return Heap::undefined_value();
3075 ASSERT(proto->IsJSGlobalObject());
3076 return proto;
3077 }
3078 return this;
3079}
3080
3081
3082bool JSObject::HasHiddenPropertiesObject() {
3083 ASSERT(!IsJSGlobalProxy());
3084 return GetPropertyAttributePostInterceptor(this,
3085 Heap::hidden_symbol(),
3086 false) != ABSENT;
3087}
3088
3089
3090Object* JSObject::GetHiddenPropertiesObject() {
3091 ASSERT(!IsJSGlobalProxy());
3092 PropertyAttributes attributes;
3093 return GetLocalPropertyPostInterceptor(this,
3094 Heap::hidden_symbol(),
3095 &attributes);
3096}
3097
3098
3099Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3100 ASSERT(!IsJSGlobalProxy());
3101 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3102 hidden_obj,
3103 DONT_ENUM);
3104}
3105
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003106
3107bool JSObject::HasElement(uint32_t index) {
3108 return HasElementWithReceiver(this, index);
3109}
3110
3111
3112bool AccessorInfo::all_can_read() {
3113 return BooleanBit::get(flag(), kAllCanReadBit);
3114}
3115
3116
3117void AccessorInfo::set_all_can_read(bool value) {
3118 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3119}
3120
3121
3122bool AccessorInfo::all_can_write() {
3123 return BooleanBit::get(flag(), kAllCanWriteBit);
3124}
3125
3126
3127void AccessorInfo::set_all_can_write(bool value) {
3128 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3129}
3130
3131
ager@chromium.org870a0b62008-11-04 11:43:05 +00003132bool AccessorInfo::prohibits_overwriting() {
3133 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3134}
3135
3136
3137void AccessorInfo::set_prohibits_overwriting(bool value) {
3138 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3139}
3140
3141
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003142PropertyAttributes AccessorInfo::property_attributes() {
3143 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3144}
3145
3146
3147void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3148 ASSERT(AttributesField::is_valid(attributes));
3149 int rest_value = flag()->value() & ~AttributesField::mask();
3150 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3151}
3152
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003153template<typename Shape, typename Key>
3154void Dictionary<Shape, Key>::SetEntry(int entry,
3155 Object* key,
3156 Object* value,
3157 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00003158 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003159 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003160 AssertNoAllocation no_gc;
3161 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00003162 FixedArray::set(index, key, mode);
3163 FixedArray::set(index+1, value, mode);
3164 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003165}
3166
3167
3168void Map::ClearCodeCache() {
3169 // No write barrier is needed since empty_fixed_array is not in new space.
3170 // Please note this function is used during marking:
3171 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00003172 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3173 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003174}
3175
3176
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003177void JSArray::EnsureSize(int required_size) {
3178 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003179 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00003180 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3181 if (elts->length() < required_size) {
3182 // Doubling in size would be overkill, but leave some slack to avoid
3183 // constantly growing.
3184 Expand(required_size + (required_size >> 3));
3185 // It's a performance benefit to keep a frequently used array in new-space.
3186 } else if (!Heap::new_space()->Contains(elts) &&
3187 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3188 // Expand will allocate a new backing store in new space even if the size
3189 // we asked for isn't larger than what we had before.
3190 Expand(required_size);
3191 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003192}
3193
3194
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003195void JSArray::set_length(Smi* length) {
3196 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3197}
3198
3199
ager@chromium.org7c537e22008-10-16 08:43:32 +00003200void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003201 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00003202 set_elements(storage);
3203}
3204
3205
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003206Object* FixedArray::Copy() {
3207 if (length() == 0) return this;
3208 return Heap::CopyFixedArray(this);
3209}
3210
3211
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003212#undef CAST_ACCESSOR
3213#undef INT_ACCESSORS
3214#undef SMI_ACCESSORS
3215#undef ACCESSORS
3216#undef FIELD_ADDR
3217#undef READ_FIELD
3218#undef WRITE_FIELD
3219#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003220#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003221#undef READ_MEMADDR_FIELD
3222#undef WRITE_MEMADDR_FIELD
3223#undef READ_DOUBLE_FIELD
3224#undef WRITE_DOUBLE_FIELD
3225#undef READ_INT_FIELD
3226#undef WRITE_INT_FIELD
3227#undef READ_SHORT_FIELD
3228#undef WRITE_SHORT_FIELD
3229#undef READ_BYTE_FIELD
3230#undef WRITE_BYTE_FIELD
3231
3232
3233} } // namespace v8::internal
3234
3235#endif // V8_OBJECTS_INL_H_