blob: 78211780887695d813d2923115356b7ab87a991b [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
43namespace v8 { namespace internal {
44
45PropertyDetails::PropertyDetails(Smi* smi) {
46 value_ = smi->value();
47}
48
49
50Smi* PropertyDetails::AsSmi() {
51 return Smi::FromInt(value_);
52}
53
54
55#define CAST_ACCESSOR(type) \
56 type* type::cast(Object* object) { \
57 ASSERT(object->Is##type()); \
58 return reinterpret_cast<type*>(object); \
59 }
60
61
62#define INT_ACCESSORS(holder, name, offset) \
63 int holder::name() { return READ_INT_FIELD(this, offset); } \
64 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
65
66
67#define ACCESSORS(holder, name, type, offset) \
68 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000069 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000071 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000072 }
73
74
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000075
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076#define SMI_ACCESSORS(holder, name, offset) \
77 int holder::name() { \
78 Object* value = READ_FIELD(this, offset); \
79 return Smi::cast(value)->value(); \
80 } \
81 void holder::set_##name(int value) { \
82 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
83 }
84
85
86#define BOOL_ACCESSORS(holder, field, name, offset) \
87 bool holder::name() { \
88 return BooleanBit::get(field(), offset); \
89 } \
90 void holder::set_##name(bool value) { \
91 set_##field(BooleanBit::set(field(), offset, value)); \
92 }
93
94
95bool Object::IsSmi() {
96 return HAS_SMI_TAG(this);
97}
98
99
100bool Object::IsHeapObject() {
101 return HAS_HEAP_OBJECT_TAG(this);
102}
103
104
105bool Object::IsHeapNumber() {
106 return Object::IsHeapObject()
107 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
108}
109
110
111bool Object::IsString() {
112 return Object::IsHeapObject()
113 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
114}
115
116
ager@chromium.org870a0b62008-11-04 11:43:05 +0000117bool Object::IsSymbol() {
118 if (!this->IsHeapObject()) return false;
119 uint32_t type = HeapObject::cast(this)->map()->instance_type();
120 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
121 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122}
123
124
125bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000126 if (!this->IsHeapObject()) return false;
127 uint32_t type = HeapObject::cast(this)->map()->instance_type();
128 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
129 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130}
131
132
ager@chromium.org870a0b62008-11-04 11:43:05 +0000133#ifdef DEBUG
134// These are for cast checks. If you need one of these in release
135// mode you should consider using a StringShape before moving it out
136// of the ifdef
137
138bool Object::IsSeqString() {
139 if (!IsString()) return false;
140 return StringShape(String::cast(this)).IsSequential();
141}
142
143
144bool Object::IsSeqAsciiString() {
145 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000146 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000147 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000148}
149
150
151bool Object::IsSeqTwoByteString() {
152 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000153 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000154 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155}
156
157
158bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000159 if (!IsString()) return false;
160 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161}
162
163
164bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000165 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000166 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000167 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000168}
169
170
171bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000172 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000173 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000174 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000175}
176
177
ager@chromium.org870a0b62008-11-04 11:43:05 +0000178bool Object::IsSlicedString() {
179 if (!IsString()) return false;
180 return StringShape(String::cast(this)).IsSliced();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181}
182
183
ager@chromium.org870a0b62008-11-04 11:43:05 +0000184#endif // DEBUG
185
186
187StringShape::StringShape(String* str)
188 : type_(str->map()->instance_type()) {
189 set_valid();
190 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191}
192
193
ager@chromium.org870a0b62008-11-04 11:43:05 +0000194StringShape::StringShape(Map* map)
195 : type_(map->instance_type()) {
196 set_valid();
197 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198}
199
200
ager@chromium.org870a0b62008-11-04 11:43:05 +0000201StringShape::StringShape(InstanceType t)
202 : type_(static_cast<uint32_t>(t)) {
203 set_valid();
204 ASSERT((type_ & kIsNotStringMask) == kStringTag);
205}
206
207
208bool StringShape::IsSymbol() {
209 ASSERT(valid());
210 return (type_ & kIsSymbolMask) == kSymbolTag;
211}
212
213
ager@chromium.org5ec48922009-05-05 07:25:34 +0000214bool String::IsAsciiRepresentation() {
215 uint32_t type = map()->instance_type();
216 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
217 return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
218 }
219 if ((type & kStringRepresentationMask) == kConsStringTag &&
220 ConsString::cast(this)->second()->length() == 0) {
221 return ConsString::cast(this)->first()->IsAsciiRepresentation();
222 }
223 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000224}
225
226
ager@chromium.org5ec48922009-05-05 07:25:34 +0000227bool String::IsTwoByteRepresentation() {
228 uint32_t type = map()->instance_type();
229 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
230 return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
231 } else if ((type & kStringRepresentationMask) == kConsStringTag &&
232 ConsString::cast(this)->second()->length() == 0) {
233 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
234 }
235 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000236}
237
238
239bool StringShape::IsCons() {
240 return (type_ & kStringRepresentationMask) == kConsStringTag;
241}
242
243
244bool StringShape::IsSliced() {
245 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
246}
247
248
249bool StringShape::IsExternal() {
250 return (type_ & kStringRepresentationMask) == kExternalStringTag;
251}
252
253
254bool StringShape::IsSequential() {
255 return (type_ & kStringRepresentationMask) == kSeqStringTag;
256}
257
258
259StringRepresentationTag StringShape::representation_tag() {
260 uint32_t tag = (type_ & kStringRepresentationMask);
261 return static_cast<StringRepresentationTag>(tag);
262}
263
264
265uint32_t StringShape::full_representation_tag() {
266 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
267}
268
269
270uint32_t StringShape::size_tag() {
271 return (type_ & kStringSizeMask);
272}
273
274
275bool StringShape::IsSequentialAscii() {
276 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
277}
278
279
280bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000281 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000282}
283
284
285bool StringShape::IsExternalAscii() {
286 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
287}
288
289
290bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000291 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292}
293
294
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000295uc32 FlatStringReader::Get(int index) {
296 ASSERT(0 <= index && index <= length_);
297 if (is_ascii_) {
298 return static_cast<const byte*>(start_)[index];
299 } else {
300 return static_cast<const uc16*>(start_)[index];
301 }
302}
303
304
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305bool Object::IsNumber() {
306 return IsSmi() || IsHeapNumber();
307}
308
309
310bool Object::IsByteArray() {
311 return Object::IsHeapObject()
312 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
313}
314
315
316bool Object::IsFailure() {
317 return HAS_FAILURE_TAG(this);
318}
319
320
321bool Object::IsRetryAfterGC() {
322 return HAS_FAILURE_TAG(this)
323 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
324}
325
326
ager@chromium.org7c537e22008-10-16 08:43:32 +0000327bool Object::IsOutOfMemoryFailure() {
328 return HAS_FAILURE_TAG(this)
329 && Failure::cast(this)->IsOutOfMemoryException();
330}
331
332
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000333bool Object::IsException() {
334 return this == Failure::Exception();
335}
336
337
338bool Object::IsJSObject() {
339 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000340 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000341}
342
343
ager@chromium.org32912102009-01-16 10:38:43 +0000344bool Object::IsJSContextExtensionObject() {
345 return IsHeapObject()
346 && (HeapObject::cast(this)->map()->instance_type() ==
347 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
348}
349
350
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351bool Object::IsMap() {
352 return Object::IsHeapObject()
353 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
354}
355
356
357bool Object::IsFixedArray() {
358 return Object::IsHeapObject()
359 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
360}
361
362
363bool Object::IsDescriptorArray() {
364 return IsFixedArray();
365}
366
367
368bool Object::IsContext() {
369 return Object::IsHeapObject()
370 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000371 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000372 HeapObject::cast(this)->map() == Heap::global_context_map());
373}
374
375
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000376bool Object::IsCatchContext() {
377 return Object::IsHeapObject()
378 && HeapObject::cast(this)->map() == Heap::catch_context_map();
379}
380
381
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000382bool Object::IsGlobalContext() {
383 return Object::IsHeapObject()
384 && HeapObject::cast(this)->map() == Heap::global_context_map();
385}
386
387
388bool Object::IsJSFunction() {
389 return Object::IsHeapObject()
390 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
391}
392
393
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000394template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000395 return obj->IsJSFunction();
396}
397
398
399bool Object::IsCode() {
400 return Object::IsHeapObject()
401 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
402}
403
404
405bool Object::IsOddball() {
406 return Object::IsHeapObject()
407 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
408}
409
410
411bool Object::IsSharedFunctionInfo() {
412 return Object::IsHeapObject() &&
413 (HeapObject::cast(this)->map()->instance_type() ==
414 SHARED_FUNCTION_INFO_TYPE);
415}
416
417
418bool Object::IsJSValue() {
419 return Object::IsHeapObject()
420 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
421}
422
423
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000424bool Object::IsStringWrapper() {
425 return IsJSValue() && JSValue::cast(this)->value()->IsString();
426}
427
428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429bool Object::IsProxy() {
430 return Object::IsHeapObject()
431 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
432}
433
434
435bool Object::IsBoolean() {
436 return IsTrue() || IsFalse();
437}
438
439
440bool Object::IsJSArray() {
441 return Object::IsHeapObject()
442 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
443}
444
445
ager@chromium.org236ad962008-09-25 09:45:57 +0000446bool Object::IsJSRegExp() {
447 return Object::IsHeapObject()
448 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
449}
450
451
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000452template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000453 return obj->IsJSArray();
454}
455
456
457bool Object::IsHashTable() {
458 return Object::IsHeapObject()
459 && HeapObject::cast(this)->map() == Heap::hash_table_map();
460}
461
462
463bool Object::IsDictionary() {
464 return IsHashTable() && this != Heap::symbol_table();
465}
466
467
468bool Object::IsSymbolTable() {
469 return IsHashTable() && this == Heap::symbol_table();
470}
471
472
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000473bool Object::IsCompilationCacheTable() {
474 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000475}
476
477
ager@chromium.org236ad962008-09-25 09:45:57 +0000478bool Object::IsMapCache() {
479 return IsHashTable();
480}
481
482
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000483bool Object::IsLookupCache() {
484 return IsHashTable();
485}
486
487
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488bool Object::IsPrimitive() {
489 return IsOddball() || IsNumber() || IsString();
490}
491
492
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000493bool Object::IsJSGlobalProxy() {
494 bool result = IsHeapObject() &&
495 (HeapObject::cast(this)->map()->instance_type() ==
496 JS_GLOBAL_PROXY_TYPE);
497 ASSERT(!result || IsAccessCheckNeeded());
498 return result;
499}
500
501
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000503 if (!IsHeapObject()) return false;
504
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000505 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000506 return type == JS_GLOBAL_OBJECT_TYPE ||
507 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508}
509
510
511bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000512 return IsHeapObject() &&
513 (HeapObject::cast(this)->map()->instance_type() ==
514 JS_GLOBAL_OBJECT_TYPE);
515}
516
517
518bool Object::IsJSBuiltinsObject() {
519 return IsHeapObject() &&
520 (HeapObject::cast(this)->map()->instance_type() ==
521 JS_BUILTINS_OBJECT_TYPE);
522}
523
524
525bool Object::IsUndetectableObject() {
526 return IsHeapObject()
527 && HeapObject::cast(this)->map()->is_undetectable();
528}
529
530
531bool Object::IsAccessCheckNeeded() {
532 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000533 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534}
535
536
537bool Object::IsStruct() {
538 if (!IsHeapObject()) return false;
539 switch (HeapObject::cast(this)->map()->instance_type()) {
540#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
541 STRUCT_LIST(MAKE_STRUCT_CASE)
542#undef MAKE_STRUCT_CASE
543 default: return false;
544 }
545}
546
547
548#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
549 bool Object::Is##Name() { \
550 return Object::IsHeapObject() \
551 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
552 }
553 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
554#undef MAKE_STRUCT_PREDICATE
555
556
557bool Object::IsUndefined() {
558 return this == Heap::undefined_value();
559}
560
561
562bool Object::IsTheHole() {
563 return this == Heap::the_hole_value();
564}
565
566
567bool Object::IsNull() {
568 return this == Heap::null_value();
569}
570
571
572bool Object::IsTrue() {
573 return this == Heap::true_value();
574}
575
576
577bool Object::IsFalse() {
578 return this == Heap::false_value();
579}
580
581
582double Object::Number() {
583 ASSERT(IsNumber());
584 return IsSmi()
585 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
586 : reinterpret_cast<HeapNumber*>(this)->value();
587}
588
589
590
591Object* Object::ToSmi() {
592 if (IsSmi()) return this;
593 if (IsHeapNumber()) {
594 double value = HeapNumber::cast(this)->value();
595 int int_value = FastD2I(value);
596 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
597 return Smi::FromInt(int_value);
598 }
599 }
600 return Failure::Exception();
601}
602
603
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000604bool Object::HasSpecificClassOf(String* name) {
605 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
606}
607
608
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609Object* Object::GetElement(uint32_t index) {
610 return GetElementWithReceiver(this, index);
611}
612
613
614Object* Object::GetProperty(String* key) {
615 PropertyAttributes attributes;
616 return GetPropertyWithReceiver(this, key, &attributes);
617}
618
619
620Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
621 return GetPropertyWithReceiver(this, key, attributes);
622}
623
624
625#define FIELD_ADDR(p, offset) \
626 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
627
628#define READ_FIELD(p, offset) \
629 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
630
631#define WRITE_FIELD(p, offset, value) \
632 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
633
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000634
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000635#define WRITE_BARRIER(object, offset) \
636 Heap::RecordWrite(object->address(), offset);
637
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000638// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000639// write due to the assert validating the written value.
640#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
641 if (mode == UPDATE_WRITE_BARRIER) { \
642 Heap::RecordWrite(object->address(), offset); \
643 } else { \
644 ASSERT(mode == SKIP_WRITE_BARRIER); \
645 ASSERT(Heap::InNewSpace(object) || \
646 !Heap::InNewSpace(READ_FIELD(object, offset))); \
647 }
648
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649#define READ_DOUBLE_FIELD(p, offset) \
650 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
651
652#define WRITE_DOUBLE_FIELD(p, offset, value) \
653 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
654
655#define READ_INT_FIELD(p, offset) \
656 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
657
658#define WRITE_INT_FIELD(p, offset, value) \
659 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
660
ager@chromium.org7c537e22008-10-16 08:43:32 +0000661#define READ_UINT32_FIELD(p, offset) \
662 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
663
664#define WRITE_UINT32_FIELD(p, offset, value) \
665 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
666
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667#define READ_SHORT_FIELD(p, offset) \
668 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
669
670#define WRITE_SHORT_FIELD(p, offset, value) \
671 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
672
673#define READ_BYTE_FIELD(p, offset) \
674 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
675
676#define WRITE_BYTE_FIELD(p, offset, value) \
677 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
678
679
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000680Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
681 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000682}
683
684
685int Smi::value() {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000686 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kSmiTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000687}
688
689
690Smi* Smi::FromInt(int value) {
691 ASSERT(Smi::IsValid(value));
ager@chromium.org9085a012009-05-11 19:22:57 +0000692 intptr_t tagged_value =
693 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
694 return reinterpret_cast<Smi*>(tagged_value);
695}
696
697
698Smi* Smi::FromIntptr(intptr_t value) {
699 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000700 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
701}
702
703
704Failure::Type Failure::type() const {
705 return static_cast<Type>(value() & kFailureTypeTagMask);
706}
707
708
709bool Failure::IsInternalError() const {
710 return type() == INTERNAL_ERROR;
711}
712
713
714bool Failure::IsOutOfMemoryException() const {
715 return type() == OUT_OF_MEMORY_EXCEPTION;
716}
717
718
719int Failure::requested() const {
720 const int kShiftBits =
721 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
722 STATIC_ASSERT(kShiftBits >= 0);
723 ASSERT(type() == RETRY_AFTER_GC);
724 return value() >> kShiftBits;
725}
726
727
728AllocationSpace Failure::allocation_space() const {
729 ASSERT_EQ(RETRY_AFTER_GC, type());
730 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
731 & kSpaceTagMask);
732}
733
734
735Failure* Failure::InternalError() {
736 return Construct(INTERNAL_ERROR);
737}
738
739
740Failure* Failure::Exception() {
741 return Construct(EXCEPTION);
742}
743
744Failure* Failure::OutOfMemoryException() {
745 return Construct(OUT_OF_MEMORY_EXCEPTION);
746}
747
748
749int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000750 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000751}
752
753
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000754Failure* Failure::RetryAfterGC(int requested_bytes) {
755 int requested = requested_bytes >> kObjectAlignmentBits;
756 int value = (requested << kSpaceTagSize) | NEW_SPACE;
757 ASSERT(value >> kSpaceTagSize == requested);
758 ASSERT(Smi::IsValid(value));
759 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
760 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
761 return Construct(RETRY_AFTER_GC, value);
762}
763
764
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000765Failure* Failure::Construct(Type type, int value) {
766 int info = (value << kFailureTypeTagSize) | type;
767 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000768 return reinterpret_cast<Failure*>(
769 static_cast<intptr_t>((info << kFailureTagSize) | kFailureTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000770}
771
772
773bool Smi::IsValid(int value) {
774#ifdef DEBUG
775 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
776#endif
777 // To be representable as an tagged small integer, the two
778 // most-significant bits of 'value' must be either 00 or 11 due to
779 // sign-extension. To check this we add 01 to the two
780 // most-significant bits, and check if the most-significant bit is 0
781 //
782 // CAUTION: The original code below:
783 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
784 // may lead to incorrect results according to the C language spec, and
785 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
786 // compiler may produce undefined results in case of signed integer
787 // overflow. The computation must be done w/ unsigned ints.
788 bool result =
789 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
790 ASSERT(result == in_range);
791 return result;
792}
793
794
ager@chromium.org9085a012009-05-11 19:22:57 +0000795bool Smi::IsIntptrValid(intptr_t value) {
796#ifdef DEBUG
797 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
798#endif
799 // See Smi::IsValid(int) for description.
800 bool result =
801 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
802 ASSERT(result == in_range);
803 return result;
804}
805
806
kasper.lund7276f142008-07-30 08:49:36 +0000807MapWord MapWord::FromMap(Map* map) {
808 return MapWord(reinterpret_cast<uintptr_t>(map));
809}
810
811
812Map* MapWord::ToMap() {
813 return reinterpret_cast<Map*>(value_);
814}
815
816
817bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000818 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000819}
820
821
822MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000823 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
824 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000825}
826
827
828HeapObject* MapWord::ToForwardingAddress() {
829 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000830 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000831}
832
833
834bool MapWord::IsMarked() {
835 return (value_ & kMarkingMask) == 0;
836}
837
838
839void MapWord::SetMark() {
840 value_ &= ~kMarkingMask;
841}
842
843
844void MapWord::ClearMark() {
845 value_ |= kMarkingMask;
846}
847
848
849bool MapWord::IsOverflowed() {
850 return (value_ & kOverflowMask) != 0;
851}
852
853
854void MapWord::SetOverflow() {
855 value_ |= kOverflowMask;
856}
857
858
859void MapWord::ClearOverflow() {
860 value_ &= ~kOverflowMask;
861}
862
863
864MapWord MapWord::EncodeAddress(Address map_address, int offset) {
865 // Offset is the distance in live bytes from the first live object in the
866 // same page. The offset between two objects in the same page should not
867 // exceed the object area size of a page.
868 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
869
870 int compact_offset = offset >> kObjectAlignmentBits;
871 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
872
873 Page* map_page = Page::FromAddress(map_address);
874 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
875
876 int map_page_offset =
877 map_page->Offset(map_address) >> kObjectAlignmentBits;
878
879 uintptr_t encoding =
880 (compact_offset << kForwardingOffsetShift) |
881 (map_page_offset << kMapPageOffsetShift) |
882 (map_page->mc_page_index << kMapPageIndexShift);
883 return MapWord(encoding);
884}
885
886
887Address MapWord::DecodeMapAddress(MapSpace* map_space) {
888 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
889 ASSERT_MAP_PAGE_INDEX(map_page_index);
890
891 int map_page_offset =
892 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
893 << kObjectAlignmentBits;
894
895 return (map_space->PageAddress(map_page_index) + map_page_offset);
896}
897
898
899int MapWord::DecodeOffset() {
900 // The offset field is represented in the kForwardingOffsetBits
901 // most-significant bits.
902 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
903 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
904 return offset;
905}
906
907
908MapWord MapWord::FromEncodedAddress(Address address) {
909 return MapWord(reinterpret_cast<uintptr_t>(address));
910}
911
912
913Address MapWord::ToEncodedAddress() {
914 return reinterpret_cast<Address>(value_);
915}
916
917
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918#ifdef DEBUG
919void HeapObject::VerifyObjectField(int offset) {
920 VerifyPointer(READ_FIELD(this, offset));
921}
922#endif
923
924
925Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000926 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000927}
928
929
930void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000931 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000932}
933
934
kasper.lund7276f142008-07-30 08:49:36 +0000935MapWord HeapObject::map_word() {
936 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
937}
938
939
940void HeapObject::set_map_word(MapWord map_word) {
941 // WRITE_FIELD does not update the remembered set, but there is no need
942 // here.
943 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
944}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000945
946
947HeapObject* HeapObject::FromAddress(Address address) {
948 ASSERT_TAG_ALIGNED(address);
949 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
950}
951
952
953Address HeapObject::address() {
954 return reinterpret_cast<Address>(this) - kHeapObjectTag;
955}
956
957
958int HeapObject::Size() {
959 return SizeFromMap(map());
960}
961
962
963void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
964 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
965 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
966}
967
968
969void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
970 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
971}
972
973
kasper.lund7276f142008-07-30 08:49:36 +0000974bool HeapObject::IsMarked() {
975 return map_word().IsMarked();
976}
977
978
979void HeapObject::SetMark() {
980 ASSERT(!IsMarked());
981 MapWord first_word = map_word();
982 first_word.SetMark();
983 set_map_word(first_word);
984}
985
986
987void HeapObject::ClearMark() {
988 ASSERT(IsMarked());
989 MapWord first_word = map_word();
990 first_word.ClearMark();
991 set_map_word(first_word);
992}
993
994
995bool HeapObject::IsOverflowed() {
996 return map_word().IsOverflowed();
997}
998
999
1000void HeapObject::SetOverflow() {
1001 MapWord first_word = map_word();
1002 first_word.SetOverflow();
1003 set_map_word(first_word);
1004}
1005
1006
1007void HeapObject::ClearOverflow() {
1008 ASSERT(IsOverflowed());
1009 MapWord first_word = map_word();
1010 first_word.ClearOverflow();
1011 set_map_word(first_word);
1012}
1013
1014
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001015double HeapNumber::value() {
1016 return READ_DOUBLE_FIELD(this, kValueOffset);
1017}
1018
1019
1020void HeapNumber::set_value(double value) {
1021 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1022}
1023
1024
1025ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001026ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001027
1028
1029void JSObject::initialize_properties() {
1030 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1031 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1032}
1033
1034
1035void JSObject::initialize_elements() {
1036 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1037 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1038}
1039
1040
1041ACCESSORS(Oddball, to_string, String, kToStringOffset)
1042ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1043
1044
1045int JSObject::GetHeaderSize() {
1046 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001047 case JS_GLOBAL_PROXY_TYPE:
1048 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049 case JS_GLOBAL_OBJECT_TYPE:
1050 return JSGlobalObject::kSize;
1051 case JS_BUILTINS_OBJECT_TYPE:
1052 return JSBuiltinsObject::kSize;
1053 case JS_FUNCTION_TYPE:
1054 return JSFunction::kSize;
1055 case JS_VALUE_TYPE:
1056 return JSValue::kSize;
1057 case JS_ARRAY_TYPE:
1058 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001059 case JS_REGEXP_TYPE:
1060 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001062 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001063 return JSObject::kHeaderSize;
1064 default:
1065 UNREACHABLE();
1066 return 0;
1067 }
1068}
1069
1070
1071int JSObject::GetInternalFieldCount() {
1072 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001073 // Make sure to adjust for the number of in-object properties. These
1074 // properties do contribute to the size, but are not internal fields.
1075 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1076 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001077}
1078
1079
1080Object* JSObject::GetInternalField(int index) {
1081 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001082 // Internal objects do follow immediately after the header, whereas in-object
1083 // properties are at the end of the object. Therefore there is no need
1084 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001085 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1086}
1087
1088
1089void JSObject::SetInternalField(int index, Object* value) {
1090 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001091 // Internal objects do follow immediately after the header, whereas in-object
1092 // properties are at the end of the object. Therefore there is no need
1093 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094 int offset = GetHeaderSize() + (kPointerSize * index);
1095 WRITE_FIELD(this, offset, value);
1096 WRITE_BARRIER(this, offset);
1097}
1098
1099
ager@chromium.org7c537e22008-10-16 08:43:32 +00001100// Access fast-case object properties at index. The use of these routines
1101// is needed to correctly distinguish between properties stored in-object and
1102// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001103Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001104 // Adjust for the number of properties stored in the object.
1105 index -= map()->inobject_properties();
1106 if (index < 0) {
1107 int offset = map()->instance_size() + (index * kPointerSize);
1108 return READ_FIELD(this, offset);
1109 } else {
1110 ASSERT(index < properties()->length());
1111 return properties()->get(index);
1112 }
1113}
1114
1115
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001116Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001117 // Adjust for the number of properties stored in the object.
1118 index -= map()->inobject_properties();
1119 if (index < 0) {
1120 int offset = map()->instance_size() + (index * kPointerSize);
1121 WRITE_FIELD(this, offset, value);
1122 WRITE_BARRIER(this, offset);
1123 } else {
1124 ASSERT(index < properties()->length());
1125 properties()->set(index, value);
1126 }
1127 return value;
1128}
1129
1130
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001131Object* JSObject::InObjectPropertyAt(int index) {
1132 // Adjust for the number of properties stored in the object.
1133 index -= map()->inobject_properties();
1134 ASSERT(index < 0);
1135 int offset = map()->instance_size() + (index * kPointerSize);
1136 return READ_FIELD(this, offset);
1137}
1138
1139
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001140Object* JSObject::InObjectPropertyAtPut(int index,
1141 Object* value,
1142 WriteBarrierMode mode) {
1143 // Adjust for the number of properties stored in the object.
1144 index -= map()->inobject_properties();
1145 ASSERT(index < 0);
1146 int offset = map()->instance_size() + (index * kPointerSize);
1147 WRITE_FIELD(this, offset, value);
1148 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1149 return value;
1150}
1151
1152
1153
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001154void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001155 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001156 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001157 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001158 }
1159}
1160
1161
1162void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001163 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001164 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001165 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001166 }
1167}
1168
1169
1170bool JSObject::HasFastProperties() {
1171 return !properties()->IsDictionary();
1172}
1173
1174
1175bool Array::IndexFromObject(Object* object, uint32_t* index) {
1176 if (object->IsSmi()) {
1177 int value = Smi::cast(object)->value();
1178 if (value < 0) return false;
1179 *index = value;
1180 return true;
1181 }
1182 if (object->IsHeapNumber()) {
1183 double value = HeapNumber::cast(object)->value();
1184 uint32_t uint_value = static_cast<uint32_t>(value);
1185 if (value == static_cast<double>(uint_value)) {
1186 *index = uint_value;
1187 return true;
1188 }
1189 }
1190 return false;
1191}
1192
1193
1194bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1195 if (!this->IsJSValue()) return false;
1196
1197 JSValue* js_value = JSValue::cast(this);
1198 if (!js_value->value()->IsString()) return false;
1199
1200 String* str = String::cast(js_value->value());
1201 if (index >= (uint32_t)str->length()) return false;
1202
1203 return true;
1204}
1205
1206
1207Object* FixedArray::get(int index) {
1208 ASSERT(index >= 0 && index < this->length());
1209 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1210}
1211
1212
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001213void FixedArray::set(int index, Smi* value) {
1214 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1215 int offset = kHeaderSize + index * kPointerSize;
1216 WRITE_FIELD(this, offset, value);
1217}
1218
1219
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001220void FixedArray::set(int index, Object* value) {
1221 ASSERT(index >= 0 && index < this->length());
1222 int offset = kHeaderSize + index * kPointerSize;
1223 WRITE_FIELD(this, offset, value);
1224 WRITE_BARRIER(this, offset);
1225}
1226
1227
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001228WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001229 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1230 return UPDATE_WRITE_BARRIER;
1231}
1232
1233
1234void FixedArray::set(int index,
1235 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001236 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001237 ASSERT(index >= 0 && index < this->length());
1238 int offset = kHeaderSize + index * kPointerSize;
1239 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001240 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001241}
1242
1243
1244void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1245 ASSERT(index >= 0 && index < array->length());
1246 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1247}
1248
1249
1250void FixedArray::set_undefined(int index) {
1251 ASSERT(index >= 0 && index < this->length());
1252 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1253 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1254 Heap::undefined_value());
1255}
1256
1257
ager@chromium.org236ad962008-09-25 09:45:57 +00001258void FixedArray::set_null(int index) {
1259 ASSERT(index >= 0 && index < this->length());
1260 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1261 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1262}
1263
1264
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001265void FixedArray::set_the_hole(int index) {
1266 ASSERT(index >= 0 && index < this->length());
1267 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1268 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1269}
1270
1271
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001272bool DescriptorArray::IsEmpty() {
1273 ASSERT(this == Heap::empty_descriptor_array() ||
1274 this->length() > 2);
1275 return this == Heap::empty_descriptor_array();
1276}
1277
1278
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001279void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1280 Object* tmp = array->get(first);
1281 fast_set(array, first, array->get(second));
1282 fast_set(array, second, tmp);
1283}
1284
1285
1286int DescriptorArray::Search(String* name) {
1287 SLOW_ASSERT(IsSortedNoDuplicates());
1288
1289 // Check for empty descriptor array.
1290 int nof = number_of_descriptors();
1291 if (nof == 0) return kNotFound;
1292
1293 // Fast case: do linear search for small arrays.
1294 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001295 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001296 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297 }
1298
1299 // Slow case: perform binary search.
1300 return BinarySearch(name, 0, nof - 1);
1301}
1302
1303
1304
1305String* DescriptorArray::GetKey(int descriptor_number) {
1306 ASSERT(descriptor_number < number_of_descriptors());
1307 return String::cast(get(ToKeyIndex(descriptor_number)));
1308}
1309
1310
1311Object* DescriptorArray::GetValue(int descriptor_number) {
1312 ASSERT(descriptor_number < number_of_descriptors());
1313 return GetContentArray()->get(ToValueIndex(descriptor_number));
1314}
1315
1316
1317Smi* DescriptorArray::GetDetails(int descriptor_number) {
1318 ASSERT(descriptor_number < number_of_descriptors());
1319 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1320}
1321
1322
1323void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1324 desc->Init(GetKey(descriptor_number),
1325 GetValue(descriptor_number),
1326 GetDetails(descriptor_number));
1327}
1328
1329
1330void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1331 // Range check.
1332 ASSERT(descriptor_number < number_of_descriptors());
1333
1334 // Make sure non of the elements in desc are in new space.
1335 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1336 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1337
1338 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1339 FixedArray* content_array = GetContentArray();
1340 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1341 fast_set(content_array, ToDetailsIndex(descriptor_number),
1342 desc->GetDetails().AsSmi());
1343}
1344
1345
1346void DescriptorArray::Swap(int first, int second) {
1347 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1348 FixedArray* content_array = GetContentArray();
1349 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1350 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1351}
1352
1353
1354bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001355 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356 if (!max_index_object->IsSmi()) return false;
1357 return 0 !=
1358 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1359}
1360
1361
1362uint32_t Dictionary::max_number_key() {
1363 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001364 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365 if (!max_index_object->IsSmi()) return 0;
1366 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1367 return value >> kRequiresSlowElementsTagSize;
1368}
1369
1370
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001371void Dictionary::set_requires_slow_elements() {
1372 set(kMaxNumberKeyIndex,
1373 Smi::FromInt(kRequiresSlowElementsMask),
1374 SKIP_WRITE_BARRIER);
1375}
1376
1377
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001378// ------------------------------------
1379// Cast operations
1380
1381
1382CAST_ACCESSOR(FixedArray)
1383CAST_ACCESSOR(DescriptorArray)
1384CAST_ACCESSOR(Dictionary)
1385CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001386CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001387CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001388CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389CAST_ACCESSOR(String)
1390CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001391CAST_ACCESSOR(SeqAsciiString)
1392CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001393CAST_ACCESSOR(ConsString)
1394CAST_ACCESSOR(SlicedString)
1395CAST_ACCESSOR(ExternalString)
1396CAST_ACCESSOR(ExternalAsciiString)
1397CAST_ACCESSOR(ExternalTwoByteString)
1398CAST_ACCESSOR(JSObject)
1399CAST_ACCESSOR(Smi)
1400CAST_ACCESSOR(Failure)
1401CAST_ACCESSOR(HeapObject)
1402CAST_ACCESSOR(HeapNumber)
1403CAST_ACCESSOR(Oddball)
1404CAST_ACCESSOR(SharedFunctionInfo)
1405CAST_ACCESSOR(Map)
1406CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001407CAST_ACCESSOR(GlobalObject)
1408CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001409CAST_ACCESSOR(JSGlobalObject)
1410CAST_ACCESSOR(JSBuiltinsObject)
1411CAST_ACCESSOR(Code)
1412CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001413CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001414CAST_ACCESSOR(Proxy)
1415CAST_ACCESSOR(ByteArray)
1416CAST_ACCESSOR(Struct)
1417
1418
1419#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1420 STRUCT_LIST(MAKE_STRUCT_CAST)
1421#undef MAKE_STRUCT_CAST
1422
1423template <int prefix_size, int elem_size>
1424HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1425 Object* obj) {
1426 ASSERT(obj->IsHashTable());
1427 return reinterpret_cast<HashTable*>(obj);
1428}
1429
1430
1431INT_ACCESSORS(Array, length, kLengthOffset)
1432
1433
1434bool String::Equals(String* other) {
1435 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001436 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1437 return false;
1438 }
1439 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001440}
1441
1442
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001443int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001444 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1445
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001446 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1447 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1448 ASSERT(kLongStringTag == 0);
1449
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001450 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001451}
1452
1453
1454void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001455 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1456 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1457 ASSERT(kLongStringTag == 0);
1458
1459 WRITE_INT_FIELD(this,
1460 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001461 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462}
1463
1464
ager@chromium.org7c537e22008-10-16 08:43:32 +00001465uint32_t String::length_field() {
1466 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001467}
1468
1469
ager@chromium.org7c537e22008-10-16 08:43:32 +00001470void String::set_length_field(uint32_t value) {
1471 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001472}
1473
1474
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001475Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001476 // We don't need to flatten strings that are already flat. Since this code
1477 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001478 if (!IsFlat()) {
1479 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001480 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001481 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001482}
1483
1484
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001485uint16_t String::Get(int index) {
1486 ASSERT(index >= 0 && index < length());
1487 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001488 case kSeqStringTag | kAsciiStringTag:
1489 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1490 case kSeqStringTag | kTwoByteStringTag:
1491 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1492 case kConsStringTag | kAsciiStringTag:
1493 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001495 case kSlicedStringTag | kAsciiStringTag:
1496 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001497 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001498 case kExternalStringTag | kAsciiStringTag:
1499 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1500 case kExternalStringTag | kTwoByteStringTag:
1501 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502 default:
1503 break;
1504 }
1505
1506 UNREACHABLE();
1507 return 0;
1508}
1509
1510
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001511void String::Set(int index, uint16_t value) {
1512 ASSERT(index >= 0 && index < length());
1513 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514
ager@chromium.org5ec48922009-05-05 07:25:34 +00001515 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001516 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1517 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001518}
1519
1520
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001521bool String::IsFlat() {
1522 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001523 case kConsStringTag: {
1524 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001525 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001526 return second->length() == 0;
1527 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001528 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001529 StringRepresentationTag tag =
1530 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001531 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001532 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001533 default:
1534 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001535 }
1536}
1537
1538
ager@chromium.org7c537e22008-10-16 08:43:32 +00001539uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540 ASSERT(index >= 0 && index < length());
1541 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1542}
1543
1544
ager@chromium.org7c537e22008-10-16 08:43:32 +00001545void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001546 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1547 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1548 static_cast<byte>(value));
1549}
1550
1551
ager@chromium.org7c537e22008-10-16 08:43:32 +00001552Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001553 return FIELD_ADDR(this, kHeaderSize);
1554}
1555
1556
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001557char* SeqAsciiString::GetChars() {
1558 return reinterpret_cast<char*>(GetCharsAddress());
1559}
1560
1561
ager@chromium.org7c537e22008-10-16 08:43:32 +00001562Address SeqTwoByteString::GetCharsAddress() {
1563 return FIELD_ADDR(this, kHeaderSize);
1564}
1565
1566
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001567uc16* SeqTwoByteString::GetChars() {
1568 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1569}
1570
1571
ager@chromium.org7c537e22008-10-16 08:43:32 +00001572uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001573 ASSERT(index >= 0 && index < length());
1574 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1575}
1576
1577
ager@chromium.org7c537e22008-10-16 08:43:32 +00001578void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579 ASSERT(index >= 0 && index < length());
1580 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1581}
1582
1583
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001584int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1586
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001587 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1588 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1589 ASSERT(kLongStringTag == 0);
1590
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001591 // Use the map (and not 'this') to compute the size tag, since
1592 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001593 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001594
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001595 return SizeFor(length);
1596}
1597
1598
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001599int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1601
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001602 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1603 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1604 ASSERT(kLongStringTag == 0);
1605
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001606 // Use the map (and not 'this') to compute the size tag, since
1607 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001608 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001609
1610 return SizeFor(length);
1611}
1612
1613
ager@chromium.org870a0b62008-11-04 11:43:05 +00001614String* ConsString::first() {
1615 return String::cast(READ_FIELD(this, kFirstOffset));
1616}
1617
1618
1619Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001620 return READ_FIELD(this, kFirstOffset);
1621}
1622
1623
ager@chromium.org870a0b62008-11-04 11:43:05 +00001624void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001626 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627}
1628
1629
ager@chromium.org870a0b62008-11-04 11:43:05 +00001630String* ConsString::second() {
1631 return String::cast(READ_FIELD(this, kSecondOffset));
1632}
1633
1634
1635Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001636 return READ_FIELD(this, kSecondOffset);
1637}
1638
1639
ager@chromium.org870a0b62008-11-04 11:43:05 +00001640void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001641 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001642 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643}
1644
1645
ager@chromium.org870a0b62008-11-04 11:43:05 +00001646String* SlicedString::buffer() {
1647 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648}
1649
1650
ager@chromium.org870a0b62008-11-04 11:43:05 +00001651void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001652 WRITE_FIELD(this, kBufferOffset, buffer);
1653 WRITE_BARRIER(this, kBufferOffset);
1654}
1655
1656
1657int SlicedString::start() {
1658 return READ_INT_FIELD(this, kStartOffset);
1659}
1660
1661
1662void SlicedString::set_start(int start) {
1663 WRITE_INT_FIELD(this, kStartOffset, start);
1664}
1665
1666
1667ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1668 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1669}
1670
1671
1672void ExternalAsciiString::set_resource(
1673 ExternalAsciiString::Resource* resource) {
1674 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1675}
1676
1677
ager@chromium.org6f10e412009-02-13 10:11:16 +00001678Map* ExternalAsciiString::StringMap(int length) {
1679 Map* map;
1680 // Number of characters: determines the map.
1681 if (length <= String::kMaxShortStringSize) {
1682 map = Heap::short_external_ascii_string_map();
1683 } else if (length <= String::kMaxMediumStringSize) {
1684 map = Heap::medium_external_ascii_string_map();
1685 } else {
1686 map = Heap::long_external_ascii_string_map();
1687 }
1688 return map;
1689}
1690
1691
1692Map* ExternalAsciiString::SymbolMap(int length) {
1693 Map* map;
1694 // Number of characters: determines the map.
1695 if (length <= String::kMaxShortStringSize) {
1696 map = Heap::short_external_ascii_symbol_map();
1697 } else if (length <= String::kMaxMediumStringSize) {
1698 map = Heap::medium_external_ascii_symbol_map();
1699 } else {
1700 map = Heap::long_external_ascii_symbol_map();
1701 }
1702 return map;
1703}
1704
1705
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001706ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1707 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1708}
1709
1710
1711void ExternalTwoByteString::set_resource(
1712 ExternalTwoByteString::Resource* resource) {
1713 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1714}
1715
1716
ager@chromium.org6f10e412009-02-13 10:11:16 +00001717Map* ExternalTwoByteString::StringMap(int length) {
1718 Map* map;
1719 // Number of characters: determines the map.
1720 if (length <= String::kMaxShortStringSize) {
1721 map = Heap::short_external_string_map();
1722 } else if (length <= String::kMaxMediumStringSize) {
1723 map = Heap::medium_external_string_map();
1724 } else {
1725 map = Heap::long_external_string_map();
1726 }
1727 return map;
1728}
1729
1730
1731Map* ExternalTwoByteString::SymbolMap(int length) {
1732 Map* map;
1733 // Number of characters: determines the map.
1734 if (length <= String::kMaxShortStringSize) {
1735 map = Heap::short_external_symbol_map();
1736 } else if (length <= String::kMaxMediumStringSize) {
1737 map = Heap::medium_external_symbol_map();
1738 } else {
1739 map = Heap::long_external_symbol_map();
1740 }
1741 return map;
1742}
1743
1744
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745byte ByteArray::get(int index) {
1746 ASSERT(index >= 0 && index < this->length());
1747 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1748}
1749
1750
1751void ByteArray::set(int index, byte value) {
1752 ASSERT(index >= 0 && index < this->length());
1753 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1754}
1755
1756
1757int ByteArray::get_int(int index) {
1758 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1759 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1760}
1761
1762
1763ByteArray* ByteArray::FromDataStartAddress(Address address) {
1764 ASSERT_TAG_ALIGNED(address);
1765 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1766}
1767
1768
1769Address ByteArray::GetDataStartAddress() {
1770 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1771}
1772
1773
1774int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001775 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1776}
1777
1778
1779int Map::inobject_properties() {
1780 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001781}
1782
1783
1784int HeapObject::SizeFromMap(Map* map) {
1785 InstanceType instance_type = map->instance_type();
1786 // Only inline the two most frequent cases.
1787 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1788 if (instance_type == FIXED_ARRAY_TYPE) {
1789 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1790 }
1791 // Otherwise do the general size computation.
1792 return SlowSizeFromMap(map);
1793}
1794
1795
1796void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001797 ASSERT((value & ~(kPointerSize - 1)) == value);
1798 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001799 ASSERT(0 <= value && value < 256);
1800 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1801}
1802
1803
ager@chromium.org7c537e22008-10-16 08:43:32 +00001804void Map::set_inobject_properties(int value) {
1805 ASSERT(0 <= value && value < 256);
1806 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1807}
1808
1809
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001810InstanceType Map::instance_type() {
1811 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1812}
1813
1814
1815void Map::set_instance_type(InstanceType value) {
1816 ASSERT(0 <= value && value < 256);
1817 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1818}
1819
1820
1821int Map::unused_property_fields() {
1822 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1823}
1824
1825
1826void Map::set_unused_property_fields(int value) {
1827 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1828}
1829
1830
1831byte Map::bit_field() {
1832 return READ_BYTE_FIELD(this, kBitFieldOffset);
1833}
1834
1835
1836void Map::set_bit_field(byte value) {
1837 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1838}
1839
1840
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001841byte Map::bit_field2() {
1842 return READ_BYTE_FIELD(this, kBitField2Offset);
1843}
1844
1845
1846void Map::set_bit_field2(byte value) {
1847 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1848}
1849
1850
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001851void Map::set_non_instance_prototype(bool value) {
1852 if (value) {
1853 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1854 } else {
1855 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1856 }
1857}
1858
1859
1860bool Map::has_non_instance_prototype() {
1861 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1862}
1863
1864
ager@chromium.org870a0b62008-11-04 11:43:05 +00001865void Map::set_is_access_check_needed(bool access_check_needed) {
1866 if (access_check_needed) {
1867 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1868 } else {
1869 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1870 }
1871}
1872
1873
1874bool Map::is_access_check_needed() {
1875 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1876}
1877
1878
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001879Code::Flags Code::flags() {
1880 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1881}
1882
1883
1884void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001885 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001886 // Make sure that all call stubs have an arguments count.
1887 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1888 ExtractArgumentsCountFromFlags(flags) >= 0);
1889 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1890}
1891
1892
1893Code::Kind Code::kind() {
1894 return ExtractKindFromFlags(flags());
1895}
1896
1897
kasper.lund7276f142008-07-30 08:49:36 +00001898InlineCacheState Code::ic_state() {
1899 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001900 // Only allow uninitialized or debugger states for non-IC code
1901 // objects. This is used in the debugger to determine whether or not
1902 // a call to code object has been replaced with a debug break call.
1903 ASSERT(is_inline_cache_stub() ||
1904 result == UNINITIALIZED ||
1905 result == DEBUG_BREAK ||
1906 result == DEBUG_PREPARE_STEP_IN);
1907 return result;
1908}
1909
1910
1911PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001912 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001913 return ExtractTypeFromFlags(flags());
1914}
1915
1916
1917int Code::arguments_count() {
1918 ASSERT(is_call_stub() || kind() == STUB);
1919 return ExtractArgumentsCountFromFlags(flags());
1920}
1921
1922
1923CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001924 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001925 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1926 kStubMajorKeyOffset));
1927}
1928
1929
1930void Code::set_major_key(CodeStub::Major major) {
1931 ASSERT(kind() == STUB);
1932 ASSERT(0 <= major && major < 256);
1933 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001934}
1935
1936
1937bool Code::is_inline_cache_stub() {
1938 Kind kind = this->kind();
1939 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1940}
1941
1942
1943Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001944 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001945 PropertyType type,
1946 int argc) {
1947 // Compute the bit mask.
1948 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001949 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001950 bits |= type << kFlagsTypeShift;
1951 bits |= argc << kFlagsArgumentsCountShift;
1952 // Cast to flags and validate result before returning it.
1953 Flags result = static_cast<Flags>(bits);
1954 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001955 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001956 ASSERT(ExtractTypeFromFlags(result) == type);
1957 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1958 return result;
1959}
1960
1961
1962Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1963 PropertyType type,
1964 int argc) {
1965 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1966}
1967
1968
1969Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1970 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1971 return static_cast<Kind>(bits);
1972}
1973
1974
kasper.lund7276f142008-07-30 08:49:36 +00001975InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1976 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001977 return static_cast<InlineCacheState>(bits);
1978}
1979
1980
1981PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1982 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1983 return static_cast<PropertyType>(bits);
1984}
1985
1986
1987int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1988 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1989}
1990
1991
1992Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1993 int bits = flags & ~kFlagsTypeMask;
1994 return static_cast<Flags>(bits);
1995}
1996
1997
ager@chromium.org8bb60582008-12-11 12:02:20 +00001998Code* Code::GetCodeFromTargetAddress(Address address) {
1999 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2000 // GetCodeFromTargetAddress might be called when marking objects during mark
2001 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2002 // Code::cast. Code::cast does not work when the object's map is
2003 // marked.
2004 Code* result = reinterpret_cast<Code*>(code);
2005 return result;
2006}
2007
2008
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002009Object* Map::prototype() {
2010 return READ_FIELD(this, kPrototypeOffset);
2011}
2012
2013
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002014void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002015 ASSERT(value->IsNull() || value->IsJSObject());
2016 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002017 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002018}
2019
2020
2021ACCESSORS(Map, instance_descriptors, DescriptorArray,
2022 kInstanceDescriptorsOffset)
2023ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2024ACCESSORS(Map, constructor, Object, kConstructorOffset)
2025
2026ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2027ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2028
2029ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2030ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002031ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002032
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002033ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002034
2035ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2036ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2037ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2038ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2039ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2040
2041ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2042ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2043ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2044
2045ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2046ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2047ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2048ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2049ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2050ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2051
2052ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2053ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2054
2055ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2056ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2057
2058ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2059ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002060ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2061 kPropertyAccessorsOffset)
2062ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2063 kPrototypeTemplateOffset)
2064ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2065ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2066 kNamedPropertyHandlerOffset)
2067ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2068 kIndexedPropertyHandlerOffset)
2069ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2070 kInstanceTemplateOffset)
2071ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2072ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002073ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2074 kInstanceCallHandlerOffset)
2075ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2076 kAccessCheckInfoOffset)
2077ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2078
2079ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002080ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2081 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002082
2083ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2084ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2085
2086ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2087
2088ACCESSORS(Script, source, Object, kSourceOffset)
2089ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002090ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2092ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002093ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002094ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002095ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2096ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002097ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002098
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002099#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002100ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2101ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2102ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2103ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2104
2105ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2106ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2107ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2108ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002109#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002110
2111ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2112ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2113 kInstanceClassNameOffset)
2114ACCESSORS(SharedFunctionInfo, function_data, Object,
2115 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002116ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2117ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002118ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002119
2120BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2121 kHiddenPrototypeBit)
2122BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2123BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2124 kNeedsAccessCheckBit)
2125BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2126 kIsExpressionBit)
2127BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2128 kIsTopLevelBit)
2129
2130INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2131INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2132 kFormalParameterCountOffset)
2133INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2134 kExpectedNofPropertiesOffset)
2135INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2136 kStartPositionAndTypeOffset)
2137INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2138INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2139 kFunctionTokenPositionOffset)
2140
2141
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002142void SharedFunctionInfo::DontAdaptArguments() {
2143 ASSERT(code()->kind() == Code::BUILTIN);
2144 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2145}
2146
2147
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002148int SharedFunctionInfo::start_position() {
2149 return start_position_and_type() >> kStartPositionShift;
2150}
2151
2152
2153void SharedFunctionInfo::set_start_position(int start_position) {
2154 set_start_position_and_type((start_position << kStartPositionShift)
2155 | (start_position_and_type() & ~kStartPositionMask));
2156}
2157
2158
2159Code* SharedFunctionInfo::code() {
2160 return Code::cast(READ_FIELD(this, kCodeOffset));
2161}
2162
2163
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002164void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002165 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002166 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002167}
2168
2169
2170bool SharedFunctionInfo::is_compiled() {
2171 // TODO(1242782): Create a code kind for uncompiled code.
2172 return code()->kind() != Code::STUB;
2173}
2174
2175
2176bool JSFunction::IsBoilerplate() {
2177 return map() == Heap::boilerplate_function_map();
2178}
2179
2180
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002181bool JSObject::IsLoaded() {
2182 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002183}
2184
2185
2186Code* JSFunction::code() {
2187 return shared()->code();
2188}
2189
2190
2191void JSFunction::set_code(Code* value) {
2192 shared()->set_code(value);
2193}
2194
2195
2196Context* JSFunction::context() {
2197 return Context::cast(READ_FIELD(this, kContextOffset));
2198}
2199
2200
2201Object* JSFunction::unchecked_context() {
2202 return READ_FIELD(this, kContextOffset);
2203}
2204
2205
2206void JSFunction::set_context(Object* value) {
2207 ASSERT(value == Heap::undefined_value() || value->IsContext());
2208 WRITE_FIELD(this, kContextOffset, value);
2209 WRITE_BARRIER(this, kContextOffset);
2210}
2211
2212ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2213 kPrototypeOrInitialMapOffset)
2214
2215
2216Map* JSFunction::initial_map() {
2217 return Map::cast(prototype_or_initial_map());
2218}
2219
2220
2221void JSFunction::set_initial_map(Map* value) {
2222 set_prototype_or_initial_map(value);
2223}
2224
2225
2226bool JSFunction::has_initial_map() {
2227 return prototype_or_initial_map()->IsMap();
2228}
2229
2230
2231bool JSFunction::has_instance_prototype() {
2232 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2233}
2234
2235
2236bool JSFunction::has_prototype() {
2237 return map()->has_non_instance_prototype() || has_instance_prototype();
2238}
2239
2240
2241Object* JSFunction::instance_prototype() {
2242 ASSERT(has_instance_prototype());
2243 if (has_initial_map()) return initial_map()->prototype();
2244 // When there is no initial map and the prototype is a JSObject, the
2245 // initial map field is used for the prototype field.
2246 return prototype_or_initial_map();
2247}
2248
2249
2250Object* JSFunction::prototype() {
2251 ASSERT(has_prototype());
2252 // If the function's prototype property has been set to a non-JSObject
2253 // value, that value is stored in the constructor field of the map.
2254 if (map()->has_non_instance_prototype()) return map()->constructor();
2255 return instance_prototype();
2256}
2257
2258
2259bool JSFunction::is_compiled() {
2260 return shared()->is_compiled();
2261}
2262
2263
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002264int JSFunction::NumberOfLiterals() {
2265 return literals()->length();
2266}
2267
2268
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002269Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2270 ASSERT(0 <= id && id < kJSBuiltinsCount);
2271 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2272}
2273
2274
2275void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2276 Object* value) {
2277 ASSERT(0 <= id && id < kJSBuiltinsCount);
2278 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2279 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2280}
2281
2282
2283Address Proxy::proxy() {
2284 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2285}
2286
2287
2288void Proxy::set_proxy(Address value) {
2289 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2290}
2291
2292
2293void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2294 visitor->VisitExternalReference(
2295 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2296}
2297
2298
2299ACCESSORS(JSValue, value, Object, kValueOffset)
2300
2301
2302JSValue* JSValue::cast(Object* obj) {
2303 ASSERT(obj->IsJSValue());
2304 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2305 return reinterpret_cast<JSValue*>(obj);
2306}
2307
2308
2309INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2310INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2311INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2312
2313
2314Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002315 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002316}
2317
2318
2319void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002320 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002321}
2322
2323
2324byte* Code::instruction_start() {
2325 return FIELD_ADDR(this, kHeaderSize);
2326}
2327
2328
2329int Code::body_size() {
2330 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2331}
2332
2333
2334byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002335 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002336}
2337
2338
2339byte* Code::entry() {
2340 return instruction_start();
2341}
2342
2343
2344bool Code::contains(byte* pc) {
2345 return (instruction_start() <= pc) &&
2346 (pc < instruction_start() + instruction_size());
2347}
2348
2349
2350byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002351 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002352}
2353
2354
2355ACCESSORS(JSArray, length, Object, kLengthOffset)
2356
2357
ager@chromium.org236ad962008-09-25 09:45:57 +00002358ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002359
2360
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002361JSRegExp::Type JSRegExp::TypeTag() {
2362 Object* data = this->data();
2363 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2364 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2365 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002366}
2367
2368
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002369int JSRegExp::CaptureCount() {
2370 switch (TypeTag()) {
2371 case ATOM:
2372 return 0;
2373 case IRREGEXP:
2374 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2375 default:
2376 UNREACHABLE();
2377 return -1;
2378 }
2379}
2380
2381
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002382JSRegExp::Flags JSRegExp::GetFlags() {
2383 ASSERT(this->data()->IsFixedArray());
2384 Object* data = this->data();
2385 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2386 return Flags(smi->value());
2387}
2388
2389
2390String* JSRegExp::Pattern() {
2391 ASSERT(this->data()->IsFixedArray());
2392 Object* data = this->data();
2393 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2394 return pattern;
2395}
2396
2397
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002398Object* JSRegExp::DataAt(int index) {
2399 ASSERT(TypeTag() != NOT_COMPILED);
2400 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002401}
2402
2403
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002404void JSRegExp::SetDataAt(int index, Object* value) {
2405 ASSERT(TypeTag() != NOT_COMPILED);
2406 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2407 FixedArray::cast(data())->set(index, value);
2408}
2409
2410
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002411bool JSObject::HasFastElements() {
2412 return !elements()->IsDictionary();
2413}
2414
2415
2416bool JSObject::HasNamedInterceptor() {
2417 return map()->has_named_interceptor();
2418}
2419
2420
2421bool JSObject::HasIndexedInterceptor() {
2422 return map()->has_indexed_interceptor();
2423}
2424
2425
2426Dictionary* JSObject::property_dictionary() {
2427 ASSERT(!HasFastProperties());
2428 return Dictionary::cast(properties());
2429}
2430
2431
2432Dictionary* JSObject::element_dictionary() {
2433 ASSERT(!HasFastElements());
2434 return Dictionary::cast(elements());
2435}
2436
2437
2438bool String::HasHashCode() {
2439 return (length_field() & kHashComputedMask) != 0;
2440}
2441
2442
2443uint32_t String::Hash() {
2444 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002445 uint32_t field = length_field();
2446 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002447 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002448 return ComputeAndSetHash();
2449}
2450
2451
ager@chromium.org7c537e22008-10-16 08:43:32 +00002452StringHasher::StringHasher(int length)
2453 : length_(length),
2454 raw_running_hash_(0),
2455 array_index_(0),
2456 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2457 is_first_char_(true),
2458 is_valid_(true) { }
2459
2460
2461bool StringHasher::has_trivial_hash() {
2462 return length_ > String::kMaxMediumStringSize;
2463}
2464
2465
2466void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002467 // Use the Jenkins one-at-a-time hash function to update the hash
2468 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002469 raw_running_hash_ += c;
2470 raw_running_hash_ += (raw_running_hash_ << 10);
2471 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002472 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002473 if (is_array_index_) {
2474 if (c < '0' || c > '9') {
2475 is_array_index_ = false;
2476 } else {
2477 int d = c - '0';
2478 if (is_first_char_) {
2479 is_first_char_ = false;
2480 if (c == '0' && length_ > 1) {
2481 is_array_index_ = false;
2482 return;
2483 }
2484 }
2485 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2486 is_array_index_ = false;
2487 } else {
2488 array_index_ = array_index_ * 10 + d;
2489 }
2490 }
2491 }
2492}
2493
2494
2495void StringHasher::AddCharacterNoIndex(uc32 c) {
2496 ASSERT(!is_array_index());
2497 raw_running_hash_ += c;
2498 raw_running_hash_ += (raw_running_hash_ << 10);
2499 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2500}
2501
2502
2503uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002504 // Get the calculated raw hash value and do some more bit ops to distribute
2505 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002506 uint32_t result = raw_running_hash_;
2507 result += (result << 3);
2508 result ^= (result >> 11);
2509 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002510 if (result == 0) {
2511 result = 27;
2512 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002513 return result;
2514}
2515
2516
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002517bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002518 uint32_t field = length_field();
2519 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002520 return SlowAsArrayIndex(index);
2521}
2522
2523
2524Object* JSObject::GetPrototype() {
2525 return JSObject::cast(this)->map()->prototype();
2526}
2527
2528
2529PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2530 return GetPropertyAttributeWithReceiver(this, key);
2531}
2532
2533
2534bool JSObject::HasElement(uint32_t index) {
2535 return HasElementWithReceiver(this, index);
2536}
2537
2538
2539bool AccessorInfo::all_can_read() {
2540 return BooleanBit::get(flag(), kAllCanReadBit);
2541}
2542
2543
2544void AccessorInfo::set_all_can_read(bool value) {
2545 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2546}
2547
2548
2549bool AccessorInfo::all_can_write() {
2550 return BooleanBit::get(flag(), kAllCanWriteBit);
2551}
2552
2553
2554void AccessorInfo::set_all_can_write(bool value) {
2555 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2556}
2557
2558
ager@chromium.org870a0b62008-11-04 11:43:05 +00002559bool AccessorInfo::prohibits_overwriting() {
2560 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2561}
2562
2563
2564void AccessorInfo::set_prohibits_overwriting(bool value) {
2565 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2566}
2567
2568
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002569PropertyAttributes AccessorInfo::property_attributes() {
2570 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2571}
2572
2573
2574void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2575 ASSERT(AttributesField::is_valid(attributes));
2576 int rest_value = flag()->value() & ~AttributesField::mask();
2577 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2578}
2579
2580void Dictionary::SetEntry(int entry,
2581 Object* key,
2582 Object* value,
2583 PropertyDetails details) {
2584 ASSERT(!key->IsString() || details.index() > 0);
2585 int index = EntryToIndex(entry);
2586 WriteBarrierMode mode = GetWriteBarrierMode();
2587 set(index, key, mode);
2588 set(index+1, value, mode);
2589 fast_set(this, index+2, details.AsSmi());
2590}
2591
2592
2593void Map::ClearCodeCache() {
2594 // No write barrier is needed since empty_fixed_array is not in new space.
2595 // Please note this function is used during marking:
2596 // - MarkCompactCollector::MarkUnmarkedObject
2597 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2598 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2599}
2600
2601
ager@chromium.org7c537e22008-10-16 08:43:32 +00002602void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002603 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002604 set_elements(storage);
2605}
2606
2607
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002608Object* FixedArray::Copy() {
2609 if (length() == 0) return this;
2610 return Heap::CopyFixedArray(this);
2611}
2612
2613
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002614#undef CAST_ACCESSOR
2615#undef INT_ACCESSORS
2616#undef SMI_ACCESSORS
2617#undef ACCESSORS
2618#undef FIELD_ADDR
2619#undef READ_FIELD
2620#undef WRITE_FIELD
2621#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002622#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002623#undef READ_MEMADDR_FIELD
2624#undef WRITE_MEMADDR_FIELD
2625#undef READ_DOUBLE_FIELD
2626#undef WRITE_DOUBLE_FIELD
2627#undef READ_INT_FIELD
2628#undef WRITE_INT_FIELD
2629#undef READ_SHORT_FIELD
2630#undef WRITE_SHORT_FIELD
2631#undef READ_BYTE_FIELD
2632#undef WRITE_BYTE_FIELD
2633
2634
2635} } // namespace v8::internal
2636
2637#endif // V8_OBJECTS_INL_H_