blob: 653ee0dcc7913e9f2c5a085ecea74006e75141b3 [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() &&
147 StringShape(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() &&
154 StringShape(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() &&
167 StringShape(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() &&
174 StringShape(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
214bool StringShape::IsAsciiRepresentation() {
215 return (type_ & kStringEncodingMask) == kAsciiStringTag;
216}
217
218
219bool StringShape::IsTwoByteRepresentation() {
220 return (type_ & kStringEncodingMask) == kTwoByteStringTag;
221}
222
223
224bool StringShape::IsCons() {
225 return (type_ & kStringRepresentationMask) == kConsStringTag;
226}
227
228
229bool StringShape::IsSliced() {
230 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
231}
232
233
234bool StringShape::IsExternal() {
235 return (type_ & kStringRepresentationMask) == kExternalStringTag;
236}
237
238
239bool StringShape::IsSequential() {
240 return (type_ & kStringRepresentationMask) == kSeqStringTag;
241}
242
243
244StringRepresentationTag StringShape::representation_tag() {
245 uint32_t tag = (type_ & kStringRepresentationMask);
246 return static_cast<StringRepresentationTag>(tag);
247}
248
249
250uint32_t StringShape::full_representation_tag() {
251 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
252}
253
254
255uint32_t StringShape::size_tag() {
256 return (type_ & kStringSizeMask);
257}
258
259
260bool StringShape::IsSequentialAscii() {
261 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
262}
263
264
265bool StringShape::IsSequentialTwoByte() {
266 return (type_ & (kStringRepresentationMask | kStringEncodingMask)) ==
267 (kSeqStringTag | kTwoByteStringTag);
268}
269
270
271bool StringShape::IsExternalAscii() {
272 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
273}
274
275
276bool StringShape::IsExternalTwoByte() {
277 return (type_ & (kStringRepresentationMask | kStringEncodingMask)) ==
278 (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279}
280
281
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000282uc32 FlatStringReader::Get(int index) {
283 ASSERT(0 <= index && index <= length_);
284 if (is_ascii_) {
285 return static_cast<const byte*>(start_)[index];
286 } else {
287 return static_cast<const uc16*>(start_)[index];
288 }
289}
290
291
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292bool Object::IsNumber() {
293 return IsSmi() || IsHeapNumber();
294}
295
296
297bool Object::IsByteArray() {
298 return Object::IsHeapObject()
299 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
300}
301
302
303bool Object::IsFailure() {
304 return HAS_FAILURE_TAG(this);
305}
306
307
308bool Object::IsRetryAfterGC() {
309 return HAS_FAILURE_TAG(this)
310 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
311}
312
313
ager@chromium.org7c537e22008-10-16 08:43:32 +0000314bool Object::IsOutOfMemoryFailure() {
315 return HAS_FAILURE_TAG(this)
316 && Failure::cast(this)->IsOutOfMemoryException();
317}
318
319
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320bool Object::IsException() {
321 return this == Failure::Exception();
322}
323
324
325bool Object::IsJSObject() {
326 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000327 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328}
329
330
ager@chromium.org32912102009-01-16 10:38:43 +0000331bool Object::IsJSContextExtensionObject() {
332 return IsHeapObject()
333 && (HeapObject::cast(this)->map()->instance_type() ==
334 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
335}
336
337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338bool Object::IsMap() {
339 return Object::IsHeapObject()
340 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
341}
342
343
344bool Object::IsFixedArray() {
345 return Object::IsHeapObject()
346 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
347}
348
349
350bool Object::IsDescriptorArray() {
351 return IsFixedArray();
352}
353
354
355bool Object::IsContext() {
356 return Object::IsHeapObject()
357 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000358 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000359 HeapObject::cast(this)->map() == Heap::global_context_map());
360}
361
362
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000363bool Object::IsCatchContext() {
364 return Object::IsHeapObject()
365 && HeapObject::cast(this)->map() == Heap::catch_context_map();
366}
367
368
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369bool Object::IsGlobalContext() {
370 return Object::IsHeapObject()
371 && HeapObject::cast(this)->map() == Heap::global_context_map();
372}
373
374
375bool Object::IsJSFunction() {
376 return Object::IsHeapObject()
377 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
378}
379
380
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000381template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000382 return obj->IsJSFunction();
383}
384
385
386bool Object::IsCode() {
387 return Object::IsHeapObject()
388 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
389}
390
391
392bool Object::IsOddball() {
393 return Object::IsHeapObject()
394 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
395}
396
397
398bool Object::IsSharedFunctionInfo() {
399 return Object::IsHeapObject() &&
400 (HeapObject::cast(this)->map()->instance_type() ==
401 SHARED_FUNCTION_INFO_TYPE);
402}
403
404
405bool Object::IsJSValue() {
406 return Object::IsHeapObject()
407 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
408}
409
410
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000411bool Object::IsStringWrapper() {
412 return IsJSValue() && JSValue::cast(this)->value()->IsString();
413}
414
415
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416bool Object::IsProxy() {
417 return Object::IsHeapObject()
418 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
419}
420
421
422bool Object::IsBoolean() {
423 return IsTrue() || IsFalse();
424}
425
426
427bool Object::IsJSArray() {
428 return Object::IsHeapObject()
429 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
430}
431
432
ager@chromium.org236ad962008-09-25 09:45:57 +0000433bool Object::IsJSRegExp() {
434 return Object::IsHeapObject()
435 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
436}
437
438
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000439template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000440 return obj->IsJSArray();
441}
442
443
444bool Object::IsHashTable() {
445 return Object::IsHeapObject()
446 && HeapObject::cast(this)->map() == Heap::hash_table_map();
447}
448
449
450bool Object::IsDictionary() {
451 return IsHashTable() && this != Heap::symbol_table();
452}
453
454
455bool Object::IsSymbolTable() {
456 return IsHashTable() && this == Heap::symbol_table();
457}
458
459
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000460bool Object::IsCompilationCacheTable() {
461 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000462}
463
464
ager@chromium.org236ad962008-09-25 09:45:57 +0000465bool Object::IsMapCache() {
466 return IsHashTable();
467}
468
469
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000470bool Object::IsLookupCache() {
471 return IsHashTable();
472}
473
474
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475bool Object::IsPrimitive() {
476 return IsOddball() || IsNumber() || IsString();
477}
478
479
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000480bool Object::IsJSGlobalProxy() {
481 bool result = IsHeapObject() &&
482 (HeapObject::cast(this)->map()->instance_type() ==
483 JS_GLOBAL_PROXY_TYPE);
484 ASSERT(!result || IsAccessCheckNeeded());
485 return result;
486}
487
488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000490 if (!IsHeapObject()) return false;
491
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000492 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000493 return type == JS_GLOBAL_OBJECT_TYPE ||
494 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000495}
496
497
498bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499 return IsHeapObject() &&
500 (HeapObject::cast(this)->map()->instance_type() ==
501 JS_GLOBAL_OBJECT_TYPE);
502}
503
504
505bool Object::IsJSBuiltinsObject() {
506 return IsHeapObject() &&
507 (HeapObject::cast(this)->map()->instance_type() ==
508 JS_BUILTINS_OBJECT_TYPE);
509}
510
511
512bool Object::IsUndetectableObject() {
513 return IsHeapObject()
514 && HeapObject::cast(this)->map()->is_undetectable();
515}
516
517
518bool Object::IsAccessCheckNeeded() {
519 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000520 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521}
522
523
524bool Object::IsStruct() {
525 if (!IsHeapObject()) return false;
526 switch (HeapObject::cast(this)->map()->instance_type()) {
527#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
528 STRUCT_LIST(MAKE_STRUCT_CASE)
529#undef MAKE_STRUCT_CASE
530 default: return false;
531 }
532}
533
534
535#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
536 bool Object::Is##Name() { \
537 return Object::IsHeapObject() \
538 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
539 }
540 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
541#undef MAKE_STRUCT_PREDICATE
542
543
544bool Object::IsUndefined() {
545 return this == Heap::undefined_value();
546}
547
548
549bool Object::IsTheHole() {
550 return this == Heap::the_hole_value();
551}
552
553
554bool Object::IsNull() {
555 return this == Heap::null_value();
556}
557
558
559bool Object::IsTrue() {
560 return this == Heap::true_value();
561}
562
563
564bool Object::IsFalse() {
565 return this == Heap::false_value();
566}
567
568
569double Object::Number() {
570 ASSERT(IsNumber());
571 return IsSmi()
572 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
573 : reinterpret_cast<HeapNumber*>(this)->value();
574}
575
576
577
578Object* Object::ToSmi() {
579 if (IsSmi()) return this;
580 if (IsHeapNumber()) {
581 double value = HeapNumber::cast(this)->value();
582 int int_value = FastD2I(value);
583 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
584 return Smi::FromInt(int_value);
585 }
586 }
587 return Failure::Exception();
588}
589
590
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000591bool Object::HasSpecificClassOf(String* name) {
592 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
593}
594
595
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596Object* Object::GetElement(uint32_t index) {
597 return GetElementWithReceiver(this, index);
598}
599
600
601Object* Object::GetProperty(String* key) {
602 PropertyAttributes attributes;
603 return GetPropertyWithReceiver(this, key, &attributes);
604}
605
606
607Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
608 return GetPropertyWithReceiver(this, key, attributes);
609}
610
611
612#define FIELD_ADDR(p, offset) \
613 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
614
615#define READ_FIELD(p, offset) \
616 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
617
618#define WRITE_FIELD(p, offset, value) \
619 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
620
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000621
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000622#define WRITE_BARRIER(object, offset) \
623 Heap::RecordWrite(object->address(), offset);
624
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000625// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000626// write due to the assert validating the written value.
627#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
628 if (mode == UPDATE_WRITE_BARRIER) { \
629 Heap::RecordWrite(object->address(), offset); \
630 } else { \
631 ASSERT(mode == SKIP_WRITE_BARRIER); \
632 ASSERT(Heap::InNewSpace(object) || \
633 !Heap::InNewSpace(READ_FIELD(object, offset))); \
634 }
635
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636#define READ_DOUBLE_FIELD(p, offset) \
637 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
638
639#define WRITE_DOUBLE_FIELD(p, offset, value) \
640 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
641
642#define READ_INT_FIELD(p, offset) \
643 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
644
645#define WRITE_INT_FIELD(p, offset, value) \
646 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
647
ager@chromium.org7c537e22008-10-16 08:43:32 +0000648#define READ_UINT32_FIELD(p, offset) \
649 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
650
651#define WRITE_UINT32_FIELD(p, offset, value) \
652 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
653
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654#define READ_SHORT_FIELD(p, offset) \
655 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
656
657#define WRITE_SHORT_FIELD(p, offset, value) \
658 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
659
660#define READ_BYTE_FIELD(p, offset) \
661 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
662
663#define WRITE_BYTE_FIELD(p, offset, value) \
664 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
665
666
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000667Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
668 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000669}
670
671
672int Smi::value() {
673 return reinterpret_cast<int>(this) >> kSmiTagSize;
674}
675
676
677Smi* Smi::FromInt(int value) {
678 ASSERT(Smi::IsValid(value));
679 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
680}
681
682
683Failure::Type Failure::type() const {
684 return static_cast<Type>(value() & kFailureTypeTagMask);
685}
686
687
688bool Failure::IsInternalError() const {
689 return type() == INTERNAL_ERROR;
690}
691
692
693bool Failure::IsOutOfMemoryException() const {
694 return type() == OUT_OF_MEMORY_EXCEPTION;
695}
696
697
698int Failure::requested() const {
699 const int kShiftBits =
700 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
701 STATIC_ASSERT(kShiftBits >= 0);
702 ASSERT(type() == RETRY_AFTER_GC);
703 return value() >> kShiftBits;
704}
705
706
707AllocationSpace Failure::allocation_space() const {
708 ASSERT_EQ(RETRY_AFTER_GC, type());
709 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
710 & kSpaceTagMask);
711}
712
713
714Failure* Failure::InternalError() {
715 return Construct(INTERNAL_ERROR);
716}
717
718
719Failure* Failure::Exception() {
720 return Construct(EXCEPTION);
721}
722
723Failure* Failure::OutOfMemoryException() {
724 return Construct(OUT_OF_MEMORY_EXCEPTION);
725}
726
727
728int Failure::value() const {
729 return reinterpret_cast<int>(this) >> kFailureTagSize;
730}
731
732
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000733Failure* Failure::RetryAfterGC(int requested_bytes) {
734 int requested = requested_bytes >> kObjectAlignmentBits;
735 int value = (requested << kSpaceTagSize) | NEW_SPACE;
736 ASSERT(value >> kSpaceTagSize == requested);
737 ASSERT(Smi::IsValid(value));
738 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
739 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
740 return Construct(RETRY_AFTER_GC, value);
741}
742
743
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000744Failure* Failure::Construct(Type type, int value) {
745 int info = (value << kFailureTypeTagSize) | type;
746 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
747 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
748}
749
750
751bool Smi::IsValid(int value) {
752#ifdef DEBUG
753 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
754#endif
755 // To be representable as an tagged small integer, the two
756 // most-significant bits of 'value' must be either 00 or 11 due to
757 // sign-extension. To check this we add 01 to the two
758 // most-significant bits, and check if the most-significant bit is 0
759 //
760 // CAUTION: The original code below:
761 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
762 // may lead to incorrect results according to the C language spec, and
763 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
764 // compiler may produce undefined results in case of signed integer
765 // overflow. The computation must be done w/ unsigned ints.
766 bool result =
767 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
768 ASSERT(result == in_range);
769 return result;
770}
771
772
kasper.lund7276f142008-07-30 08:49:36 +0000773MapWord MapWord::FromMap(Map* map) {
774 return MapWord(reinterpret_cast<uintptr_t>(map));
775}
776
777
778Map* MapWord::ToMap() {
779 return reinterpret_cast<Map*>(value_);
780}
781
782
783bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000784 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000785}
786
787
788MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000789 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
790 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000791}
792
793
794HeapObject* MapWord::ToForwardingAddress() {
795 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000796 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000797}
798
799
800bool MapWord::IsMarked() {
801 return (value_ & kMarkingMask) == 0;
802}
803
804
805void MapWord::SetMark() {
806 value_ &= ~kMarkingMask;
807}
808
809
810void MapWord::ClearMark() {
811 value_ |= kMarkingMask;
812}
813
814
815bool MapWord::IsOverflowed() {
816 return (value_ & kOverflowMask) != 0;
817}
818
819
820void MapWord::SetOverflow() {
821 value_ |= kOverflowMask;
822}
823
824
825void MapWord::ClearOverflow() {
826 value_ &= ~kOverflowMask;
827}
828
829
830MapWord MapWord::EncodeAddress(Address map_address, int offset) {
831 // Offset is the distance in live bytes from the first live object in the
832 // same page. The offset between two objects in the same page should not
833 // exceed the object area size of a page.
834 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
835
836 int compact_offset = offset >> kObjectAlignmentBits;
837 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
838
839 Page* map_page = Page::FromAddress(map_address);
840 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
841
842 int map_page_offset =
843 map_page->Offset(map_address) >> kObjectAlignmentBits;
844
845 uintptr_t encoding =
846 (compact_offset << kForwardingOffsetShift) |
847 (map_page_offset << kMapPageOffsetShift) |
848 (map_page->mc_page_index << kMapPageIndexShift);
849 return MapWord(encoding);
850}
851
852
853Address MapWord::DecodeMapAddress(MapSpace* map_space) {
854 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
855 ASSERT_MAP_PAGE_INDEX(map_page_index);
856
857 int map_page_offset =
858 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
859 << kObjectAlignmentBits;
860
861 return (map_space->PageAddress(map_page_index) + map_page_offset);
862}
863
864
865int MapWord::DecodeOffset() {
866 // The offset field is represented in the kForwardingOffsetBits
867 // most-significant bits.
868 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
869 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
870 return offset;
871}
872
873
874MapWord MapWord::FromEncodedAddress(Address address) {
875 return MapWord(reinterpret_cast<uintptr_t>(address));
876}
877
878
879Address MapWord::ToEncodedAddress() {
880 return reinterpret_cast<Address>(value_);
881}
882
883
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000884#ifdef DEBUG
885void HeapObject::VerifyObjectField(int offset) {
886 VerifyPointer(READ_FIELD(this, offset));
887}
888#endif
889
890
891Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000892 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893}
894
895
896void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000897 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898}
899
900
kasper.lund7276f142008-07-30 08:49:36 +0000901MapWord HeapObject::map_word() {
902 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
903}
904
905
906void HeapObject::set_map_word(MapWord map_word) {
907 // WRITE_FIELD does not update the remembered set, but there is no need
908 // here.
909 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
910}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911
912
913HeapObject* HeapObject::FromAddress(Address address) {
914 ASSERT_TAG_ALIGNED(address);
915 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
916}
917
918
919Address HeapObject::address() {
920 return reinterpret_cast<Address>(this) - kHeapObjectTag;
921}
922
923
924int HeapObject::Size() {
925 return SizeFromMap(map());
926}
927
928
929void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
930 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
931 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
932}
933
934
935void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
936 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
937}
938
939
kasper.lund7276f142008-07-30 08:49:36 +0000940bool HeapObject::IsMarked() {
941 return map_word().IsMarked();
942}
943
944
945void HeapObject::SetMark() {
946 ASSERT(!IsMarked());
947 MapWord first_word = map_word();
948 first_word.SetMark();
949 set_map_word(first_word);
950}
951
952
953void HeapObject::ClearMark() {
954 ASSERT(IsMarked());
955 MapWord first_word = map_word();
956 first_word.ClearMark();
957 set_map_word(first_word);
958}
959
960
961bool HeapObject::IsOverflowed() {
962 return map_word().IsOverflowed();
963}
964
965
966void HeapObject::SetOverflow() {
967 MapWord first_word = map_word();
968 first_word.SetOverflow();
969 set_map_word(first_word);
970}
971
972
973void HeapObject::ClearOverflow() {
974 ASSERT(IsOverflowed());
975 MapWord first_word = map_word();
976 first_word.ClearOverflow();
977 set_map_word(first_word);
978}
979
980
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000981double HeapNumber::value() {
982 return READ_DOUBLE_FIELD(this, kValueOffset);
983}
984
985
986void HeapNumber::set_value(double value) {
987 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
988}
989
990
991ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000992ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000993
994
995void JSObject::initialize_properties() {
996 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
997 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
998}
999
1000
1001void JSObject::initialize_elements() {
1002 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1003 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1004}
1005
1006
1007ACCESSORS(Oddball, to_string, String, kToStringOffset)
1008ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1009
1010
1011int JSObject::GetHeaderSize() {
1012 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001013 case JS_GLOBAL_PROXY_TYPE:
1014 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001015 case JS_GLOBAL_OBJECT_TYPE:
1016 return JSGlobalObject::kSize;
1017 case JS_BUILTINS_OBJECT_TYPE:
1018 return JSBuiltinsObject::kSize;
1019 case JS_FUNCTION_TYPE:
1020 return JSFunction::kSize;
1021 case JS_VALUE_TYPE:
1022 return JSValue::kSize;
1023 case JS_ARRAY_TYPE:
1024 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001025 case JS_REGEXP_TYPE:
1026 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001027 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001028 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001029 return JSObject::kHeaderSize;
1030 default:
1031 UNREACHABLE();
1032 return 0;
1033 }
1034}
1035
1036
1037int JSObject::GetInternalFieldCount() {
1038 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001039 // Make sure to adjust for the number of in-object properties. These
1040 // properties do contribute to the size, but are not internal fields.
1041 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1042 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001043}
1044
1045
1046Object* JSObject::GetInternalField(int index) {
1047 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001048 // Internal objects do follow immediately after the header, whereas in-object
1049 // properties are at the end of the object. Therefore there is no need
1050 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001051 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1052}
1053
1054
1055void JSObject::SetInternalField(int index, Object* value) {
1056 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001057 // Internal objects do follow immediately after the header, whereas in-object
1058 // properties are at the end of the object. Therefore there is no need
1059 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001060 int offset = GetHeaderSize() + (kPointerSize * index);
1061 WRITE_FIELD(this, offset, value);
1062 WRITE_BARRIER(this, offset);
1063}
1064
1065
ager@chromium.org7c537e22008-10-16 08:43:32 +00001066// Access fast-case object properties at index. The use of these routines
1067// is needed to correctly distinguish between properties stored in-object and
1068// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001069Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001070 // Adjust for the number of properties stored in the object.
1071 index -= map()->inobject_properties();
1072 if (index < 0) {
1073 int offset = map()->instance_size() + (index * kPointerSize);
1074 return READ_FIELD(this, offset);
1075 } else {
1076 ASSERT(index < properties()->length());
1077 return properties()->get(index);
1078 }
1079}
1080
1081
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001082Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001083 // Adjust for the number of properties stored in the object.
1084 index -= map()->inobject_properties();
1085 if (index < 0) {
1086 int offset = map()->instance_size() + (index * kPointerSize);
1087 WRITE_FIELD(this, offset, value);
1088 WRITE_BARRIER(this, offset);
1089 } else {
1090 ASSERT(index < properties()->length());
1091 properties()->set(index, value);
1092 }
1093 return value;
1094}
1095
1096
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001097Object* JSObject::InObjectPropertyAt(int index) {
1098 // Adjust for the number of properties stored in the object.
1099 index -= map()->inobject_properties();
1100 ASSERT(index < 0);
1101 int offset = map()->instance_size() + (index * kPointerSize);
1102 return READ_FIELD(this, offset);
1103}
1104
1105
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001106Object* JSObject::InObjectPropertyAtPut(int index,
1107 Object* value,
1108 WriteBarrierMode mode) {
1109 // Adjust for the number of properties stored in the object.
1110 index -= map()->inobject_properties();
1111 ASSERT(index < 0);
1112 int offset = map()->instance_size() + (index * kPointerSize);
1113 WRITE_FIELD(this, offset, value);
1114 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1115 return value;
1116}
1117
1118
1119
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001120void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001121 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001122 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001123 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001124 }
1125}
1126
1127
1128void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001129 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001130 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001131 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001132 }
1133}
1134
1135
1136bool JSObject::HasFastProperties() {
1137 return !properties()->IsDictionary();
1138}
1139
1140
1141bool Array::IndexFromObject(Object* object, uint32_t* index) {
1142 if (object->IsSmi()) {
1143 int value = Smi::cast(object)->value();
1144 if (value < 0) return false;
1145 *index = value;
1146 return true;
1147 }
1148 if (object->IsHeapNumber()) {
1149 double value = HeapNumber::cast(object)->value();
1150 uint32_t uint_value = static_cast<uint32_t>(value);
1151 if (value == static_cast<double>(uint_value)) {
1152 *index = uint_value;
1153 return true;
1154 }
1155 }
1156 return false;
1157}
1158
1159
1160bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1161 if (!this->IsJSValue()) return false;
1162
1163 JSValue* js_value = JSValue::cast(this);
1164 if (!js_value->value()->IsString()) return false;
1165
1166 String* str = String::cast(js_value->value());
1167 if (index >= (uint32_t)str->length()) return false;
1168
1169 return true;
1170}
1171
1172
1173Object* FixedArray::get(int index) {
1174 ASSERT(index >= 0 && index < this->length());
1175 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1176}
1177
1178
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001179void FixedArray::set(int index, Smi* value) {
1180 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1181 int offset = kHeaderSize + index * kPointerSize;
1182 WRITE_FIELD(this, offset, value);
1183}
1184
1185
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186void FixedArray::set(int index, Object* value) {
1187 ASSERT(index >= 0 && index < this->length());
1188 int offset = kHeaderSize + index * kPointerSize;
1189 WRITE_FIELD(this, offset, value);
1190 WRITE_BARRIER(this, offset);
1191}
1192
1193
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001194WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001195 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1196 return UPDATE_WRITE_BARRIER;
1197}
1198
1199
1200void FixedArray::set(int index,
1201 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001202 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001203 ASSERT(index >= 0 && index < this->length());
1204 int offset = kHeaderSize + index * kPointerSize;
1205 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001206 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001207}
1208
1209
1210void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1211 ASSERT(index >= 0 && index < array->length());
1212 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1213}
1214
1215
1216void FixedArray::set_undefined(int index) {
1217 ASSERT(index >= 0 && index < this->length());
1218 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1219 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1220 Heap::undefined_value());
1221}
1222
1223
ager@chromium.org236ad962008-09-25 09:45:57 +00001224void FixedArray::set_null(int index) {
1225 ASSERT(index >= 0 && index < this->length());
1226 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1227 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1228}
1229
1230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001231void FixedArray::set_the_hole(int index) {
1232 ASSERT(index >= 0 && index < this->length());
1233 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1234 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1235}
1236
1237
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001238bool DescriptorArray::IsEmpty() {
1239 ASSERT(this == Heap::empty_descriptor_array() ||
1240 this->length() > 2);
1241 return this == Heap::empty_descriptor_array();
1242}
1243
1244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1246 Object* tmp = array->get(first);
1247 fast_set(array, first, array->get(second));
1248 fast_set(array, second, tmp);
1249}
1250
1251
1252int DescriptorArray::Search(String* name) {
1253 SLOW_ASSERT(IsSortedNoDuplicates());
1254
1255 // Check for empty descriptor array.
1256 int nof = number_of_descriptors();
1257 if (nof == 0) return kNotFound;
1258
1259 // Fast case: do linear search for small arrays.
1260 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001261 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001262 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001263 }
1264
1265 // Slow case: perform binary search.
1266 return BinarySearch(name, 0, nof - 1);
1267}
1268
1269
1270
1271String* DescriptorArray::GetKey(int descriptor_number) {
1272 ASSERT(descriptor_number < number_of_descriptors());
1273 return String::cast(get(ToKeyIndex(descriptor_number)));
1274}
1275
1276
1277Object* DescriptorArray::GetValue(int descriptor_number) {
1278 ASSERT(descriptor_number < number_of_descriptors());
1279 return GetContentArray()->get(ToValueIndex(descriptor_number));
1280}
1281
1282
1283Smi* DescriptorArray::GetDetails(int descriptor_number) {
1284 ASSERT(descriptor_number < number_of_descriptors());
1285 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1286}
1287
1288
1289void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1290 desc->Init(GetKey(descriptor_number),
1291 GetValue(descriptor_number),
1292 GetDetails(descriptor_number));
1293}
1294
1295
1296void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1297 // Range check.
1298 ASSERT(descriptor_number < number_of_descriptors());
1299
1300 // Make sure non of the elements in desc are in new space.
1301 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1302 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1303
1304 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1305 FixedArray* content_array = GetContentArray();
1306 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1307 fast_set(content_array, ToDetailsIndex(descriptor_number),
1308 desc->GetDetails().AsSmi());
1309}
1310
1311
1312void DescriptorArray::Swap(int first, int second) {
1313 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1314 FixedArray* content_array = GetContentArray();
1315 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1316 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1317}
1318
1319
1320bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001321 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001322 if (!max_index_object->IsSmi()) return false;
1323 return 0 !=
1324 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1325}
1326
1327
1328uint32_t Dictionary::max_number_key() {
1329 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001330 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331 if (!max_index_object->IsSmi()) return 0;
1332 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1333 return value >> kRequiresSlowElementsTagSize;
1334}
1335
1336
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001337void Dictionary::set_requires_slow_elements() {
1338 set(kMaxNumberKeyIndex,
1339 Smi::FromInt(kRequiresSlowElementsMask),
1340 SKIP_WRITE_BARRIER);
1341}
1342
1343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001344// ------------------------------------
1345// Cast operations
1346
1347
1348CAST_ACCESSOR(FixedArray)
1349CAST_ACCESSOR(DescriptorArray)
1350CAST_ACCESSOR(Dictionary)
1351CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001352CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001353CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001354CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001355CAST_ACCESSOR(String)
1356CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001357CAST_ACCESSOR(SeqAsciiString)
1358CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359CAST_ACCESSOR(ConsString)
1360CAST_ACCESSOR(SlicedString)
1361CAST_ACCESSOR(ExternalString)
1362CAST_ACCESSOR(ExternalAsciiString)
1363CAST_ACCESSOR(ExternalTwoByteString)
1364CAST_ACCESSOR(JSObject)
1365CAST_ACCESSOR(Smi)
1366CAST_ACCESSOR(Failure)
1367CAST_ACCESSOR(HeapObject)
1368CAST_ACCESSOR(HeapNumber)
1369CAST_ACCESSOR(Oddball)
1370CAST_ACCESSOR(SharedFunctionInfo)
1371CAST_ACCESSOR(Map)
1372CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001373CAST_ACCESSOR(GlobalObject)
1374CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001375CAST_ACCESSOR(JSGlobalObject)
1376CAST_ACCESSOR(JSBuiltinsObject)
1377CAST_ACCESSOR(Code)
1378CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001379CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380CAST_ACCESSOR(Proxy)
1381CAST_ACCESSOR(ByteArray)
1382CAST_ACCESSOR(Struct)
1383
1384
1385#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1386 STRUCT_LIST(MAKE_STRUCT_CAST)
1387#undef MAKE_STRUCT_CAST
1388
1389template <int prefix_size, int elem_size>
1390HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1391 Object* obj) {
1392 ASSERT(obj->IsHashTable());
1393 return reinterpret_cast<HashTable*>(obj);
1394}
1395
1396
1397INT_ACCESSORS(Array, length, kLengthOffset)
1398
1399
1400bool String::Equals(String* other) {
1401 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001402 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1403 return false;
1404 }
1405 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001406}
1407
1408
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001409int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001410 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1411
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001412 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1413 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1414 ASSERT(kLongStringTag == 0);
1415
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001416 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417}
1418
1419
1420void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001421 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1422 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1423 ASSERT(kLongStringTag == 0);
1424
1425 WRITE_INT_FIELD(this,
1426 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001427 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001428}
1429
1430
ager@chromium.org7c537e22008-10-16 08:43:32 +00001431uint32_t String::length_field() {
1432 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433}
1434
1435
ager@chromium.org7c537e22008-10-16 08:43:32 +00001436void String::set_length_field(uint32_t value) {
1437 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001438}
1439
1440
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001441Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001442 // We don't need to flatten strings that are already flat. Since this code
1443 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001444 if (!IsFlat()) {
1445 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001446 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001447 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001448}
1449
1450
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001451uint16_t String::Get(int index) {
1452 ASSERT(index >= 0 && index < length());
1453 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001454 case kSeqStringTag | kAsciiStringTag:
1455 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1456 case kSeqStringTag | kTwoByteStringTag:
1457 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1458 case kConsStringTag | kAsciiStringTag:
1459 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001460 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001461 case kSlicedStringTag | kAsciiStringTag:
1462 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001463 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001464 case kExternalStringTag | kAsciiStringTag:
1465 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1466 case kExternalStringTag | kTwoByteStringTag:
1467 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001468 default:
1469 break;
1470 }
1471
1472 UNREACHABLE();
1473 return 0;
1474}
1475
1476
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001477void String::Set(int index, uint16_t value) {
1478 ASSERT(index >= 0 && index < length());
1479 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001480
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001481 return StringShape(this).IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001482 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1483 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001484}
1485
1486
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001487bool String::IsFlat() {
1488 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001489 case kConsStringTag: {
1490 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001491 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001492 return second->length() == 0;
1493 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001494 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001495 StringRepresentationTag tag =
1496 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001497 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001499 default:
1500 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001501 }
1502}
1503
1504
ager@chromium.org7c537e22008-10-16 08:43:32 +00001505uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001506 ASSERT(index >= 0 && index < length());
1507 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1508}
1509
1510
ager@chromium.org7c537e22008-10-16 08:43:32 +00001511void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001512 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1513 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1514 static_cast<byte>(value));
1515}
1516
1517
ager@chromium.org7c537e22008-10-16 08:43:32 +00001518Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001519 return FIELD_ADDR(this, kHeaderSize);
1520}
1521
1522
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001523char* SeqAsciiString::GetChars() {
1524 return reinterpret_cast<char*>(GetCharsAddress());
1525}
1526
1527
ager@chromium.org7c537e22008-10-16 08:43:32 +00001528Address SeqTwoByteString::GetCharsAddress() {
1529 return FIELD_ADDR(this, kHeaderSize);
1530}
1531
1532
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001533uc16* SeqTwoByteString::GetChars() {
1534 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1535}
1536
1537
ager@chromium.org7c537e22008-10-16 08:43:32 +00001538uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001539 ASSERT(index >= 0 && index < length());
1540 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1541}
1542
1543
ager@chromium.org7c537e22008-10-16 08:43:32 +00001544void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545 ASSERT(index >= 0 && index < length());
1546 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1547}
1548
1549
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001550int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1552
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001553 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1554 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1555 ASSERT(kLongStringTag == 0);
1556
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557 // Use the map (and not 'this') to compute the size tag, since
1558 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001559 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001560
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001561 return SizeFor(length);
1562}
1563
1564
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001565int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001566 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1567
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001568 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1569 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1570 ASSERT(kLongStringTag == 0);
1571
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001572 // Use the map (and not 'this') to compute the size tag, since
1573 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001574 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001575
1576 return SizeFor(length);
1577}
1578
1579
ager@chromium.org870a0b62008-11-04 11:43:05 +00001580String* ConsString::first() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001581 ASSERT(String::cast(READ_FIELD(this, kSecondOffset))->length() != 0 ||
1582 StringShape(
1583 String::cast(
1584 READ_FIELD(this, kFirstOffset))).IsAsciiRepresentation()
1585 == StringShape(this).IsAsciiRepresentation());
ager@chromium.org870a0b62008-11-04 11:43:05 +00001586 return String::cast(READ_FIELD(this, kFirstOffset));
1587}
1588
1589
1590Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001591 return READ_FIELD(this, kFirstOffset);
1592}
1593
1594
ager@chromium.org870a0b62008-11-04 11:43:05 +00001595void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001596 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001597 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001598}
1599
1600
ager@chromium.org870a0b62008-11-04 11:43:05 +00001601String* ConsString::second() {
1602 return String::cast(READ_FIELD(this, kSecondOffset));
1603}
1604
1605
1606Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001607 return READ_FIELD(this, kSecondOffset);
1608}
1609
1610
ager@chromium.org870a0b62008-11-04 11:43:05 +00001611void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001613 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001614}
1615
1616
ager@chromium.org870a0b62008-11-04 11:43:05 +00001617String* SlicedString::buffer() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001618 ASSERT(
1619 StringShape(
1620 String::cast(READ_FIELD(this, kBufferOffset))).IsAsciiRepresentation()
1621 == StringShape(this).IsAsciiRepresentation());
ager@chromium.org870a0b62008-11-04 11:43:05 +00001622 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623}
1624
1625
ager@chromium.org870a0b62008-11-04 11:43:05 +00001626void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627 WRITE_FIELD(this, kBufferOffset, buffer);
1628 WRITE_BARRIER(this, kBufferOffset);
1629}
1630
1631
1632int SlicedString::start() {
1633 return READ_INT_FIELD(this, kStartOffset);
1634}
1635
1636
1637void SlicedString::set_start(int start) {
1638 WRITE_INT_FIELD(this, kStartOffset, start);
1639}
1640
1641
1642ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1643 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1644}
1645
1646
1647void ExternalAsciiString::set_resource(
1648 ExternalAsciiString::Resource* resource) {
1649 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1650}
1651
1652
ager@chromium.org6f10e412009-02-13 10:11:16 +00001653Map* ExternalAsciiString::StringMap(int length) {
1654 Map* map;
1655 // Number of characters: determines the map.
1656 if (length <= String::kMaxShortStringSize) {
1657 map = Heap::short_external_ascii_string_map();
1658 } else if (length <= String::kMaxMediumStringSize) {
1659 map = Heap::medium_external_ascii_string_map();
1660 } else {
1661 map = Heap::long_external_ascii_string_map();
1662 }
1663 return map;
1664}
1665
1666
1667Map* ExternalAsciiString::SymbolMap(int length) {
1668 Map* map;
1669 // Number of characters: determines the map.
1670 if (length <= String::kMaxShortStringSize) {
1671 map = Heap::short_external_ascii_symbol_map();
1672 } else if (length <= String::kMaxMediumStringSize) {
1673 map = Heap::medium_external_ascii_symbol_map();
1674 } else {
1675 map = Heap::long_external_ascii_symbol_map();
1676 }
1677 return map;
1678}
1679
1680
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001681ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1682 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1683}
1684
1685
1686void ExternalTwoByteString::set_resource(
1687 ExternalTwoByteString::Resource* resource) {
1688 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1689}
1690
1691
ager@chromium.org6f10e412009-02-13 10:11:16 +00001692Map* ExternalTwoByteString::StringMap(int length) {
1693 Map* map;
1694 // Number of characters: determines the map.
1695 if (length <= String::kMaxShortStringSize) {
1696 map = Heap::short_external_string_map();
1697 } else if (length <= String::kMaxMediumStringSize) {
1698 map = Heap::medium_external_string_map();
1699 } else {
1700 map = Heap::long_external_string_map();
1701 }
1702 return map;
1703}
1704
1705
1706Map* ExternalTwoByteString::SymbolMap(int length) {
1707 Map* map;
1708 // Number of characters: determines the map.
1709 if (length <= String::kMaxShortStringSize) {
1710 map = Heap::short_external_symbol_map();
1711 } else if (length <= String::kMaxMediumStringSize) {
1712 map = Heap::medium_external_symbol_map();
1713 } else {
1714 map = Heap::long_external_symbol_map();
1715 }
1716 return map;
1717}
1718
1719
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001720byte ByteArray::get(int index) {
1721 ASSERT(index >= 0 && index < this->length());
1722 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1723}
1724
1725
1726void ByteArray::set(int index, byte value) {
1727 ASSERT(index >= 0 && index < this->length());
1728 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1729}
1730
1731
1732int ByteArray::get_int(int index) {
1733 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1734 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1735}
1736
1737
1738ByteArray* ByteArray::FromDataStartAddress(Address address) {
1739 ASSERT_TAG_ALIGNED(address);
1740 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1741}
1742
1743
1744Address ByteArray::GetDataStartAddress() {
1745 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1746}
1747
1748
1749int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001750 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1751}
1752
1753
1754int Map::inobject_properties() {
1755 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756}
1757
1758
1759int HeapObject::SizeFromMap(Map* map) {
1760 InstanceType instance_type = map->instance_type();
1761 // Only inline the two most frequent cases.
1762 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1763 if (instance_type == FIXED_ARRAY_TYPE) {
1764 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1765 }
1766 // Otherwise do the general size computation.
1767 return SlowSizeFromMap(map);
1768}
1769
1770
1771void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001772 ASSERT((value & ~(kPointerSize - 1)) == value);
1773 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001774 ASSERT(0 <= value && value < 256);
1775 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1776}
1777
1778
ager@chromium.org7c537e22008-10-16 08:43:32 +00001779void Map::set_inobject_properties(int value) {
1780 ASSERT(0 <= value && value < 256);
1781 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1782}
1783
1784
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001785InstanceType Map::instance_type() {
1786 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1787}
1788
1789
1790void Map::set_instance_type(InstanceType value) {
1791 ASSERT(0 <= value && value < 256);
1792 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1793}
1794
1795
1796int Map::unused_property_fields() {
1797 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1798}
1799
1800
1801void Map::set_unused_property_fields(int value) {
1802 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1803}
1804
1805
1806byte Map::bit_field() {
1807 return READ_BYTE_FIELD(this, kBitFieldOffset);
1808}
1809
1810
1811void Map::set_bit_field(byte value) {
1812 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1813}
1814
1815
1816void Map::set_non_instance_prototype(bool value) {
1817 if (value) {
1818 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1819 } else {
1820 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1821 }
1822}
1823
1824
1825bool Map::has_non_instance_prototype() {
1826 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1827}
1828
1829
ager@chromium.org870a0b62008-11-04 11:43:05 +00001830void Map::set_is_access_check_needed(bool access_check_needed) {
1831 if (access_check_needed) {
1832 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1833 } else {
1834 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1835 }
1836}
1837
1838
1839bool Map::is_access_check_needed() {
1840 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1841}
1842
1843
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001844Code::Flags Code::flags() {
1845 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1846}
1847
1848
1849void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001850 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001851 // Make sure that all call stubs have an arguments count.
1852 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1853 ExtractArgumentsCountFromFlags(flags) >= 0);
1854 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1855}
1856
1857
1858Code::Kind Code::kind() {
1859 return ExtractKindFromFlags(flags());
1860}
1861
1862
kasper.lund7276f142008-07-30 08:49:36 +00001863InlineCacheState Code::ic_state() {
1864 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001865 // Only allow uninitialized or debugger states for non-IC code
1866 // objects. This is used in the debugger to determine whether or not
1867 // a call to code object has been replaced with a debug break call.
1868 ASSERT(is_inline_cache_stub() ||
1869 result == UNINITIALIZED ||
1870 result == DEBUG_BREAK ||
1871 result == DEBUG_PREPARE_STEP_IN);
1872 return result;
1873}
1874
1875
1876PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001877 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001878 return ExtractTypeFromFlags(flags());
1879}
1880
1881
1882int Code::arguments_count() {
1883 ASSERT(is_call_stub() || kind() == STUB);
1884 return ExtractArgumentsCountFromFlags(flags());
1885}
1886
1887
1888CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001890 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1891 kStubMajorKeyOffset));
1892}
1893
1894
1895void Code::set_major_key(CodeStub::Major major) {
1896 ASSERT(kind() == STUB);
1897 ASSERT(0 <= major && major < 256);
1898 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001899}
1900
1901
1902bool Code::is_inline_cache_stub() {
1903 Kind kind = this->kind();
1904 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1905}
1906
1907
1908Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001909 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001910 PropertyType type,
1911 int argc) {
1912 // Compute the bit mask.
1913 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001914 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001915 bits |= type << kFlagsTypeShift;
1916 bits |= argc << kFlagsArgumentsCountShift;
1917 // Cast to flags and validate result before returning it.
1918 Flags result = static_cast<Flags>(bits);
1919 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001920 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001921 ASSERT(ExtractTypeFromFlags(result) == type);
1922 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1923 return result;
1924}
1925
1926
1927Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1928 PropertyType type,
1929 int argc) {
1930 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1931}
1932
1933
1934Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1935 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1936 return static_cast<Kind>(bits);
1937}
1938
1939
kasper.lund7276f142008-07-30 08:49:36 +00001940InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1941 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942 return static_cast<InlineCacheState>(bits);
1943}
1944
1945
1946PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1947 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1948 return static_cast<PropertyType>(bits);
1949}
1950
1951
1952int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1953 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1954}
1955
1956
1957Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1958 int bits = flags & ~kFlagsTypeMask;
1959 return static_cast<Flags>(bits);
1960}
1961
1962
ager@chromium.org8bb60582008-12-11 12:02:20 +00001963Code* Code::GetCodeFromTargetAddress(Address address) {
1964 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1965 // GetCodeFromTargetAddress might be called when marking objects during mark
1966 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1967 // Code::cast. Code::cast does not work when the object's map is
1968 // marked.
1969 Code* result = reinterpret_cast<Code*>(code);
1970 return result;
1971}
1972
1973
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001974Object* Map::prototype() {
1975 return READ_FIELD(this, kPrototypeOffset);
1976}
1977
1978
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001979void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001980 ASSERT(value->IsNull() || value->IsJSObject());
1981 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001982 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001983}
1984
1985
1986ACCESSORS(Map, instance_descriptors, DescriptorArray,
1987 kInstanceDescriptorsOffset)
1988ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1989ACCESSORS(Map, constructor, Object, kConstructorOffset)
1990
1991ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1992ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1993
1994ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1995ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001996ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001997
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001998ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001999
2000ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2001ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2002ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2003ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2004ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2005
2006ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2007ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2008ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2009
2010ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2011ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2012ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2013ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2014ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2015ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2016
2017ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2018ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2019
2020ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2021ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2022
2023ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2024ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002025ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2026 kPropertyAccessorsOffset)
2027ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2028 kPrototypeTemplateOffset)
2029ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2030ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2031 kNamedPropertyHandlerOffset)
2032ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2033 kIndexedPropertyHandlerOffset)
2034ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2035 kInstanceTemplateOffset)
2036ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2037ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002038ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2039 kInstanceCallHandlerOffset)
2040ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2041 kAccessCheckInfoOffset)
2042ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2043
2044ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002045ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2046 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002047
2048ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2049ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2050
2051ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2052
2053ACCESSORS(Script, source, Object, kSourceOffset)
2054ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002055ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002056ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2057ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2058ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2059ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002060ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002061
2062ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2063ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2064ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2065ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2066
2067ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2068ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2069ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2070ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2071
2072ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2073ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2074 kInstanceClassNameOffset)
2075ACCESSORS(SharedFunctionInfo, function_data, Object,
2076 kExternalReferenceDataOffset)
2077ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
2078ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2079ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002080ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002081
2082BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2083 kHiddenPrototypeBit)
2084BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2085BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2086 kNeedsAccessCheckBit)
2087BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2088 kIsExpressionBit)
2089BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2090 kIsTopLevelBit)
2091
2092INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2093INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2094 kFormalParameterCountOffset)
2095INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2096 kExpectedNofPropertiesOffset)
2097INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2098 kStartPositionAndTypeOffset)
2099INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2100INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2101 kFunctionTokenPositionOffset)
2102
2103
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002104void SharedFunctionInfo::DontAdaptArguments() {
2105 ASSERT(code()->kind() == Code::BUILTIN);
2106 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2107}
2108
2109
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002110int SharedFunctionInfo::start_position() {
2111 return start_position_and_type() >> kStartPositionShift;
2112}
2113
2114
2115void SharedFunctionInfo::set_start_position(int start_position) {
2116 set_start_position_and_type((start_position << kStartPositionShift)
2117 | (start_position_and_type() & ~kStartPositionMask));
2118}
2119
2120
2121Code* SharedFunctionInfo::code() {
2122 return Code::cast(READ_FIELD(this, kCodeOffset));
2123}
2124
2125
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002126void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002127 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002128 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002129}
2130
2131
2132bool SharedFunctionInfo::is_compiled() {
2133 // TODO(1242782): Create a code kind for uncompiled code.
2134 return code()->kind() != Code::STUB;
2135}
2136
2137
2138bool JSFunction::IsBoilerplate() {
2139 return map() == Heap::boilerplate_function_map();
2140}
2141
2142
2143bool JSFunction::IsLoaded() {
2144 return shared()->lazy_load_data() == Heap::undefined_value();
2145}
2146
2147
2148Code* JSFunction::code() {
2149 return shared()->code();
2150}
2151
2152
2153void JSFunction::set_code(Code* value) {
2154 shared()->set_code(value);
2155}
2156
2157
2158Context* JSFunction::context() {
2159 return Context::cast(READ_FIELD(this, kContextOffset));
2160}
2161
2162
2163Object* JSFunction::unchecked_context() {
2164 return READ_FIELD(this, kContextOffset);
2165}
2166
2167
2168void JSFunction::set_context(Object* value) {
2169 ASSERT(value == Heap::undefined_value() || value->IsContext());
2170 WRITE_FIELD(this, kContextOffset, value);
2171 WRITE_BARRIER(this, kContextOffset);
2172}
2173
2174ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2175 kPrototypeOrInitialMapOffset)
2176
2177
2178Map* JSFunction::initial_map() {
2179 return Map::cast(prototype_or_initial_map());
2180}
2181
2182
2183void JSFunction::set_initial_map(Map* value) {
2184 set_prototype_or_initial_map(value);
2185}
2186
2187
2188bool JSFunction::has_initial_map() {
2189 return prototype_or_initial_map()->IsMap();
2190}
2191
2192
2193bool JSFunction::has_instance_prototype() {
2194 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2195}
2196
2197
2198bool JSFunction::has_prototype() {
2199 return map()->has_non_instance_prototype() || has_instance_prototype();
2200}
2201
2202
2203Object* JSFunction::instance_prototype() {
2204 ASSERT(has_instance_prototype());
2205 if (has_initial_map()) return initial_map()->prototype();
2206 // When there is no initial map and the prototype is a JSObject, the
2207 // initial map field is used for the prototype field.
2208 return prototype_or_initial_map();
2209}
2210
2211
2212Object* JSFunction::prototype() {
2213 ASSERT(has_prototype());
2214 // If the function's prototype property has been set to a non-JSObject
2215 // value, that value is stored in the constructor field of the map.
2216 if (map()->has_non_instance_prototype()) return map()->constructor();
2217 return instance_prototype();
2218}
2219
2220
2221bool JSFunction::is_compiled() {
2222 return shared()->is_compiled();
2223}
2224
2225
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002226int JSFunction::NumberOfLiterals() {
2227 return literals()->length();
2228}
2229
2230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002231Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2232 ASSERT(0 <= id && id < kJSBuiltinsCount);
2233 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2234}
2235
2236
2237void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2238 Object* value) {
2239 ASSERT(0 <= id && id < kJSBuiltinsCount);
2240 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2241 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2242}
2243
2244
2245Address Proxy::proxy() {
2246 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2247}
2248
2249
2250void Proxy::set_proxy(Address value) {
2251 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2252}
2253
2254
2255void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2256 visitor->VisitExternalReference(
2257 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2258}
2259
2260
2261ACCESSORS(JSValue, value, Object, kValueOffset)
2262
2263
2264JSValue* JSValue::cast(Object* obj) {
2265 ASSERT(obj->IsJSValue());
2266 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2267 return reinterpret_cast<JSValue*>(obj);
2268}
2269
2270
2271INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2272INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2273INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2274
2275
2276Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002277 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002278}
2279
2280
2281void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002282 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002283}
2284
2285
2286byte* Code::instruction_start() {
2287 return FIELD_ADDR(this, kHeaderSize);
2288}
2289
2290
2291int Code::body_size() {
2292 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2293}
2294
2295
2296byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002297 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002298}
2299
2300
2301byte* Code::entry() {
2302 return instruction_start();
2303}
2304
2305
2306bool Code::contains(byte* pc) {
2307 return (instruction_start() <= pc) &&
2308 (pc < instruction_start() + instruction_size());
2309}
2310
2311
2312byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002313 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002314}
2315
2316
2317ACCESSORS(JSArray, length, Object, kLengthOffset)
2318
2319
ager@chromium.org236ad962008-09-25 09:45:57 +00002320ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002321
2322
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002323JSRegExp::Type JSRegExp::TypeTag() {
2324 Object* data = this->data();
2325 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2326 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2327 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002328}
2329
2330
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002331int JSRegExp::CaptureCount() {
2332 switch (TypeTag()) {
2333 case ATOM:
2334 return 0;
2335 case IRREGEXP:
2336 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2337 default:
2338 UNREACHABLE();
2339 return -1;
2340 }
2341}
2342
2343
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002344JSRegExp::Flags JSRegExp::GetFlags() {
2345 ASSERT(this->data()->IsFixedArray());
2346 Object* data = this->data();
2347 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2348 return Flags(smi->value());
2349}
2350
2351
2352String* JSRegExp::Pattern() {
2353 ASSERT(this->data()->IsFixedArray());
2354 Object* data = this->data();
2355 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2356 return pattern;
2357}
2358
2359
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002360Object* JSRegExp::DataAt(int index) {
2361 ASSERT(TypeTag() != NOT_COMPILED);
2362 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002363}
2364
2365
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002366void JSRegExp::SetDataAt(int index, Object* value) {
2367 ASSERT(TypeTag() != NOT_COMPILED);
2368 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2369 FixedArray::cast(data())->set(index, value);
2370}
2371
2372
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002373bool JSObject::HasFastElements() {
2374 return !elements()->IsDictionary();
2375}
2376
2377
2378bool JSObject::HasNamedInterceptor() {
2379 return map()->has_named_interceptor();
2380}
2381
2382
2383bool JSObject::HasIndexedInterceptor() {
2384 return map()->has_indexed_interceptor();
2385}
2386
2387
2388Dictionary* JSObject::property_dictionary() {
2389 ASSERT(!HasFastProperties());
2390 return Dictionary::cast(properties());
2391}
2392
2393
2394Dictionary* JSObject::element_dictionary() {
2395 ASSERT(!HasFastElements());
2396 return Dictionary::cast(elements());
2397}
2398
2399
2400bool String::HasHashCode() {
2401 return (length_field() & kHashComputedMask) != 0;
2402}
2403
2404
2405uint32_t String::Hash() {
2406 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002407 uint32_t field = length_field();
2408 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002409 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002410 return ComputeAndSetHash();
2411}
2412
2413
ager@chromium.org7c537e22008-10-16 08:43:32 +00002414StringHasher::StringHasher(int length)
2415 : length_(length),
2416 raw_running_hash_(0),
2417 array_index_(0),
2418 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2419 is_first_char_(true),
2420 is_valid_(true) { }
2421
2422
2423bool StringHasher::has_trivial_hash() {
2424 return length_ > String::kMaxMediumStringSize;
2425}
2426
2427
2428void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002429 // Use the Jenkins one-at-a-time hash function to update the hash
2430 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002431 raw_running_hash_ += c;
2432 raw_running_hash_ += (raw_running_hash_ << 10);
2433 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002434 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002435 if (is_array_index_) {
2436 if (c < '0' || c > '9') {
2437 is_array_index_ = false;
2438 } else {
2439 int d = c - '0';
2440 if (is_first_char_) {
2441 is_first_char_ = false;
2442 if (c == '0' && length_ > 1) {
2443 is_array_index_ = false;
2444 return;
2445 }
2446 }
2447 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2448 is_array_index_ = false;
2449 } else {
2450 array_index_ = array_index_ * 10 + d;
2451 }
2452 }
2453 }
2454}
2455
2456
2457void StringHasher::AddCharacterNoIndex(uc32 c) {
2458 ASSERT(!is_array_index());
2459 raw_running_hash_ += c;
2460 raw_running_hash_ += (raw_running_hash_ << 10);
2461 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2462}
2463
2464
2465uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002466 // Get the calculated raw hash value and do some more bit ops to distribute
2467 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002468 uint32_t result = raw_running_hash_;
2469 result += (result << 3);
2470 result ^= (result >> 11);
2471 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002472 if (result == 0) {
2473 result = 27;
2474 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002475 return result;
2476}
2477
2478
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002479bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002480 uint32_t field = length_field();
2481 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002482 return SlowAsArrayIndex(index);
2483}
2484
2485
2486Object* JSObject::GetPrototype() {
2487 return JSObject::cast(this)->map()->prototype();
2488}
2489
2490
2491PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2492 return GetPropertyAttributeWithReceiver(this, key);
2493}
2494
2495
2496bool JSObject::HasElement(uint32_t index) {
2497 return HasElementWithReceiver(this, index);
2498}
2499
2500
2501bool AccessorInfo::all_can_read() {
2502 return BooleanBit::get(flag(), kAllCanReadBit);
2503}
2504
2505
2506void AccessorInfo::set_all_can_read(bool value) {
2507 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2508}
2509
2510
2511bool AccessorInfo::all_can_write() {
2512 return BooleanBit::get(flag(), kAllCanWriteBit);
2513}
2514
2515
2516void AccessorInfo::set_all_can_write(bool value) {
2517 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2518}
2519
2520
ager@chromium.org870a0b62008-11-04 11:43:05 +00002521bool AccessorInfo::prohibits_overwriting() {
2522 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2523}
2524
2525
2526void AccessorInfo::set_prohibits_overwriting(bool value) {
2527 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2528}
2529
2530
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002531PropertyAttributes AccessorInfo::property_attributes() {
2532 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2533}
2534
2535
2536void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2537 ASSERT(AttributesField::is_valid(attributes));
2538 int rest_value = flag()->value() & ~AttributesField::mask();
2539 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2540}
2541
2542void Dictionary::SetEntry(int entry,
2543 Object* key,
2544 Object* value,
2545 PropertyDetails details) {
2546 ASSERT(!key->IsString() || details.index() > 0);
2547 int index = EntryToIndex(entry);
2548 WriteBarrierMode mode = GetWriteBarrierMode();
2549 set(index, key, mode);
2550 set(index+1, value, mode);
2551 fast_set(this, index+2, details.AsSmi());
2552}
2553
2554
2555void Map::ClearCodeCache() {
2556 // No write barrier is needed since empty_fixed_array is not in new space.
2557 // Please note this function is used during marking:
2558 // - MarkCompactCollector::MarkUnmarkedObject
2559 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2560 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2561}
2562
2563
ager@chromium.org7c537e22008-10-16 08:43:32 +00002564void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002565 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002566 set_elements(storage);
2567}
2568
2569
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002570Object* FixedArray::Copy() {
2571 if (length() == 0) return this;
2572 return Heap::CopyFixedArray(this);
2573}
2574
2575
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002576#undef CAST_ACCESSOR
2577#undef INT_ACCESSORS
2578#undef SMI_ACCESSORS
2579#undef ACCESSORS
2580#undef FIELD_ADDR
2581#undef READ_FIELD
2582#undef WRITE_FIELD
2583#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002584#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002585#undef READ_MEMADDR_FIELD
2586#undef WRITE_MEMADDR_FIELD
2587#undef READ_DOUBLE_FIELD
2588#undef WRITE_DOUBLE_FIELD
2589#undef READ_INT_FIELD
2590#undef WRITE_INT_FIELD
2591#undef READ_SHORT_FIELD
2592#undef WRITE_SHORT_FIELD
2593#undef READ_BYTE_FIELD
2594#undef WRITE_BYTE_FIELD
2595
2596
2597} } // namespace v8::internal
2598
2599#endif // V8_OBJECTS_INL_H_