blob: 475b57bf82c31cf68290caaacf8885332df074a9 [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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48}
49
50
51Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53}
54
55
56#define CAST_ACCESSOR(type) \
57 type* type::cast(Object* object) { \
58 ASSERT(object->Is##type()); \
59 return reinterpret_cast<type*>(object); \
60 }
61
62
63#define INT_ACCESSORS(holder, name, offset) \
64 int holder::name() { return READ_INT_FIELD(this, offset); } \
65 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
66
67
68#define ACCESSORS(holder, name, type, offset) \
69 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000070 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000072 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073 }
74
75
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000076
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077#define SMI_ACCESSORS(holder, name, offset) \
78 int holder::name() { \
79 Object* value = READ_FIELD(this, offset); \
80 return Smi::cast(value)->value(); \
81 } \
82 void holder::set_##name(int value) { \
83 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
84 }
85
86
87#define BOOL_ACCESSORS(holder, field, name, offset) \
88 bool holder::name() { \
89 return BooleanBit::get(field(), offset); \
90 } \
91 void holder::set_##name(bool value) { \
92 set_##field(BooleanBit::set(field(), offset, value)); \
93 }
94
95
96bool Object::IsSmi() {
97 return HAS_SMI_TAG(this);
98}
99
100
101bool Object::IsHeapObject() {
102 return HAS_HEAP_OBJECT_TAG(this);
103}
104
105
106bool Object::IsHeapNumber() {
107 return Object::IsHeapObject()
108 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
109}
110
111
112bool Object::IsString() {
113 return Object::IsHeapObject()
114 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
115}
116
117
ager@chromium.org870a0b62008-11-04 11:43:05 +0000118bool Object::IsSymbol() {
119 if (!this->IsHeapObject()) return false;
120 uint32_t type = HeapObject::cast(this)->map()->instance_type();
121 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
122 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123}
124
125
126bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000127 if (!this->IsHeapObject()) return false;
128 uint32_t type = HeapObject::cast(this)->map()->instance_type();
129 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
130 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131}
132
133
ager@chromium.org870a0b62008-11-04 11:43:05 +0000134#ifdef DEBUG
135// These are for cast checks. If you need one of these in release
136// mode you should consider using a StringShape before moving it out
137// of the ifdef
138
139bool Object::IsSeqString() {
140 if (!IsString()) return false;
141 return StringShape(String::cast(this)).IsSequential();
142}
143
144
145bool Object::IsSeqAsciiString() {
146 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000147 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000148 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000149}
150
151
152bool Object::IsSeqTwoByteString() {
153 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000154 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000155 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156}
157
158
159bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000160 if (!IsString()) return false;
161 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162}
163
164
165bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000166 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000167 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000168 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169}
170
171
172bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000173 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000174 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000175 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176}
177
178
ager@chromium.org870a0b62008-11-04 11:43:05 +0000179bool Object::IsSlicedString() {
180 if (!IsString()) return false;
181 return StringShape(String::cast(this)).IsSliced();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182}
183
184
ager@chromium.org870a0b62008-11-04 11:43:05 +0000185#endif // DEBUG
186
187
188StringShape::StringShape(String* str)
189 : type_(str->map()->instance_type()) {
190 set_valid();
191 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000192}
193
194
ager@chromium.org870a0b62008-11-04 11:43:05 +0000195StringShape::StringShape(Map* map)
196 : type_(map->instance_type()) {
197 set_valid();
198 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199}
200
201
ager@chromium.org870a0b62008-11-04 11:43:05 +0000202StringShape::StringShape(InstanceType t)
203 : type_(static_cast<uint32_t>(t)) {
204 set_valid();
205 ASSERT((type_ & kIsNotStringMask) == kStringTag);
206}
207
208
209bool StringShape::IsSymbol() {
210 ASSERT(valid());
211 return (type_ & kIsSymbolMask) == kSymbolTag;
212}
213
214
ager@chromium.org5ec48922009-05-05 07:25:34 +0000215bool String::IsAsciiRepresentation() {
216 uint32_t type = map()->instance_type();
217 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
218 return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
219 }
220 if ((type & kStringRepresentationMask) == kConsStringTag &&
221 ConsString::cast(this)->second()->length() == 0) {
222 return ConsString::cast(this)->first()->IsAsciiRepresentation();
223 }
224 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000225}
226
227
ager@chromium.org5ec48922009-05-05 07:25:34 +0000228bool String::IsTwoByteRepresentation() {
229 uint32_t type = map()->instance_type();
230 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
231 return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
232 } else if ((type & kStringRepresentationMask) == kConsStringTag &&
233 ConsString::cast(this)->second()->length() == 0) {
234 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
235 }
236 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000237}
238
239
240bool StringShape::IsCons() {
241 return (type_ & kStringRepresentationMask) == kConsStringTag;
242}
243
244
245bool StringShape::IsSliced() {
246 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
247}
248
249
250bool StringShape::IsExternal() {
251 return (type_ & kStringRepresentationMask) == kExternalStringTag;
252}
253
254
255bool StringShape::IsSequential() {
256 return (type_ & kStringRepresentationMask) == kSeqStringTag;
257}
258
259
260StringRepresentationTag StringShape::representation_tag() {
261 uint32_t tag = (type_ & kStringRepresentationMask);
262 return static_cast<StringRepresentationTag>(tag);
263}
264
265
266uint32_t StringShape::full_representation_tag() {
267 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
268}
269
270
271uint32_t StringShape::size_tag() {
272 return (type_ & kStringSizeMask);
273}
274
275
276bool StringShape::IsSequentialAscii() {
277 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
278}
279
280
281bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000282 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000283}
284
285
286bool StringShape::IsExternalAscii() {
287 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
288}
289
290
291bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000292 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000293}
294
295
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000296uc32 FlatStringReader::Get(int index) {
297 ASSERT(0 <= index && index <= length_);
298 if (is_ascii_) {
299 return static_cast<const byte*>(start_)[index];
300 } else {
301 return static_cast<const uc16*>(start_)[index];
302 }
303}
304
305
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306bool Object::IsNumber() {
307 return IsSmi() || IsHeapNumber();
308}
309
310
311bool Object::IsByteArray() {
312 return Object::IsHeapObject()
313 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
314}
315
316
317bool Object::IsFailure() {
318 return HAS_FAILURE_TAG(this);
319}
320
321
322bool Object::IsRetryAfterGC() {
323 return HAS_FAILURE_TAG(this)
324 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
325}
326
327
ager@chromium.org7c537e22008-10-16 08:43:32 +0000328bool Object::IsOutOfMemoryFailure() {
329 return HAS_FAILURE_TAG(this)
330 && Failure::cast(this)->IsOutOfMemoryException();
331}
332
333
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000334bool Object::IsException() {
335 return this == Failure::Exception();
336}
337
338
339bool Object::IsJSObject() {
340 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000341 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342}
343
344
ager@chromium.org32912102009-01-16 10:38:43 +0000345bool Object::IsJSContextExtensionObject() {
346 return IsHeapObject()
347 && (HeapObject::cast(this)->map()->instance_type() ==
348 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
349}
350
351
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000352bool Object::IsMap() {
353 return Object::IsHeapObject()
354 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
355}
356
357
358bool Object::IsFixedArray() {
359 return Object::IsHeapObject()
360 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
361}
362
363
364bool Object::IsDescriptorArray() {
365 return IsFixedArray();
366}
367
368
369bool Object::IsContext() {
370 return Object::IsHeapObject()
371 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000372 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000373 HeapObject::cast(this)->map() == Heap::global_context_map());
374}
375
376
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000377bool Object::IsCatchContext() {
378 return Object::IsHeapObject()
379 && HeapObject::cast(this)->map() == Heap::catch_context_map();
380}
381
382
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000383bool Object::IsGlobalContext() {
384 return Object::IsHeapObject()
385 && HeapObject::cast(this)->map() == Heap::global_context_map();
386}
387
388
389bool Object::IsJSFunction() {
390 return Object::IsHeapObject()
391 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
392}
393
394
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000395template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396 return obj->IsJSFunction();
397}
398
399
400bool Object::IsCode() {
401 return Object::IsHeapObject()
402 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
403}
404
405
406bool Object::IsOddball() {
407 return Object::IsHeapObject()
408 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
409}
410
411
412bool Object::IsSharedFunctionInfo() {
413 return Object::IsHeapObject() &&
414 (HeapObject::cast(this)->map()->instance_type() ==
415 SHARED_FUNCTION_INFO_TYPE);
416}
417
418
419bool Object::IsJSValue() {
420 return Object::IsHeapObject()
421 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
422}
423
424
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000425bool Object::IsStringWrapper() {
426 return IsJSValue() && JSValue::cast(this)->value()->IsString();
427}
428
429
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000430bool Object::IsProxy() {
431 return Object::IsHeapObject()
432 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
433}
434
435
436bool Object::IsBoolean() {
437 return IsTrue() || IsFalse();
438}
439
440
441bool Object::IsJSArray() {
442 return Object::IsHeapObject()
443 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
444}
445
446
ager@chromium.org236ad962008-09-25 09:45:57 +0000447bool Object::IsJSRegExp() {
448 return Object::IsHeapObject()
449 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
450}
451
452
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000453template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000454 return obj->IsJSArray();
455}
456
457
458bool Object::IsHashTable() {
459 return Object::IsHeapObject()
460 && HeapObject::cast(this)->map() == Heap::hash_table_map();
461}
462
463
464bool Object::IsDictionary() {
465 return IsHashTable() && this != Heap::symbol_table();
466}
467
468
469bool Object::IsSymbolTable() {
470 return IsHashTable() && this == Heap::symbol_table();
471}
472
473
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000474bool Object::IsCompilationCacheTable() {
475 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000476}
477
478
ager@chromium.org236ad962008-09-25 09:45:57 +0000479bool Object::IsMapCache() {
480 return IsHashTable();
481}
482
483
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000484bool Object::IsLookupCache() {
485 return IsHashTable();
486}
487
488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489bool Object::IsPrimitive() {
490 return IsOddball() || IsNumber() || IsString();
491}
492
493
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000494bool Object::IsJSGlobalProxy() {
495 bool result = IsHeapObject() &&
496 (HeapObject::cast(this)->map()->instance_type() ==
497 JS_GLOBAL_PROXY_TYPE);
498 ASSERT(!result || IsAccessCheckNeeded());
499 return result;
500}
501
502
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000504 if (!IsHeapObject()) return false;
505
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000506 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000507 return type == JS_GLOBAL_OBJECT_TYPE ||
508 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509}
510
511
512bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513 return IsHeapObject() &&
514 (HeapObject::cast(this)->map()->instance_type() ==
515 JS_GLOBAL_OBJECT_TYPE);
516}
517
518
519bool Object::IsJSBuiltinsObject() {
520 return IsHeapObject() &&
521 (HeapObject::cast(this)->map()->instance_type() ==
522 JS_BUILTINS_OBJECT_TYPE);
523}
524
525
526bool Object::IsUndetectableObject() {
527 return IsHeapObject()
528 && HeapObject::cast(this)->map()->is_undetectable();
529}
530
531
532bool Object::IsAccessCheckNeeded() {
533 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000534 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000535}
536
537
538bool Object::IsStruct() {
539 if (!IsHeapObject()) return false;
540 switch (HeapObject::cast(this)->map()->instance_type()) {
541#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
542 STRUCT_LIST(MAKE_STRUCT_CASE)
543#undef MAKE_STRUCT_CASE
544 default: return false;
545 }
546}
547
548
549#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
550 bool Object::Is##Name() { \
551 return Object::IsHeapObject() \
552 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
553 }
554 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
555#undef MAKE_STRUCT_PREDICATE
556
557
558bool Object::IsUndefined() {
559 return this == Heap::undefined_value();
560}
561
562
563bool Object::IsTheHole() {
564 return this == Heap::the_hole_value();
565}
566
567
568bool Object::IsNull() {
569 return this == Heap::null_value();
570}
571
572
573bool Object::IsTrue() {
574 return this == Heap::true_value();
575}
576
577
578bool Object::IsFalse() {
579 return this == Heap::false_value();
580}
581
582
583double Object::Number() {
584 ASSERT(IsNumber());
585 return IsSmi()
586 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
587 : reinterpret_cast<HeapNumber*>(this)->value();
588}
589
590
591
592Object* Object::ToSmi() {
593 if (IsSmi()) return this;
594 if (IsHeapNumber()) {
595 double value = HeapNumber::cast(this)->value();
596 int int_value = FastD2I(value);
597 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
598 return Smi::FromInt(int_value);
599 }
600 }
601 return Failure::Exception();
602}
603
604
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000605bool Object::HasSpecificClassOf(String* name) {
606 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
607}
608
609
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000610Object* Object::GetElement(uint32_t index) {
611 return GetElementWithReceiver(this, index);
612}
613
614
615Object* Object::GetProperty(String* key) {
616 PropertyAttributes attributes;
617 return GetPropertyWithReceiver(this, key, &attributes);
618}
619
620
621Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
622 return GetPropertyWithReceiver(this, key, attributes);
623}
624
625
626#define FIELD_ADDR(p, offset) \
627 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
628
629#define READ_FIELD(p, offset) \
630 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
631
632#define WRITE_FIELD(p, offset, value) \
633 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
634
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000635
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636#define WRITE_BARRIER(object, offset) \
637 Heap::RecordWrite(object->address(), offset);
638
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000639// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000640// write due to the assert validating the written value.
641#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
642 if (mode == UPDATE_WRITE_BARRIER) { \
643 Heap::RecordWrite(object->address(), offset); \
644 } else { \
645 ASSERT(mode == SKIP_WRITE_BARRIER); \
646 ASSERT(Heap::InNewSpace(object) || \
647 !Heap::InNewSpace(READ_FIELD(object, offset))); \
648 }
649
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650#define READ_DOUBLE_FIELD(p, offset) \
651 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
652
653#define WRITE_DOUBLE_FIELD(p, offset, value) \
654 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
655
656#define READ_INT_FIELD(p, offset) \
657 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
658
659#define WRITE_INT_FIELD(p, offset, value) \
660 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
661
ager@chromium.org7c537e22008-10-16 08:43:32 +0000662#define READ_UINT32_FIELD(p, offset) \
663 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
664
665#define WRITE_UINT32_FIELD(p, offset, value) \
666 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
667
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668#define READ_SHORT_FIELD(p, offset) \
669 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
670
671#define WRITE_SHORT_FIELD(p, offset, value) \
672 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
673
674#define READ_BYTE_FIELD(p, offset) \
675 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
676
677#define WRITE_BYTE_FIELD(p, offset, value) \
678 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
679
680
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000681Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
682 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683}
684
685
686int Smi::value() {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000687 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kSmiTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688}
689
690
691Smi* Smi::FromInt(int value) {
692 ASSERT(Smi::IsValid(value));
ager@chromium.org9085a012009-05-11 19:22:57 +0000693 intptr_t tagged_value =
694 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
695 return reinterpret_cast<Smi*>(tagged_value);
696}
697
698
699Smi* Smi::FromIntptr(intptr_t value) {
700 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000701 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
702}
703
704
705Failure::Type Failure::type() const {
706 return static_cast<Type>(value() & kFailureTypeTagMask);
707}
708
709
710bool Failure::IsInternalError() const {
711 return type() == INTERNAL_ERROR;
712}
713
714
715bool Failure::IsOutOfMemoryException() const {
716 return type() == OUT_OF_MEMORY_EXCEPTION;
717}
718
719
720int Failure::requested() const {
721 const int kShiftBits =
722 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
723 STATIC_ASSERT(kShiftBits >= 0);
724 ASSERT(type() == RETRY_AFTER_GC);
725 return value() >> kShiftBits;
726}
727
728
729AllocationSpace Failure::allocation_space() const {
730 ASSERT_EQ(RETRY_AFTER_GC, type());
731 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
732 & kSpaceTagMask);
733}
734
735
736Failure* Failure::InternalError() {
737 return Construct(INTERNAL_ERROR);
738}
739
740
741Failure* Failure::Exception() {
742 return Construct(EXCEPTION);
743}
744
745Failure* Failure::OutOfMemoryException() {
746 return Construct(OUT_OF_MEMORY_EXCEPTION);
747}
748
749
750int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000751 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752}
753
754
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000755Failure* Failure::RetryAfterGC(int requested_bytes) {
756 int requested = requested_bytes >> kObjectAlignmentBits;
757 int value = (requested << kSpaceTagSize) | NEW_SPACE;
758 ASSERT(value >> kSpaceTagSize == requested);
759 ASSERT(Smi::IsValid(value));
760 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
761 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
762 return Construct(RETRY_AFTER_GC, value);
763}
764
765
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766Failure* Failure::Construct(Type type, int value) {
767 int info = (value << kFailureTypeTagSize) | type;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000768 // TODO(X64): Stop using Smi validation for non-smi checks, even if they
769 // happen to be identical at the moment.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000770 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000771 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000772 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000773}
774
775
776bool Smi::IsValid(int value) {
777#ifdef DEBUG
778 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
779#endif
780 // To be representable as an tagged small integer, the two
781 // most-significant bits of 'value' must be either 00 or 11 due to
782 // sign-extension. To check this we add 01 to the two
783 // most-significant bits, and check if the most-significant bit is 0
784 //
785 // CAUTION: The original code below:
786 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
787 // may lead to incorrect results according to the C language spec, and
788 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
789 // compiler may produce undefined results in case of signed integer
790 // overflow. The computation must be done w/ unsigned ints.
791 bool result =
792 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
793 ASSERT(result == in_range);
794 return result;
795}
796
797
ager@chromium.org9085a012009-05-11 19:22:57 +0000798bool Smi::IsIntptrValid(intptr_t value) {
799#ifdef DEBUG
800 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
801#endif
802 // See Smi::IsValid(int) for description.
803 bool result =
804 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
805 ASSERT(result == in_range);
806 return result;
807}
808
809
kasper.lund7276f142008-07-30 08:49:36 +0000810MapWord MapWord::FromMap(Map* map) {
811 return MapWord(reinterpret_cast<uintptr_t>(map));
812}
813
814
815Map* MapWord::ToMap() {
816 return reinterpret_cast<Map*>(value_);
817}
818
819
820bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000821 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000822}
823
824
825MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000826 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
827 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000828}
829
830
831HeapObject* MapWord::ToForwardingAddress() {
832 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000833 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000834}
835
836
837bool MapWord::IsMarked() {
838 return (value_ & kMarkingMask) == 0;
839}
840
841
842void MapWord::SetMark() {
843 value_ &= ~kMarkingMask;
844}
845
846
847void MapWord::ClearMark() {
848 value_ |= kMarkingMask;
849}
850
851
852bool MapWord::IsOverflowed() {
853 return (value_ & kOverflowMask) != 0;
854}
855
856
857void MapWord::SetOverflow() {
858 value_ |= kOverflowMask;
859}
860
861
862void MapWord::ClearOverflow() {
863 value_ &= ~kOverflowMask;
864}
865
866
867MapWord MapWord::EncodeAddress(Address map_address, int offset) {
868 // Offset is the distance in live bytes from the first live object in the
869 // same page. The offset between two objects in the same page should not
870 // exceed the object area size of a page.
871 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
872
873 int compact_offset = offset >> kObjectAlignmentBits;
874 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
875
876 Page* map_page = Page::FromAddress(map_address);
877 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
878
879 int map_page_offset =
880 map_page->Offset(map_address) >> kObjectAlignmentBits;
881
882 uintptr_t encoding =
883 (compact_offset << kForwardingOffsetShift) |
884 (map_page_offset << kMapPageOffsetShift) |
885 (map_page->mc_page_index << kMapPageIndexShift);
886 return MapWord(encoding);
887}
888
889
890Address MapWord::DecodeMapAddress(MapSpace* map_space) {
891 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
892 ASSERT_MAP_PAGE_INDEX(map_page_index);
893
894 int map_page_offset =
895 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
896 << kObjectAlignmentBits;
897
898 return (map_space->PageAddress(map_page_index) + map_page_offset);
899}
900
901
902int MapWord::DecodeOffset() {
903 // The offset field is represented in the kForwardingOffsetBits
904 // most-significant bits.
905 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
906 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
907 return offset;
908}
909
910
911MapWord MapWord::FromEncodedAddress(Address address) {
912 return MapWord(reinterpret_cast<uintptr_t>(address));
913}
914
915
916Address MapWord::ToEncodedAddress() {
917 return reinterpret_cast<Address>(value_);
918}
919
920
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921#ifdef DEBUG
922void HeapObject::VerifyObjectField(int offset) {
923 VerifyPointer(READ_FIELD(this, offset));
924}
925#endif
926
927
928Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000929 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000930}
931
932
933void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000934 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000935}
936
937
kasper.lund7276f142008-07-30 08:49:36 +0000938MapWord HeapObject::map_word() {
939 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
940}
941
942
943void HeapObject::set_map_word(MapWord map_word) {
944 // WRITE_FIELD does not update the remembered set, but there is no need
945 // here.
946 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
947}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000948
949
950HeapObject* HeapObject::FromAddress(Address address) {
951 ASSERT_TAG_ALIGNED(address);
952 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
953}
954
955
956Address HeapObject::address() {
957 return reinterpret_cast<Address>(this) - kHeapObjectTag;
958}
959
960
961int HeapObject::Size() {
962 return SizeFromMap(map());
963}
964
965
966void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
967 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
968 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
969}
970
971
972void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
973 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
974}
975
976
kasper.lund7276f142008-07-30 08:49:36 +0000977bool HeapObject::IsMarked() {
978 return map_word().IsMarked();
979}
980
981
982void HeapObject::SetMark() {
983 ASSERT(!IsMarked());
984 MapWord first_word = map_word();
985 first_word.SetMark();
986 set_map_word(first_word);
987}
988
989
990void HeapObject::ClearMark() {
991 ASSERT(IsMarked());
992 MapWord first_word = map_word();
993 first_word.ClearMark();
994 set_map_word(first_word);
995}
996
997
998bool HeapObject::IsOverflowed() {
999 return map_word().IsOverflowed();
1000}
1001
1002
1003void HeapObject::SetOverflow() {
1004 MapWord first_word = map_word();
1005 first_word.SetOverflow();
1006 set_map_word(first_word);
1007}
1008
1009
1010void HeapObject::ClearOverflow() {
1011 ASSERT(IsOverflowed());
1012 MapWord first_word = map_word();
1013 first_word.ClearOverflow();
1014 set_map_word(first_word);
1015}
1016
1017
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018double HeapNumber::value() {
1019 return READ_DOUBLE_FIELD(this, kValueOffset);
1020}
1021
1022
1023void HeapNumber::set_value(double value) {
1024 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1025}
1026
1027
1028ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001029ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001030
1031
1032void JSObject::initialize_properties() {
1033 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1034 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1035}
1036
1037
1038void JSObject::initialize_elements() {
1039 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1040 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1041}
1042
1043
1044ACCESSORS(Oddball, to_string, String, kToStringOffset)
1045ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1046
1047
1048int JSObject::GetHeaderSize() {
1049 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001050 case JS_GLOBAL_PROXY_TYPE:
1051 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001052 case JS_GLOBAL_OBJECT_TYPE:
1053 return JSGlobalObject::kSize;
1054 case JS_BUILTINS_OBJECT_TYPE:
1055 return JSBuiltinsObject::kSize;
1056 case JS_FUNCTION_TYPE:
1057 return JSFunction::kSize;
1058 case JS_VALUE_TYPE:
1059 return JSValue::kSize;
1060 case JS_ARRAY_TYPE:
1061 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001062 case JS_REGEXP_TYPE:
1063 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001064 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001065 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001066 return JSObject::kHeaderSize;
1067 default:
1068 UNREACHABLE();
1069 return 0;
1070 }
1071}
1072
1073
1074int JSObject::GetInternalFieldCount() {
1075 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001076 // Make sure to adjust for the number of in-object properties. These
1077 // properties do contribute to the size, but are not internal fields.
1078 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1079 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001080}
1081
1082
1083Object* JSObject::GetInternalField(int index) {
1084 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001085 // Internal objects do follow immediately after the header, whereas in-object
1086 // properties are at the end of the object. Therefore there is no need
1087 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1089}
1090
1091
1092void JSObject::SetInternalField(int index, Object* value) {
1093 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001094 // Internal objects do follow immediately after the header, whereas in-object
1095 // properties are at the end of the object. Therefore there is no need
1096 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001097 int offset = GetHeaderSize() + (kPointerSize * index);
1098 WRITE_FIELD(this, offset, value);
1099 WRITE_BARRIER(this, offset);
1100}
1101
1102
ager@chromium.org7c537e22008-10-16 08:43:32 +00001103// Access fast-case object properties at index. The use of these routines
1104// is needed to correctly distinguish between properties stored in-object and
1105// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001106Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001107 // Adjust for the number of properties stored in the object.
1108 index -= map()->inobject_properties();
1109 if (index < 0) {
1110 int offset = map()->instance_size() + (index * kPointerSize);
1111 return READ_FIELD(this, offset);
1112 } else {
1113 ASSERT(index < properties()->length());
1114 return properties()->get(index);
1115 }
1116}
1117
1118
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001119Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001120 // Adjust for the number of properties stored in the object.
1121 index -= map()->inobject_properties();
1122 if (index < 0) {
1123 int offset = map()->instance_size() + (index * kPointerSize);
1124 WRITE_FIELD(this, offset, value);
1125 WRITE_BARRIER(this, offset);
1126 } else {
1127 ASSERT(index < properties()->length());
1128 properties()->set(index, value);
1129 }
1130 return value;
1131}
1132
1133
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001134Object* JSObject::InObjectPropertyAt(int index) {
1135 // Adjust for the number of properties stored in the object.
1136 index -= map()->inobject_properties();
1137 ASSERT(index < 0);
1138 int offset = map()->instance_size() + (index * kPointerSize);
1139 return READ_FIELD(this, offset);
1140}
1141
1142
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001143Object* JSObject::InObjectPropertyAtPut(int index,
1144 Object* value,
1145 WriteBarrierMode mode) {
1146 // Adjust for the number of properties stored in the object.
1147 index -= map()->inobject_properties();
1148 ASSERT(index < 0);
1149 int offset = map()->instance_size() + (index * kPointerSize);
1150 WRITE_FIELD(this, offset, value);
1151 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1152 return value;
1153}
1154
1155
1156
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001157void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001158 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001159 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001160 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001161 }
1162}
1163
1164
1165void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001166 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001167 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001168 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001169 }
1170}
1171
1172
1173bool JSObject::HasFastProperties() {
1174 return !properties()->IsDictionary();
1175}
1176
1177
1178bool Array::IndexFromObject(Object* object, uint32_t* index) {
1179 if (object->IsSmi()) {
1180 int value = Smi::cast(object)->value();
1181 if (value < 0) return false;
1182 *index = value;
1183 return true;
1184 }
1185 if (object->IsHeapNumber()) {
1186 double value = HeapNumber::cast(object)->value();
1187 uint32_t uint_value = static_cast<uint32_t>(value);
1188 if (value == static_cast<double>(uint_value)) {
1189 *index = uint_value;
1190 return true;
1191 }
1192 }
1193 return false;
1194}
1195
1196
1197bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1198 if (!this->IsJSValue()) return false;
1199
1200 JSValue* js_value = JSValue::cast(this);
1201 if (!js_value->value()->IsString()) return false;
1202
1203 String* str = String::cast(js_value->value());
1204 if (index >= (uint32_t)str->length()) return false;
1205
1206 return true;
1207}
1208
1209
1210Object* FixedArray::get(int index) {
1211 ASSERT(index >= 0 && index < this->length());
1212 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1213}
1214
1215
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001216void FixedArray::set(int index, Smi* value) {
1217 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1218 int offset = kHeaderSize + index * kPointerSize;
1219 WRITE_FIELD(this, offset, value);
1220}
1221
1222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223void FixedArray::set(int index, Object* value) {
1224 ASSERT(index >= 0 && index < this->length());
1225 int offset = kHeaderSize + index * kPointerSize;
1226 WRITE_FIELD(this, offset, value);
1227 WRITE_BARRIER(this, offset);
1228}
1229
1230
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001231WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001232 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1233 return UPDATE_WRITE_BARRIER;
1234}
1235
1236
1237void FixedArray::set(int index,
1238 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001239 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240 ASSERT(index >= 0 && index < this->length());
1241 int offset = kHeaderSize + index * kPointerSize;
1242 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001243 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001244}
1245
1246
1247void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1248 ASSERT(index >= 0 && index < array->length());
1249 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1250}
1251
1252
1253void FixedArray::set_undefined(int index) {
1254 ASSERT(index >= 0 && index < this->length());
1255 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1256 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1257 Heap::undefined_value());
1258}
1259
1260
ager@chromium.org236ad962008-09-25 09:45:57 +00001261void FixedArray::set_null(int index) {
1262 ASSERT(index >= 0 && index < this->length());
1263 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1264 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1265}
1266
1267
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001268void FixedArray::set_the_hole(int index) {
1269 ASSERT(index >= 0 && index < this->length());
1270 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1271 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1272}
1273
1274
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001275bool DescriptorArray::IsEmpty() {
1276 ASSERT(this == Heap::empty_descriptor_array() ||
1277 this->length() > 2);
1278 return this == Heap::empty_descriptor_array();
1279}
1280
1281
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1283 Object* tmp = array->get(first);
1284 fast_set(array, first, array->get(second));
1285 fast_set(array, second, tmp);
1286}
1287
1288
1289int DescriptorArray::Search(String* name) {
1290 SLOW_ASSERT(IsSortedNoDuplicates());
1291
1292 // Check for empty descriptor array.
1293 int nof = number_of_descriptors();
1294 if (nof == 0) return kNotFound;
1295
1296 // Fast case: do linear search for small arrays.
1297 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001298 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001299 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 }
1301
1302 // Slow case: perform binary search.
1303 return BinarySearch(name, 0, nof - 1);
1304}
1305
1306
1307
1308String* DescriptorArray::GetKey(int descriptor_number) {
1309 ASSERT(descriptor_number < number_of_descriptors());
1310 return String::cast(get(ToKeyIndex(descriptor_number)));
1311}
1312
1313
1314Object* DescriptorArray::GetValue(int descriptor_number) {
1315 ASSERT(descriptor_number < number_of_descriptors());
1316 return GetContentArray()->get(ToValueIndex(descriptor_number));
1317}
1318
1319
1320Smi* DescriptorArray::GetDetails(int descriptor_number) {
1321 ASSERT(descriptor_number < number_of_descriptors());
1322 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1323}
1324
1325
1326void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1327 desc->Init(GetKey(descriptor_number),
1328 GetValue(descriptor_number),
1329 GetDetails(descriptor_number));
1330}
1331
1332
1333void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1334 // Range check.
1335 ASSERT(descriptor_number < number_of_descriptors());
1336
1337 // Make sure non of the elements in desc are in new space.
1338 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1339 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1340
1341 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1342 FixedArray* content_array = GetContentArray();
1343 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1344 fast_set(content_array, ToDetailsIndex(descriptor_number),
1345 desc->GetDetails().AsSmi());
1346}
1347
1348
1349void DescriptorArray::Swap(int first, int second) {
1350 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1351 FixedArray* content_array = GetContentArray();
1352 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1353 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1354}
1355
1356
1357bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001358 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359 if (!max_index_object->IsSmi()) return false;
1360 return 0 !=
1361 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1362}
1363
1364
1365uint32_t Dictionary::max_number_key() {
1366 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001367 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001368 if (!max_index_object->IsSmi()) return 0;
1369 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1370 return value >> kRequiresSlowElementsTagSize;
1371}
1372
1373
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001374void Dictionary::set_requires_slow_elements() {
1375 set(kMaxNumberKeyIndex,
1376 Smi::FromInt(kRequiresSlowElementsMask),
1377 SKIP_WRITE_BARRIER);
1378}
1379
1380
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001381// ------------------------------------
1382// Cast operations
1383
1384
1385CAST_ACCESSOR(FixedArray)
1386CAST_ACCESSOR(DescriptorArray)
1387CAST_ACCESSOR(Dictionary)
1388CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001389CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001390CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001391CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001392CAST_ACCESSOR(String)
1393CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001394CAST_ACCESSOR(SeqAsciiString)
1395CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001396CAST_ACCESSOR(ConsString)
1397CAST_ACCESSOR(SlicedString)
1398CAST_ACCESSOR(ExternalString)
1399CAST_ACCESSOR(ExternalAsciiString)
1400CAST_ACCESSOR(ExternalTwoByteString)
1401CAST_ACCESSOR(JSObject)
1402CAST_ACCESSOR(Smi)
1403CAST_ACCESSOR(Failure)
1404CAST_ACCESSOR(HeapObject)
1405CAST_ACCESSOR(HeapNumber)
1406CAST_ACCESSOR(Oddball)
1407CAST_ACCESSOR(SharedFunctionInfo)
1408CAST_ACCESSOR(Map)
1409CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001410CAST_ACCESSOR(GlobalObject)
1411CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001412CAST_ACCESSOR(JSGlobalObject)
1413CAST_ACCESSOR(JSBuiltinsObject)
1414CAST_ACCESSOR(Code)
1415CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001416CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417CAST_ACCESSOR(Proxy)
1418CAST_ACCESSOR(ByteArray)
1419CAST_ACCESSOR(Struct)
1420
1421
1422#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1423 STRUCT_LIST(MAKE_STRUCT_CAST)
1424#undef MAKE_STRUCT_CAST
1425
1426template <int prefix_size, int elem_size>
1427HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1428 Object* obj) {
1429 ASSERT(obj->IsHashTable());
1430 return reinterpret_cast<HashTable*>(obj);
1431}
1432
1433
1434INT_ACCESSORS(Array, length, kLengthOffset)
1435
1436
1437bool String::Equals(String* other) {
1438 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001439 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1440 return false;
1441 }
1442 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001443}
1444
1445
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001446int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001447 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1448
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001449 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1450 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1451 ASSERT(kLongStringTag == 0);
1452
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001453 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001454}
1455
1456
1457void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001458 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1459 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1460 ASSERT(kLongStringTag == 0);
1461
1462 WRITE_INT_FIELD(this,
1463 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001464 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001465}
1466
1467
ager@chromium.org7c537e22008-10-16 08:43:32 +00001468uint32_t String::length_field() {
1469 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001470}
1471
1472
ager@chromium.org7c537e22008-10-16 08:43:32 +00001473void String::set_length_field(uint32_t value) {
1474 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001475}
1476
1477
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001478Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001479 // We don't need to flatten strings that are already flat. Since this code
1480 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001481 if (!IsFlat()) {
1482 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001483 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001484 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001485}
1486
1487
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001488uint16_t String::Get(int index) {
1489 ASSERT(index >= 0 && index < length());
1490 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001491 case kSeqStringTag | kAsciiStringTag:
1492 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1493 case kSeqStringTag | kTwoByteStringTag:
1494 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1495 case kConsStringTag | kAsciiStringTag:
1496 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001497 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001498 case kSlicedStringTag | kAsciiStringTag:
1499 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001500 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001501 case kExternalStringTag | kAsciiStringTag:
1502 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1503 case kExternalStringTag | kTwoByteStringTag:
1504 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001505 default:
1506 break;
1507 }
1508
1509 UNREACHABLE();
1510 return 0;
1511}
1512
1513
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001514void String::Set(int index, uint16_t value) {
1515 ASSERT(index >= 0 && index < length());
1516 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001517
ager@chromium.org5ec48922009-05-05 07:25:34 +00001518 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001519 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1520 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001521}
1522
1523
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001524bool String::IsFlat() {
1525 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001526 case kConsStringTag: {
1527 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001528 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001529 return second->length() == 0;
1530 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001531 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001532 StringRepresentationTag tag =
1533 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001534 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001535 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001536 default:
1537 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001538 }
1539}
1540
1541
ager@chromium.org7c537e22008-10-16 08:43:32 +00001542uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543 ASSERT(index >= 0 && index < length());
1544 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1545}
1546
1547
ager@chromium.org7c537e22008-10-16 08:43:32 +00001548void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1550 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1551 static_cast<byte>(value));
1552}
1553
1554
ager@chromium.org7c537e22008-10-16 08:43:32 +00001555Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556 return FIELD_ADDR(this, kHeaderSize);
1557}
1558
1559
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001560char* SeqAsciiString::GetChars() {
1561 return reinterpret_cast<char*>(GetCharsAddress());
1562}
1563
1564
ager@chromium.org7c537e22008-10-16 08:43:32 +00001565Address SeqTwoByteString::GetCharsAddress() {
1566 return FIELD_ADDR(this, kHeaderSize);
1567}
1568
1569
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001570uc16* SeqTwoByteString::GetChars() {
1571 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1572}
1573
1574
ager@chromium.org7c537e22008-10-16 08:43:32 +00001575uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001576 ASSERT(index >= 0 && index < length());
1577 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1578}
1579
1580
ager@chromium.org7c537e22008-10-16 08:43:32 +00001581void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001582 ASSERT(index >= 0 && index < length());
1583 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1584}
1585
1586
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001587int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001588 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1589
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001590 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1591 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1592 ASSERT(kLongStringTag == 0);
1593
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001594 // Use the map (and not 'this') to compute the size tag, since
1595 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001596 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001598 return SizeFor(length);
1599}
1600
1601
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001602int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001603 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1604
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001605 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1606 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1607 ASSERT(kLongStringTag == 0);
1608
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001609 // Use the map (and not 'this') to compute the size tag, since
1610 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001611 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612
1613 return SizeFor(length);
1614}
1615
1616
ager@chromium.org870a0b62008-11-04 11:43:05 +00001617String* ConsString::first() {
1618 return String::cast(READ_FIELD(this, kFirstOffset));
1619}
1620
1621
1622Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623 return READ_FIELD(this, kFirstOffset);
1624}
1625
1626
ager@chromium.org870a0b62008-11-04 11:43:05 +00001627void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001629 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001630}
1631
1632
ager@chromium.org870a0b62008-11-04 11:43:05 +00001633String* ConsString::second() {
1634 return String::cast(READ_FIELD(this, kSecondOffset));
1635}
1636
1637
1638Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001639 return READ_FIELD(this, kSecondOffset);
1640}
1641
1642
ager@chromium.org870a0b62008-11-04 11:43:05 +00001643void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001644 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001645 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001646}
1647
1648
ager@chromium.org870a0b62008-11-04 11:43:05 +00001649String* SlicedString::buffer() {
1650 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001651}
1652
1653
ager@chromium.org870a0b62008-11-04 11:43:05 +00001654void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001655 WRITE_FIELD(this, kBufferOffset, buffer);
1656 WRITE_BARRIER(this, kBufferOffset);
1657}
1658
1659
1660int SlicedString::start() {
1661 return READ_INT_FIELD(this, kStartOffset);
1662}
1663
1664
1665void SlicedString::set_start(int start) {
1666 WRITE_INT_FIELD(this, kStartOffset, start);
1667}
1668
1669
1670ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1671 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1672}
1673
1674
1675void ExternalAsciiString::set_resource(
1676 ExternalAsciiString::Resource* resource) {
1677 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1678}
1679
1680
ager@chromium.org6f10e412009-02-13 10:11:16 +00001681Map* ExternalAsciiString::StringMap(int length) {
1682 Map* map;
1683 // Number of characters: determines the map.
1684 if (length <= String::kMaxShortStringSize) {
1685 map = Heap::short_external_ascii_string_map();
1686 } else if (length <= String::kMaxMediumStringSize) {
1687 map = Heap::medium_external_ascii_string_map();
1688 } else {
1689 map = Heap::long_external_ascii_string_map();
1690 }
1691 return map;
1692}
1693
1694
1695Map* ExternalAsciiString::SymbolMap(int length) {
1696 Map* map;
1697 // Number of characters: determines the map.
1698 if (length <= String::kMaxShortStringSize) {
1699 map = Heap::short_external_ascii_symbol_map();
1700 } else if (length <= String::kMaxMediumStringSize) {
1701 map = Heap::medium_external_ascii_symbol_map();
1702 } else {
1703 map = Heap::long_external_ascii_symbol_map();
1704 }
1705 return map;
1706}
1707
1708
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001709ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1710 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1711}
1712
1713
1714void ExternalTwoByteString::set_resource(
1715 ExternalTwoByteString::Resource* resource) {
1716 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1717}
1718
1719
ager@chromium.org6f10e412009-02-13 10:11:16 +00001720Map* ExternalTwoByteString::StringMap(int length) {
1721 Map* map;
1722 // Number of characters: determines the map.
1723 if (length <= String::kMaxShortStringSize) {
1724 map = Heap::short_external_string_map();
1725 } else if (length <= String::kMaxMediumStringSize) {
1726 map = Heap::medium_external_string_map();
1727 } else {
1728 map = Heap::long_external_string_map();
1729 }
1730 return map;
1731}
1732
1733
1734Map* ExternalTwoByteString::SymbolMap(int length) {
1735 Map* map;
1736 // Number of characters: determines the map.
1737 if (length <= String::kMaxShortStringSize) {
1738 map = Heap::short_external_symbol_map();
1739 } else if (length <= String::kMaxMediumStringSize) {
1740 map = Heap::medium_external_symbol_map();
1741 } else {
1742 map = Heap::long_external_symbol_map();
1743 }
1744 return map;
1745}
1746
1747
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001748byte ByteArray::get(int index) {
1749 ASSERT(index >= 0 && index < this->length());
1750 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1751}
1752
1753
1754void ByteArray::set(int index, byte value) {
1755 ASSERT(index >= 0 && index < this->length());
1756 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1757}
1758
1759
1760int ByteArray::get_int(int index) {
1761 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1762 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1763}
1764
1765
1766ByteArray* ByteArray::FromDataStartAddress(Address address) {
1767 ASSERT_TAG_ALIGNED(address);
1768 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1769}
1770
1771
1772Address ByteArray::GetDataStartAddress() {
1773 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1774}
1775
1776
1777int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001778 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1779}
1780
1781
1782int Map::inobject_properties() {
1783 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001784}
1785
1786
1787int HeapObject::SizeFromMap(Map* map) {
1788 InstanceType instance_type = map->instance_type();
1789 // Only inline the two most frequent cases.
1790 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1791 if (instance_type == FIXED_ARRAY_TYPE) {
1792 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1793 }
1794 // Otherwise do the general size computation.
1795 return SlowSizeFromMap(map);
1796}
1797
1798
1799void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001800 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001801 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001802 ASSERT(0 <= value && value < 256);
1803 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1804}
1805
1806
ager@chromium.org7c537e22008-10-16 08:43:32 +00001807void Map::set_inobject_properties(int value) {
1808 ASSERT(0 <= value && value < 256);
1809 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1810}
1811
1812
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001813InstanceType Map::instance_type() {
1814 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1815}
1816
1817
1818void Map::set_instance_type(InstanceType value) {
1819 ASSERT(0 <= value && value < 256);
1820 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1821}
1822
1823
1824int Map::unused_property_fields() {
1825 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1826}
1827
1828
1829void Map::set_unused_property_fields(int value) {
1830 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1831}
1832
1833
1834byte Map::bit_field() {
1835 return READ_BYTE_FIELD(this, kBitFieldOffset);
1836}
1837
1838
1839void Map::set_bit_field(byte value) {
1840 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1841}
1842
1843
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001844byte Map::bit_field2() {
1845 return READ_BYTE_FIELD(this, kBitField2Offset);
1846}
1847
1848
1849void Map::set_bit_field2(byte value) {
1850 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1851}
1852
1853
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001854void Map::set_non_instance_prototype(bool value) {
1855 if (value) {
1856 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1857 } else {
1858 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1859 }
1860}
1861
1862
1863bool Map::has_non_instance_prototype() {
1864 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1865}
1866
1867
ager@chromium.org870a0b62008-11-04 11:43:05 +00001868void Map::set_is_access_check_needed(bool access_check_needed) {
1869 if (access_check_needed) {
1870 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1871 } else {
1872 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1873 }
1874}
1875
1876
1877bool Map::is_access_check_needed() {
1878 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1879}
1880
1881
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001882Code::Flags Code::flags() {
1883 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1884}
1885
1886
1887void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001888 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889 // Make sure that all call stubs have an arguments count.
1890 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1891 ExtractArgumentsCountFromFlags(flags) >= 0);
1892 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1893}
1894
1895
1896Code::Kind Code::kind() {
1897 return ExtractKindFromFlags(flags());
1898}
1899
1900
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001901InLoopFlag Code::ic_in_loop() {
1902 return ExtractICInLoopFromFlags(flags());
1903}
1904
1905
kasper.lund7276f142008-07-30 08:49:36 +00001906InlineCacheState Code::ic_state() {
1907 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001908 // Only allow uninitialized or debugger states for non-IC code
1909 // objects. This is used in the debugger to determine whether or not
1910 // a call to code object has been replaced with a debug break call.
1911 ASSERT(is_inline_cache_stub() ||
1912 result == UNINITIALIZED ||
1913 result == DEBUG_BREAK ||
1914 result == DEBUG_PREPARE_STEP_IN);
1915 return result;
1916}
1917
1918
1919PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001920 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001921 return ExtractTypeFromFlags(flags());
1922}
1923
1924
1925int Code::arguments_count() {
1926 ASSERT(is_call_stub() || kind() == STUB);
1927 return ExtractArgumentsCountFromFlags(flags());
1928}
1929
1930
1931CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001932 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001933 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1934 kStubMajorKeyOffset));
1935}
1936
1937
1938void Code::set_major_key(CodeStub::Major major) {
1939 ASSERT(kind() == STUB);
1940 ASSERT(0 <= major && major < 256);
1941 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942}
1943
1944
1945bool Code::is_inline_cache_stub() {
1946 Kind kind = this->kind();
1947 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1948}
1949
1950
1951Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001952 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00001953 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001954 PropertyType type,
1955 int argc) {
1956 // Compute the bit mask.
1957 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001958 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00001959 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001960 bits |= type << kFlagsTypeShift;
1961 bits |= argc << kFlagsArgumentsCountShift;
1962 // Cast to flags and validate result before returning it.
1963 Flags result = static_cast<Flags>(bits);
1964 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001965 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001966 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001967 ASSERT(ExtractTypeFromFlags(result) == type);
1968 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1969 return result;
1970}
1971
1972
1973Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1974 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001975 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001976 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001977 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001978}
1979
1980
1981Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1982 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1983 return static_cast<Kind>(bits);
1984}
1985
1986
kasper.lund7276f142008-07-30 08:49:36 +00001987InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1988 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001989 return static_cast<InlineCacheState>(bits);
1990}
1991
1992
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001993InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
1994 int bits = (flags & kFlagsICInLoopMask);
1995 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
1996}
1997
1998
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001999PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2000 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2001 return static_cast<PropertyType>(bits);
2002}
2003
2004
2005int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2006 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2007}
2008
2009
2010Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2011 int bits = flags & ~kFlagsTypeMask;
2012 return static_cast<Flags>(bits);
2013}
2014
2015
ager@chromium.org8bb60582008-12-11 12:02:20 +00002016Code* Code::GetCodeFromTargetAddress(Address address) {
2017 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2018 // GetCodeFromTargetAddress might be called when marking objects during mark
2019 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2020 // Code::cast. Code::cast does not work when the object's map is
2021 // marked.
2022 Code* result = reinterpret_cast<Code*>(code);
2023 return result;
2024}
2025
2026
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002027Object* Map::prototype() {
2028 return READ_FIELD(this, kPrototypeOffset);
2029}
2030
2031
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002032void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002033 ASSERT(value->IsNull() || value->IsJSObject());
2034 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002035 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002036}
2037
2038
2039ACCESSORS(Map, instance_descriptors, DescriptorArray,
2040 kInstanceDescriptorsOffset)
2041ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2042ACCESSORS(Map, constructor, Object, kConstructorOffset)
2043
2044ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2045ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2046
2047ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2048ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002049ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002050
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002051ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002052
2053ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2054ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2055ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2056ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2057ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2058
2059ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2060ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2061ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2062
2063ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2064ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2065ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2066ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2067ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2068ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2069
2070ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2071ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2072
2073ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2074ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2075
2076ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2077ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002078ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2079 kPropertyAccessorsOffset)
2080ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2081 kPrototypeTemplateOffset)
2082ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2083ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2084 kNamedPropertyHandlerOffset)
2085ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2086 kIndexedPropertyHandlerOffset)
2087ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2088 kInstanceTemplateOffset)
2089ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2090ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2092 kInstanceCallHandlerOffset)
2093ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2094 kAccessCheckInfoOffset)
2095ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2096
2097ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002098ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2099 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002100
2101ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2102ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2103
2104ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2105
2106ACCESSORS(Script, source, Object, kSourceOffset)
2107ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002108ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002109ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2110ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002111ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002112ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002113ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2114ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002115ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002116
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002117#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002118ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2119ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2120ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2121ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2122
2123ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2124ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2125ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2126ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002127#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128
2129ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2130ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2131 kInstanceClassNameOffset)
2132ACCESSORS(SharedFunctionInfo, function_data, Object,
2133 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002134ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2135ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002136ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002137
2138BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2139 kHiddenPrototypeBit)
2140BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2141BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2142 kNeedsAccessCheckBit)
2143BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2144 kIsExpressionBit)
2145BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2146 kIsTopLevelBit)
2147
2148INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2149INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2150 kFormalParameterCountOffset)
2151INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2152 kExpectedNofPropertiesOffset)
2153INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2154 kStartPositionAndTypeOffset)
2155INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2156INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2157 kFunctionTokenPositionOffset)
2158
2159
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002160void SharedFunctionInfo::DontAdaptArguments() {
2161 ASSERT(code()->kind() == Code::BUILTIN);
2162 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2163}
2164
2165
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002166int SharedFunctionInfo::start_position() {
2167 return start_position_and_type() >> kStartPositionShift;
2168}
2169
2170
2171void SharedFunctionInfo::set_start_position(int start_position) {
2172 set_start_position_and_type((start_position << kStartPositionShift)
2173 | (start_position_and_type() & ~kStartPositionMask));
2174}
2175
2176
2177Code* SharedFunctionInfo::code() {
2178 return Code::cast(READ_FIELD(this, kCodeOffset));
2179}
2180
2181
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002182void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002183 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002184 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002185}
2186
2187
2188bool SharedFunctionInfo::is_compiled() {
2189 // TODO(1242782): Create a code kind for uncompiled code.
2190 return code()->kind() != Code::STUB;
2191}
2192
2193
2194bool JSFunction::IsBoilerplate() {
2195 return map() == Heap::boilerplate_function_map();
2196}
2197
2198
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002199bool JSObject::IsLoaded() {
2200 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002201}
2202
2203
2204Code* JSFunction::code() {
2205 return shared()->code();
2206}
2207
2208
2209void JSFunction::set_code(Code* value) {
2210 shared()->set_code(value);
2211}
2212
2213
2214Context* JSFunction::context() {
2215 return Context::cast(READ_FIELD(this, kContextOffset));
2216}
2217
2218
2219Object* JSFunction::unchecked_context() {
2220 return READ_FIELD(this, kContextOffset);
2221}
2222
2223
2224void JSFunction::set_context(Object* value) {
2225 ASSERT(value == Heap::undefined_value() || value->IsContext());
2226 WRITE_FIELD(this, kContextOffset, value);
2227 WRITE_BARRIER(this, kContextOffset);
2228}
2229
2230ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2231 kPrototypeOrInitialMapOffset)
2232
2233
2234Map* JSFunction::initial_map() {
2235 return Map::cast(prototype_or_initial_map());
2236}
2237
2238
2239void JSFunction::set_initial_map(Map* value) {
2240 set_prototype_or_initial_map(value);
2241}
2242
2243
2244bool JSFunction::has_initial_map() {
2245 return prototype_or_initial_map()->IsMap();
2246}
2247
2248
2249bool JSFunction::has_instance_prototype() {
2250 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2251}
2252
2253
2254bool JSFunction::has_prototype() {
2255 return map()->has_non_instance_prototype() || has_instance_prototype();
2256}
2257
2258
2259Object* JSFunction::instance_prototype() {
2260 ASSERT(has_instance_prototype());
2261 if (has_initial_map()) return initial_map()->prototype();
2262 // When there is no initial map and the prototype is a JSObject, the
2263 // initial map field is used for the prototype field.
2264 return prototype_or_initial_map();
2265}
2266
2267
2268Object* JSFunction::prototype() {
2269 ASSERT(has_prototype());
2270 // If the function's prototype property has been set to a non-JSObject
2271 // value, that value is stored in the constructor field of the map.
2272 if (map()->has_non_instance_prototype()) return map()->constructor();
2273 return instance_prototype();
2274}
2275
2276
2277bool JSFunction::is_compiled() {
2278 return shared()->is_compiled();
2279}
2280
2281
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002282int JSFunction::NumberOfLiterals() {
2283 return literals()->length();
2284}
2285
2286
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002287Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2288 ASSERT(0 <= id && id < kJSBuiltinsCount);
2289 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2290}
2291
2292
2293void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2294 Object* value) {
2295 ASSERT(0 <= id && id < kJSBuiltinsCount);
2296 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2297 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2298}
2299
2300
2301Address Proxy::proxy() {
2302 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2303}
2304
2305
2306void Proxy::set_proxy(Address value) {
2307 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2308}
2309
2310
2311void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2312 visitor->VisitExternalReference(
2313 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2314}
2315
2316
2317ACCESSORS(JSValue, value, Object, kValueOffset)
2318
2319
2320JSValue* JSValue::cast(Object* obj) {
2321 ASSERT(obj->IsJSValue());
2322 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2323 return reinterpret_cast<JSValue*>(obj);
2324}
2325
2326
2327INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2328INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2329INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2330
2331
2332Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002333 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002334}
2335
2336
2337void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002338 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002339}
2340
2341
2342byte* Code::instruction_start() {
2343 return FIELD_ADDR(this, kHeaderSize);
2344}
2345
2346
2347int Code::body_size() {
2348 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2349}
2350
2351
2352byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002353 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002354}
2355
2356
2357byte* Code::entry() {
2358 return instruction_start();
2359}
2360
2361
2362bool Code::contains(byte* pc) {
2363 return (instruction_start() <= pc) &&
2364 (pc < instruction_start() + instruction_size());
2365}
2366
2367
2368byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002369 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002370}
2371
2372
2373ACCESSORS(JSArray, length, Object, kLengthOffset)
2374
2375
ager@chromium.org236ad962008-09-25 09:45:57 +00002376ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002377
2378
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002379JSRegExp::Type JSRegExp::TypeTag() {
2380 Object* data = this->data();
2381 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2382 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2383 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002384}
2385
2386
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002387int JSRegExp::CaptureCount() {
2388 switch (TypeTag()) {
2389 case ATOM:
2390 return 0;
2391 case IRREGEXP:
2392 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2393 default:
2394 UNREACHABLE();
2395 return -1;
2396 }
2397}
2398
2399
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002400JSRegExp::Flags JSRegExp::GetFlags() {
2401 ASSERT(this->data()->IsFixedArray());
2402 Object* data = this->data();
2403 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2404 return Flags(smi->value());
2405}
2406
2407
2408String* JSRegExp::Pattern() {
2409 ASSERT(this->data()->IsFixedArray());
2410 Object* data = this->data();
2411 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2412 return pattern;
2413}
2414
2415
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002416Object* JSRegExp::DataAt(int index) {
2417 ASSERT(TypeTag() != NOT_COMPILED);
2418 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002419}
2420
2421
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002422void JSRegExp::SetDataAt(int index, Object* value) {
2423 ASSERT(TypeTag() != NOT_COMPILED);
2424 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2425 FixedArray::cast(data())->set(index, value);
2426}
2427
2428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002429bool JSObject::HasFastElements() {
2430 return !elements()->IsDictionary();
2431}
2432
2433
2434bool JSObject::HasNamedInterceptor() {
2435 return map()->has_named_interceptor();
2436}
2437
2438
2439bool JSObject::HasIndexedInterceptor() {
2440 return map()->has_indexed_interceptor();
2441}
2442
2443
2444Dictionary* JSObject::property_dictionary() {
2445 ASSERT(!HasFastProperties());
2446 return Dictionary::cast(properties());
2447}
2448
2449
2450Dictionary* JSObject::element_dictionary() {
2451 ASSERT(!HasFastElements());
2452 return Dictionary::cast(elements());
2453}
2454
2455
2456bool String::HasHashCode() {
2457 return (length_field() & kHashComputedMask) != 0;
2458}
2459
2460
2461uint32_t String::Hash() {
2462 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002463 uint32_t field = length_field();
2464 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002465 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002466 return ComputeAndSetHash();
2467}
2468
2469
ager@chromium.org7c537e22008-10-16 08:43:32 +00002470StringHasher::StringHasher(int length)
2471 : length_(length),
2472 raw_running_hash_(0),
2473 array_index_(0),
2474 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2475 is_first_char_(true),
2476 is_valid_(true) { }
2477
2478
2479bool StringHasher::has_trivial_hash() {
2480 return length_ > String::kMaxMediumStringSize;
2481}
2482
2483
2484void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002485 // Use the Jenkins one-at-a-time hash function to update the hash
2486 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002487 raw_running_hash_ += c;
2488 raw_running_hash_ += (raw_running_hash_ << 10);
2489 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002490 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002491 if (is_array_index_) {
2492 if (c < '0' || c > '9') {
2493 is_array_index_ = false;
2494 } else {
2495 int d = c - '0';
2496 if (is_first_char_) {
2497 is_first_char_ = false;
2498 if (c == '0' && length_ > 1) {
2499 is_array_index_ = false;
2500 return;
2501 }
2502 }
2503 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2504 is_array_index_ = false;
2505 } else {
2506 array_index_ = array_index_ * 10 + d;
2507 }
2508 }
2509 }
2510}
2511
2512
2513void StringHasher::AddCharacterNoIndex(uc32 c) {
2514 ASSERT(!is_array_index());
2515 raw_running_hash_ += c;
2516 raw_running_hash_ += (raw_running_hash_ << 10);
2517 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2518}
2519
2520
2521uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002522 // Get the calculated raw hash value and do some more bit ops to distribute
2523 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002524 uint32_t result = raw_running_hash_;
2525 result += (result << 3);
2526 result ^= (result >> 11);
2527 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002528 if (result == 0) {
2529 result = 27;
2530 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002531 return result;
2532}
2533
2534
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002535bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002536 uint32_t field = length_field();
2537 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002538 return SlowAsArrayIndex(index);
2539}
2540
2541
2542Object* JSObject::GetPrototype() {
2543 return JSObject::cast(this)->map()->prototype();
2544}
2545
2546
2547PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2548 return GetPropertyAttributeWithReceiver(this, key);
2549}
2550
2551
2552bool JSObject::HasElement(uint32_t index) {
2553 return HasElementWithReceiver(this, index);
2554}
2555
2556
2557bool AccessorInfo::all_can_read() {
2558 return BooleanBit::get(flag(), kAllCanReadBit);
2559}
2560
2561
2562void AccessorInfo::set_all_can_read(bool value) {
2563 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2564}
2565
2566
2567bool AccessorInfo::all_can_write() {
2568 return BooleanBit::get(flag(), kAllCanWriteBit);
2569}
2570
2571
2572void AccessorInfo::set_all_can_write(bool value) {
2573 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2574}
2575
2576
ager@chromium.org870a0b62008-11-04 11:43:05 +00002577bool AccessorInfo::prohibits_overwriting() {
2578 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2579}
2580
2581
2582void AccessorInfo::set_prohibits_overwriting(bool value) {
2583 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2584}
2585
2586
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002587PropertyAttributes AccessorInfo::property_attributes() {
2588 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2589}
2590
2591
2592void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2593 ASSERT(AttributesField::is_valid(attributes));
2594 int rest_value = flag()->value() & ~AttributesField::mask();
2595 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2596}
2597
2598void Dictionary::SetEntry(int entry,
2599 Object* key,
2600 Object* value,
2601 PropertyDetails details) {
2602 ASSERT(!key->IsString() || details.index() > 0);
2603 int index = EntryToIndex(entry);
2604 WriteBarrierMode mode = GetWriteBarrierMode();
2605 set(index, key, mode);
2606 set(index+1, value, mode);
2607 fast_set(this, index+2, details.AsSmi());
2608}
2609
2610
2611void Map::ClearCodeCache() {
2612 // No write barrier is needed since empty_fixed_array is not in new space.
2613 // Please note this function is used during marking:
2614 // - MarkCompactCollector::MarkUnmarkedObject
2615 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2616 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2617}
2618
2619
ager@chromium.org7c537e22008-10-16 08:43:32 +00002620void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002621 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002622 set_elements(storage);
2623}
2624
2625
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002626Object* FixedArray::Copy() {
2627 if (length() == 0) return this;
2628 return Heap::CopyFixedArray(this);
2629}
2630
2631
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002632#undef CAST_ACCESSOR
2633#undef INT_ACCESSORS
2634#undef SMI_ACCESSORS
2635#undef ACCESSORS
2636#undef FIELD_ADDR
2637#undef READ_FIELD
2638#undef WRITE_FIELD
2639#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002640#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002641#undef READ_MEMADDR_FIELD
2642#undef WRITE_MEMADDR_FIELD
2643#undef READ_DOUBLE_FIELD
2644#undef WRITE_DOUBLE_FIELD
2645#undef READ_INT_FIELD
2646#undef WRITE_INT_FIELD
2647#undef READ_SHORT_FIELD
2648#undef WRITE_SHORT_FIELD
2649#undef READ_BYTE_FIELD
2650#undef WRITE_BYTE_FIELD
2651
2652
2653} } // namespace v8::internal
2654
2655#endif // V8_OBJECTS_INL_H_