blob: 762bb63638a9213e1f9f26f0def24cf505887725 [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)
2080
2081BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2082 kHiddenPrototypeBit)
2083BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2084BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2085 kNeedsAccessCheckBit)
2086BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2087 kIsExpressionBit)
2088BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2089 kIsTopLevelBit)
2090
2091INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2092INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2093 kFormalParameterCountOffset)
2094INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2095 kExpectedNofPropertiesOffset)
2096INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2097 kStartPositionAndTypeOffset)
2098INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2099INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2100 kFunctionTokenPositionOffset)
2101
2102
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002103void SharedFunctionInfo::DontAdaptArguments() {
2104 ASSERT(code()->kind() == Code::BUILTIN);
2105 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2106}
2107
2108
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002109int SharedFunctionInfo::start_position() {
2110 return start_position_and_type() >> kStartPositionShift;
2111}
2112
2113
2114void SharedFunctionInfo::set_start_position(int start_position) {
2115 set_start_position_and_type((start_position << kStartPositionShift)
2116 | (start_position_and_type() & ~kStartPositionMask));
2117}
2118
2119
2120Code* SharedFunctionInfo::code() {
2121 return Code::cast(READ_FIELD(this, kCodeOffset));
2122}
2123
2124
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002125void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002126 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002127 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128}
2129
2130
2131bool SharedFunctionInfo::is_compiled() {
2132 // TODO(1242782): Create a code kind for uncompiled code.
2133 return code()->kind() != Code::STUB;
2134}
2135
2136
2137bool JSFunction::IsBoilerplate() {
2138 return map() == Heap::boilerplate_function_map();
2139}
2140
2141
2142bool JSFunction::IsLoaded() {
2143 return shared()->lazy_load_data() == Heap::undefined_value();
2144}
2145
2146
2147Code* JSFunction::code() {
2148 return shared()->code();
2149}
2150
2151
2152void JSFunction::set_code(Code* value) {
2153 shared()->set_code(value);
2154}
2155
2156
2157Context* JSFunction::context() {
2158 return Context::cast(READ_FIELD(this, kContextOffset));
2159}
2160
2161
2162Object* JSFunction::unchecked_context() {
2163 return READ_FIELD(this, kContextOffset);
2164}
2165
2166
2167void JSFunction::set_context(Object* value) {
2168 ASSERT(value == Heap::undefined_value() || value->IsContext());
2169 WRITE_FIELD(this, kContextOffset, value);
2170 WRITE_BARRIER(this, kContextOffset);
2171}
2172
2173ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2174 kPrototypeOrInitialMapOffset)
2175
2176
2177Map* JSFunction::initial_map() {
2178 return Map::cast(prototype_or_initial_map());
2179}
2180
2181
2182void JSFunction::set_initial_map(Map* value) {
2183 set_prototype_or_initial_map(value);
2184}
2185
2186
2187bool JSFunction::has_initial_map() {
2188 return prototype_or_initial_map()->IsMap();
2189}
2190
2191
2192bool JSFunction::has_instance_prototype() {
2193 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2194}
2195
2196
2197bool JSFunction::has_prototype() {
2198 return map()->has_non_instance_prototype() || has_instance_prototype();
2199}
2200
2201
2202Object* JSFunction::instance_prototype() {
2203 ASSERT(has_instance_prototype());
2204 if (has_initial_map()) return initial_map()->prototype();
2205 // When there is no initial map and the prototype is a JSObject, the
2206 // initial map field is used for the prototype field.
2207 return prototype_or_initial_map();
2208}
2209
2210
2211Object* JSFunction::prototype() {
2212 ASSERT(has_prototype());
2213 // If the function's prototype property has been set to a non-JSObject
2214 // value, that value is stored in the constructor field of the map.
2215 if (map()->has_non_instance_prototype()) return map()->constructor();
2216 return instance_prototype();
2217}
2218
2219
2220bool JSFunction::is_compiled() {
2221 return shared()->is_compiled();
2222}
2223
2224
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002225int JSFunction::NumberOfLiterals() {
2226 return literals()->length();
2227}
2228
2229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002230Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2231 ASSERT(0 <= id && id < kJSBuiltinsCount);
2232 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2233}
2234
2235
2236void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2237 Object* value) {
2238 ASSERT(0 <= id && id < kJSBuiltinsCount);
2239 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2240 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2241}
2242
2243
2244Address Proxy::proxy() {
2245 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2246}
2247
2248
2249void Proxy::set_proxy(Address value) {
2250 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2251}
2252
2253
2254void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2255 visitor->VisitExternalReference(
2256 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2257}
2258
2259
2260ACCESSORS(JSValue, value, Object, kValueOffset)
2261
2262
2263JSValue* JSValue::cast(Object* obj) {
2264 ASSERT(obj->IsJSValue());
2265 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2266 return reinterpret_cast<JSValue*>(obj);
2267}
2268
2269
2270INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2271INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2272INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2273
2274
2275Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002276 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002277}
2278
2279
2280void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002281 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002282}
2283
2284
2285byte* Code::instruction_start() {
2286 return FIELD_ADDR(this, kHeaderSize);
2287}
2288
2289
2290int Code::body_size() {
2291 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2292}
2293
2294
2295byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002296 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002297}
2298
2299
2300byte* Code::entry() {
2301 return instruction_start();
2302}
2303
2304
2305bool Code::contains(byte* pc) {
2306 return (instruction_start() <= pc) &&
2307 (pc < instruction_start() + instruction_size());
2308}
2309
2310
2311byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002312 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002313}
2314
2315
2316ACCESSORS(JSArray, length, Object, kLengthOffset)
2317
2318
ager@chromium.org236ad962008-09-25 09:45:57 +00002319ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002320
2321
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002322JSRegExp::Type JSRegExp::TypeTag() {
2323 Object* data = this->data();
2324 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2325 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2326 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002327}
2328
2329
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002330int JSRegExp::CaptureCount() {
2331 switch (TypeTag()) {
2332 case ATOM:
2333 return 0;
2334 case IRREGEXP:
2335 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2336 default:
2337 UNREACHABLE();
2338 return -1;
2339 }
2340}
2341
2342
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002343JSRegExp::Flags JSRegExp::GetFlags() {
2344 ASSERT(this->data()->IsFixedArray());
2345 Object* data = this->data();
2346 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2347 return Flags(smi->value());
2348}
2349
2350
2351String* JSRegExp::Pattern() {
2352 ASSERT(this->data()->IsFixedArray());
2353 Object* data = this->data();
2354 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2355 return pattern;
2356}
2357
2358
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002359Object* JSRegExp::DataAt(int index) {
2360 ASSERT(TypeTag() != NOT_COMPILED);
2361 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002362}
2363
2364
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002365void JSRegExp::SetDataAt(int index, Object* value) {
2366 ASSERT(TypeTag() != NOT_COMPILED);
2367 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2368 FixedArray::cast(data())->set(index, value);
2369}
2370
2371
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002372bool JSObject::HasFastElements() {
2373 return !elements()->IsDictionary();
2374}
2375
2376
2377bool JSObject::HasNamedInterceptor() {
2378 return map()->has_named_interceptor();
2379}
2380
2381
2382bool JSObject::HasIndexedInterceptor() {
2383 return map()->has_indexed_interceptor();
2384}
2385
2386
2387Dictionary* JSObject::property_dictionary() {
2388 ASSERT(!HasFastProperties());
2389 return Dictionary::cast(properties());
2390}
2391
2392
2393Dictionary* JSObject::element_dictionary() {
2394 ASSERT(!HasFastElements());
2395 return Dictionary::cast(elements());
2396}
2397
2398
2399bool String::HasHashCode() {
2400 return (length_field() & kHashComputedMask) != 0;
2401}
2402
2403
2404uint32_t String::Hash() {
2405 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002406 uint32_t field = length_field();
2407 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002408 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002409 return ComputeAndSetHash();
2410}
2411
2412
ager@chromium.org7c537e22008-10-16 08:43:32 +00002413StringHasher::StringHasher(int length)
2414 : length_(length),
2415 raw_running_hash_(0),
2416 array_index_(0),
2417 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2418 is_first_char_(true),
2419 is_valid_(true) { }
2420
2421
2422bool StringHasher::has_trivial_hash() {
2423 return length_ > String::kMaxMediumStringSize;
2424}
2425
2426
2427void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002428 // Use the Jenkins one-at-a-time hash function to update the hash
2429 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002430 raw_running_hash_ += c;
2431 raw_running_hash_ += (raw_running_hash_ << 10);
2432 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002433 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002434 if (is_array_index_) {
2435 if (c < '0' || c > '9') {
2436 is_array_index_ = false;
2437 } else {
2438 int d = c - '0';
2439 if (is_first_char_) {
2440 is_first_char_ = false;
2441 if (c == '0' && length_ > 1) {
2442 is_array_index_ = false;
2443 return;
2444 }
2445 }
2446 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2447 is_array_index_ = false;
2448 } else {
2449 array_index_ = array_index_ * 10 + d;
2450 }
2451 }
2452 }
2453}
2454
2455
2456void StringHasher::AddCharacterNoIndex(uc32 c) {
2457 ASSERT(!is_array_index());
2458 raw_running_hash_ += c;
2459 raw_running_hash_ += (raw_running_hash_ << 10);
2460 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2461}
2462
2463
2464uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002465 // Get the calculated raw hash value and do some more bit ops to distribute
2466 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002467 uint32_t result = raw_running_hash_;
2468 result += (result << 3);
2469 result ^= (result >> 11);
2470 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002471 if (result == 0) {
2472 result = 27;
2473 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002474 return result;
2475}
2476
2477
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002478bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002479 uint32_t field = length_field();
2480 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002481 return SlowAsArrayIndex(index);
2482}
2483
2484
2485Object* JSObject::GetPrototype() {
2486 return JSObject::cast(this)->map()->prototype();
2487}
2488
2489
2490PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2491 return GetPropertyAttributeWithReceiver(this, key);
2492}
2493
2494
2495bool JSObject::HasElement(uint32_t index) {
2496 return HasElementWithReceiver(this, index);
2497}
2498
2499
2500bool AccessorInfo::all_can_read() {
2501 return BooleanBit::get(flag(), kAllCanReadBit);
2502}
2503
2504
2505void AccessorInfo::set_all_can_read(bool value) {
2506 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2507}
2508
2509
2510bool AccessorInfo::all_can_write() {
2511 return BooleanBit::get(flag(), kAllCanWriteBit);
2512}
2513
2514
2515void AccessorInfo::set_all_can_write(bool value) {
2516 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2517}
2518
2519
ager@chromium.org870a0b62008-11-04 11:43:05 +00002520bool AccessorInfo::prohibits_overwriting() {
2521 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2522}
2523
2524
2525void AccessorInfo::set_prohibits_overwriting(bool value) {
2526 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2527}
2528
2529
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002530PropertyAttributes AccessorInfo::property_attributes() {
2531 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2532}
2533
2534
2535void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2536 ASSERT(AttributesField::is_valid(attributes));
2537 int rest_value = flag()->value() & ~AttributesField::mask();
2538 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2539}
2540
2541void Dictionary::SetEntry(int entry,
2542 Object* key,
2543 Object* value,
2544 PropertyDetails details) {
2545 ASSERT(!key->IsString() || details.index() > 0);
2546 int index = EntryToIndex(entry);
2547 WriteBarrierMode mode = GetWriteBarrierMode();
2548 set(index, key, mode);
2549 set(index+1, value, mode);
2550 fast_set(this, index+2, details.AsSmi());
2551}
2552
2553
2554void Map::ClearCodeCache() {
2555 // No write barrier is needed since empty_fixed_array is not in new space.
2556 // Please note this function is used during marking:
2557 // - MarkCompactCollector::MarkUnmarkedObject
2558 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2559 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2560}
2561
2562
ager@chromium.org7c537e22008-10-16 08:43:32 +00002563void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002564 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002565 set_elements(storage);
2566}
2567
2568
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002569Object* FixedArray::Copy() {
2570 if (length() == 0) return this;
2571 return Heap::CopyFixedArray(this);
2572}
2573
2574
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002575#undef CAST_ACCESSOR
2576#undef INT_ACCESSORS
2577#undef SMI_ACCESSORS
2578#undef ACCESSORS
2579#undef FIELD_ADDR
2580#undef READ_FIELD
2581#undef WRITE_FIELD
2582#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002583#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002584#undef READ_MEMADDR_FIELD
2585#undef WRITE_MEMADDR_FIELD
2586#undef READ_DOUBLE_FIELD
2587#undef WRITE_DOUBLE_FIELD
2588#undef READ_INT_FIELD
2589#undef WRITE_INT_FIELD
2590#undef READ_SHORT_FIELD
2591#undef WRITE_SHORT_FIELD
2592#undef READ_BYTE_FIELD
2593#undef WRITE_BYTE_FIELD
2594
2595
2596} } // namespace v8::internal
2597
2598#endif // V8_OBJECTS_INL_H_