blob: 43f1a04c21d7cbea3233a06d51a7a6cf6445ef4c [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;
146 StringShape shape(String::cast(this));
147 return shape.IsSequential() && shape.IsAsciiRepresentation();
148}
149
150
151bool Object::IsSeqTwoByteString() {
152 if (!IsString()) return false;
153 StringShape shape(String::cast(this));
154 return shape.IsSequential() && shape.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;
166 StringShape shape(String::cast(this));
167 return shape.IsExternal() && shape.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;
173 StringShape shape(String::cast(this));
174 return shape.IsExternal() && shape.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
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001097Object* JSObject::InObjectPropertyAtPut(int index,
1098 Object* value,
1099 WriteBarrierMode mode) {
1100 // Adjust for the number of properties stored in the object.
1101 index -= map()->inobject_properties();
1102 ASSERT(index < 0);
1103 int offset = map()->instance_size() + (index * kPointerSize);
1104 WRITE_FIELD(this, offset, value);
1105 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1106 return value;
1107}
1108
1109
1110
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001111void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001112 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001113 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001114 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001115 }
1116}
1117
1118
1119void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001120 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001121 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001122 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123 }
1124}
1125
1126
1127bool JSObject::HasFastProperties() {
1128 return !properties()->IsDictionary();
1129}
1130
1131
1132bool Array::IndexFromObject(Object* object, uint32_t* index) {
1133 if (object->IsSmi()) {
1134 int value = Smi::cast(object)->value();
1135 if (value < 0) return false;
1136 *index = value;
1137 return true;
1138 }
1139 if (object->IsHeapNumber()) {
1140 double value = HeapNumber::cast(object)->value();
1141 uint32_t uint_value = static_cast<uint32_t>(value);
1142 if (value == static_cast<double>(uint_value)) {
1143 *index = uint_value;
1144 return true;
1145 }
1146 }
1147 return false;
1148}
1149
1150
1151bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1152 if (!this->IsJSValue()) return false;
1153
1154 JSValue* js_value = JSValue::cast(this);
1155 if (!js_value->value()->IsString()) return false;
1156
1157 String* str = String::cast(js_value->value());
1158 if (index >= (uint32_t)str->length()) return false;
1159
1160 return true;
1161}
1162
1163
1164Object* FixedArray::get(int index) {
1165 ASSERT(index >= 0 && index < this->length());
1166 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1167}
1168
1169
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001170void FixedArray::set(int index, Smi* value) {
1171 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1172 int offset = kHeaderSize + index * kPointerSize;
1173 WRITE_FIELD(this, offset, value);
1174}
1175
1176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177void FixedArray::set(int index, Object* value) {
1178 ASSERT(index >= 0 && index < this->length());
1179 int offset = kHeaderSize + index * kPointerSize;
1180 WRITE_FIELD(this, offset, value);
1181 WRITE_BARRIER(this, offset);
1182}
1183
1184
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001185WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1187 return UPDATE_WRITE_BARRIER;
1188}
1189
1190
1191void FixedArray::set(int index,
1192 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001193 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001194 ASSERT(index >= 0 && index < this->length());
1195 int offset = kHeaderSize + index * kPointerSize;
1196 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001197 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001198}
1199
1200
1201void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1202 ASSERT(index >= 0 && index < array->length());
1203 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1204}
1205
1206
1207void FixedArray::set_undefined(int index) {
1208 ASSERT(index >= 0 && index < this->length());
1209 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1210 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1211 Heap::undefined_value());
1212}
1213
1214
ager@chromium.org236ad962008-09-25 09:45:57 +00001215void FixedArray::set_null(int index) {
1216 ASSERT(index >= 0 && index < this->length());
1217 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1218 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1219}
1220
1221
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001222void FixedArray::set_the_hole(int index) {
1223 ASSERT(index >= 0 && index < this->length());
1224 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1225 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1226}
1227
1228
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001229bool DescriptorArray::IsEmpty() {
1230 ASSERT(this == Heap::empty_descriptor_array() ||
1231 this->length() > 2);
1232 return this == Heap::empty_descriptor_array();
1233}
1234
1235
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001236void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1237 Object* tmp = array->get(first);
1238 fast_set(array, first, array->get(second));
1239 fast_set(array, second, tmp);
1240}
1241
1242
1243int DescriptorArray::Search(String* name) {
1244 SLOW_ASSERT(IsSortedNoDuplicates());
1245
ager@chromium.org870a0b62008-11-04 11:43:05 +00001246 StringShape shape(name);
1247
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001248 // Check for empty descriptor array.
1249 int nof = number_of_descriptors();
1250 if (nof == 0) return kNotFound;
1251
1252 // Fast case: do linear search for small arrays.
1253 const int kMaxElementsForLinearSearch = 8;
ager@chromium.org870a0b62008-11-04 11:43:05 +00001254 if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001255 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001256 }
1257
1258 // Slow case: perform binary search.
1259 return BinarySearch(name, 0, nof - 1);
1260}
1261
1262
1263
1264String* DescriptorArray::GetKey(int descriptor_number) {
1265 ASSERT(descriptor_number < number_of_descriptors());
1266 return String::cast(get(ToKeyIndex(descriptor_number)));
1267}
1268
1269
1270Object* DescriptorArray::GetValue(int descriptor_number) {
1271 ASSERT(descriptor_number < number_of_descriptors());
1272 return GetContentArray()->get(ToValueIndex(descriptor_number));
1273}
1274
1275
1276Smi* DescriptorArray::GetDetails(int descriptor_number) {
1277 ASSERT(descriptor_number < number_of_descriptors());
1278 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1279}
1280
1281
1282void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1283 desc->Init(GetKey(descriptor_number),
1284 GetValue(descriptor_number),
1285 GetDetails(descriptor_number));
1286}
1287
1288
1289void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1290 // Range check.
1291 ASSERT(descriptor_number < number_of_descriptors());
1292
1293 // Make sure non of the elements in desc are in new space.
1294 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1295 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1296
1297 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1298 FixedArray* content_array = GetContentArray();
1299 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1300 fast_set(content_array, ToDetailsIndex(descriptor_number),
1301 desc->GetDetails().AsSmi());
1302}
1303
1304
1305void DescriptorArray::Swap(int first, int second) {
1306 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1307 FixedArray* content_array = GetContentArray();
1308 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1309 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1310}
1311
1312
1313bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001314 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315 if (!max_index_object->IsSmi()) return false;
1316 return 0 !=
1317 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1318}
1319
1320
1321uint32_t Dictionary::max_number_key() {
1322 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001323 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324 if (!max_index_object->IsSmi()) return 0;
1325 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1326 return value >> kRequiresSlowElementsTagSize;
1327}
1328
1329
1330// ------------------------------------
1331// Cast operations
1332
1333
1334CAST_ACCESSOR(FixedArray)
1335CAST_ACCESSOR(DescriptorArray)
1336CAST_ACCESSOR(Dictionary)
1337CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001338CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001339CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001340CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001341CAST_ACCESSOR(String)
1342CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001343CAST_ACCESSOR(SeqAsciiString)
1344CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001345CAST_ACCESSOR(ConsString)
1346CAST_ACCESSOR(SlicedString)
1347CAST_ACCESSOR(ExternalString)
1348CAST_ACCESSOR(ExternalAsciiString)
1349CAST_ACCESSOR(ExternalTwoByteString)
1350CAST_ACCESSOR(JSObject)
1351CAST_ACCESSOR(Smi)
1352CAST_ACCESSOR(Failure)
1353CAST_ACCESSOR(HeapObject)
1354CAST_ACCESSOR(HeapNumber)
1355CAST_ACCESSOR(Oddball)
1356CAST_ACCESSOR(SharedFunctionInfo)
1357CAST_ACCESSOR(Map)
1358CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001359CAST_ACCESSOR(GlobalObject)
1360CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361CAST_ACCESSOR(JSGlobalObject)
1362CAST_ACCESSOR(JSBuiltinsObject)
1363CAST_ACCESSOR(Code)
1364CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001365CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001366CAST_ACCESSOR(Proxy)
1367CAST_ACCESSOR(ByteArray)
1368CAST_ACCESSOR(Struct)
1369
1370
1371#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1372 STRUCT_LIST(MAKE_STRUCT_CAST)
1373#undef MAKE_STRUCT_CAST
1374
1375template <int prefix_size, int elem_size>
1376HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1377 Object* obj) {
1378 ASSERT(obj->IsHashTable());
1379 return reinterpret_cast<HashTable*>(obj);
1380}
1381
1382
1383INT_ACCESSORS(Array, length, kLengthOffset)
1384
1385
1386bool String::Equals(String* other) {
1387 if (other == this) return true;
ager@chromium.org870a0b62008-11-04 11:43:05 +00001388 StringShape this_shape(this);
1389 StringShape other_shape(other);
1390 if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false;
1391 return SlowEquals(this_shape, other, other_shape);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001392}
1393
1394
ager@chromium.org870a0b62008-11-04 11:43:05 +00001395int String::length(StringShape shape) {
1396 ASSERT(shape.type() == StringShape(this).type());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001397 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1398
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001399 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1400 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1401 ASSERT(kLongStringTag == 0);
1402
ager@chromium.org870a0b62008-11-04 11:43:05 +00001403 return len >> (shape.size_tag() + kLongLengthShift);
1404}
1405
1406
1407int String::length() {
1408 return length(StringShape(this));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001409}
1410
1411
1412void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001413 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1414 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1415 ASSERT(kLongStringTag == 0);
1416
ager@chromium.org870a0b62008-11-04 11:43:05 +00001417 StringShape shape(this);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001418 WRITE_INT_FIELD(this,
1419 kLengthOffset,
ager@chromium.org870a0b62008-11-04 11:43:05 +00001420 value << (shape.size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001421}
1422
1423
ager@chromium.org7c537e22008-10-16 08:43:32 +00001424uint32_t String::length_field() {
1425 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001426}
1427
1428
ager@chromium.org7c537e22008-10-16 08:43:32 +00001429void String::set_length_field(uint32_t value) {
1430 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001431}
1432
1433
ager@chromium.org870a0b62008-11-04 11:43:05 +00001434void String::TryFlatten(StringShape shape) {
1435 ASSERT(shape.type() == StringShape(this).type());
ager@chromium.org236ad962008-09-25 09:45:57 +00001436 // We don't need to flatten strings that are already flat. Since this code
1437 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001438 if (!IsFlat(shape)) {
1439 Flatten(shape);
ager@chromium.org236ad962008-09-25 09:45:57 +00001440 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001441}
1442
1443
ager@chromium.org870a0b62008-11-04 11:43:05 +00001444uint16_t String::Get(StringShape shape, int index) {
1445 ASSERT(shape.type() == StringShape(this).type());
1446 ASSERT(index >= 0 && index < length(shape));
1447 switch (shape.full_representation_tag()) {
1448 case kSeqStringTag | kAsciiStringTag:
1449 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1450 case kSeqStringTag | kTwoByteStringTag:
1451 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1452 case kConsStringTag | kAsciiStringTag:
1453 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001454 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001455 case kSlicedStringTag | kAsciiStringTag:
1456 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001457 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001458 case kExternalStringTag | kAsciiStringTag:
1459 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1460 case kExternalStringTag | kTwoByteStringTag:
1461 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462 default:
1463 break;
1464 }
1465
1466 UNREACHABLE();
1467 return 0;
1468}
1469
1470
ager@chromium.org870a0b62008-11-04 11:43:05 +00001471void String::Set(StringShape shape, int index, uint16_t value) {
1472 ASSERT(shape.type() == StringShape(this).type());
1473 ASSERT(shape.type() == StringShape(this).type());
1474 ASSERT(index >= 0 && index < length(shape));
1475 ASSERT(shape.IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476
ager@chromium.org870a0b62008-11-04 11:43:05 +00001477 return shape.IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001478 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1479 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001480}
1481
1482
ager@chromium.org870a0b62008-11-04 11:43:05 +00001483bool String::IsFlat(StringShape shape) {
1484 ASSERT(shape.type() == StringShape(this).type());
1485 switch (shape.representation_tag()) {
1486 case kConsStringTag: {
1487 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001488 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001489 return second->length() == 0;
1490 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001491 case kSlicedStringTag: {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001492 StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer());
1493 StringRepresentationTag tag = slice_shape.representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001494 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001495 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001496 default:
1497 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498 }
1499}
1500
1501
ager@chromium.org7c537e22008-10-16 08:43:32 +00001502uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001503 ASSERT(index >= 0 && index < length());
1504 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1505}
1506
1507
ager@chromium.org7c537e22008-10-16 08:43:32 +00001508void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001509 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1510 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1511 static_cast<byte>(value));
1512}
1513
1514
ager@chromium.org7c537e22008-10-16 08:43:32 +00001515Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001516 return FIELD_ADDR(this, kHeaderSize);
1517}
1518
1519
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001520char* SeqAsciiString::GetChars() {
1521 return reinterpret_cast<char*>(GetCharsAddress());
1522}
1523
1524
ager@chromium.org7c537e22008-10-16 08:43:32 +00001525Address SeqTwoByteString::GetCharsAddress() {
1526 return FIELD_ADDR(this, kHeaderSize);
1527}
1528
1529
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001530uc16* SeqTwoByteString::GetChars() {
1531 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1532}
1533
1534
ager@chromium.org7c537e22008-10-16 08:43:32 +00001535uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001536 ASSERT(index >= 0 && index < length());
1537 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1538}
1539
1540
ager@chromium.org7c537e22008-10-16 08:43:32 +00001541void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001542 ASSERT(index >= 0 && index < length());
1543 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1544}
1545
1546
ager@chromium.org870a0b62008-11-04 11:43:05 +00001547int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001548 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1549
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001550 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1551 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1552 ASSERT(kLongStringTag == 0);
1553
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001554 // Use the map (and not 'this') to compute the size tag, since
1555 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001556 length >>= shape.size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001557
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001558 return SizeFor(length);
1559}
1560
1561
ager@chromium.org870a0b62008-11-04 11:43:05 +00001562int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001563 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1564
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001565 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1566 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1567 ASSERT(kLongStringTag == 0);
1568
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001569 // Use the map (and not 'this') to compute the size tag, since
1570 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001571 length >>= shape.size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001572
1573 return SizeFor(length);
1574}
1575
1576
ager@chromium.org870a0b62008-11-04 11:43:05 +00001577String* ConsString::first() {
1578 return String::cast(READ_FIELD(this, kFirstOffset));
1579}
1580
1581
1582Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583 return READ_FIELD(this, kFirstOffset);
1584}
1585
1586
ager@chromium.org870a0b62008-11-04 11:43:05 +00001587void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001588 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001589 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001590}
1591
1592
ager@chromium.org870a0b62008-11-04 11:43:05 +00001593String* ConsString::second() {
1594 return String::cast(READ_FIELD(this, kSecondOffset));
1595}
1596
1597
1598Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599 return READ_FIELD(this, kSecondOffset);
1600}
1601
1602
ager@chromium.org870a0b62008-11-04 11:43:05 +00001603void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001604 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001605 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001606}
1607
1608
ager@chromium.org870a0b62008-11-04 11:43:05 +00001609String* SlicedString::buffer() {
1610 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611}
1612
1613
ager@chromium.org870a0b62008-11-04 11:43:05 +00001614void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001615 WRITE_FIELD(this, kBufferOffset, buffer);
1616 WRITE_BARRIER(this, kBufferOffset);
1617}
1618
1619
1620int SlicedString::start() {
1621 return READ_INT_FIELD(this, kStartOffset);
1622}
1623
1624
1625void SlicedString::set_start(int start) {
1626 WRITE_INT_FIELD(this, kStartOffset, start);
1627}
1628
1629
1630ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1631 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1632}
1633
1634
1635void ExternalAsciiString::set_resource(
1636 ExternalAsciiString::Resource* resource) {
1637 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1638}
1639
1640
1641ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1642 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1643}
1644
1645
1646void ExternalTwoByteString::set_resource(
1647 ExternalTwoByteString::Resource* resource) {
1648 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1649}
1650
1651
1652byte ByteArray::get(int index) {
1653 ASSERT(index >= 0 && index < this->length());
1654 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1655}
1656
1657
1658void ByteArray::set(int index, byte value) {
1659 ASSERT(index >= 0 && index < this->length());
1660 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1661}
1662
1663
1664int ByteArray::get_int(int index) {
1665 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1666 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1667}
1668
1669
1670ByteArray* ByteArray::FromDataStartAddress(Address address) {
1671 ASSERT_TAG_ALIGNED(address);
1672 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1673}
1674
1675
1676Address ByteArray::GetDataStartAddress() {
1677 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1678}
1679
1680
1681int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001682 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1683}
1684
1685
1686int Map::inobject_properties() {
1687 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001688}
1689
1690
1691int HeapObject::SizeFromMap(Map* map) {
1692 InstanceType instance_type = map->instance_type();
1693 // Only inline the two most frequent cases.
1694 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1695 if (instance_type == FIXED_ARRAY_TYPE) {
1696 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1697 }
1698 // Otherwise do the general size computation.
1699 return SlowSizeFromMap(map);
1700}
1701
1702
1703void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001704 ASSERT((value & ~(kPointerSize - 1)) == value);
1705 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001706 ASSERT(0 <= value && value < 256);
1707 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1708}
1709
1710
ager@chromium.org7c537e22008-10-16 08:43:32 +00001711void Map::set_inobject_properties(int value) {
1712 ASSERT(0 <= value && value < 256);
1713 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1714}
1715
1716
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001717InstanceType Map::instance_type() {
1718 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1719}
1720
1721
1722void Map::set_instance_type(InstanceType value) {
1723 ASSERT(0 <= value && value < 256);
1724 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1725}
1726
1727
1728int Map::unused_property_fields() {
1729 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1730}
1731
1732
1733void Map::set_unused_property_fields(int value) {
1734 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1735}
1736
1737
1738byte Map::bit_field() {
1739 return READ_BYTE_FIELD(this, kBitFieldOffset);
1740}
1741
1742
1743void Map::set_bit_field(byte value) {
1744 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1745}
1746
1747
1748void Map::set_non_instance_prototype(bool value) {
1749 if (value) {
1750 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1751 } else {
1752 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1753 }
1754}
1755
1756
1757bool Map::has_non_instance_prototype() {
1758 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1759}
1760
1761
ager@chromium.org870a0b62008-11-04 11:43:05 +00001762void Map::set_is_access_check_needed(bool access_check_needed) {
1763 if (access_check_needed) {
1764 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1765 } else {
1766 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1767 }
1768}
1769
1770
1771bool Map::is_access_check_needed() {
1772 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1773}
1774
1775
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001776Code::Flags Code::flags() {
1777 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1778}
1779
1780
1781void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001782 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001783 // Make sure that all call stubs have an arguments count.
1784 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1785 ExtractArgumentsCountFromFlags(flags) >= 0);
1786 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1787}
1788
1789
1790Code::Kind Code::kind() {
1791 return ExtractKindFromFlags(flags());
1792}
1793
1794
kasper.lund7276f142008-07-30 08:49:36 +00001795InlineCacheState Code::ic_state() {
1796 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001797 // Only allow uninitialized or debugger states for non-IC code
1798 // objects. This is used in the debugger to determine whether or not
1799 // a call to code object has been replaced with a debug break call.
1800 ASSERT(is_inline_cache_stub() ||
1801 result == UNINITIALIZED ||
1802 result == DEBUG_BREAK ||
1803 result == DEBUG_PREPARE_STEP_IN);
1804 return result;
1805}
1806
1807
1808PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001809 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001810 return ExtractTypeFromFlags(flags());
1811}
1812
1813
1814int Code::arguments_count() {
1815 ASSERT(is_call_stub() || kind() == STUB);
1816 return ExtractArgumentsCountFromFlags(flags());
1817}
1818
1819
1820CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001821 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001822 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1823 kStubMajorKeyOffset));
1824}
1825
1826
1827void Code::set_major_key(CodeStub::Major major) {
1828 ASSERT(kind() == STUB);
1829 ASSERT(0 <= major && major < 256);
1830 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001831}
1832
1833
1834bool Code::is_inline_cache_stub() {
1835 Kind kind = this->kind();
1836 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1837}
1838
1839
1840Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001841 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001842 PropertyType type,
1843 int argc) {
1844 // Compute the bit mask.
1845 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001846 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001847 bits |= type << kFlagsTypeShift;
1848 bits |= argc << kFlagsArgumentsCountShift;
1849 // Cast to flags and validate result before returning it.
1850 Flags result = static_cast<Flags>(bits);
1851 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001852 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001853 ASSERT(ExtractTypeFromFlags(result) == type);
1854 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1855 return result;
1856}
1857
1858
1859Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1860 PropertyType type,
1861 int argc) {
1862 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1863}
1864
1865
1866Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1867 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1868 return static_cast<Kind>(bits);
1869}
1870
1871
kasper.lund7276f142008-07-30 08:49:36 +00001872InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1873 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001874 return static_cast<InlineCacheState>(bits);
1875}
1876
1877
1878PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1879 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1880 return static_cast<PropertyType>(bits);
1881}
1882
1883
1884int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1885 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1886}
1887
1888
1889Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1890 int bits = flags & ~kFlagsTypeMask;
1891 return static_cast<Flags>(bits);
1892}
1893
1894
ager@chromium.org8bb60582008-12-11 12:02:20 +00001895Code* Code::GetCodeFromTargetAddress(Address address) {
1896 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1897 // GetCodeFromTargetAddress might be called when marking objects during mark
1898 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1899 // Code::cast. Code::cast does not work when the object's map is
1900 // marked.
1901 Code* result = reinterpret_cast<Code*>(code);
1902 return result;
1903}
1904
1905
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001906Object* Map::prototype() {
1907 return READ_FIELD(this, kPrototypeOffset);
1908}
1909
1910
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001911void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001912 ASSERT(value->IsNull() || value->IsJSObject());
1913 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001914 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001915}
1916
1917
1918ACCESSORS(Map, instance_descriptors, DescriptorArray,
1919 kInstanceDescriptorsOffset)
1920ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1921ACCESSORS(Map, constructor, Object, kConstructorOffset)
1922
1923ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1924ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1925
1926ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1927ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001928ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001929
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001930ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001931
1932ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1933ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1934ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1935ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1936ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1937
1938ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1939ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1940ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1941
1942ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1943ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1944ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1945ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1946ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1947ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1948
1949ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1950ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1951
1952ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1953ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1954
1955ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1956ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001957ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1958 kPropertyAccessorsOffset)
1959ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1960 kPrototypeTemplateOffset)
1961ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1962ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1963 kNamedPropertyHandlerOffset)
1964ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1965 kIndexedPropertyHandlerOffset)
1966ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1967 kInstanceTemplateOffset)
1968ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1969ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001970ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1971 kInstanceCallHandlerOffset)
1972ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1973 kAccessCheckInfoOffset)
1974ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1975
1976ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001977ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1978 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001979
1980ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1981ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1982
1983ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1984
1985ACCESSORS(Script, source, Object, kSourceOffset)
1986ACCESSORS(Script, name, Object, kNameOffset)
1987ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1988ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1989ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1990ACCESSORS(Script, type, Smi, kTypeOffset)
1991
1992ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1993ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1994ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1995ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1996
1997ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1998ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1999ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2000ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2001
2002ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2003ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2004 kInstanceClassNameOffset)
2005ACCESSORS(SharedFunctionInfo, function_data, Object,
2006 kExternalReferenceDataOffset)
2007ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
2008ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2009ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2010
2011BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2012 kHiddenPrototypeBit)
2013BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2014BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2015 kNeedsAccessCheckBit)
2016BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2017 kIsExpressionBit)
2018BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2019 kIsTopLevelBit)
2020
2021INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2022INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2023 kFormalParameterCountOffset)
2024INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2025 kExpectedNofPropertiesOffset)
2026INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2027 kStartPositionAndTypeOffset)
2028INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2029INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2030 kFunctionTokenPositionOffset)
2031
2032
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002033void SharedFunctionInfo::DontAdaptArguments() {
2034 ASSERT(code()->kind() == Code::BUILTIN);
2035 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2036}
2037
2038
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002039int SharedFunctionInfo::start_position() {
2040 return start_position_and_type() >> kStartPositionShift;
2041}
2042
2043
2044void SharedFunctionInfo::set_start_position(int start_position) {
2045 set_start_position_and_type((start_position << kStartPositionShift)
2046 | (start_position_and_type() & ~kStartPositionMask));
2047}
2048
2049
2050Code* SharedFunctionInfo::code() {
2051 return Code::cast(READ_FIELD(this, kCodeOffset));
2052}
2053
2054
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002055void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002056 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002057 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002058}
2059
2060
2061bool SharedFunctionInfo::is_compiled() {
2062 // TODO(1242782): Create a code kind for uncompiled code.
2063 return code()->kind() != Code::STUB;
2064}
2065
2066
2067bool JSFunction::IsBoilerplate() {
2068 return map() == Heap::boilerplate_function_map();
2069}
2070
2071
2072bool JSFunction::IsLoaded() {
2073 return shared()->lazy_load_data() == Heap::undefined_value();
2074}
2075
2076
2077Code* JSFunction::code() {
2078 return shared()->code();
2079}
2080
2081
2082void JSFunction::set_code(Code* value) {
2083 shared()->set_code(value);
2084}
2085
2086
2087Context* JSFunction::context() {
2088 return Context::cast(READ_FIELD(this, kContextOffset));
2089}
2090
2091
2092Object* JSFunction::unchecked_context() {
2093 return READ_FIELD(this, kContextOffset);
2094}
2095
2096
2097void JSFunction::set_context(Object* value) {
2098 ASSERT(value == Heap::undefined_value() || value->IsContext());
2099 WRITE_FIELD(this, kContextOffset, value);
2100 WRITE_BARRIER(this, kContextOffset);
2101}
2102
2103ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2104 kPrototypeOrInitialMapOffset)
2105
2106
2107Map* JSFunction::initial_map() {
2108 return Map::cast(prototype_or_initial_map());
2109}
2110
2111
2112void JSFunction::set_initial_map(Map* value) {
2113 set_prototype_or_initial_map(value);
2114}
2115
2116
2117bool JSFunction::has_initial_map() {
2118 return prototype_or_initial_map()->IsMap();
2119}
2120
2121
2122bool JSFunction::has_instance_prototype() {
2123 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2124}
2125
2126
2127bool JSFunction::has_prototype() {
2128 return map()->has_non_instance_prototype() || has_instance_prototype();
2129}
2130
2131
2132Object* JSFunction::instance_prototype() {
2133 ASSERT(has_instance_prototype());
2134 if (has_initial_map()) return initial_map()->prototype();
2135 // When there is no initial map and the prototype is a JSObject, the
2136 // initial map field is used for the prototype field.
2137 return prototype_or_initial_map();
2138}
2139
2140
2141Object* JSFunction::prototype() {
2142 ASSERT(has_prototype());
2143 // If the function's prototype property has been set to a non-JSObject
2144 // value, that value is stored in the constructor field of the map.
2145 if (map()->has_non_instance_prototype()) return map()->constructor();
2146 return instance_prototype();
2147}
2148
2149
2150bool JSFunction::is_compiled() {
2151 return shared()->is_compiled();
2152}
2153
2154
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002155int JSFunction::NumberOfLiterals() {
2156 return literals()->length();
2157}
2158
2159
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002160Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2161 ASSERT(0 <= id && id < kJSBuiltinsCount);
2162 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2163}
2164
2165
2166void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2167 Object* value) {
2168 ASSERT(0 <= id && id < kJSBuiltinsCount);
2169 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2170 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2171}
2172
2173
2174Address Proxy::proxy() {
2175 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2176}
2177
2178
2179void Proxy::set_proxy(Address value) {
2180 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2181}
2182
2183
2184void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2185 visitor->VisitExternalReference(
2186 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2187}
2188
2189
2190ACCESSORS(JSValue, value, Object, kValueOffset)
2191
2192
2193JSValue* JSValue::cast(Object* obj) {
2194 ASSERT(obj->IsJSValue());
2195 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2196 return reinterpret_cast<JSValue*>(obj);
2197}
2198
2199
2200INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2201INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2202INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2203
2204
2205Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002206 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002207}
2208
2209
2210void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002211 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002212}
2213
2214
2215byte* Code::instruction_start() {
2216 return FIELD_ADDR(this, kHeaderSize);
2217}
2218
2219
2220int Code::body_size() {
2221 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2222}
2223
2224
2225byte* Code::relocation_start() {
2226 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2227}
2228
2229
2230byte* Code::entry() {
2231 return instruction_start();
2232}
2233
2234
2235bool Code::contains(byte* pc) {
2236 return (instruction_start() <= pc) &&
2237 (pc < instruction_start() + instruction_size());
2238}
2239
2240
2241byte* Code::sinfo_start() {
2242 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2243}
2244
2245
2246ACCESSORS(JSArray, length, Object, kLengthOffset)
2247
2248
ager@chromium.org236ad962008-09-25 09:45:57 +00002249ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002250
2251
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002252JSRegExp::Type JSRegExp::TypeTag() {
2253 Object* data = this->data();
2254 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2255 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2256 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002257}
2258
2259
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002260JSRegExp::Flags JSRegExp::GetFlags() {
2261 ASSERT(this->data()->IsFixedArray());
2262 Object* data = this->data();
2263 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2264 return Flags(smi->value());
2265}
2266
2267
2268String* JSRegExp::Pattern() {
2269 ASSERT(this->data()->IsFixedArray());
2270 Object* data = this->data();
2271 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2272 return pattern;
2273}
2274
2275
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002276Object* JSRegExp::DataAt(int index) {
2277 ASSERT(TypeTag() != NOT_COMPILED);
2278 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002279}
2280
2281
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002282bool JSObject::HasFastElements() {
2283 return !elements()->IsDictionary();
2284}
2285
2286
2287bool JSObject::HasNamedInterceptor() {
2288 return map()->has_named_interceptor();
2289}
2290
2291
2292bool JSObject::HasIndexedInterceptor() {
2293 return map()->has_indexed_interceptor();
2294}
2295
2296
2297Dictionary* JSObject::property_dictionary() {
2298 ASSERT(!HasFastProperties());
2299 return Dictionary::cast(properties());
2300}
2301
2302
2303Dictionary* JSObject::element_dictionary() {
2304 ASSERT(!HasFastElements());
2305 return Dictionary::cast(elements());
2306}
2307
2308
2309bool String::HasHashCode() {
2310 return (length_field() & kHashComputedMask) != 0;
2311}
2312
2313
2314uint32_t String::Hash() {
2315 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002316 uint32_t field = length_field();
2317 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002318 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002319 return ComputeAndSetHash();
2320}
2321
2322
ager@chromium.org7c537e22008-10-16 08:43:32 +00002323StringHasher::StringHasher(int length)
2324 : length_(length),
2325 raw_running_hash_(0),
2326 array_index_(0),
2327 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2328 is_first_char_(true),
2329 is_valid_(true) { }
2330
2331
2332bool StringHasher::has_trivial_hash() {
2333 return length_ > String::kMaxMediumStringSize;
2334}
2335
2336
2337void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002338 // Use the Jenkins one-at-a-time hash function to update the hash
2339 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002340 raw_running_hash_ += c;
2341 raw_running_hash_ += (raw_running_hash_ << 10);
2342 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002343 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002344 if (is_array_index_) {
2345 if (c < '0' || c > '9') {
2346 is_array_index_ = false;
2347 } else {
2348 int d = c - '0';
2349 if (is_first_char_) {
2350 is_first_char_ = false;
2351 if (c == '0' && length_ > 1) {
2352 is_array_index_ = false;
2353 return;
2354 }
2355 }
2356 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2357 is_array_index_ = false;
2358 } else {
2359 array_index_ = array_index_ * 10 + d;
2360 }
2361 }
2362 }
2363}
2364
2365
2366void StringHasher::AddCharacterNoIndex(uc32 c) {
2367 ASSERT(!is_array_index());
2368 raw_running_hash_ += c;
2369 raw_running_hash_ += (raw_running_hash_ << 10);
2370 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2371}
2372
2373
2374uint32_t StringHasher::GetHash() {
2375 uint32_t result = raw_running_hash_;
2376 result += (result << 3);
2377 result ^= (result >> 11);
2378 result += (result << 15);
2379 return result;
2380}
2381
2382
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002383bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002384 uint32_t field = length_field();
2385 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002386 return SlowAsArrayIndex(index);
2387}
2388
2389
2390Object* JSObject::GetPrototype() {
2391 return JSObject::cast(this)->map()->prototype();
2392}
2393
2394
2395PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2396 return GetPropertyAttributeWithReceiver(this, key);
2397}
2398
2399
2400bool JSObject::HasElement(uint32_t index) {
2401 return HasElementWithReceiver(this, index);
2402}
2403
2404
2405bool AccessorInfo::all_can_read() {
2406 return BooleanBit::get(flag(), kAllCanReadBit);
2407}
2408
2409
2410void AccessorInfo::set_all_can_read(bool value) {
2411 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2412}
2413
2414
2415bool AccessorInfo::all_can_write() {
2416 return BooleanBit::get(flag(), kAllCanWriteBit);
2417}
2418
2419
2420void AccessorInfo::set_all_can_write(bool value) {
2421 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2422}
2423
2424
ager@chromium.org870a0b62008-11-04 11:43:05 +00002425bool AccessorInfo::prohibits_overwriting() {
2426 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2427}
2428
2429
2430void AccessorInfo::set_prohibits_overwriting(bool value) {
2431 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2432}
2433
2434
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002435PropertyAttributes AccessorInfo::property_attributes() {
2436 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2437}
2438
2439
2440void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2441 ASSERT(AttributesField::is_valid(attributes));
2442 int rest_value = flag()->value() & ~AttributesField::mask();
2443 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2444}
2445
2446void Dictionary::SetEntry(int entry,
2447 Object* key,
2448 Object* value,
2449 PropertyDetails details) {
2450 ASSERT(!key->IsString() || details.index() > 0);
2451 int index = EntryToIndex(entry);
2452 WriteBarrierMode mode = GetWriteBarrierMode();
2453 set(index, key, mode);
2454 set(index+1, value, mode);
2455 fast_set(this, index+2, details.AsSmi());
2456}
2457
2458
2459void Map::ClearCodeCache() {
2460 // No write barrier is needed since empty_fixed_array is not in new space.
2461 // Please note this function is used during marking:
2462 // - MarkCompactCollector::MarkUnmarkedObject
2463 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2464 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2465}
2466
2467
ager@chromium.org7c537e22008-10-16 08:43:32 +00002468void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002469 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002470 set_elements(storage);
2471}
2472
2473
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002474Object* FixedArray::Copy() {
2475 if (length() == 0) return this;
2476 return Heap::CopyFixedArray(this);
2477}
2478
2479
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002480#undef CAST_ACCESSOR
2481#undef INT_ACCESSORS
2482#undef SMI_ACCESSORS
2483#undef ACCESSORS
2484#undef FIELD_ADDR
2485#undef READ_FIELD
2486#undef WRITE_FIELD
2487#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002488#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002489#undef READ_MEMADDR_FIELD
2490#undef WRITE_MEMADDR_FIELD
2491#undef READ_DOUBLE_FIELD
2492#undef WRITE_DOUBLE_FIELD
2493#undef READ_INT_FIELD
2494#undef WRITE_INT_FIELD
2495#undef READ_SHORT_FIELD
2496#undef WRITE_SHORT_FIELD
2497#undef READ_BYTE_FIELD
2498#undef WRITE_BYTE_FIELD
2499
2500
2501} } // namespace v8::internal
2502
2503#endif // V8_OBJECTS_INL_H_