blob: 58e4f7c666bec9af375ad458fc6d8bd5d08afc58 [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));
692 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
693}
694
695
696Failure::Type Failure::type() const {
697 return static_cast<Type>(value() & kFailureTypeTagMask);
698}
699
700
701bool Failure::IsInternalError() const {
702 return type() == INTERNAL_ERROR;
703}
704
705
706bool Failure::IsOutOfMemoryException() const {
707 return type() == OUT_OF_MEMORY_EXCEPTION;
708}
709
710
711int Failure::requested() const {
712 const int kShiftBits =
713 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
714 STATIC_ASSERT(kShiftBits >= 0);
715 ASSERT(type() == RETRY_AFTER_GC);
716 return value() >> kShiftBits;
717}
718
719
720AllocationSpace Failure::allocation_space() const {
721 ASSERT_EQ(RETRY_AFTER_GC, type());
722 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
723 & kSpaceTagMask);
724}
725
726
727Failure* Failure::InternalError() {
728 return Construct(INTERNAL_ERROR);
729}
730
731
732Failure* Failure::Exception() {
733 return Construct(EXCEPTION);
734}
735
736Failure* Failure::OutOfMemoryException() {
737 return Construct(OUT_OF_MEMORY_EXCEPTION);
738}
739
740
741int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000742 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743}
744
745
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000746Failure* Failure::RetryAfterGC(int requested_bytes) {
747 int requested = requested_bytes >> kObjectAlignmentBits;
748 int value = (requested << kSpaceTagSize) | NEW_SPACE;
749 ASSERT(value >> kSpaceTagSize == requested);
750 ASSERT(Smi::IsValid(value));
751 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
752 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
753 return Construct(RETRY_AFTER_GC, value);
754}
755
756
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757Failure* Failure::Construct(Type type, int value) {
758 int info = (value << kFailureTypeTagSize) | type;
759 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000760 return reinterpret_cast<Failure*>(
761 static_cast<intptr_t>((info << kFailureTagSize) | kFailureTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762}
763
764
765bool Smi::IsValid(int value) {
766#ifdef DEBUG
767 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
768#endif
769 // To be representable as an tagged small integer, the two
770 // most-significant bits of 'value' must be either 00 or 11 due to
771 // sign-extension. To check this we add 01 to the two
772 // most-significant bits, and check if the most-significant bit is 0
773 //
774 // CAUTION: The original code below:
775 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
776 // may lead to incorrect results according to the C language spec, and
777 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
778 // compiler may produce undefined results in case of signed integer
779 // overflow. The computation must be done w/ unsigned ints.
780 bool result =
781 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
782 ASSERT(result == in_range);
783 return result;
784}
785
786
kasper.lund7276f142008-07-30 08:49:36 +0000787MapWord MapWord::FromMap(Map* map) {
788 return MapWord(reinterpret_cast<uintptr_t>(map));
789}
790
791
792Map* MapWord::ToMap() {
793 return reinterpret_cast<Map*>(value_);
794}
795
796
797bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000798 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000799}
800
801
802MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000803 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
804 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000805}
806
807
808HeapObject* MapWord::ToForwardingAddress() {
809 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000810 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000811}
812
813
814bool MapWord::IsMarked() {
815 return (value_ & kMarkingMask) == 0;
816}
817
818
819void MapWord::SetMark() {
820 value_ &= ~kMarkingMask;
821}
822
823
824void MapWord::ClearMark() {
825 value_ |= kMarkingMask;
826}
827
828
829bool MapWord::IsOverflowed() {
830 return (value_ & kOverflowMask) != 0;
831}
832
833
834void MapWord::SetOverflow() {
835 value_ |= kOverflowMask;
836}
837
838
839void MapWord::ClearOverflow() {
840 value_ &= ~kOverflowMask;
841}
842
843
844MapWord MapWord::EncodeAddress(Address map_address, int offset) {
845 // Offset is the distance in live bytes from the first live object in the
846 // same page. The offset between two objects in the same page should not
847 // exceed the object area size of a page.
848 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
849
850 int compact_offset = offset >> kObjectAlignmentBits;
851 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
852
853 Page* map_page = Page::FromAddress(map_address);
854 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
855
856 int map_page_offset =
857 map_page->Offset(map_address) >> kObjectAlignmentBits;
858
859 uintptr_t encoding =
860 (compact_offset << kForwardingOffsetShift) |
861 (map_page_offset << kMapPageOffsetShift) |
862 (map_page->mc_page_index << kMapPageIndexShift);
863 return MapWord(encoding);
864}
865
866
867Address MapWord::DecodeMapAddress(MapSpace* map_space) {
868 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
869 ASSERT_MAP_PAGE_INDEX(map_page_index);
870
871 int map_page_offset =
872 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
873 << kObjectAlignmentBits;
874
875 return (map_space->PageAddress(map_page_index) + map_page_offset);
876}
877
878
879int MapWord::DecodeOffset() {
880 // The offset field is represented in the kForwardingOffsetBits
881 // most-significant bits.
882 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
883 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
884 return offset;
885}
886
887
888MapWord MapWord::FromEncodedAddress(Address address) {
889 return MapWord(reinterpret_cast<uintptr_t>(address));
890}
891
892
893Address MapWord::ToEncodedAddress() {
894 return reinterpret_cast<Address>(value_);
895}
896
897
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898#ifdef DEBUG
899void HeapObject::VerifyObjectField(int offset) {
900 VerifyPointer(READ_FIELD(this, offset));
901}
902#endif
903
904
905Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000906 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907}
908
909
910void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000911 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000912}
913
914
kasper.lund7276f142008-07-30 08:49:36 +0000915MapWord HeapObject::map_word() {
916 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
917}
918
919
920void HeapObject::set_map_word(MapWord map_word) {
921 // WRITE_FIELD does not update the remembered set, but there is no need
922 // here.
923 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
924}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000925
926
927HeapObject* HeapObject::FromAddress(Address address) {
928 ASSERT_TAG_ALIGNED(address);
929 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
930}
931
932
933Address HeapObject::address() {
934 return reinterpret_cast<Address>(this) - kHeapObjectTag;
935}
936
937
938int HeapObject::Size() {
939 return SizeFromMap(map());
940}
941
942
943void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
944 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
945 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
946}
947
948
949void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
950 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
951}
952
953
kasper.lund7276f142008-07-30 08:49:36 +0000954bool HeapObject::IsMarked() {
955 return map_word().IsMarked();
956}
957
958
959void HeapObject::SetMark() {
960 ASSERT(!IsMarked());
961 MapWord first_word = map_word();
962 first_word.SetMark();
963 set_map_word(first_word);
964}
965
966
967void HeapObject::ClearMark() {
968 ASSERT(IsMarked());
969 MapWord first_word = map_word();
970 first_word.ClearMark();
971 set_map_word(first_word);
972}
973
974
975bool HeapObject::IsOverflowed() {
976 return map_word().IsOverflowed();
977}
978
979
980void HeapObject::SetOverflow() {
981 MapWord first_word = map_word();
982 first_word.SetOverflow();
983 set_map_word(first_word);
984}
985
986
987void HeapObject::ClearOverflow() {
988 ASSERT(IsOverflowed());
989 MapWord first_word = map_word();
990 first_word.ClearOverflow();
991 set_map_word(first_word);
992}
993
994
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995double HeapNumber::value() {
996 return READ_DOUBLE_FIELD(this, kValueOffset);
997}
998
999
1000void HeapNumber::set_value(double value) {
1001 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1002}
1003
1004
1005ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001006ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001007
1008
1009void JSObject::initialize_properties() {
1010 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1011 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1012}
1013
1014
1015void JSObject::initialize_elements() {
1016 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1017 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1018}
1019
1020
1021ACCESSORS(Oddball, to_string, String, kToStringOffset)
1022ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1023
1024
1025int JSObject::GetHeaderSize() {
1026 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001027 case JS_GLOBAL_PROXY_TYPE:
1028 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001029 case JS_GLOBAL_OBJECT_TYPE:
1030 return JSGlobalObject::kSize;
1031 case JS_BUILTINS_OBJECT_TYPE:
1032 return JSBuiltinsObject::kSize;
1033 case JS_FUNCTION_TYPE:
1034 return JSFunction::kSize;
1035 case JS_VALUE_TYPE:
1036 return JSValue::kSize;
1037 case JS_ARRAY_TYPE:
1038 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001039 case JS_REGEXP_TYPE:
1040 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001042 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001043 return JSObject::kHeaderSize;
1044 default:
1045 UNREACHABLE();
1046 return 0;
1047 }
1048}
1049
1050
1051int JSObject::GetInternalFieldCount() {
1052 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001053 // Make sure to adjust for the number of in-object properties. These
1054 // properties do contribute to the size, but are not internal fields.
1055 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1056 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001057}
1058
1059
1060Object* JSObject::GetInternalField(int index) {
1061 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001062 // Internal objects do follow immediately after the header, whereas in-object
1063 // properties are at the end of the object. Therefore there is no need
1064 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001065 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1066}
1067
1068
1069void JSObject::SetInternalField(int index, Object* value) {
1070 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001071 // Internal objects do follow immediately after the header, whereas in-object
1072 // properties are at the end of the object. Therefore there is no need
1073 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001074 int offset = GetHeaderSize() + (kPointerSize * index);
1075 WRITE_FIELD(this, offset, value);
1076 WRITE_BARRIER(this, offset);
1077}
1078
1079
ager@chromium.org7c537e22008-10-16 08:43:32 +00001080// Access fast-case object properties at index. The use of these routines
1081// is needed to correctly distinguish between properties stored in-object and
1082// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001083Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001084 // Adjust for the number of properties stored in the object.
1085 index -= map()->inobject_properties();
1086 if (index < 0) {
1087 int offset = map()->instance_size() + (index * kPointerSize);
1088 return READ_FIELD(this, offset);
1089 } else {
1090 ASSERT(index < properties()->length());
1091 return properties()->get(index);
1092 }
1093}
1094
1095
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001096Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001097 // Adjust for the number of properties stored in the object.
1098 index -= map()->inobject_properties();
1099 if (index < 0) {
1100 int offset = map()->instance_size() + (index * kPointerSize);
1101 WRITE_FIELD(this, offset, value);
1102 WRITE_BARRIER(this, offset);
1103 } else {
1104 ASSERT(index < properties()->length());
1105 properties()->set(index, value);
1106 }
1107 return value;
1108}
1109
1110
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001111Object* JSObject::InObjectPropertyAt(int index) {
1112 // Adjust for the number of properties stored in the object.
1113 index -= map()->inobject_properties();
1114 ASSERT(index < 0);
1115 int offset = map()->instance_size() + (index * kPointerSize);
1116 return READ_FIELD(this, offset);
1117}
1118
1119
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001120Object* JSObject::InObjectPropertyAtPut(int index,
1121 Object* value,
1122 WriteBarrierMode mode) {
1123 // Adjust for the number of properties stored in the object.
1124 index -= map()->inobject_properties();
1125 ASSERT(index < 0);
1126 int offset = map()->instance_size() + (index * kPointerSize);
1127 WRITE_FIELD(this, offset, value);
1128 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1129 return value;
1130}
1131
1132
1133
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001134void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001135 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001136 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001137 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001138 }
1139}
1140
1141
1142void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001143 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001144 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001145 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146 }
1147}
1148
1149
1150bool JSObject::HasFastProperties() {
1151 return !properties()->IsDictionary();
1152}
1153
1154
1155bool Array::IndexFromObject(Object* object, uint32_t* index) {
1156 if (object->IsSmi()) {
1157 int value = Smi::cast(object)->value();
1158 if (value < 0) return false;
1159 *index = value;
1160 return true;
1161 }
1162 if (object->IsHeapNumber()) {
1163 double value = HeapNumber::cast(object)->value();
1164 uint32_t uint_value = static_cast<uint32_t>(value);
1165 if (value == static_cast<double>(uint_value)) {
1166 *index = uint_value;
1167 return true;
1168 }
1169 }
1170 return false;
1171}
1172
1173
1174bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1175 if (!this->IsJSValue()) return false;
1176
1177 JSValue* js_value = JSValue::cast(this);
1178 if (!js_value->value()->IsString()) return false;
1179
1180 String* str = String::cast(js_value->value());
1181 if (index >= (uint32_t)str->length()) return false;
1182
1183 return true;
1184}
1185
1186
1187Object* FixedArray::get(int index) {
1188 ASSERT(index >= 0 && index < this->length());
1189 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1190}
1191
1192
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001193void FixedArray::set(int index, Smi* value) {
1194 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1195 int offset = kHeaderSize + index * kPointerSize;
1196 WRITE_FIELD(this, offset, value);
1197}
1198
1199
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001200void FixedArray::set(int index, Object* value) {
1201 ASSERT(index >= 0 && index < this->length());
1202 int offset = kHeaderSize + index * kPointerSize;
1203 WRITE_FIELD(this, offset, value);
1204 WRITE_BARRIER(this, offset);
1205}
1206
1207
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001208WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001209 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1210 return UPDATE_WRITE_BARRIER;
1211}
1212
1213
1214void FixedArray::set(int index,
1215 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001216 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001217 ASSERT(index >= 0 && index < this->length());
1218 int offset = kHeaderSize + index * kPointerSize;
1219 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001220 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001221}
1222
1223
1224void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1225 ASSERT(index >= 0 && index < array->length());
1226 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1227}
1228
1229
1230void FixedArray::set_undefined(int index) {
1231 ASSERT(index >= 0 && index < this->length());
1232 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1233 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1234 Heap::undefined_value());
1235}
1236
1237
ager@chromium.org236ad962008-09-25 09:45:57 +00001238void FixedArray::set_null(int index) {
1239 ASSERT(index >= 0 && index < this->length());
1240 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1241 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1242}
1243
1244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245void FixedArray::set_the_hole(int index) {
1246 ASSERT(index >= 0 && index < this->length());
1247 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1248 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1249}
1250
1251
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001252bool DescriptorArray::IsEmpty() {
1253 ASSERT(this == Heap::empty_descriptor_array() ||
1254 this->length() > 2);
1255 return this == Heap::empty_descriptor_array();
1256}
1257
1258
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001259void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1260 Object* tmp = array->get(first);
1261 fast_set(array, first, array->get(second));
1262 fast_set(array, second, tmp);
1263}
1264
1265
1266int DescriptorArray::Search(String* name) {
1267 SLOW_ASSERT(IsSortedNoDuplicates());
1268
1269 // Check for empty descriptor array.
1270 int nof = number_of_descriptors();
1271 if (nof == 0) return kNotFound;
1272
1273 // Fast case: do linear search for small arrays.
1274 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001275 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001276 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277 }
1278
1279 // Slow case: perform binary search.
1280 return BinarySearch(name, 0, nof - 1);
1281}
1282
1283
1284
1285String* DescriptorArray::GetKey(int descriptor_number) {
1286 ASSERT(descriptor_number < number_of_descriptors());
1287 return String::cast(get(ToKeyIndex(descriptor_number)));
1288}
1289
1290
1291Object* DescriptorArray::GetValue(int descriptor_number) {
1292 ASSERT(descriptor_number < number_of_descriptors());
1293 return GetContentArray()->get(ToValueIndex(descriptor_number));
1294}
1295
1296
1297Smi* DescriptorArray::GetDetails(int descriptor_number) {
1298 ASSERT(descriptor_number < number_of_descriptors());
1299 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1300}
1301
1302
1303void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1304 desc->Init(GetKey(descriptor_number),
1305 GetValue(descriptor_number),
1306 GetDetails(descriptor_number));
1307}
1308
1309
1310void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1311 // Range check.
1312 ASSERT(descriptor_number < number_of_descriptors());
1313
1314 // Make sure non of the elements in desc are in new space.
1315 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1316 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1317
1318 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1319 FixedArray* content_array = GetContentArray();
1320 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1321 fast_set(content_array, ToDetailsIndex(descriptor_number),
1322 desc->GetDetails().AsSmi());
1323}
1324
1325
1326void DescriptorArray::Swap(int first, int second) {
1327 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1328 FixedArray* content_array = GetContentArray();
1329 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1330 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1331}
1332
1333
1334bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001335 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001336 if (!max_index_object->IsSmi()) return false;
1337 return 0 !=
1338 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1339}
1340
1341
1342uint32_t Dictionary::max_number_key() {
1343 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001344 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001345 if (!max_index_object->IsSmi()) return 0;
1346 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1347 return value >> kRequiresSlowElementsTagSize;
1348}
1349
1350
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001351void Dictionary::set_requires_slow_elements() {
1352 set(kMaxNumberKeyIndex,
1353 Smi::FromInt(kRequiresSlowElementsMask),
1354 SKIP_WRITE_BARRIER);
1355}
1356
1357
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001358// ------------------------------------
1359// Cast operations
1360
1361
1362CAST_ACCESSOR(FixedArray)
1363CAST_ACCESSOR(DescriptorArray)
1364CAST_ACCESSOR(Dictionary)
1365CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001366CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001367CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001368CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001369CAST_ACCESSOR(String)
1370CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001371CAST_ACCESSOR(SeqAsciiString)
1372CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001373CAST_ACCESSOR(ConsString)
1374CAST_ACCESSOR(SlicedString)
1375CAST_ACCESSOR(ExternalString)
1376CAST_ACCESSOR(ExternalAsciiString)
1377CAST_ACCESSOR(ExternalTwoByteString)
1378CAST_ACCESSOR(JSObject)
1379CAST_ACCESSOR(Smi)
1380CAST_ACCESSOR(Failure)
1381CAST_ACCESSOR(HeapObject)
1382CAST_ACCESSOR(HeapNumber)
1383CAST_ACCESSOR(Oddball)
1384CAST_ACCESSOR(SharedFunctionInfo)
1385CAST_ACCESSOR(Map)
1386CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001387CAST_ACCESSOR(GlobalObject)
1388CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389CAST_ACCESSOR(JSGlobalObject)
1390CAST_ACCESSOR(JSBuiltinsObject)
1391CAST_ACCESSOR(Code)
1392CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001393CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394CAST_ACCESSOR(Proxy)
1395CAST_ACCESSOR(ByteArray)
1396CAST_ACCESSOR(Struct)
1397
1398
1399#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1400 STRUCT_LIST(MAKE_STRUCT_CAST)
1401#undef MAKE_STRUCT_CAST
1402
1403template <int prefix_size, int elem_size>
1404HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1405 Object* obj) {
1406 ASSERT(obj->IsHashTable());
1407 return reinterpret_cast<HashTable*>(obj);
1408}
1409
1410
1411INT_ACCESSORS(Array, length, kLengthOffset)
1412
1413
1414bool String::Equals(String* other) {
1415 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001416 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1417 return false;
1418 }
1419 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001420}
1421
1422
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001423int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001424 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1425
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001426 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1427 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1428 ASSERT(kLongStringTag == 0);
1429
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001430 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001431}
1432
1433
1434void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001435 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1436 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1437 ASSERT(kLongStringTag == 0);
1438
1439 WRITE_INT_FIELD(this,
1440 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001441 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001442}
1443
1444
ager@chromium.org7c537e22008-10-16 08:43:32 +00001445uint32_t String::length_field() {
1446 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001447}
1448
1449
ager@chromium.org7c537e22008-10-16 08:43:32 +00001450void String::set_length_field(uint32_t value) {
1451 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001452}
1453
1454
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001455Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001456 // We don't need to flatten strings that are already flat. Since this code
1457 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001458 if (!IsFlat()) {
1459 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001460 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001461 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462}
1463
1464
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001465uint16_t String::Get(int index) {
1466 ASSERT(index >= 0 && index < length());
1467 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001468 case kSeqStringTag | kAsciiStringTag:
1469 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1470 case kSeqStringTag | kTwoByteStringTag:
1471 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1472 case kConsStringTag | kAsciiStringTag:
1473 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001475 case kSlicedStringTag | kAsciiStringTag:
1476 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001477 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001478 case kExternalStringTag | kAsciiStringTag:
1479 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1480 case kExternalStringTag | kTwoByteStringTag:
1481 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001482 default:
1483 break;
1484 }
1485
1486 UNREACHABLE();
1487 return 0;
1488}
1489
1490
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001491void String::Set(int index, uint16_t value) {
1492 ASSERT(index >= 0 && index < length());
1493 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494
ager@chromium.org5ec48922009-05-05 07:25:34 +00001495 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001496 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1497 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498}
1499
1500
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001501bool String::IsFlat() {
1502 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001503 case kConsStringTag: {
1504 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001505 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001506 return second->length() == 0;
1507 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001508 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001509 StringRepresentationTag tag =
1510 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001511 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001512 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001513 default:
1514 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001515 }
1516}
1517
1518
ager@chromium.org7c537e22008-10-16 08:43:32 +00001519uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001520 ASSERT(index >= 0 && index < length());
1521 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1522}
1523
1524
ager@chromium.org7c537e22008-10-16 08:43:32 +00001525void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001526 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1527 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1528 static_cast<byte>(value));
1529}
1530
1531
ager@chromium.org7c537e22008-10-16 08:43:32 +00001532Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001533 return FIELD_ADDR(this, kHeaderSize);
1534}
1535
1536
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001537char* SeqAsciiString::GetChars() {
1538 return reinterpret_cast<char*>(GetCharsAddress());
1539}
1540
1541
ager@chromium.org7c537e22008-10-16 08:43:32 +00001542Address SeqTwoByteString::GetCharsAddress() {
1543 return FIELD_ADDR(this, kHeaderSize);
1544}
1545
1546
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001547uc16* SeqTwoByteString::GetChars() {
1548 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1549}
1550
1551
ager@chromium.org7c537e22008-10-16 08:43:32 +00001552uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001553 ASSERT(index >= 0 && index < length());
1554 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1555}
1556
1557
ager@chromium.org7c537e22008-10-16 08:43:32 +00001558void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559 ASSERT(index >= 0 && index < length());
1560 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1561}
1562
1563
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001564int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001565 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1566
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001567 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1568 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1569 ASSERT(kLongStringTag == 0);
1570
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001571 // Use the map (and not 'this') to compute the size tag, since
1572 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001573 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001574
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001575 return SizeFor(length);
1576}
1577
1578
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001579int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1581
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001582 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1583 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1584 ASSERT(kLongStringTag == 0);
1585
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001586 // Use the map (and not 'this') to compute the size tag, since
1587 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001588 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589
1590 return SizeFor(length);
1591}
1592
1593
ager@chromium.org870a0b62008-11-04 11:43:05 +00001594String* ConsString::first() {
1595 return String::cast(READ_FIELD(this, kFirstOffset));
1596}
1597
1598
1599Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 return READ_FIELD(this, kFirstOffset);
1601}
1602
1603
ager@chromium.org870a0b62008-11-04 11:43:05 +00001604void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001605 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001606 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001607}
1608
1609
ager@chromium.org870a0b62008-11-04 11:43:05 +00001610String* ConsString::second() {
1611 return String::cast(READ_FIELD(this, kSecondOffset));
1612}
1613
1614
1615Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001616 return READ_FIELD(this, kSecondOffset);
1617}
1618
1619
ager@chromium.org870a0b62008-11-04 11:43:05 +00001620void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001621 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001622 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623}
1624
1625
ager@chromium.org870a0b62008-11-04 11:43:05 +00001626String* SlicedString::buffer() {
1627 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628}
1629
1630
ager@chromium.org870a0b62008-11-04 11:43:05 +00001631void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001632 WRITE_FIELD(this, kBufferOffset, buffer);
1633 WRITE_BARRIER(this, kBufferOffset);
1634}
1635
1636
1637int SlicedString::start() {
1638 return READ_INT_FIELD(this, kStartOffset);
1639}
1640
1641
1642void SlicedString::set_start(int start) {
1643 WRITE_INT_FIELD(this, kStartOffset, start);
1644}
1645
1646
1647ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1648 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1649}
1650
1651
1652void ExternalAsciiString::set_resource(
1653 ExternalAsciiString::Resource* resource) {
1654 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1655}
1656
1657
ager@chromium.org6f10e412009-02-13 10:11:16 +00001658Map* ExternalAsciiString::StringMap(int length) {
1659 Map* map;
1660 // Number of characters: determines the map.
1661 if (length <= String::kMaxShortStringSize) {
1662 map = Heap::short_external_ascii_string_map();
1663 } else if (length <= String::kMaxMediumStringSize) {
1664 map = Heap::medium_external_ascii_string_map();
1665 } else {
1666 map = Heap::long_external_ascii_string_map();
1667 }
1668 return map;
1669}
1670
1671
1672Map* ExternalAsciiString::SymbolMap(int length) {
1673 Map* map;
1674 // Number of characters: determines the map.
1675 if (length <= String::kMaxShortStringSize) {
1676 map = Heap::short_external_ascii_symbol_map();
1677 } else if (length <= String::kMaxMediumStringSize) {
1678 map = Heap::medium_external_ascii_symbol_map();
1679 } else {
1680 map = Heap::long_external_ascii_symbol_map();
1681 }
1682 return map;
1683}
1684
1685
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001686ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1687 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1688}
1689
1690
1691void ExternalTwoByteString::set_resource(
1692 ExternalTwoByteString::Resource* resource) {
1693 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1694}
1695
1696
ager@chromium.org6f10e412009-02-13 10:11:16 +00001697Map* ExternalTwoByteString::StringMap(int length) {
1698 Map* map;
1699 // Number of characters: determines the map.
1700 if (length <= String::kMaxShortStringSize) {
1701 map = Heap::short_external_string_map();
1702 } else if (length <= String::kMaxMediumStringSize) {
1703 map = Heap::medium_external_string_map();
1704 } else {
1705 map = Heap::long_external_string_map();
1706 }
1707 return map;
1708}
1709
1710
1711Map* ExternalTwoByteString::SymbolMap(int length) {
1712 Map* map;
1713 // Number of characters: determines the map.
1714 if (length <= String::kMaxShortStringSize) {
1715 map = Heap::short_external_symbol_map();
1716 } else if (length <= String::kMaxMediumStringSize) {
1717 map = Heap::medium_external_symbol_map();
1718 } else {
1719 map = Heap::long_external_symbol_map();
1720 }
1721 return map;
1722}
1723
1724
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725byte ByteArray::get(int index) {
1726 ASSERT(index >= 0 && index < this->length());
1727 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1728}
1729
1730
1731void ByteArray::set(int index, byte value) {
1732 ASSERT(index >= 0 && index < this->length());
1733 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1734}
1735
1736
1737int ByteArray::get_int(int index) {
1738 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1739 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1740}
1741
1742
1743ByteArray* ByteArray::FromDataStartAddress(Address address) {
1744 ASSERT_TAG_ALIGNED(address);
1745 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1746}
1747
1748
1749Address ByteArray::GetDataStartAddress() {
1750 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1751}
1752
1753
1754int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001755 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1756}
1757
1758
1759int Map::inobject_properties() {
1760 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761}
1762
1763
1764int HeapObject::SizeFromMap(Map* map) {
1765 InstanceType instance_type = map->instance_type();
1766 // Only inline the two most frequent cases.
1767 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1768 if (instance_type == FIXED_ARRAY_TYPE) {
1769 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1770 }
1771 // Otherwise do the general size computation.
1772 return SlowSizeFromMap(map);
1773}
1774
1775
1776void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001777 ASSERT((value & ~(kPointerSize - 1)) == value);
1778 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001779 ASSERT(0 <= value && value < 256);
1780 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1781}
1782
1783
ager@chromium.org7c537e22008-10-16 08:43:32 +00001784void Map::set_inobject_properties(int value) {
1785 ASSERT(0 <= value && value < 256);
1786 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1787}
1788
1789
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001790InstanceType Map::instance_type() {
1791 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1792}
1793
1794
1795void Map::set_instance_type(InstanceType value) {
1796 ASSERT(0 <= value && value < 256);
1797 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1798}
1799
1800
1801int Map::unused_property_fields() {
1802 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1803}
1804
1805
1806void Map::set_unused_property_fields(int value) {
1807 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1808}
1809
1810
1811byte Map::bit_field() {
1812 return READ_BYTE_FIELD(this, kBitFieldOffset);
1813}
1814
1815
1816void Map::set_bit_field(byte value) {
1817 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1818}
1819
1820
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001821byte Map::bit_field2() {
1822 return READ_BYTE_FIELD(this, kBitField2Offset);
1823}
1824
1825
1826void Map::set_bit_field2(byte value) {
1827 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1828}
1829
1830
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001831void Map::set_non_instance_prototype(bool value) {
1832 if (value) {
1833 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1834 } else {
1835 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1836 }
1837}
1838
1839
1840bool Map::has_non_instance_prototype() {
1841 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1842}
1843
1844
ager@chromium.org870a0b62008-11-04 11:43:05 +00001845void Map::set_is_access_check_needed(bool access_check_needed) {
1846 if (access_check_needed) {
1847 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1848 } else {
1849 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1850 }
1851}
1852
1853
1854bool Map::is_access_check_needed() {
1855 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1856}
1857
1858
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001859Code::Flags Code::flags() {
1860 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1861}
1862
1863
1864void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001865 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001866 // Make sure that all call stubs have an arguments count.
1867 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1868 ExtractArgumentsCountFromFlags(flags) >= 0);
1869 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1870}
1871
1872
1873Code::Kind Code::kind() {
1874 return ExtractKindFromFlags(flags());
1875}
1876
1877
kasper.lund7276f142008-07-30 08:49:36 +00001878InlineCacheState Code::ic_state() {
1879 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001880 // Only allow uninitialized or debugger states for non-IC code
1881 // objects. This is used in the debugger to determine whether or not
1882 // a call to code object has been replaced with a debug break call.
1883 ASSERT(is_inline_cache_stub() ||
1884 result == UNINITIALIZED ||
1885 result == DEBUG_BREAK ||
1886 result == DEBUG_PREPARE_STEP_IN);
1887 return result;
1888}
1889
1890
1891PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001892 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001893 return ExtractTypeFromFlags(flags());
1894}
1895
1896
1897int Code::arguments_count() {
1898 ASSERT(is_call_stub() || kind() == STUB);
1899 return ExtractArgumentsCountFromFlags(flags());
1900}
1901
1902
1903CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001904 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001905 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1906 kStubMajorKeyOffset));
1907}
1908
1909
1910void Code::set_major_key(CodeStub::Major major) {
1911 ASSERT(kind() == STUB);
1912 ASSERT(0 <= major && major < 256);
1913 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001914}
1915
1916
1917bool Code::is_inline_cache_stub() {
1918 Kind kind = this->kind();
1919 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1920}
1921
1922
1923Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001924 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001925 PropertyType type,
1926 int argc) {
1927 // Compute the bit mask.
1928 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001929 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001930 bits |= type << kFlagsTypeShift;
1931 bits |= argc << kFlagsArgumentsCountShift;
1932 // Cast to flags and validate result before returning it.
1933 Flags result = static_cast<Flags>(bits);
1934 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001935 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001936 ASSERT(ExtractTypeFromFlags(result) == type);
1937 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1938 return result;
1939}
1940
1941
1942Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1943 PropertyType type,
1944 int argc) {
1945 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1946}
1947
1948
1949Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1950 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1951 return static_cast<Kind>(bits);
1952}
1953
1954
kasper.lund7276f142008-07-30 08:49:36 +00001955InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1956 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001957 return static_cast<InlineCacheState>(bits);
1958}
1959
1960
1961PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1962 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1963 return static_cast<PropertyType>(bits);
1964}
1965
1966
1967int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1968 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1969}
1970
1971
1972Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1973 int bits = flags & ~kFlagsTypeMask;
1974 return static_cast<Flags>(bits);
1975}
1976
1977
ager@chromium.org8bb60582008-12-11 12:02:20 +00001978Code* Code::GetCodeFromTargetAddress(Address address) {
1979 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1980 // GetCodeFromTargetAddress might be called when marking objects during mark
1981 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1982 // Code::cast. Code::cast does not work when the object's map is
1983 // marked.
1984 Code* result = reinterpret_cast<Code*>(code);
1985 return result;
1986}
1987
1988
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001989Object* Map::prototype() {
1990 return READ_FIELD(this, kPrototypeOffset);
1991}
1992
1993
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001994void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995 ASSERT(value->IsNull() || value->IsJSObject());
1996 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001997 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001998}
1999
2000
2001ACCESSORS(Map, instance_descriptors, DescriptorArray,
2002 kInstanceDescriptorsOffset)
2003ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2004ACCESSORS(Map, constructor, Object, kConstructorOffset)
2005
2006ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2007ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2008
2009ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2010ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002011ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002012
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002013ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002014
2015ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2016ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2017ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2018ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2019ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2020
2021ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2022ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2023ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2024
2025ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2026ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2027ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2028ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2029ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2030ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2031
2032ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2033ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2034
2035ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2036ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2037
2038ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2039ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002040ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2041 kPropertyAccessorsOffset)
2042ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2043 kPrototypeTemplateOffset)
2044ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2045ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2046 kNamedPropertyHandlerOffset)
2047ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2048 kIndexedPropertyHandlerOffset)
2049ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2050 kInstanceTemplateOffset)
2051ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2052ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002053ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2054 kInstanceCallHandlerOffset)
2055ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2056 kAccessCheckInfoOffset)
2057ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2058
2059ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002060ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2061 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002062
2063ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2064ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2065
2066ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2067
2068ACCESSORS(Script, source, Object, kSourceOffset)
2069ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002070ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002071ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2072ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002073ACCESSORS(Script, data, Object, kDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002074ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2075ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002076ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002077
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002078#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002079ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2080ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2081ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2082ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2083
2084ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2085ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2086ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2087ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002088#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002089
2090ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2091ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2092 kInstanceClassNameOffset)
2093ACCESSORS(SharedFunctionInfo, function_data, Object,
2094 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002095ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2096ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002097ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002098
2099BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2100 kHiddenPrototypeBit)
2101BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2102BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2103 kNeedsAccessCheckBit)
2104BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2105 kIsExpressionBit)
2106BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2107 kIsTopLevelBit)
2108
2109INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2110INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2111 kFormalParameterCountOffset)
2112INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2113 kExpectedNofPropertiesOffset)
2114INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2115 kStartPositionAndTypeOffset)
2116INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2117INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2118 kFunctionTokenPositionOffset)
2119
2120
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002121void SharedFunctionInfo::DontAdaptArguments() {
2122 ASSERT(code()->kind() == Code::BUILTIN);
2123 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2124}
2125
2126
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002127int SharedFunctionInfo::start_position() {
2128 return start_position_and_type() >> kStartPositionShift;
2129}
2130
2131
2132void SharedFunctionInfo::set_start_position(int start_position) {
2133 set_start_position_and_type((start_position << kStartPositionShift)
2134 | (start_position_and_type() & ~kStartPositionMask));
2135}
2136
2137
2138Code* SharedFunctionInfo::code() {
2139 return Code::cast(READ_FIELD(this, kCodeOffset));
2140}
2141
2142
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002143void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002144 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002145 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002146}
2147
2148
2149bool SharedFunctionInfo::is_compiled() {
2150 // TODO(1242782): Create a code kind for uncompiled code.
2151 return code()->kind() != Code::STUB;
2152}
2153
2154
2155bool JSFunction::IsBoilerplate() {
2156 return map() == Heap::boilerplate_function_map();
2157}
2158
2159
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002160bool JSObject::IsLoaded() {
2161 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002162}
2163
2164
2165Code* JSFunction::code() {
2166 return shared()->code();
2167}
2168
2169
2170void JSFunction::set_code(Code* value) {
2171 shared()->set_code(value);
2172}
2173
2174
2175Context* JSFunction::context() {
2176 return Context::cast(READ_FIELD(this, kContextOffset));
2177}
2178
2179
2180Object* JSFunction::unchecked_context() {
2181 return READ_FIELD(this, kContextOffset);
2182}
2183
2184
2185void JSFunction::set_context(Object* value) {
2186 ASSERT(value == Heap::undefined_value() || value->IsContext());
2187 WRITE_FIELD(this, kContextOffset, value);
2188 WRITE_BARRIER(this, kContextOffset);
2189}
2190
2191ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2192 kPrototypeOrInitialMapOffset)
2193
2194
2195Map* JSFunction::initial_map() {
2196 return Map::cast(prototype_or_initial_map());
2197}
2198
2199
2200void JSFunction::set_initial_map(Map* value) {
2201 set_prototype_or_initial_map(value);
2202}
2203
2204
2205bool JSFunction::has_initial_map() {
2206 return prototype_or_initial_map()->IsMap();
2207}
2208
2209
2210bool JSFunction::has_instance_prototype() {
2211 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2212}
2213
2214
2215bool JSFunction::has_prototype() {
2216 return map()->has_non_instance_prototype() || has_instance_prototype();
2217}
2218
2219
2220Object* JSFunction::instance_prototype() {
2221 ASSERT(has_instance_prototype());
2222 if (has_initial_map()) return initial_map()->prototype();
2223 // When there is no initial map and the prototype is a JSObject, the
2224 // initial map field is used for the prototype field.
2225 return prototype_or_initial_map();
2226}
2227
2228
2229Object* JSFunction::prototype() {
2230 ASSERT(has_prototype());
2231 // If the function's prototype property has been set to a non-JSObject
2232 // value, that value is stored in the constructor field of the map.
2233 if (map()->has_non_instance_prototype()) return map()->constructor();
2234 return instance_prototype();
2235}
2236
2237
2238bool JSFunction::is_compiled() {
2239 return shared()->is_compiled();
2240}
2241
2242
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002243int JSFunction::NumberOfLiterals() {
2244 return literals()->length();
2245}
2246
2247
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002248Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2249 ASSERT(0 <= id && id < kJSBuiltinsCount);
2250 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2251}
2252
2253
2254void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2255 Object* value) {
2256 ASSERT(0 <= id && id < kJSBuiltinsCount);
2257 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2258 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2259}
2260
2261
2262Address Proxy::proxy() {
2263 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2264}
2265
2266
2267void Proxy::set_proxy(Address value) {
2268 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2269}
2270
2271
2272void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2273 visitor->VisitExternalReference(
2274 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2275}
2276
2277
2278ACCESSORS(JSValue, value, Object, kValueOffset)
2279
2280
2281JSValue* JSValue::cast(Object* obj) {
2282 ASSERT(obj->IsJSValue());
2283 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2284 return reinterpret_cast<JSValue*>(obj);
2285}
2286
2287
2288INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2289INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2290INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2291
2292
2293Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002294 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002295}
2296
2297
2298void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002299 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002300}
2301
2302
2303byte* Code::instruction_start() {
2304 return FIELD_ADDR(this, kHeaderSize);
2305}
2306
2307
2308int Code::body_size() {
2309 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2310}
2311
2312
2313byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002314 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002315}
2316
2317
2318byte* Code::entry() {
2319 return instruction_start();
2320}
2321
2322
2323bool Code::contains(byte* pc) {
2324 return (instruction_start() <= pc) &&
2325 (pc < instruction_start() + instruction_size());
2326}
2327
2328
2329byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002330 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002331}
2332
2333
2334ACCESSORS(JSArray, length, Object, kLengthOffset)
2335
2336
ager@chromium.org236ad962008-09-25 09:45:57 +00002337ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002338
2339
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002340JSRegExp::Type JSRegExp::TypeTag() {
2341 Object* data = this->data();
2342 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2343 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2344 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002345}
2346
2347
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002348int JSRegExp::CaptureCount() {
2349 switch (TypeTag()) {
2350 case ATOM:
2351 return 0;
2352 case IRREGEXP:
2353 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2354 default:
2355 UNREACHABLE();
2356 return -1;
2357 }
2358}
2359
2360
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002361JSRegExp::Flags JSRegExp::GetFlags() {
2362 ASSERT(this->data()->IsFixedArray());
2363 Object* data = this->data();
2364 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2365 return Flags(smi->value());
2366}
2367
2368
2369String* JSRegExp::Pattern() {
2370 ASSERT(this->data()->IsFixedArray());
2371 Object* data = this->data();
2372 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2373 return pattern;
2374}
2375
2376
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002377Object* JSRegExp::DataAt(int index) {
2378 ASSERT(TypeTag() != NOT_COMPILED);
2379 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002380}
2381
2382
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002383void JSRegExp::SetDataAt(int index, Object* value) {
2384 ASSERT(TypeTag() != NOT_COMPILED);
2385 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2386 FixedArray::cast(data())->set(index, value);
2387}
2388
2389
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002390bool JSObject::HasFastElements() {
2391 return !elements()->IsDictionary();
2392}
2393
2394
2395bool JSObject::HasNamedInterceptor() {
2396 return map()->has_named_interceptor();
2397}
2398
2399
2400bool JSObject::HasIndexedInterceptor() {
2401 return map()->has_indexed_interceptor();
2402}
2403
2404
2405Dictionary* JSObject::property_dictionary() {
2406 ASSERT(!HasFastProperties());
2407 return Dictionary::cast(properties());
2408}
2409
2410
2411Dictionary* JSObject::element_dictionary() {
2412 ASSERT(!HasFastElements());
2413 return Dictionary::cast(elements());
2414}
2415
2416
2417bool String::HasHashCode() {
2418 return (length_field() & kHashComputedMask) != 0;
2419}
2420
2421
2422uint32_t String::Hash() {
2423 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002424 uint32_t field = length_field();
2425 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002426 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002427 return ComputeAndSetHash();
2428}
2429
2430
ager@chromium.org7c537e22008-10-16 08:43:32 +00002431StringHasher::StringHasher(int length)
2432 : length_(length),
2433 raw_running_hash_(0),
2434 array_index_(0),
2435 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2436 is_first_char_(true),
2437 is_valid_(true) { }
2438
2439
2440bool StringHasher::has_trivial_hash() {
2441 return length_ > String::kMaxMediumStringSize;
2442}
2443
2444
2445void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002446 // Use the Jenkins one-at-a-time hash function to update the hash
2447 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002448 raw_running_hash_ += c;
2449 raw_running_hash_ += (raw_running_hash_ << 10);
2450 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002451 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002452 if (is_array_index_) {
2453 if (c < '0' || c > '9') {
2454 is_array_index_ = false;
2455 } else {
2456 int d = c - '0';
2457 if (is_first_char_) {
2458 is_first_char_ = false;
2459 if (c == '0' && length_ > 1) {
2460 is_array_index_ = false;
2461 return;
2462 }
2463 }
2464 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2465 is_array_index_ = false;
2466 } else {
2467 array_index_ = array_index_ * 10 + d;
2468 }
2469 }
2470 }
2471}
2472
2473
2474void StringHasher::AddCharacterNoIndex(uc32 c) {
2475 ASSERT(!is_array_index());
2476 raw_running_hash_ += c;
2477 raw_running_hash_ += (raw_running_hash_ << 10);
2478 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2479}
2480
2481
2482uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002483 // Get the calculated raw hash value and do some more bit ops to distribute
2484 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002485 uint32_t result = raw_running_hash_;
2486 result += (result << 3);
2487 result ^= (result >> 11);
2488 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002489 if (result == 0) {
2490 result = 27;
2491 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002492 return result;
2493}
2494
2495
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002496bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002497 uint32_t field = length_field();
2498 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002499 return SlowAsArrayIndex(index);
2500}
2501
2502
2503Object* JSObject::GetPrototype() {
2504 return JSObject::cast(this)->map()->prototype();
2505}
2506
2507
2508PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2509 return GetPropertyAttributeWithReceiver(this, key);
2510}
2511
2512
2513bool JSObject::HasElement(uint32_t index) {
2514 return HasElementWithReceiver(this, index);
2515}
2516
2517
2518bool AccessorInfo::all_can_read() {
2519 return BooleanBit::get(flag(), kAllCanReadBit);
2520}
2521
2522
2523void AccessorInfo::set_all_can_read(bool value) {
2524 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2525}
2526
2527
2528bool AccessorInfo::all_can_write() {
2529 return BooleanBit::get(flag(), kAllCanWriteBit);
2530}
2531
2532
2533void AccessorInfo::set_all_can_write(bool value) {
2534 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2535}
2536
2537
ager@chromium.org870a0b62008-11-04 11:43:05 +00002538bool AccessorInfo::prohibits_overwriting() {
2539 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2540}
2541
2542
2543void AccessorInfo::set_prohibits_overwriting(bool value) {
2544 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2545}
2546
2547
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002548PropertyAttributes AccessorInfo::property_attributes() {
2549 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2550}
2551
2552
2553void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2554 ASSERT(AttributesField::is_valid(attributes));
2555 int rest_value = flag()->value() & ~AttributesField::mask();
2556 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2557}
2558
2559void Dictionary::SetEntry(int entry,
2560 Object* key,
2561 Object* value,
2562 PropertyDetails details) {
2563 ASSERT(!key->IsString() || details.index() > 0);
2564 int index = EntryToIndex(entry);
2565 WriteBarrierMode mode = GetWriteBarrierMode();
2566 set(index, key, mode);
2567 set(index+1, value, mode);
2568 fast_set(this, index+2, details.AsSmi());
2569}
2570
2571
2572void Map::ClearCodeCache() {
2573 // No write barrier is needed since empty_fixed_array is not in new space.
2574 // Please note this function is used during marking:
2575 // - MarkCompactCollector::MarkUnmarkedObject
2576 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2577 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2578}
2579
2580
ager@chromium.org7c537e22008-10-16 08:43:32 +00002581void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002582 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002583 set_elements(storage);
2584}
2585
2586
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002587Object* FixedArray::Copy() {
2588 if (length() == 0) return this;
2589 return Heap::CopyFixedArray(this);
2590}
2591
2592
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002593#undef CAST_ACCESSOR
2594#undef INT_ACCESSORS
2595#undef SMI_ACCESSORS
2596#undef ACCESSORS
2597#undef FIELD_ADDR
2598#undef READ_FIELD
2599#undef WRITE_FIELD
2600#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002601#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002602#undef READ_MEMADDR_FIELD
2603#undef WRITE_MEMADDR_FIELD
2604#undef READ_DOUBLE_FIELD
2605#undef WRITE_DOUBLE_FIELD
2606#undef READ_INT_FIELD
2607#undef WRITE_INT_FIELD
2608#undef READ_SHORT_FIELD
2609#undef WRITE_SHORT_FIELD
2610#undef READ_BYTE_FIELD
2611#undef WRITE_BYTE_FIELD
2612
2613
2614} } // namespace v8::internal
2615
2616#endif // V8_OBJECTS_INL_H_