blob: 941b84c12018a1bfb683790883b00ea38d4d2c6d [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.orgddb913d2009-01-27 10:01:48 +00001434Object* String::TryFlattenIfNotFlat(StringShape shape) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001435 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)) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001439 return TryFlatten(shape);
ager@chromium.org236ad962008-09-25 09:45:57 +00001440 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001441 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001442}
1443
1444
ager@chromium.org870a0b62008-11-04 11:43:05 +00001445uint16_t String::Get(StringShape shape, int index) {
1446 ASSERT(shape.type() == StringShape(this).type());
1447 ASSERT(index >= 0 && index < length(shape));
1448 switch (shape.full_representation_tag()) {
1449 case kSeqStringTag | kAsciiStringTag:
1450 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1451 case kSeqStringTag | kTwoByteStringTag:
1452 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1453 case kConsStringTag | kAsciiStringTag:
1454 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001455 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001456 case kSlicedStringTag | kAsciiStringTag:
1457 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001458 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001459 case kExternalStringTag | kAsciiStringTag:
1460 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1461 case kExternalStringTag | kTwoByteStringTag:
1462 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001463 default:
1464 break;
1465 }
1466
1467 UNREACHABLE();
1468 return 0;
1469}
1470
1471
ager@chromium.org870a0b62008-11-04 11:43:05 +00001472void String::Set(StringShape shape, int index, uint16_t value) {
1473 ASSERT(shape.type() == StringShape(this).type());
1474 ASSERT(shape.type() == StringShape(this).type());
1475 ASSERT(index >= 0 && index < length(shape));
1476 ASSERT(shape.IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001477
ager@chromium.org870a0b62008-11-04 11:43:05 +00001478 return shape.IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001479 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1480 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001481}
1482
1483
ager@chromium.org870a0b62008-11-04 11:43:05 +00001484bool String::IsFlat(StringShape shape) {
1485 ASSERT(shape.type() == StringShape(this).type());
1486 switch (shape.representation_tag()) {
1487 case kConsStringTag: {
1488 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001489 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001490 return second->length() == 0;
1491 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001492 case kSlicedStringTag: {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001493 StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer());
1494 StringRepresentationTag tag = slice_shape.representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001495 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001496 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001497 default:
1498 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001499 }
1500}
1501
1502
ager@chromium.org7c537e22008-10-16 08:43:32 +00001503uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001504 ASSERT(index >= 0 && index < length());
1505 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1506}
1507
1508
ager@chromium.org7c537e22008-10-16 08:43:32 +00001509void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1511 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1512 static_cast<byte>(value));
1513}
1514
1515
ager@chromium.org7c537e22008-10-16 08:43:32 +00001516Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001517 return FIELD_ADDR(this, kHeaderSize);
1518}
1519
1520
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001521char* SeqAsciiString::GetChars() {
1522 return reinterpret_cast<char*>(GetCharsAddress());
1523}
1524
1525
ager@chromium.org7c537e22008-10-16 08:43:32 +00001526Address SeqTwoByteString::GetCharsAddress() {
1527 return FIELD_ADDR(this, kHeaderSize);
1528}
1529
1530
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001531uc16* SeqTwoByteString::GetChars() {
1532 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1533}
1534
1535
ager@chromium.org7c537e22008-10-16 08:43:32 +00001536uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 ASSERT(index >= 0 && index < length());
1538 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1539}
1540
1541
ager@chromium.org7c537e22008-10-16 08:43:32 +00001542void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543 ASSERT(index >= 0 && index < length());
1544 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1545}
1546
1547
ager@chromium.org870a0b62008-11-04 11:43:05 +00001548int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1550
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001551 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1552 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1553 ASSERT(kLongStringTag == 0);
1554
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001555 // Use the map (and not 'this') to compute the size tag, since
1556 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001557 length >>= shape.size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001558
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559 return SizeFor(length);
1560}
1561
1562
ager@chromium.org870a0b62008-11-04 11:43:05 +00001563int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001564 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1565
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001566 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1567 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1568 ASSERT(kLongStringTag == 0);
1569
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570 // Use the map (and not 'this') to compute the size tag, since
1571 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001572 length >>= shape.size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001573
1574 return SizeFor(length);
1575}
1576
1577
ager@chromium.org870a0b62008-11-04 11:43:05 +00001578String* ConsString::first() {
1579 return String::cast(READ_FIELD(this, kFirstOffset));
1580}
1581
1582
1583Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001584 return READ_FIELD(this, kFirstOffset);
1585}
1586
1587
ager@chromium.org870a0b62008-11-04 11:43:05 +00001588void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001590 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001591}
1592
1593
ager@chromium.org870a0b62008-11-04 11:43:05 +00001594String* ConsString::second() {
1595 return String::cast(READ_FIELD(this, kSecondOffset));
1596}
1597
1598
1599Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 return READ_FIELD(this, kSecondOffset);
1601}
1602
1603
ager@chromium.org870a0b62008-11-04 11:43:05 +00001604void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001605 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001606 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001607}
1608
1609
ager@chromium.org870a0b62008-11-04 11:43:05 +00001610String* SlicedString::buffer() {
1611 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612}
1613
1614
ager@chromium.org870a0b62008-11-04 11:43:05 +00001615void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001616 WRITE_FIELD(this, kBufferOffset, buffer);
1617 WRITE_BARRIER(this, kBufferOffset);
1618}
1619
1620
1621int SlicedString::start() {
1622 return READ_INT_FIELD(this, kStartOffset);
1623}
1624
1625
1626void SlicedString::set_start(int start) {
1627 WRITE_INT_FIELD(this, kStartOffset, start);
1628}
1629
1630
1631ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1632 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1633}
1634
1635
1636void ExternalAsciiString::set_resource(
1637 ExternalAsciiString::Resource* resource) {
1638 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1639}
1640
1641
ager@chromium.org6f10e412009-02-13 10:11:16 +00001642Map* ExternalAsciiString::StringMap(int length) {
1643 Map* map;
1644 // Number of characters: determines the map.
1645 if (length <= String::kMaxShortStringSize) {
1646 map = Heap::short_external_ascii_string_map();
1647 } else if (length <= String::kMaxMediumStringSize) {
1648 map = Heap::medium_external_ascii_string_map();
1649 } else {
1650 map = Heap::long_external_ascii_string_map();
1651 }
1652 return map;
1653}
1654
1655
1656Map* ExternalAsciiString::SymbolMap(int length) {
1657 Map* map;
1658 // Number of characters: determines the map.
1659 if (length <= String::kMaxShortStringSize) {
1660 map = Heap::short_external_ascii_symbol_map();
1661 } else if (length <= String::kMaxMediumStringSize) {
1662 map = Heap::medium_external_ascii_symbol_map();
1663 } else {
1664 map = Heap::long_external_ascii_symbol_map();
1665 }
1666 return map;
1667}
1668
1669
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001670ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1671 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1672}
1673
1674
1675void ExternalTwoByteString::set_resource(
1676 ExternalTwoByteString::Resource* resource) {
1677 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1678}
1679
1680
ager@chromium.org6f10e412009-02-13 10:11:16 +00001681Map* ExternalTwoByteString::StringMap(int length) {
1682 Map* map;
1683 // Number of characters: determines the map.
1684 if (length <= String::kMaxShortStringSize) {
1685 map = Heap::short_external_string_map();
1686 } else if (length <= String::kMaxMediumStringSize) {
1687 map = Heap::medium_external_string_map();
1688 } else {
1689 map = Heap::long_external_string_map();
1690 }
1691 return map;
1692}
1693
1694
1695Map* ExternalTwoByteString::SymbolMap(int length) {
1696 Map* map;
1697 // Number of characters: determines the map.
1698 if (length <= String::kMaxShortStringSize) {
1699 map = Heap::short_external_symbol_map();
1700 } else if (length <= String::kMaxMediumStringSize) {
1701 map = Heap::medium_external_symbol_map();
1702 } else {
1703 map = Heap::long_external_symbol_map();
1704 }
1705 return map;
1706}
1707
1708
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001709byte ByteArray::get(int index) {
1710 ASSERT(index >= 0 && index < this->length());
1711 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1712}
1713
1714
1715void ByteArray::set(int index, byte value) {
1716 ASSERT(index >= 0 && index < this->length());
1717 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1718}
1719
1720
1721int ByteArray::get_int(int index) {
1722 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1723 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1724}
1725
1726
1727ByteArray* ByteArray::FromDataStartAddress(Address address) {
1728 ASSERT_TAG_ALIGNED(address);
1729 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1730}
1731
1732
1733Address ByteArray::GetDataStartAddress() {
1734 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1735}
1736
1737
1738int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001739 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1740}
1741
1742
1743int Map::inobject_properties() {
1744 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745}
1746
1747
1748int HeapObject::SizeFromMap(Map* map) {
1749 InstanceType instance_type = map->instance_type();
1750 // Only inline the two most frequent cases.
1751 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1752 if (instance_type == FIXED_ARRAY_TYPE) {
1753 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1754 }
1755 // Otherwise do the general size computation.
1756 return SlowSizeFromMap(map);
1757}
1758
1759
1760void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001761 ASSERT((value & ~(kPointerSize - 1)) == value);
1762 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001763 ASSERT(0 <= value && value < 256);
1764 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1765}
1766
1767
ager@chromium.org7c537e22008-10-16 08:43:32 +00001768void Map::set_inobject_properties(int value) {
1769 ASSERT(0 <= value && value < 256);
1770 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1771}
1772
1773
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001774InstanceType Map::instance_type() {
1775 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1776}
1777
1778
1779void Map::set_instance_type(InstanceType value) {
1780 ASSERT(0 <= value && value < 256);
1781 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1782}
1783
1784
1785int Map::unused_property_fields() {
1786 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1787}
1788
1789
1790void Map::set_unused_property_fields(int value) {
1791 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1792}
1793
1794
1795byte Map::bit_field() {
1796 return READ_BYTE_FIELD(this, kBitFieldOffset);
1797}
1798
1799
1800void Map::set_bit_field(byte value) {
1801 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1802}
1803
1804
1805void Map::set_non_instance_prototype(bool value) {
1806 if (value) {
1807 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1808 } else {
1809 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1810 }
1811}
1812
1813
1814bool Map::has_non_instance_prototype() {
1815 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1816}
1817
1818
ager@chromium.org870a0b62008-11-04 11:43:05 +00001819void Map::set_is_access_check_needed(bool access_check_needed) {
1820 if (access_check_needed) {
1821 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1822 } else {
1823 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1824 }
1825}
1826
1827
1828bool Map::is_access_check_needed() {
1829 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1830}
1831
1832
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001833Code::Flags Code::flags() {
1834 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1835}
1836
1837
1838void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001839 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001840 // Make sure that all call stubs have an arguments count.
1841 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1842 ExtractArgumentsCountFromFlags(flags) >= 0);
1843 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1844}
1845
1846
1847Code::Kind Code::kind() {
1848 return ExtractKindFromFlags(flags());
1849}
1850
1851
kasper.lund7276f142008-07-30 08:49:36 +00001852InlineCacheState Code::ic_state() {
1853 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001854 // Only allow uninitialized or debugger states for non-IC code
1855 // objects. This is used in the debugger to determine whether or not
1856 // a call to code object has been replaced with a debug break call.
1857 ASSERT(is_inline_cache_stub() ||
1858 result == UNINITIALIZED ||
1859 result == DEBUG_BREAK ||
1860 result == DEBUG_PREPARE_STEP_IN);
1861 return result;
1862}
1863
1864
1865PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001866 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001867 return ExtractTypeFromFlags(flags());
1868}
1869
1870
1871int Code::arguments_count() {
1872 ASSERT(is_call_stub() || kind() == STUB);
1873 return ExtractArgumentsCountFromFlags(flags());
1874}
1875
1876
1877CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001878 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001879 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1880 kStubMajorKeyOffset));
1881}
1882
1883
1884void Code::set_major_key(CodeStub::Major major) {
1885 ASSERT(kind() == STUB);
1886 ASSERT(0 <= major && major < 256);
1887 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001888}
1889
1890
1891bool Code::is_inline_cache_stub() {
1892 Kind kind = this->kind();
1893 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1894}
1895
1896
1897Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001898 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001899 PropertyType type,
1900 int argc) {
1901 // Compute the bit mask.
1902 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001903 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001904 bits |= type << kFlagsTypeShift;
1905 bits |= argc << kFlagsArgumentsCountShift;
1906 // Cast to flags and validate result before returning it.
1907 Flags result = static_cast<Flags>(bits);
1908 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001909 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001910 ASSERT(ExtractTypeFromFlags(result) == type);
1911 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1912 return result;
1913}
1914
1915
1916Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1917 PropertyType type,
1918 int argc) {
1919 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1920}
1921
1922
1923Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1924 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1925 return static_cast<Kind>(bits);
1926}
1927
1928
kasper.lund7276f142008-07-30 08:49:36 +00001929InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1930 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001931 return static_cast<InlineCacheState>(bits);
1932}
1933
1934
1935PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1936 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1937 return static_cast<PropertyType>(bits);
1938}
1939
1940
1941int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1942 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1943}
1944
1945
1946Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1947 int bits = flags & ~kFlagsTypeMask;
1948 return static_cast<Flags>(bits);
1949}
1950
1951
ager@chromium.org8bb60582008-12-11 12:02:20 +00001952Code* Code::GetCodeFromTargetAddress(Address address) {
1953 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1954 // GetCodeFromTargetAddress might be called when marking objects during mark
1955 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1956 // Code::cast. Code::cast does not work when the object's map is
1957 // marked.
1958 Code* result = reinterpret_cast<Code*>(code);
1959 return result;
1960}
1961
1962
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001963Object* Map::prototype() {
1964 return READ_FIELD(this, kPrototypeOffset);
1965}
1966
1967
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001968void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001969 ASSERT(value->IsNull() || value->IsJSObject());
1970 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001971 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001972}
1973
1974
1975ACCESSORS(Map, instance_descriptors, DescriptorArray,
1976 kInstanceDescriptorsOffset)
1977ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1978ACCESSORS(Map, constructor, Object, kConstructorOffset)
1979
1980ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1981ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1982
1983ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1984ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001985ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001986
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001987ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001988
1989ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1990ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1991ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1992ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1993ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1994
1995ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1996ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1997ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1998
1999ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2000ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2001ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2002ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2003ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2004ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2005
2006ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2007ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2008
2009ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2010ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2011
2012ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2013ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002014ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2015 kPropertyAccessorsOffset)
2016ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2017 kPrototypeTemplateOffset)
2018ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2019ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2020 kNamedPropertyHandlerOffset)
2021ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2022 kIndexedPropertyHandlerOffset)
2023ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2024 kInstanceTemplateOffset)
2025ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2026ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002027ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2028 kInstanceCallHandlerOffset)
2029ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2030 kAccessCheckInfoOffset)
2031ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2032
2033ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002034ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2035 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002036
2037ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2038ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2039
2040ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2041
2042ACCESSORS(Script, source, Object, kSourceOffset)
2043ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002044ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002045ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2046ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2047ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2048ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002049ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002050
2051ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2052ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2053ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2054ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2055
2056ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2057ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2058ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2059ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2060
2061ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2062ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2063 kInstanceClassNameOffset)
2064ACCESSORS(SharedFunctionInfo, function_data, Object,
2065 kExternalReferenceDataOffset)
2066ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
2067ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2068ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2069
2070BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2071 kHiddenPrototypeBit)
2072BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2073BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2074 kNeedsAccessCheckBit)
2075BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2076 kIsExpressionBit)
2077BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2078 kIsTopLevelBit)
2079
2080INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2081INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2082 kFormalParameterCountOffset)
2083INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2084 kExpectedNofPropertiesOffset)
2085INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2086 kStartPositionAndTypeOffset)
2087INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2088INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2089 kFunctionTokenPositionOffset)
2090
2091
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002092void SharedFunctionInfo::DontAdaptArguments() {
2093 ASSERT(code()->kind() == Code::BUILTIN);
2094 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2095}
2096
2097
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002098int SharedFunctionInfo::start_position() {
2099 return start_position_and_type() >> kStartPositionShift;
2100}
2101
2102
2103void SharedFunctionInfo::set_start_position(int start_position) {
2104 set_start_position_and_type((start_position << kStartPositionShift)
2105 | (start_position_and_type() & ~kStartPositionMask));
2106}
2107
2108
2109Code* SharedFunctionInfo::code() {
2110 return Code::cast(READ_FIELD(this, kCodeOffset));
2111}
2112
2113
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002114void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002115 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002116 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002117}
2118
2119
2120bool SharedFunctionInfo::is_compiled() {
2121 // TODO(1242782): Create a code kind for uncompiled code.
2122 return code()->kind() != Code::STUB;
2123}
2124
2125
2126bool JSFunction::IsBoilerplate() {
2127 return map() == Heap::boilerplate_function_map();
2128}
2129
2130
2131bool JSFunction::IsLoaded() {
2132 return shared()->lazy_load_data() == Heap::undefined_value();
2133}
2134
2135
2136Code* JSFunction::code() {
2137 return shared()->code();
2138}
2139
2140
2141void JSFunction::set_code(Code* value) {
2142 shared()->set_code(value);
2143}
2144
2145
2146Context* JSFunction::context() {
2147 return Context::cast(READ_FIELD(this, kContextOffset));
2148}
2149
2150
2151Object* JSFunction::unchecked_context() {
2152 return READ_FIELD(this, kContextOffset);
2153}
2154
2155
2156void JSFunction::set_context(Object* value) {
2157 ASSERT(value == Heap::undefined_value() || value->IsContext());
2158 WRITE_FIELD(this, kContextOffset, value);
2159 WRITE_BARRIER(this, kContextOffset);
2160}
2161
2162ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2163 kPrototypeOrInitialMapOffset)
2164
2165
2166Map* JSFunction::initial_map() {
2167 return Map::cast(prototype_or_initial_map());
2168}
2169
2170
2171void JSFunction::set_initial_map(Map* value) {
2172 set_prototype_or_initial_map(value);
2173}
2174
2175
2176bool JSFunction::has_initial_map() {
2177 return prototype_or_initial_map()->IsMap();
2178}
2179
2180
2181bool JSFunction::has_instance_prototype() {
2182 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2183}
2184
2185
2186bool JSFunction::has_prototype() {
2187 return map()->has_non_instance_prototype() || has_instance_prototype();
2188}
2189
2190
2191Object* JSFunction::instance_prototype() {
2192 ASSERT(has_instance_prototype());
2193 if (has_initial_map()) return initial_map()->prototype();
2194 // When there is no initial map and the prototype is a JSObject, the
2195 // initial map field is used for the prototype field.
2196 return prototype_or_initial_map();
2197}
2198
2199
2200Object* JSFunction::prototype() {
2201 ASSERT(has_prototype());
2202 // If the function's prototype property has been set to a non-JSObject
2203 // value, that value is stored in the constructor field of the map.
2204 if (map()->has_non_instance_prototype()) return map()->constructor();
2205 return instance_prototype();
2206}
2207
2208
2209bool JSFunction::is_compiled() {
2210 return shared()->is_compiled();
2211}
2212
2213
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002214int JSFunction::NumberOfLiterals() {
2215 return literals()->length();
2216}
2217
2218
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002219Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2220 ASSERT(0 <= id && id < kJSBuiltinsCount);
2221 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2222}
2223
2224
2225void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2226 Object* value) {
2227 ASSERT(0 <= id && id < kJSBuiltinsCount);
2228 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2229 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2230}
2231
2232
2233Address Proxy::proxy() {
2234 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2235}
2236
2237
2238void Proxy::set_proxy(Address value) {
2239 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2240}
2241
2242
2243void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2244 visitor->VisitExternalReference(
2245 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2246}
2247
2248
2249ACCESSORS(JSValue, value, Object, kValueOffset)
2250
2251
2252JSValue* JSValue::cast(Object* obj) {
2253 ASSERT(obj->IsJSValue());
2254 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2255 return reinterpret_cast<JSValue*>(obj);
2256}
2257
2258
2259INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2260INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2261INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2262
2263
2264Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002265 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002266}
2267
2268
2269void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002270 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002271}
2272
2273
2274byte* Code::instruction_start() {
2275 return FIELD_ADDR(this, kHeaderSize);
2276}
2277
2278
2279int Code::body_size() {
2280 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2281}
2282
2283
2284byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002285 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002286}
2287
2288
2289byte* Code::entry() {
2290 return instruction_start();
2291}
2292
2293
2294bool Code::contains(byte* pc) {
2295 return (instruction_start() <= pc) &&
2296 (pc < instruction_start() + instruction_size());
2297}
2298
2299
2300byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002301 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002302}
2303
2304
2305ACCESSORS(JSArray, length, Object, kLengthOffset)
2306
2307
ager@chromium.org236ad962008-09-25 09:45:57 +00002308ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002309
2310
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002311JSRegExp::Type JSRegExp::TypeTag() {
2312 Object* data = this->data();
2313 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2314 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2315 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002316}
2317
2318
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002319JSRegExp::Flags JSRegExp::GetFlags() {
2320 ASSERT(this->data()->IsFixedArray());
2321 Object* data = this->data();
2322 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2323 return Flags(smi->value());
2324}
2325
2326
2327String* JSRegExp::Pattern() {
2328 ASSERT(this->data()->IsFixedArray());
2329 Object* data = this->data();
2330 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2331 return pattern;
2332}
2333
2334
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002335Object* JSRegExp::DataAt(int index) {
2336 ASSERT(TypeTag() != NOT_COMPILED);
2337 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002338}
2339
2340
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002341void JSRegExp::SetDataAt(int index, Object* value) {
2342 ASSERT(TypeTag() != NOT_COMPILED);
2343 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2344 FixedArray::cast(data())->set(index, value);
2345}
2346
2347
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002348bool JSObject::HasFastElements() {
2349 return !elements()->IsDictionary();
2350}
2351
2352
2353bool JSObject::HasNamedInterceptor() {
2354 return map()->has_named_interceptor();
2355}
2356
2357
2358bool JSObject::HasIndexedInterceptor() {
2359 return map()->has_indexed_interceptor();
2360}
2361
2362
2363Dictionary* JSObject::property_dictionary() {
2364 ASSERT(!HasFastProperties());
2365 return Dictionary::cast(properties());
2366}
2367
2368
2369Dictionary* JSObject::element_dictionary() {
2370 ASSERT(!HasFastElements());
2371 return Dictionary::cast(elements());
2372}
2373
2374
2375bool String::HasHashCode() {
2376 return (length_field() & kHashComputedMask) != 0;
2377}
2378
2379
2380uint32_t String::Hash() {
2381 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002382 uint32_t field = length_field();
2383 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002384 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002385 return ComputeAndSetHash();
2386}
2387
2388
ager@chromium.org7c537e22008-10-16 08:43:32 +00002389StringHasher::StringHasher(int length)
2390 : length_(length),
2391 raw_running_hash_(0),
2392 array_index_(0),
2393 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2394 is_first_char_(true),
2395 is_valid_(true) { }
2396
2397
2398bool StringHasher::has_trivial_hash() {
2399 return length_ > String::kMaxMediumStringSize;
2400}
2401
2402
2403void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002404 // Use the Jenkins one-at-a-time hash function to update the hash
2405 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002406 raw_running_hash_ += c;
2407 raw_running_hash_ += (raw_running_hash_ << 10);
2408 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002409 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002410 if (is_array_index_) {
2411 if (c < '0' || c > '9') {
2412 is_array_index_ = false;
2413 } else {
2414 int d = c - '0';
2415 if (is_first_char_) {
2416 is_first_char_ = false;
2417 if (c == '0' && length_ > 1) {
2418 is_array_index_ = false;
2419 return;
2420 }
2421 }
2422 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2423 is_array_index_ = false;
2424 } else {
2425 array_index_ = array_index_ * 10 + d;
2426 }
2427 }
2428 }
2429}
2430
2431
2432void StringHasher::AddCharacterNoIndex(uc32 c) {
2433 ASSERT(!is_array_index());
2434 raw_running_hash_ += c;
2435 raw_running_hash_ += (raw_running_hash_ << 10);
2436 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2437}
2438
2439
2440uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002441 // Get the calculated raw hash value and do some more bit ops to distribute
2442 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002443 uint32_t result = raw_running_hash_;
2444 result += (result << 3);
2445 result ^= (result >> 11);
2446 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002447 if (result == 0) {
2448 result = 27;
2449 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002450 return result;
2451}
2452
2453
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002454bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002455 uint32_t field = length_field();
2456 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002457 return SlowAsArrayIndex(index);
2458}
2459
2460
2461Object* JSObject::GetPrototype() {
2462 return JSObject::cast(this)->map()->prototype();
2463}
2464
2465
2466PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2467 return GetPropertyAttributeWithReceiver(this, key);
2468}
2469
2470
2471bool JSObject::HasElement(uint32_t index) {
2472 return HasElementWithReceiver(this, index);
2473}
2474
2475
2476bool AccessorInfo::all_can_read() {
2477 return BooleanBit::get(flag(), kAllCanReadBit);
2478}
2479
2480
2481void AccessorInfo::set_all_can_read(bool value) {
2482 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2483}
2484
2485
2486bool AccessorInfo::all_can_write() {
2487 return BooleanBit::get(flag(), kAllCanWriteBit);
2488}
2489
2490
2491void AccessorInfo::set_all_can_write(bool value) {
2492 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2493}
2494
2495
ager@chromium.org870a0b62008-11-04 11:43:05 +00002496bool AccessorInfo::prohibits_overwriting() {
2497 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2498}
2499
2500
2501void AccessorInfo::set_prohibits_overwriting(bool value) {
2502 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2503}
2504
2505
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002506PropertyAttributes AccessorInfo::property_attributes() {
2507 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2508}
2509
2510
2511void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2512 ASSERT(AttributesField::is_valid(attributes));
2513 int rest_value = flag()->value() & ~AttributesField::mask();
2514 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2515}
2516
2517void Dictionary::SetEntry(int entry,
2518 Object* key,
2519 Object* value,
2520 PropertyDetails details) {
2521 ASSERT(!key->IsString() || details.index() > 0);
2522 int index = EntryToIndex(entry);
2523 WriteBarrierMode mode = GetWriteBarrierMode();
2524 set(index, key, mode);
2525 set(index+1, value, mode);
2526 fast_set(this, index+2, details.AsSmi());
2527}
2528
2529
2530void Map::ClearCodeCache() {
2531 // No write barrier is needed since empty_fixed_array is not in new space.
2532 // Please note this function is used during marking:
2533 // - MarkCompactCollector::MarkUnmarkedObject
2534 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2535 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2536}
2537
2538
ager@chromium.org7c537e22008-10-16 08:43:32 +00002539void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002540 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002541 set_elements(storage);
2542}
2543
2544
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002545Object* FixedArray::Copy() {
2546 if (length() == 0) return this;
2547 return Heap::CopyFixedArray(this);
2548}
2549
2550
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002551#undef CAST_ACCESSOR
2552#undef INT_ACCESSORS
2553#undef SMI_ACCESSORS
2554#undef ACCESSORS
2555#undef FIELD_ADDR
2556#undef READ_FIELD
2557#undef WRITE_FIELD
2558#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002559#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002560#undef READ_MEMADDR_FIELD
2561#undef WRITE_MEMADDR_FIELD
2562#undef READ_DOUBLE_FIELD
2563#undef WRITE_DOUBLE_FIELD
2564#undef READ_INT_FIELD
2565#undef WRITE_INT_FIELD
2566#undef READ_SHORT_FIELD
2567#undef WRITE_SHORT_FIELD
2568#undef READ_BYTE_FIELD
2569#undef WRITE_BYTE_FIELD
2570
2571
2572} } // namespace v8::internal
2573
2574#endif // V8_OBJECTS_INL_H_