blob: 8514a412c163a6d8ef0fa28fc363cab009c55f1d [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();
153 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
154 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155}
156
157
158bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000159 if (!this->IsHeapObject()) return false;
160 uint32_t type = HeapObject::cast(this)->map()->instance_type();
161 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
162 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000163}
164
165
ager@chromium.org870a0b62008-11-04 11:43:05 +0000166bool Object::IsSeqString() {
167 if (!IsString()) return false;
168 return StringShape(String::cast(this)).IsSequential();
169}
170
171
172bool Object::IsSeqAsciiString() {
173 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000174 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000175 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000176}
177
178
179bool Object::IsSeqTwoByteString() {
180 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000181 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000182 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183}
184
185
186bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000187 if (!IsString()) return false;
188 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189}
190
191
192bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000193 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000194 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000195 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196}
197
198
199bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000200 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000201 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000202 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000203}
204
205
ager@chromium.org870a0b62008-11-04 11:43:05 +0000206StringShape::StringShape(String* str)
207 : type_(str->map()->instance_type()) {
208 set_valid();
209 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210}
211
212
ager@chromium.org870a0b62008-11-04 11:43:05 +0000213StringShape::StringShape(Map* map)
214 : type_(map->instance_type()) {
215 set_valid();
216 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217}
218
219
ager@chromium.org870a0b62008-11-04 11:43:05 +0000220StringShape::StringShape(InstanceType t)
221 : type_(static_cast<uint32_t>(t)) {
222 set_valid();
223 ASSERT((type_ & kIsNotStringMask) == kStringTag);
224}
225
226
227bool StringShape::IsSymbol() {
228 ASSERT(valid());
229 return (type_ & kIsSymbolMask) == kSymbolTag;
230}
231
232
ager@chromium.org5ec48922009-05-05 07:25:34 +0000233bool String::IsAsciiRepresentation() {
234 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000235 if ((type & kStringRepresentationMask) == kConsStringTag &&
236 ConsString::cast(this)->second()->length() == 0) {
237 return ConsString::cast(this)->first()->IsAsciiRepresentation();
238 }
239 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000240}
241
242
ager@chromium.org5ec48922009-05-05 07:25:34 +0000243bool String::IsTwoByteRepresentation() {
244 uint32_t type = map()->instance_type();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000245 if ((type & kStringRepresentationMask) == kConsStringTag &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000246 ConsString::cast(this)->second()->length() == 0) {
247 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
248 }
249 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000250}
251
252
253bool StringShape::IsCons() {
254 return (type_ & kStringRepresentationMask) == kConsStringTag;
255}
256
257
ager@chromium.org870a0b62008-11-04 11:43:05 +0000258bool StringShape::IsExternal() {
259 return (type_ & kStringRepresentationMask) == kExternalStringTag;
260}
261
262
263bool StringShape::IsSequential() {
264 return (type_ & kStringRepresentationMask) == kSeqStringTag;
265}
266
267
268StringRepresentationTag StringShape::representation_tag() {
269 uint32_t tag = (type_ & kStringRepresentationMask);
270 return static_cast<StringRepresentationTag>(tag);
271}
272
273
274uint32_t StringShape::full_representation_tag() {
275 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
276}
277
278
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000279STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
280 Internals::kFullStringRepresentationMask);
281
282
ager@chromium.org870a0b62008-11-04 11:43:05 +0000283bool StringShape::IsSequentialAscii() {
284 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
285}
286
287
288bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000289 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000290}
291
292
293bool StringShape::IsExternalAscii() {
294 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
295}
296
297
298bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000299 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000300}
301
302
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000303STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
304 Internals::kExternalTwoByteRepresentationTag);
305
306
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000307uc32 FlatStringReader::Get(int index) {
308 ASSERT(0 <= index && index <= length_);
309 if (is_ascii_) {
310 return static_cast<const byte*>(start_)[index];
311 } else {
312 return static_cast<const uc16*>(start_)[index];
313 }
314}
315
316
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317bool Object::IsNumber() {
318 return IsSmi() || IsHeapNumber();
319}
320
321
322bool Object::IsByteArray() {
323 return Object::IsHeapObject()
324 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
325}
326
327
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000328bool Object::IsPixelArray() {
329 return Object::IsHeapObject() &&
330 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
331}
332
333
ager@chromium.org3811b432009-10-28 14:53:37 +0000334bool Object::IsExternalArray() {
335 if (!Object::IsHeapObject())
336 return false;
337 InstanceType instance_type =
338 HeapObject::cast(this)->map()->instance_type();
339 return (instance_type >= EXTERNAL_BYTE_ARRAY_TYPE &&
340 instance_type <= EXTERNAL_FLOAT_ARRAY_TYPE);
341}
342
343
344bool Object::IsExternalByteArray() {
345 return Object::IsHeapObject() &&
346 HeapObject::cast(this)->map()->instance_type() ==
347 EXTERNAL_BYTE_ARRAY_TYPE;
348}
349
350
351bool Object::IsExternalUnsignedByteArray() {
352 return Object::IsHeapObject() &&
353 HeapObject::cast(this)->map()->instance_type() ==
354 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
355}
356
357
358bool Object::IsExternalShortArray() {
359 return Object::IsHeapObject() &&
360 HeapObject::cast(this)->map()->instance_type() ==
361 EXTERNAL_SHORT_ARRAY_TYPE;
362}
363
364
365bool Object::IsExternalUnsignedShortArray() {
366 return Object::IsHeapObject() &&
367 HeapObject::cast(this)->map()->instance_type() ==
368 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
369}
370
371
372bool Object::IsExternalIntArray() {
373 return Object::IsHeapObject() &&
374 HeapObject::cast(this)->map()->instance_type() ==
375 EXTERNAL_INT_ARRAY_TYPE;
376}
377
378
379bool Object::IsExternalUnsignedIntArray() {
380 return Object::IsHeapObject() &&
381 HeapObject::cast(this)->map()->instance_type() ==
382 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
383}
384
385
386bool Object::IsExternalFloatArray() {
387 return Object::IsHeapObject() &&
388 HeapObject::cast(this)->map()->instance_type() ==
389 EXTERNAL_FLOAT_ARRAY_TYPE;
390}
391
392
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393bool Object::IsFailure() {
394 return HAS_FAILURE_TAG(this);
395}
396
397
398bool Object::IsRetryAfterGC() {
399 return HAS_FAILURE_TAG(this)
400 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
401}
402
403
ager@chromium.org7c537e22008-10-16 08:43:32 +0000404bool Object::IsOutOfMemoryFailure() {
405 return HAS_FAILURE_TAG(this)
406 && Failure::cast(this)->IsOutOfMemoryException();
407}
408
409
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410bool Object::IsException() {
411 return this == Failure::Exception();
412}
413
414
415bool Object::IsJSObject() {
416 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000417 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418}
419
420
ager@chromium.org32912102009-01-16 10:38:43 +0000421bool Object::IsJSContextExtensionObject() {
422 return IsHeapObject()
423 && (HeapObject::cast(this)->map()->instance_type() ==
424 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
425}
426
427
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000428bool Object::IsMap() {
429 return Object::IsHeapObject()
430 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
431}
432
433
434bool Object::IsFixedArray() {
435 return Object::IsHeapObject()
436 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
437}
438
439
440bool Object::IsDescriptorArray() {
441 return IsFixedArray();
442}
443
444
445bool Object::IsContext() {
446 return Object::IsHeapObject()
447 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000448 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000449 HeapObject::cast(this)->map() == Heap::global_context_map());
450}
451
452
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000453bool Object::IsCatchContext() {
454 return Object::IsHeapObject()
455 && HeapObject::cast(this)->map() == Heap::catch_context_map();
456}
457
458
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000459bool Object::IsGlobalContext() {
460 return Object::IsHeapObject()
461 && HeapObject::cast(this)->map() == Heap::global_context_map();
462}
463
464
465bool Object::IsJSFunction() {
466 return Object::IsHeapObject()
467 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
468}
469
470
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000471template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000472 return obj->IsJSFunction();
473}
474
475
476bool Object::IsCode() {
477 return Object::IsHeapObject()
478 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
479}
480
481
482bool Object::IsOddball() {
483 return Object::IsHeapObject()
484 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
485}
486
487
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000488bool Object::IsJSGlobalPropertyCell() {
489 return Object::IsHeapObject()
490 && HeapObject::cast(this)->map()->instance_type()
491 == JS_GLOBAL_PROPERTY_CELL_TYPE;
492}
493
494
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000495bool Object::IsSharedFunctionInfo() {
496 return Object::IsHeapObject() &&
497 (HeapObject::cast(this)->map()->instance_type() ==
498 SHARED_FUNCTION_INFO_TYPE);
499}
500
501
502bool Object::IsJSValue() {
503 return Object::IsHeapObject()
504 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
505}
506
507
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000508bool Object::IsStringWrapper() {
509 return IsJSValue() && JSValue::cast(this)->value()->IsString();
510}
511
512
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513bool Object::IsProxy() {
514 return Object::IsHeapObject()
515 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
516}
517
518
519bool Object::IsBoolean() {
520 return IsTrue() || IsFalse();
521}
522
523
524bool Object::IsJSArray() {
525 return Object::IsHeapObject()
526 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
527}
528
529
ager@chromium.org236ad962008-09-25 09:45:57 +0000530bool Object::IsJSRegExp() {
531 return Object::IsHeapObject()
532 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
533}
534
535
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000536template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537 return obj->IsJSArray();
538}
539
540
541bool Object::IsHashTable() {
542 return Object::IsHeapObject()
543 && HeapObject::cast(this)->map() == Heap::hash_table_map();
544}
545
546
547bool Object::IsDictionary() {
548 return IsHashTable() && this != Heap::symbol_table();
549}
550
551
552bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000553 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554}
555
556
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000557bool Object::IsCompilationCacheTable() {
558 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000559}
560
561
ager@chromium.org236ad962008-09-25 09:45:57 +0000562bool Object::IsMapCache() {
563 return IsHashTable();
564}
565
566
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000567bool Object::IsPrimitive() {
568 return IsOddball() || IsNumber() || IsString();
569}
570
571
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000572bool Object::IsJSGlobalProxy() {
573 bool result = IsHeapObject() &&
574 (HeapObject::cast(this)->map()->instance_type() ==
575 JS_GLOBAL_PROXY_TYPE);
576 ASSERT(!result || IsAccessCheckNeeded());
577 return result;
578}
579
580
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000582 if (!IsHeapObject()) return false;
583
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000584 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000585 return type == JS_GLOBAL_OBJECT_TYPE ||
586 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000587}
588
589
590bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000591 return IsHeapObject() &&
592 (HeapObject::cast(this)->map()->instance_type() ==
593 JS_GLOBAL_OBJECT_TYPE);
594}
595
596
597bool Object::IsJSBuiltinsObject() {
598 return IsHeapObject() &&
599 (HeapObject::cast(this)->map()->instance_type() ==
600 JS_BUILTINS_OBJECT_TYPE);
601}
602
603
604bool Object::IsUndetectableObject() {
605 return IsHeapObject()
606 && HeapObject::cast(this)->map()->is_undetectable();
607}
608
609
610bool Object::IsAccessCheckNeeded() {
611 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000612 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613}
614
615
616bool Object::IsStruct() {
617 if (!IsHeapObject()) return false;
618 switch (HeapObject::cast(this)->map()->instance_type()) {
619#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
620 STRUCT_LIST(MAKE_STRUCT_CASE)
621#undef MAKE_STRUCT_CASE
622 default: return false;
623 }
624}
625
626
627#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
628 bool Object::Is##Name() { \
629 return Object::IsHeapObject() \
630 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
631 }
632 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
633#undef MAKE_STRUCT_PREDICATE
634
635
636bool Object::IsUndefined() {
637 return this == Heap::undefined_value();
638}
639
640
641bool Object::IsTheHole() {
642 return this == Heap::the_hole_value();
643}
644
645
646bool Object::IsNull() {
647 return this == Heap::null_value();
648}
649
650
651bool Object::IsTrue() {
652 return this == Heap::true_value();
653}
654
655
656bool Object::IsFalse() {
657 return this == Heap::false_value();
658}
659
660
661double Object::Number() {
662 ASSERT(IsNumber());
663 return IsSmi()
664 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
665 : reinterpret_cast<HeapNumber*>(this)->value();
666}
667
668
669
670Object* Object::ToSmi() {
671 if (IsSmi()) return this;
672 if (IsHeapNumber()) {
673 double value = HeapNumber::cast(this)->value();
674 int int_value = FastD2I(value);
675 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
676 return Smi::FromInt(int_value);
677 }
678 }
679 return Failure::Exception();
680}
681
682
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000683bool Object::HasSpecificClassOf(String* name) {
684 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
685}
686
687
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688Object* Object::GetElement(uint32_t index) {
689 return GetElementWithReceiver(this, index);
690}
691
692
693Object* Object::GetProperty(String* key) {
694 PropertyAttributes attributes;
695 return GetPropertyWithReceiver(this, key, &attributes);
696}
697
698
699Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
700 return GetPropertyWithReceiver(this, key, attributes);
701}
702
703
704#define FIELD_ADDR(p, offset) \
705 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
706
707#define READ_FIELD(p, offset) \
708 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
709
710#define WRITE_FIELD(p, offset, value) \
711 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
712
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000713
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000714#define WRITE_BARRIER(object, offset) \
715 Heap::RecordWrite(object->address(), offset);
716
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000717// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000718// write due to the assert validating the written value.
719#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
720 if (mode == UPDATE_WRITE_BARRIER) { \
721 Heap::RecordWrite(object->address(), offset); \
722 } else { \
723 ASSERT(mode == SKIP_WRITE_BARRIER); \
724 ASSERT(Heap::InNewSpace(object) || \
725 !Heap::InNewSpace(READ_FIELD(object, offset))); \
726 }
727
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728#define READ_DOUBLE_FIELD(p, offset) \
729 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
730
731#define WRITE_DOUBLE_FIELD(p, offset, value) \
732 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
733
734#define READ_INT_FIELD(p, offset) \
735 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
736
737#define WRITE_INT_FIELD(p, offset, value) \
738 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
739
ager@chromium.org3e875802009-06-29 08:26:34 +0000740#define READ_INTPTR_FIELD(p, offset) \
741 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
742
743#define WRITE_INTPTR_FIELD(p, offset, value) \
744 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
745
ager@chromium.org7c537e22008-10-16 08:43:32 +0000746#define READ_UINT32_FIELD(p, offset) \
747 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
748
749#define WRITE_UINT32_FIELD(p, offset, value) \
750 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
751
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752#define READ_SHORT_FIELD(p, offset) \
753 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
754
755#define WRITE_SHORT_FIELD(p, offset, value) \
756 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
757
758#define READ_BYTE_FIELD(p, offset) \
759 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
760
761#define WRITE_BYTE_FIELD(p, offset, value) \
762 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
763
764
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000765Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
766 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000767}
768
769
770int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000771 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772}
773
774
775Smi* Smi::FromInt(int value) {
776 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000777 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000778 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000779 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000780 return reinterpret_cast<Smi*>(tagged_value);
781}
782
783
784Smi* Smi::FromIntptr(intptr_t value) {
785 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000786 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
787 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788}
789
790
791Failure::Type Failure::type() const {
792 return static_cast<Type>(value() & kFailureTypeTagMask);
793}
794
795
796bool Failure::IsInternalError() const {
797 return type() == INTERNAL_ERROR;
798}
799
800
801bool Failure::IsOutOfMemoryException() const {
802 return type() == OUT_OF_MEMORY_EXCEPTION;
803}
804
805
806int Failure::requested() const {
807 const int kShiftBits =
808 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
809 STATIC_ASSERT(kShiftBits >= 0);
810 ASSERT(type() == RETRY_AFTER_GC);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000811 return static_cast<int>(value() >> kShiftBits);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812}
813
814
815AllocationSpace Failure::allocation_space() const {
816 ASSERT_EQ(RETRY_AFTER_GC, type());
817 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
818 & kSpaceTagMask);
819}
820
821
822Failure* Failure::InternalError() {
823 return Construct(INTERNAL_ERROR);
824}
825
826
827Failure* Failure::Exception() {
828 return Construct(EXCEPTION);
829}
830
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000831
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832Failure* Failure::OutOfMemoryException() {
833 return Construct(OUT_OF_MEMORY_EXCEPTION);
834}
835
836
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000837intptr_t Failure::value() const {
838 return reinterpret_cast<intptr_t>(this) >> kFailureTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839}
840
841
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000842Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000843 // Assert that the space encoding fits in the three bytes allotted for it.
844 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000845 intptr_t requested = requested_bytes >> kObjectAlignmentBits;
846 int tag_bits = kSpaceTagSize + kFailureTypeTagSize;
847 if (((requested << tag_bits) >> tag_bits) != requested) {
848 // No room for entire requested size in the bits. Round down to
849 // maximally representable size.
850 requested = static_cast<intptr_t>(
851 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
852 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000853 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000854 return Construct(RETRY_AFTER_GC, value);
855}
856
857
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000858Failure* Failure::Construct(Type type, intptr_t value) {
859 intptr_t info = (static_cast<intptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000860 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000861 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862}
863
864
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000865bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866#ifdef DEBUG
867 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
868#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000869
870#ifdef V8_TARGET_ARCH_X64
871 // To be representable as a long smi, the value must be a 32-bit integer.
872 bool result = (value == static_cast<int32_t>(value));
873#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874 // To be representable as an tagged small integer, the two
875 // most-significant bits of 'value' must be either 00 or 11 due to
876 // sign-extension. To check this we add 01 to the two
877 // most-significant bits, and check if the most-significant bit is 0
878 //
879 // CAUTION: The original code below:
880 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
881 // may lead to incorrect results according to the C language spec, and
882 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
883 // compiler may produce undefined results in case of signed integer
884 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000885 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000886#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000887 ASSERT(result == in_range);
888 return result;
889}
890
891
kasper.lund7276f142008-07-30 08:49:36 +0000892MapWord MapWord::FromMap(Map* map) {
893 return MapWord(reinterpret_cast<uintptr_t>(map));
894}
895
896
897Map* MapWord::ToMap() {
898 return reinterpret_cast<Map*>(value_);
899}
900
901
902bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000903 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000904}
905
906
907MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000908 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
909 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000910}
911
912
913HeapObject* MapWord::ToForwardingAddress() {
914 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000915 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000916}
917
918
919bool MapWord::IsMarked() {
920 return (value_ & kMarkingMask) == 0;
921}
922
923
924void MapWord::SetMark() {
925 value_ &= ~kMarkingMask;
926}
927
928
929void MapWord::ClearMark() {
930 value_ |= kMarkingMask;
931}
932
933
934bool MapWord::IsOverflowed() {
935 return (value_ & kOverflowMask) != 0;
936}
937
938
939void MapWord::SetOverflow() {
940 value_ |= kOverflowMask;
941}
942
943
944void MapWord::ClearOverflow() {
945 value_ &= ~kOverflowMask;
946}
947
948
949MapWord MapWord::EncodeAddress(Address map_address, int offset) {
950 // Offset is the distance in live bytes from the first live object in the
951 // same page. The offset between two objects in the same page should not
952 // exceed the object area size of a page.
953 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
954
955 int compact_offset = offset >> kObjectAlignmentBits;
956 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
957
958 Page* map_page = Page::FromAddress(map_address);
959 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
960
961 int map_page_offset =
962 map_page->Offset(map_address) >> kObjectAlignmentBits;
963
964 uintptr_t encoding =
965 (compact_offset << kForwardingOffsetShift) |
966 (map_page_offset << kMapPageOffsetShift) |
967 (map_page->mc_page_index << kMapPageIndexShift);
968 return MapWord(encoding);
969}
970
971
972Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000973 int map_page_index =
974 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +0000975 ASSERT_MAP_PAGE_INDEX(map_page_index);
976
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000977 int map_page_offset = static_cast<int>(
kasper.lund7276f142008-07-30 08:49:36 +0000978 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000979 << kObjectAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +0000980
981 return (map_space->PageAddress(map_page_index) + map_page_offset);
982}
983
984
985int MapWord::DecodeOffset() {
986 // The offset field is represented in the kForwardingOffsetBits
987 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000988 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
989 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
990 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +0000991}
992
993
994MapWord MapWord::FromEncodedAddress(Address address) {
995 return MapWord(reinterpret_cast<uintptr_t>(address));
996}
997
998
999Address MapWord::ToEncodedAddress() {
1000 return reinterpret_cast<Address>(value_);
1001}
1002
1003
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001004#ifdef DEBUG
1005void HeapObject::VerifyObjectField(int offset) {
1006 VerifyPointer(READ_FIELD(this, offset));
1007}
1008#endif
1009
1010
1011Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001012 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001013}
1014
1015
1016void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001017 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018}
1019
1020
kasper.lund7276f142008-07-30 08:49:36 +00001021MapWord HeapObject::map_word() {
1022 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1023}
1024
1025
1026void HeapObject::set_map_word(MapWord map_word) {
1027 // WRITE_FIELD does not update the remembered set, but there is no need
1028 // here.
1029 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1030}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001031
1032
1033HeapObject* HeapObject::FromAddress(Address address) {
1034 ASSERT_TAG_ALIGNED(address);
1035 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1036}
1037
1038
1039Address HeapObject::address() {
1040 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1041}
1042
1043
1044int HeapObject::Size() {
1045 return SizeFromMap(map());
1046}
1047
1048
1049void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1050 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1051 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1052}
1053
1054
1055void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1056 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1057}
1058
1059
kasper.lund7276f142008-07-30 08:49:36 +00001060bool HeapObject::IsMarked() {
1061 return map_word().IsMarked();
1062}
1063
1064
1065void HeapObject::SetMark() {
1066 ASSERT(!IsMarked());
1067 MapWord first_word = map_word();
1068 first_word.SetMark();
1069 set_map_word(first_word);
1070}
1071
1072
1073void HeapObject::ClearMark() {
1074 ASSERT(IsMarked());
1075 MapWord first_word = map_word();
1076 first_word.ClearMark();
1077 set_map_word(first_word);
1078}
1079
1080
1081bool HeapObject::IsOverflowed() {
1082 return map_word().IsOverflowed();
1083}
1084
1085
1086void HeapObject::SetOverflow() {
1087 MapWord first_word = map_word();
1088 first_word.SetOverflow();
1089 set_map_word(first_word);
1090}
1091
1092
1093void HeapObject::ClearOverflow() {
1094 ASSERT(IsOverflowed());
1095 MapWord first_word = map_word();
1096 first_word.ClearOverflow();
1097 set_map_word(first_word);
1098}
1099
1100
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101double HeapNumber::value() {
1102 return READ_DOUBLE_FIELD(this, kValueOffset);
1103}
1104
1105
1106void HeapNumber::set_value(double value) {
1107 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1108}
1109
1110
1111ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001112
1113
1114Array* JSObject::elements() {
1115 Object* array = READ_FIELD(this, kElementsOffset);
1116 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001117 ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1118 array->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001119 return reinterpret_cast<Array*>(array);
1120}
1121
1122
1123void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1124 // In the assert below Dictionary is covered under FixedArray.
ager@chromium.org3811b432009-10-28 14:53:37 +00001125 ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1126 value->IsExternalArray());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001127 WRITE_FIELD(this, kElementsOffset, value);
1128 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1129}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130
1131
1132void JSObject::initialize_properties() {
1133 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1134 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1135}
1136
1137
1138void JSObject::initialize_elements() {
1139 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1140 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1141}
1142
1143
1144ACCESSORS(Oddball, to_string, String, kToStringOffset)
1145ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1146
1147
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001148Object* JSGlobalPropertyCell::value() {
1149 return READ_FIELD(this, kValueOffset);
1150}
1151
1152
1153void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1154 // The write barrier is not used for global property cells.
1155 ASSERT(!val->IsJSGlobalPropertyCell());
1156 WRITE_FIELD(this, kValueOffset, val);
1157}
1158
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001159
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001160int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001161 InstanceType type = map()->instance_type();
1162 // Check for the most common kind of JavaScript object before
1163 // falling into the generic switch. This speeds up the internal
1164 // field operations considerably on average.
1165 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1166 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001167 case JS_GLOBAL_PROXY_TYPE:
1168 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001169 case JS_GLOBAL_OBJECT_TYPE:
1170 return JSGlobalObject::kSize;
1171 case JS_BUILTINS_OBJECT_TYPE:
1172 return JSBuiltinsObject::kSize;
1173 case JS_FUNCTION_TYPE:
1174 return JSFunction::kSize;
1175 case JS_VALUE_TYPE:
1176 return JSValue::kSize;
1177 case JS_ARRAY_TYPE:
1178 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001179 case JS_REGEXP_TYPE:
1180 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001181 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001182 return JSObject::kHeaderSize;
1183 default:
1184 UNREACHABLE();
1185 return 0;
1186 }
1187}
1188
1189
1190int JSObject::GetInternalFieldCount() {
1191 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001192 // Make sure to adjust for the number of in-object properties. These
1193 // properties do contribute to the size, but are not internal fields.
1194 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1195 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001196}
1197
1198
1199Object* JSObject::GetInternalField(int index) {
1200 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001201 // Internal objects do follow immediately after the header, whereas in-object
1202 // properties are at the end of the object. Therefore there is no need
1203 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001204 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1205}
1206
1207
1208void JSObject::SetInternalField(int index, Object* value) {
1209 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001210 // Internal objects do follow immediately after the header, whereas in-object
1211 // properties are at the end of the object. Therefore there is no need
1212 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001213 int offset = GetHeaderSize() + (kPointerSize * index);
1214 WRITE_FIELD(this, offset, value);
1215 WRITE_BARRIER(this, offset);
1216}
1217
1218
ager@chromium.org7c537e22008-10-16 08:43:32 +00001219// Access fast-case object properties at index. The use of these routines
1220// is needed to correctly distinguish between properties stored in-object and
1221// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001222Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001223 // Adjust for the number of properties stored in the object.
1224 index -= map()->inobject_properties();
1225 if (index < 0) {
1226 int offset = map()->instance_size() + (index * kPointerSize);
1227 return READ_FIELD(this, offset);
1228 } else {
1229 ASSERT(index < properties()->length());
1230 return properties()->get(index);
1231 }
1232}
1233
1234
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001235Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001236 // Adjust for the number of properties stored in the object.
1237 index -= map()->inobject_properties();
1238 if (index < 0) {
1239 int offset = map()->instance_size() + (index * kPointerSize);
1240 WRITE_FIELD(this, offset, value);
1241 WRITE_BARRIER(this, offset);
1242 } else {
1243 ASSERT(index < properties()->length());
1244 properties()->set(index, value);
1245 }
1246 return value;
1247}
1248
1249
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001250Object* JSObject::InObjectPropertyAt(int index) {
1251 // Adjust for the number of properties stored in the object.
1252 index -= map()->inobject_properties();
1253 ASSERT(index < 0);
1254 int offset = map()->instance_size() + (index * kPointerSize);
1255 return READ_FIELD(this, offset);
1256}
1257
1258
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001259Object* JSObject::InObjectPropertyAtPut(int index,
1260 Object* value,
1261 WriteBarrierMode mode) {
1262 // Adjust for the number of properties stored in the object.
1263 index -= map()->inobject_properties();
1264 ASSERT(index < 0);
1265 int offset = map()->instance_size() + (index * kPointerSize);
1266 WRITE_FIELD(this, offset, value);
1267 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1268 return value;
1269}
1270
1271
1272
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001274 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001275 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001276 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277 }
1278}
1279
1280
1281void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001282 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001283 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001284 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001285 }
1286}
1287
1288
1289bool JSObject::HasFastProperties() {
1290 return !properties()->IsDictionary();
1291}
1292
1293
1294bool Array::IndexFromObject(Object* object, uint32_t* index) {
1295 if (object->IsSmi()) {
1296 int value = Smi::cast(object)->value();
1297 if (value < 0) return false;
1298 *index = value;
1299 return true;
1300 }
1301 if (object->IsHeapNumber()) {
1302 double value = HeapNumber::cast(object)->value();
1303 uint32_t uint_value = static_cast<uint32_t>(value);
1304 if (value == static_cast<double>(uint_value)) {
1305 *index = uint_value;
1306 return true;
1307 }
1308 }
1309 return false;
1310}
1311
1312
1313bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1314 if (!this->IsJSValue()) return false;
1315
1316 JSValue* js_value = JSValue::cast(this);
1317 if (!js_value->value()->IsString()) return false;
1318
1319 String* str = String::cast(js_value->value());
1320 if (index >= (uint32_t)str->length()) return false;
1321
1322 return true;
1323}
1324
1325
1326Object* FixedArray::get(int index) {
1327 ASSERT(index >= 0 && index < this->length());
1328 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1329}
1330
1331
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001332void FixedArray::set(int index, Smi* value) {
1333 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1334 int offset = kHeaderSize + index * kPointerSize;
1335 WRITE_FIELD(this, offset, value);
1336}
1337
1338
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001339void FixedArray::set(int index, Object* value) {
1340 ASSERT(index >= 0 && index < this->length());
1341 int offset = kHeaderSize + index * kPointerSize;
1342 WRITE_FIELD(this, offset, value);
1343 WRITE_BARRIER(this, offset);
1344}
1345
1346
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001347WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001348 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1349 return UPDATE_WRITE_BARRIER;
1350}
1351
1352
1353void FixedArray::set(int index,
1354 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001355 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356 ASSERT(index >= 0 && index < this->length());
1357 int offset = kHeaderSize + index * kPointerSize;
1358 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001359 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001360}
1361
1362
1363void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1364 ASSERT(index >= 0 && index < array->length());
1365 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1366}
1367
1368
1369void FixedArray::set_undefined(int index) {
1370 ASSERT(index >= 0 && index < this->length());
1371 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1372 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1373 Heap::undefined_value());
1374}
1375
1376
ager@chromium.org236ad962008-09-25 09:45:57 +00001377void FixedArray::set_null(int index) {
1378 ASSERT(index >= 0 && index < this->length());
1379 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1380 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1381}
1382
1383
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001384void FixedArray::set_the_hole(int index) {
1385 ASSERT(index >= 0 && index < this->length());
1386 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1387 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1388}
1389
1390
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001391bool DescriptorArray::IsEmpty() {
1392 ASSERT(this == Heap::empty_descriptor_array() ||
1393 this->length() > 2);
1394 return this == Heap::empty_descriptor_array();
1395}
1396
1397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001398void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1399 Object* tmp = array->get(first);
1400 fast_set(array, first, array->get(second));
1401 fast_set(array, second, tmp);
1402}
1403
1404
1405int DescriptorArray::Search(String* name) {
1406 SLOW_ASSERT(IsSortedNoDuplicates());
1407
1408 // Check for empty descriptor array.
1409 int nof = number_of_descriptors();
1410 if (nof == 0) return kNotFound;
1411
1412 // Fast case: do linear search for small arrays.
1413 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001414 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001415 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001416 }
1417
1418 // Slow case: perform binary search.
1419 return BinarySearch(name, 0, nof - 1);
1420}
1421
1422
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423String* DescriptorArray::GetKey(int descriptor_number) {
1424 ASSERT(descriptor_number < number_of_descriptors());
1425 return String::cast(get(ToKeyIndex(descriptor_number)));
1426}
1427
1428
1429Object* DescriptorArray::GetValue(int descriptor_number) {
1430 ASSERT(descriptor_number < number_of_descriptors());
1431 return GetContentArray()->get(ToValueIndex(descriptor_number));
1432}
1433
1434
1435Smi* DescriptorArray::GetDetails(int descriptor_number) {
1436 ASSERT(descriptor_number < number_of_descriptors());
1437 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1438}
1439
1440
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001441PropertyType DescriptorArray::GetType(int descriptor_number) {
1442 ASSERT(descriptor_number < number_of_descriptors());
1443 return PropertyDetails(GetDetails(descriptor_number)).type();
1444}
1445
1446
1447int DescriptorArray::GetFieldIndex(int descriptor_number) {
1448 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1449}
1450
1451
1452JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1453 return JSFunction::cast(GetValue(descriptor_number));
1454}
1455
1456
1457Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1458 ASSERT(GetType(descriptor_number) == CALLBACKS);
1459 return GetValue(descriptor_number);
1460}
1461
1462
1463AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1464 ASSERT(GetType(descriptor_number) == CALLBACKS);
1465 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1466 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1467}
1468
1469
1470bool DescriptorArray::IsProperty(int descriptor_number) {
1471 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1472}
1473
1474
1475bool DescriptorArray::IsTransition(int descriptor_number) {
1476 PropertyType t = GetType(descriptor_number);
1477 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1478}
1479
1480
1481bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1482 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1483}
1484
1485
1486bool DescriptorArray::IsDontEnum(int descriptor_number) {
1487 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1488}
1489
1490
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001491void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1492 desc->Init(GetKey(descriptor_number),
1493 GetValue(descriptor_number),
1494 GetDetails(descriptor_number));
1495}
1496
1497
1498void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1499 // Range check.
1500 ASSERT(descriptor_number < number_of_descriptors());
1501
1502 // Make sure non of the elements in desc are in new space.
1503 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1504 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1505
1506 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1507 FixedArray* content_array = GetContentArray();
1508 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1509 fast_set(content_array, ToDetailsIndex(descriptor_number),
1510 desc->GetDetails().AsSmi());
1511}
1512
1513
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001514void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1515 Descriptor desc;
1516 src->Get(src_index, &desc);
1517 Set(index, &desc);
1518}
1519
1520
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001521void DescriptorArray::Swap(int first, int second) {
1522 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1523 FixedArray* content_array = GetContentArray();
1524 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1525 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1526}
1527
1528
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001529bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001530 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001531 if (!max_index_object->IsSmi()) return false;
1532 return 0 !=
1533 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1534}
1535
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001536uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001538 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001539 if (!max_index_object->IsSmi()) return 0;
1540 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1541 return value >> kRequiresSlowElementsTagSize;
1542}
1543
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001544void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001545 set(kMaxNumberKeyIndex,
1546 Smi::FromInt(kRequiresSlowElementsMask),
1547 SKIP_WRITE_BARRIER);
1548}
1549
1550
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551// ------------------------------------
1552// Cast operations
1553
1554
1555CAST_ACCESSOR(FixedArray)
1556CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001558CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001559CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001560CAST_ACCESSOR(String)
1561CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001562CAST_ACCESSOR(SeqAsciiString)
1563CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001564CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001565CAST_ACCESSOR(ExternalString)
1566CAST_ACCESSOR(ExternalAsciiString)
1567CAST_ACCESSOR(ExternalTwoByteString)
1568CAST_ACCESSOR(JSObject)
1569CAST_ACCESSOR(Smi)
1570CAST_ACCESSOR(Failure)
1571CAST_ACCESSOR(HeapObject)
1572CAST_ACCESSOR(HeapNumber)
1573CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001574CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001575CAST_ACCESSOR(SharedFunctionInfo)
1576CAST_ACCESSOR(Map)
1577CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001578CAST_ACCESSOR(GlobalObject)
1579CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580CAST_ACCESSOR(JSGlobalObject)
1581CAST_ACCESSOR(JSBuiltinsObject)
1582CAST_ACCESSOR(Code)
1583CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001584CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585CAST_ACCESSOR(Proxy)
1586CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001587CAST_ACCESSOR(PixelArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00001588CAST_ACCESSOR(ExternalArray)
1589CAST_ACCESSOR(ExternalByteArray)
1590CAST_ACCESSOR(ExternalUnsignedByteArray)
1591CAST_ACCESSOR(ExternalShortArray)
1592CAST_ACCESSOR(ExternalUnsignedShortArray)
1593CAST_ACCESSOR(ExternalIntArray)
1594CAST_ACCESSOR(ExternalUnsignedIntArray)
1595CAST_ACCESSOR(ExternalFloatArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001596CAST_ACCESSOR(Struct)
1597
1598
1599#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1600 STRUCT_LIST(MAKE_STRUCT_CAST)
1601#undef MAKE_STRUCT_CAST
1602
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001603
1604template <typename Shape, typename Key>
1605HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001606 ASSERT(obj->IsHashTable());
1607 return reinterpret_cast<HashTable*>(obj);
1608}
1609
1610
1611INT_ACCESSORS(Array, length, kLengthOffset)
1612
1613
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001614INT_ACCESSORS(String, length, kLengthOffset)
1615
1616
1617uint32_t String::hash_field() {
1618 return READ_UINT32_FIELD(this, kHashFieldOffset);
1619}
1620
1621
1622void String::set_hash_field(uint32_t value) {
1623 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1624}
1625
1626
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627bool String::Equals(String* other) {
1628 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001629 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1630 return false;
1631 }
1632 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633}
1634
1635
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001636Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001637 // We don't need to flatten strings that are already flat. Since this code
1638 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001639 if (!IsFlat()) {
1640 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001641 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001642 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643}
1644
1645
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001646uint16_t String::Get(int index) {
1647 ASSERT(index >= 0 && index < length());
1648 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001649 case kSeqStringTag | kAsciiStringTag:
1650 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1651 case kSeqStringTag | kTwoByteStringTag:
1652 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1653 case kConsStringTag | kAsciiStringTag:
1654 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001655 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001656 case kExternalStringTag | kAsciiStringTag:
1657 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1658 case kExternalStringTag | kTwoByteStringTag:
1659 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001660 default:
1661 break;
1662 }
1663
1664 UNREACHABLE();
1665 return 0;
1666}
1667
1668
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001669void String::Set(int index, uint16_t value) {
1670 ASSERT(index >= 0 && index < length());
1671 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001672
ager@chromium.org5ec48922009-05-05 07:25:34 +00001673 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001674 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1675 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676}
1677
1678
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001679bool String::IsFlat() {
1680 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001681 case kConsStringTag: {
1682 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001683 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001684 return second->length() == 0;
1685 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001686 default:
1687 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001688 }
1689}
1690
1691
ager@chromium.org7c537e22008-10-16 08:43:32 +00001692uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001693 ASSERT(index >= 0 && index < length());
1694 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1695}
1696
1697
ager@chromium.org7c537e22008-10-16 08:43:32 +00001698void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001699 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1700 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1701 static_cast<byte>(value));
1702}
1703
1704
ager@chromium.org7c537e22008-10-16 08:43:32 +00001705Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001706 return FIELD_ADDR(this, kHeaderSize);
1707}
1708
1709
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001710char* SeqAsciiString::GetChars() {
1711 return reinterpret_cast<char*>(GetCharsAddress());
1712}
1713
1714
ager@chromium.org7c537e22008-10-16 08:43:32 +00001715Address SeqTwoByteString::GetCharsAddress() {
1716 return FIELD_ADDR(this, kHeaderSize);
1717}
1718
1719
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001720uc16* SeqTwoByteString::GetChars() {
1721 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1722}
1723
1724
ager@chromium.org7c537e22008-10-16 08:43:32 +00001725uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001726 ASSERT(index >= 0 && index < length());
1727 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1728}
1729
1730
ager@chromium.org7c537e22008-10-16 08:43:32 +00001731void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001732 ASSERT(index >= 0 && index < length());
1733 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1734}
1735
1736
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001737int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001738 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739 return SizeFor(length);
1740}
1741
1742
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001743int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745 return SizeFor(length);
1746}
1747
1748
ager@chromium.org870a0b62008-11-04 11:43:05 +00001749String* ConsString::first() {
1750 return String::cast(READ_FIELD(this, kFirstOffset));
1751}
1752
1753
1754Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001755 return READ_FIELD(this, kFirstOffset);
1756}
1757
1758
ager@chromium.org870a0b62008-11-04 11:43:05 +00001759void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001760 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001761 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001762}
1763
1764
ager@chromium.org870a0b62008-11-04 11:43:05 +00001765String* ConsString::second() {
1766 return String::cast(READ_FIELD(this, kSecondOffset));
1767}
1768
1769
1770Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001771 return READ_FIELD(this, kSecondOffset);
1772}
1773
1774
ager@chromium.org870a0b62008-11-04 11:43:05 +00001775void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001776 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001777 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001778}
1779
1780
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001781ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1782 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1783}
1784
1785
1786void ExternalAsciiString::set_resource(
1787 ExternalAsciiString::Resource* resource) {
1788 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1789}
1790
1791
1792ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1793 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1794}
1795
1796
1797void ExternalTwoByteString::set_resource(
1798 ExternalTwoByteString::Resource* resource) {
1799 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1800}
1801
1802
1803byte ByteArray::get(int index) {
1804 ASSERT(index >= 0 && index < this->length());
1805 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1806}
1807
1808
1809void ByteArray::set(int index, byte value) {
1810 ASSERT(index >= 0 && index < this->length());
1811 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1812}
1813
1814
1815int ByteArray::get_int(int index) {
1816 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1817 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1818}
1819
1820
1821ByteArray* ByteArray::FromDataStartAddress(Address address) {
1822 ASSERT_TAG_ALIGNED(address);
1823 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1824}
1825
1826
1827Address ByteArray::GetDataStartAddress() {
1828 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1829}
1830
1831
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001832uint8_t* PixelArray::external_pointer() {
1833 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1834 return reinterpret_cast<uint8_t*>(ptr);
1835}
1836
1837
1838void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1839 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1840 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1841}
1842
1843
1844uint8_t PixelArray::get(int index) {
1845 ASSERT((index >= 0) && (index < this->length()));
1846 uint8_t* ptr = external_pointer();
1847 return ptr[index];
1848}
1849
1850
1851void PixelArray::set(int index, uint8_t value) {
1852 ASSERT((index >= 0) && (index < this->length()));
1853 uint8_t* ptr = external_pointer();
1854 ptr[index] = value;
1855}
1856
1857
ager@chromium.org3811b432009-10-28 14:53:37 +00001858void* ExternalArray::external_pointer() {
1859 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1860 return reinterpret_cast<void*>(ptr);
1861}
1862
1863
1864void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1865 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1866 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1867}
1868
1869
1870int8_t ExternalByteArray::get(int index) {
1871 ASSERT((index >= 0) && (index < this->length()));
1872 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1873 return ptr[index];
1874}
1875
1876
1877void ExternalByteArray::set(int index, int8_t value) {
1878 ASSERT((index >= 0) && (index < this->length()));
1879 int8_t* ptr = static_cast<int8_t*>(external_pointer());
1880 ptr[index] = value;
1881}
1882
1883
1884uint8_t ExternalUnsignedByteArray::get(int index) {
1885 ASSERT((index >= 0) && (index < this->length()));
1886 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1887 return ptr[index];
1888}
1889
1890
1891void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1892 ASSERT((index >= 0) && (index < this->length()));
1893 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1894 ptr[index] = value;
1895}
1896
1897
1898int16_t ExternalShortArray::get(int index) {
1899 ASSERT((index >= 0) && (index < this->length()));
1900 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1901 return ptr[index];
1902}
1903
1904
1905void ExternalShortArray::set(int index, int16_t value) {
1906 ASSERT((index >= 0) && (index < this->length()));
1907 int16_t* ptr = static_cast<int16_t*>(external_pointer());
1908 ptr[index] = value;
1909}
1910
1911
1912uint16_t ExternalUnsignedShortArray::get(int index) {
1913 ASSERT((index >= 0) && (index < this->length()));
1914 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1915 return ptr[index];
1916}
1917
1918
1919void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1920 ASSERT((index >= 0) && (index < this->length()));
1921 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1922 ptr[index] = value;
1923}
1924
1925
1926int32_t ExternalIntArray::get(int index) {
1927 ASSERT((index >= 0) && (index < this->length()));
1928 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1929 return ptr[index];
1930}
1931
1932
1933void ExternalIntArray::set(int index, int32_t value) {
1934 ASSERT((index >= 0) && (index < this->length()));
1935 int32_t* ptr = static_cast<int32_t*>(external_pointer());
1936 ptr[index] = value;
1937}
1938
1939
1940uint32_t ExternalUnsignedIntArray::get(int index) {
1941 ASSERT((index >= 0) && (index < this->length()));
1942 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1943 return ptr[index];
1944}
1945
1946
1947void ExternalUnsignedIntArray::set(int index, uint32_t value) {
1948 ASSERT((index >= 0) && (index < this->length()));
1949 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1950 ptr[index] = value;
1951}
1952
1953
1954float ExternalFloatArray::get(int index) {
1955 ASSERT((index >= 0) && (index < this->length()));
1956 float* ptr = static_cast<float*>(external_pointer());
1957 return ptr[index];
1958}
1959
1960
1961void ExternalFloatArray::set(int index, float value) {
1962 ASSERT((index >= 0) && (index < this->length()));
1963 float* ptr = static_cast<float*>(external_pointer());
1964 ptr[index] = value;
1965}
1966
1967
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001968int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001969 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1970}
1971
1972
1973int Map::inobject_properties() {
1974 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001975}
1976
1977
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001978int Map::pre_allocated_property_fields() {
1979 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1980}
1981
1982
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001983int HeapObject::SizeFromMap(Map* map) {
1984 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001985 // Only inline the most frequent cases.
1986 if (instance_type == JS_OBJECT_TYPE ||
1987 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1988 (kStringTag | kConsStringTag) ||
1989 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001990 if (instance_type == FIXED_ARRAY_TYPE) {
1991 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1992 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001993 if (instance_type == BYTE_ARRAY_TYPE) {
1994 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1995 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001996 // Otherwise do the general size computation.
1997 return SlowSizeFromMap(map);
1998}
1999
2000
2001void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002002 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002003 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002004 ASSERT(0 <= value && value < 256);
2005 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2006}
2007
2008
ager@chromium.org7c537e22008-10-16 08:43:32 +00002009void Map::set_inobject_properties(int value) {
2010 ASSERT(0 <= value && value < 256);
2011 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2012}
2013
2014
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002015void Map::set_pre_allocated_property_fields(int value) {
2016 ASSERT(0 <= value && value < 256);
2017 WRITE_BYTE_FIELD(this,
2018 kPreAllocatedPropertyFieldsOffset,
2019 static_cast<byte>(value));
2020}
2021
2022
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002023InstanceType Map::instance_type() {
2024 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2025}
2026
2027
2028void Map::set_instance_type(InstanceType value) {
2029 ASSERT(0 <= value && value < 256);
2030 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2031}
2032
2033
2034int Map::unused_property_fields() {
2035 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2036}
2037
2038
2039void Map::set_unused_property_fields(int value) {
2040 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2041}
2042
2043
2044byte Map::bit_field() {
2045 return READ_BYTE_FIELD(this, kBitFieldOffset);
2046}
2047
2048
2049void Map::set_bit_field(byte value) {
2050 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2051}
2052
2053
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002054byte Map::bit_field2() {
2055 return READ_BYTE_FIELD(this, kBitField2Offset);
2056}
2057
2058
2059void Map::set_bit_field2(byte value) {
2060 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2061}
2062
2063
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002064void Map::set_non_instance_prototype(bool value) {
2065 if (value) {
2066 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2067 } else {
2068 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2069 }
2070}
2071
2072
2073bool Map::has_non_instance_prototype() {
2074 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2075}
2076
2077
ager@chromium.org870a0b62008-11-04 11:43:05 +00002078void Map::set_is_access_check_needed(bool access_check_needed) {
2079 if (access_check_needed) {
2080 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2081 } else {
2082 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2083 }
2084}
2085
2086
2087bool Map::is_access_check_needed() {
2088 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2089}
2090
2091
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002092Code::Flags Code::flags() {
2093 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2094}
2095
2096
2097void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002098 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002099 // Make sure that all call stubs have an arguments count.
2100 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2101 ExtractArgumentsCountFromFlags(flags) >= 0);
2102 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2103}
2104
2105
2106Code::Kind Code::kind() {
2107 return ExtractKindFromFlags(flags());
2108}
2109
2110
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002111InLoopFlag Code::ic_in_loop() {
2112 return ExtractICInLoopFromFlags(flags());
2113}
2114
2115
kasper.lund7276f142008-07-30 08:49:36 +00002116InlineCacheState Code::ic_state() {
2117 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002118 // Only allow uninitialized or debugger states for non-IC code
2119 // objects. This is used in the debugger to determine whether or not
2120 // a call to code object has been replaced with a debug break call.
2121 ASSERT(is_inline_cache_stub() ||
2122 result == UNINITIALIZED ||
2123 result == DEBUG_BREAK ||
2124 result == DEBUG_PREPARE_STEP_IN);
2125 return result;
2126}
2127
2128
2129PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002130 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002131 return ExtractTypeFromFlags(flags());
2132}
2133
2134
2135int Code::arguments_count() {
2136 ASSERT(is_call_stub() || kind() == STUB);
2137 return ExtractArgumentsCountFromFlags(flags());
2138}
2139
2140
2141CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002142 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002143 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2144 kStubMajorKeyOffset));
2145}
2146
2147
2148void Code::set_major_key(CodeStub::Major major) {
2149 ASSERT(kind() == STUB);
2150 ASSERT(0 <= major && major < 256);
2151 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002152}
2153
2154
2155bool Code::is_inline_cache_stub() {
2156 Kind kind = this->kind();
2157 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2158}
2159
2160
2161Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002162 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002163 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002164 PropertyType type,
2165 int argc) {
2166 // Compute the bit mask.
2167 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002168 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002169 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002170 bits |= type << kFlagsTypeShift;
2171 bits |= argc << kFlagsArgumentsCountShift;
2172 // Cast to flags and validate result before returning it.
2173 Flags result = static_cast<Flags>(bits);
2174 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002175 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002176 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002177 ASSERT(ExtractTypeFromFlags(result) == type);
2178 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2179 return result;
2180}
2181
2182
2183Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2184 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002185 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002186 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002187 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002188}
2189
2190
2191Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2192 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2193 return static_cast<Kind>(bits);
2194}
2195
2196
kasper.lund7276f142008-07-30 08:49:36 +00002197InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2198 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002199 return static_cast<InlineCacheState>(bits);
2200}
2201
2202
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002203InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2204 int bits = (flags & kFlagsICInLoopMask);
2205 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2206}
2207
2208
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002209PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2210 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2211 return static_cast<PropertyType>(bits);
2212}
2213
2214
2215int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2216 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2217}
2218
2219
2220Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2221 int bits = flags & ~kFlagsTypeMask;
2222 return static_cast<Flags>(bits);
2223}
2224
2225
ager@chromium.org8bb60582008-12-11 12:02:20 +00002226Code* Code::GetCodeFromTargetAddress(Address address) {
2227 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2228 // GetCodeFromTargetAddress might be called when marking objects during mark
2229 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2230 // Code::cast. Code::cast does not work when the object's map is
2231 // marked.
2232 Code* result = reinterpret_cast<Code*>(code);
2233 return result;
2234}
2235
2236
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002237Object* Map::prototype() {
2238 return READ_FIELD(this, kPrototypeOffset);
2239}
2240
2241
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002242void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002243 ASSERT(value->IsNull() || value->IsJSObject());
2244 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002245 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002246}
2247
2248
2249ACCESSORS(Map, instance_descriptors, DescriptorArray,
2250 kInstanceDescriptorsOffset)
2251ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2252ACCESSORS(Map, constructor, Object, kConstructorOffset)
2253
2254ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2255ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2256
2257ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2258ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002259ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002260
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002261ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002262
2263ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2264ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2265ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2266ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2267ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002268ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002269
2270ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2271ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2272ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2273
2274ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2275ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2276ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2277ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2278ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2279ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2280
2281ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2282ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2283
2284ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2285ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2286
2287ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2288ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002289ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2290 kPropertyAccessorsOffset)
2291ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2292 kPrototypeTemplateOffset)
2293ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2294ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2295 kNamedPropertyHandlerOffset)
2296ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2297 kIndexedPropertyHandlerOffset)
2298ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2299 kInstanceTemplateOffset)
2300ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2301ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002302ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2303 kInstanceCallHandlerOffset)
2304ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2305 kAccessCheckInfoOffset)
2306ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2307
2308ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002309ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2310 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311
2312ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2313ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2314
2315ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2316
2317ACCESSORS(Script, source, Object, kSourceOffset)
2318ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002319ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002320ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2321ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002322ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002323ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002324ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2325ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002326ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00002327ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002328ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002329ACCESSORS(Script, eval_from_instructions_offset, Smi,
2330 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002331
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002332#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002333ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2334ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2335ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2336ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2337
2338ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2339ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2340ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2341ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002342#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002343
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002344ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002345ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2346ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2347 kInstanceClassNameOffset)
2348ACCESSORS(SharedFunctionInfo, function_data, Object,
2349 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002350ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2351ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002352ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002353ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2354 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002355
2356BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2357 kHiddenPrototypeBit)
2358BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2359BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2360 kNeedsAccessCheckBit)
2361BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2362 kIsExpressionBit)
2363BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2364 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002365BOOL_GETTER(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002366 has_only_simple_this_property_assignments,
2367 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002368BOOL_ACCESSORS(SharedFunctionInfo,
2369 compiler_hints,
2370 try_fast_codegen,
2371 kTryFastCodegen)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002372
2373INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2374INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2375 kFormalParameterCountOffset)
2376INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2377 kExpectedNofPropertiesOffset)
2378INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2379 kStartPositionAndTypeOffset)
2380INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2381INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2382 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002383INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2384 kCompilerHintsOffset)
2385INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2386 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002387
2388
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002389bool Script::HasValidSource() {
2390 Object* src = this->source();
2391 if (!src->IsString()) return true;
2392 String* src_str = String::cast(src);
2393 if (!StringShape(src_str).IsExternal()) return true;
2394 if (src_str->IsAsciiRepresentation()) {
2395 return ExternalAsciiString::cast(src)->resource() != NULL;
2396 } else if (src_str->IsTwoByteRepresentation()) {
2397 return ExternalTwoByteString::cast(src)->resource() != NULL;
2398 }
2399 return true;
2400}
2401
2402
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002403void SharedFunctionInfo::DontAdaptArguments() {
2404 ASSERT(code()->kind() == Code::BUILTIN);
2405 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2406}
2407
2408
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002409int SharedFunctionInfo::start_position() {
2410 return start_position_and_type() >> kStartPositionShift;
2411}
2412
2413
2414void SharedFunctionInfo::set_start_position(int start_position) {
2415 set_start_position_and_type((start_position << kStartPositionShift)
2416 | (start_position_and_type() & ~kStartPositionMask));
2417}
2418
2419
2420Code* SharedFunctionInfo::code() {
2421 return Code::cast(READ_FIELD(this, kCodeOffset));
2422}
2423
2424
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002425void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002426 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002427 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002428}
2429
2430
2431bool SharedFunctionInfo::is_compiled() {
2432 // TODO(1242782): Create a code kind for uncompiled code.
2433 return code()->kind() != Code::STUB;
2434}
2435
2436
2437bool JSFunction::IsBoilerplate() {
2438 return map() == Heap::boilerplate_function_map();
2439}
2440
2441
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002442bool JSFunction::IsBuiltin() {
2443 return context()->global()->IsJSBuiltinsObject();
2444}
2445
2446
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002447bool JSObject::IsLoaded() {
2448 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002449}
2450
2451
2452Code* JSFunction::code() {
2453 return shared()->code();
2454}
2455
2456
2457void JSFunction::set_code(Code* value) {
2458 shared()->set_code(value);
2459}
2460
2461
2462Context* JSFunction::context() {
2463 return Context::cast(READ_FIELD(this, kContextOffset));
2464}
2465
2466
2467Object* JSFunction::unchecked_context() {
2468 return READ_FIELD(this, kContextOffset);
2469}
2470
2471
2472void JSFunction::set_context(Object* value) {
2473 ASSERT(value == Heap::undefined_value() || value->IsContext());
2474 WRITE_FIELD(this, kContextOffset, value);
2475 WRITE_BARRIER(this, kContextOffset);
2476}
2477
2478ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2479 kPrototypeOrInitialMapOffset)
2480
2481
2482Map* JSFunction::initial_map() {
2483 return Map::cast(prototype_or_initial_map());
2484}
2485
2486
2487void JSFunction::set_initial_map(Map* value) {
2488 set_prototype_or_initial_map(value);
2489}
2490
2491
2492bool JSFunction::has_initial_map() {
2493 return prototype_or_initial_map()->IsMap();
2494}
2495
2496
2497bool JSFunction::has_instance_prototype() {
2498 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2499}
2500
2501
2502bool JSFunction::has_prototype() {
2503 return map()->has_non_instance_prototype() || has_instance_prototype();
2504}
2505
2506
2507Object* JSFunction::instance_prototype() {
2508 ASSERT(has_instance_prototype());
2509 if (has_initial_map()) return initial_map()->prototype();
2510 // When there is no initial map and the prototype is a JSObject, the
2511 // initial map field is used for the prototype field.
2512 return prototype_or_initial_map();
2513}
2514
2515
2516Object* JSFunction::prototype() {
2517 ASSERT(has_prototype());
2518 // If the function's prototype property has been set to a non-JSObject
2519 // value, that value is stored in the constructor field of the map.
2520 if (map()->has_non_instance_prototype()) return map()->constructor();
2521 return instance_prototype();
2522}
2523
2524
2525bool JSFunction::is_compiled() {
2526 return shared()->is_compiled();
2527}
2528
2529
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002530int JSFunction::NumberOfLiterals() {
2531 return literals()->length();
2532}
2533
2534
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002535Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2536 ASSERT(0 <= id && id < kJSBuiltinsCount);
2537 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2538}
2539
2540
2541void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2542 Object* value) {
2543 ASSERT(0 <= id && id < kJSBuiltinsCount);
2544 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2545 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2546}
2547
2548
2549Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002550 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002551}
2552
2553
2554void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002555 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002556}
2557
2558
2559void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2560 visitor->VisitExternalReference(
2561 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2562}
2563
2564
2565ACCESSORS(JSValue, value, Object, kValueOffset)
2566
2567
2568JSValue* JSValue::cast(Object* obj) {
2569 ASSERT(obj->IsJSValue());
2570 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2571 return reinterpret_cast<JSValue*>(obj);
2572}
2573
2574
2575INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2576INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2577INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2578
2579
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002580byte* Code::instruction_start() {
2581 return FIELD_ADDR(this, kHeaderSize);
2582}
2583
2584
2585int Code::body_size() {
2586 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2587}
2588
2589
2590byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002591 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002592}
2593
2594
2595byte* Code::entry() {
2596 return instruction_start();
2597}
2598
2599
2600bool Code::contains(byte* pc) {
2601 return (instruction_start() <= pc) &&
2602 (pc < instruction_start() + instruction_size());
2603}
2604
2605
2606byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002607 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002608}
2609
2610
2611ACCESSORS(JSArray, length, Object, kLengthOffset)
2612
2613
ager@chromium.org236ad962008-09-25 09:45:57 +00002614ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002615
2616
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002617JSRegExp::Type JSRegExp::TypeTag() {
2618 Object* data = this->data();
2619 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2620 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2621 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002622}
2623
2624
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002625int JSRegExp::CaptureCount() {
2626 switch (TypeTag()) {
2627 case ATOM:
2628 return 0;
2629 case IRREGEXP:
2630 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2631 default:
2632 UNREACHABLE();
2633 return -1;
2634 }
2635}
2636
2637
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002638JSRegExp::Flags JSRegExp::GetFlags() {
2639 ASSERT(this->data()->IsFixedArray());
2640 Object* data = this->data();
2641 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2642 return Flags(smi->value());
2643}
2644
2645
2646String* JSRegExp::Pattern() {
2647 ASSERT(this->data()->IsFixedArray());
2648 Object* data = this->data();
2649 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2650 return pattern;
2651}
2652
2653
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002654Object* JSRegExp::DataAt(int index) {
2655 ASSERT(TypeTag() != NOT_COMPILED);
2656 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002657}
2658
2659
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002660void JSRegExp::SetDataAt(int index, Object* value) {
2661 ASSERT(TypeTag() != NOT_COMPILED);
2662 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2663 FixedArray::cast(data())->set(index, value);
2664}
2665
2666
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002667JSObject::ElementsKind JSObject::GetElementsKind() {
2668 Array* array = elements();
2669 if (array->IsFixedArray()) {
2670 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2671 if (array->map() == Heap::fixed_array_map()) {
2672 return FAST_ELEMENTS;
2673 }
2674 ASSERT(array->IsDictionary());
2675 return DICTIONARY_ELEMENTS;
2676 }
ager@chromium.org3811b432009-10-28 14:53:37 +00002677 if (array->IsExternalArray()) {
2678 switch (array->map()->instance_type()) {
2679 case EXTERNAL_BYTE_ARRAY_TYPE:
2680 return EXTERNAL_BYTE_ELEMENTS;
2681 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2682 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2683 case EXTERNAL_SHORT_ARRAY_TYPE:
2684 return EXTERNAL_SHORT_ELEMENTS;
2685 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2686 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2687 case EXTERNAL_INT_ARRAY_TYPE:
2688 return EXTERNAL_INT_ELEMENTS;
2689 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2690 return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2691 default:
2692 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2693 return EXTERNAL_FLOAT_ELEMENTS;
2694 }
2695 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002696 ASSERT(array->IsPixelArray());
2697 return PIXEL_ELEMENTS;
2698}
2699
2700
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002701bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002702 return GetElementsKind() == FAST_ELEMENTS;
2703}
2704
2705
2706bool JSObject::HasDictionaryElements() {
2707 return GetElementsKind() == DICTIONARY_ELEMENTS;
2708}
2709
2710
2711bool JSObject::HasPixelElements() {
2712 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002713}
2714
2715
ager@chromium.org3811b432009-10-28 14:53:37 +00002716bool JSObject::HasExternalArrayElements() {
2717 return (HasExternalByteElements() ||
2718 HasExternalUnsignedByteElements() ||
2719 HasExternalShortElements() ||
2720 HasExternalUnsignedShortElements() ||
2721 HasExternalIntElements() ||
2722 HasExternalUnsignedIntElements() ||
2723 HasExternalFloatElements());
2724}
2725
2726
2727bool JSObject::HasExternalByteElements() {
2728 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2729}
2730
2731
2732bool JSObject::HasExternalUnsignedByteElements() {
2733 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2734}
2735
2736
2737bool JSObject::HasExternalShortElements() {
2738 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2739}
2740
2741
2742bool JSObject::HasExternalUnsignedShortElements() {
2743 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2744}
2745
2746
2747bool JSObject::HasExternalIntElements() {
2748 return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2749}
2750
2751
2752bool JSObject::HasExternalUnsignedIntElements() {
2753 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2754}
2755
2756
2757bool JSObject::HasExternalFloatElements() {
2758 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2759}
2760
2761
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002762bool JSObject::HasNamedInterceptor() {
2763 return map()->has_named_interceptor();
2764}
2765
2766
2767bool JSObject::HasIndexedInterceptor() {
2768 return map()->has_indexed_interceptor();
2769}
2770
2771
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002772StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002773 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002774 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002775}
2776
2777
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002778NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002779 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002780 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781}
2782
2783
2784bool String::HasHashCode() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002785 return (hash_field() & kHashComputedMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002786}
2787
2788
2789uint32_t String::Hash() {
2790 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002791 uint32_t field = hash_field();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002792 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002793 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002794 return ComputeAndSetHash();
2795}
2796
2797
ager@chromium.org7c537e22008-10-16 08:43:32 +00002798StringHasher::StringHasher(int length)
2799 : length_(length),
2800 raw_running_hash_(0),
2801 array_index_(0),
2802 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2803 is_first_char_(true),
2804 is_valid_(true) { }
2805
2806
2807bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002808 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00002809}
2810
2811
2812void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002813 // Use the Jenkins one-at-a-time hash function to update the hash
2814 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002815 raw_running_hash_ += c;
2816 raw_running_hash_ += (raw_running_hash_ << 10);
2817 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002818 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002819 if (is_array_index_) {
2820 if (c < '0' || c > '9') {
2821 is_array_index_ = false;
2822 } else {
2823 int d = c - '0';
2824 if (is_first_char_) {
2825 is_first_char_ = false;
2826 if (c == '0' && length_ > 1) {
2827 is_array_index_ = false;
2828 return;
2829 }
2830 }
2831 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2832 is_array_index_ = false;
2833 } else {
2834 array_index_ = array_index_ * 10 + d;
2835 }
2836 }
2837 }
2838}
2839
2840
2841void StringHasher::AddCharacterNoIndex(uc32 c) {
2842 ASSERT(!is_array_index());
2843 raw_running_hash_ += c;
2844 raw_running_hash_ += (raw_running_hash_ << 10);
2845 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2846}
2847
2848
2849uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002850 // Get the calculated raw hash value and do some more bit ops to distribute
2851 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002852 uint32_t result = raw_running_hash_;
2853 result += (result << 3);
2854 result ^= (result >> 11);
2855 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002856 if (result == 0) {
2857 result = 27;
2858 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002859 return result;
2860}
2861
2862
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002863bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002864 uint32_t field = hash_field();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002865 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002866 return SlowAsArrayIndex(index);
2867}
2868
2869
2870Object* JSObject::GetPrototype() {
2871 return JSObject::cast(this)->map()->prototype();
2872}
2873
2874
2875PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2876 return GetPropertyAttributeWithReceiver(this, key);
2877}
2878
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002879// TODO(504): this may be useful in other places too where JSGlobalProxy
2880// is used.
2881Object* JSObject::BypassGlobalProxy() {
2882 if (IsJSGlobalProxy()) {
2883 Object* proto = GetPrototype();
2884 if (proto->IsNull()) return Heap::undefined_value();
2885 ASSERT(proto->IsJSGlobalObject());
2886 return proto;
2887 }
2888 return this;
2889}
2890
2891
2892bool JSObject::HasHiddenPropertiesObject() {
2893 ASSERT(!IsJSGlobalProxy());
2894 return GetPropertyAttributePostInterceptor(this,
2895 Heap::hidden_symbol(),
2896 false) != ABSENT;
2897}
2898
2899
2900Object* JSObject::GetHiddenPropertiesObject() {
2901 ASSERT(!IsJSGlobalProxy());
2902 PropertyAttributes attributes;
2903 return GetLocalPropertyPostInterceptor(this,
2904 Heap::hidden_symbol(),
2905 &attributes);
2906}
2907
2908
2909Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
2910 ASSERT(!IsJSGlobalProxy());
2911 return SetPropertyPostInterceptor(Heap::hidden_symbol(),
2912 hidden_obj,
2913 DONT_ENUM);
2914}
2915
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002916
2917bool JSObject::HasElement(uint32_t index) {
2918 return HasElementWithReceiver(this, index);
2919}
2920
2921
2922bool AccessorInfo::all_can_read() {
2923 return BooleanBit::get(flag(), kAllCanReadBit);
2924}
2925
2926
2927void AccessorInfo::set_all_can_read(bool value) {
2928 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2929}
2930
2931
2932bool AccessorInfo::all_can_write() {
2933 return BooleanBit::get(flag(), kAllCanWriteBit);
2934}
2935
2936
2937void AccessorInfo::set_all_can_write(bool value) {
2938 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2939}
2940
2941
ager@chromium.org870a0b62008-11-04 11:43:05 +00002942bool AccessorInfo::prohibits_overwriting() {
2943 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2944}
2945
2946
2947void AccessorInfo::set_prohibits_overwriting(bool value) {
2948 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2949}
2950
2951
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002952PropertyAttributes AccessorInfo::property_attributes() {
2953 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2954}
2955
2956
2957void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2958 ASSERT(AttributesField::is_valid(attributes));
2959 int rest_value = flag()->value() & ~AttributesField::mask();
2960 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2961}
2962
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002963template<typename Shape, typename Key>
2964void Dictionary<Shape, Key>::SetEntry(int entry,
2965 Object* key,
2966 Object* value,
2967 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002968 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002969 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2970 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2971 FixedArray::set(index, key, mode);
2972 FixedArray::set(index+1, value, mode);
2973 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002974}
2975
2976
2977void Map::ClearCodeCache() {
2978 // No write barrier is needed since empty_fixed_array is not in new space.
2979 // Please note this function is used during marking:
2980 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002981 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2982 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002983}
2984
2985
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002986void JSArray::EnsureSize(int required_size) {
2987 ASSERT(HasFastElements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00002988 Array* elts = elements();
2989 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
2990 if (elts->length() < required_size) {
2991 // Doubling in size would be overkill, but leave some slack to avoid
2992 // constantly growing.
2993 Expand(required_size + (required_size >> 3));
2994 // It's a performance benefit to keep a frequently used array in new-space.
2995 } else if (!Heap::new_space()->Contains(elts) &&
2996 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
2997 // Expand will allocate a new backing store in new space even if the size
2998 // we asked for isn't larger than what we had before.
2999 Expand(required_size);
3000 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00003001}
3002
3003
ager@chromium.org7c537e22008-10-16 08:43:32 +00003004void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003005 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00003006 set_elements(storage);
3007}
3008
3009
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003010Object* FixedArray::Copy() {
3011 if (length() == 0) return this;
3012 return Heap::CopyFixedArray(this);
3013}
3014
3015
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003016#undef CAST_ACCESSOR
3017#undef INT_ACCESSORS
3018#undef SMI_ACCESSORS
3019#undef ACCESSORS
3020#undef FIELD_ADDR
3021#undef READ_FIELD
3022#undef WRITE_FIELD
3023#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003024#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003025#undef READ_MEMADDR_FIELD
3026#undef WRITE_MEMADDR_FIELD
3027#undef READ_DOUBLE_FIELD
3028#undef WRITE_DOUBLE_FIELD
3029#undef READ_INT_FIELD
3030#undef WRITE_INT_FIELD
3031#undef READ_SHORT_FIELD
3032#undef WRITE_SHORT_FIELD
3033#undef READ_BYTE_FIELD
3034#undef WRITE_BYTE_FIELD
3035
3036
3037} } // namespace v8::internal
3038
3039#endif // V8_OBJECTS_INL_H_