blob: 0cfa12b01d5162cb8f0598852a33489b021d7d05 [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//
30// - The use of macros in these inline fuctions may seem superfluous
31// but it is absolutely needed to make sure gcc generates optimal
32// code. gcc is not happy when attempting to inline too deep.
33//
34
35#ifndef V8_OBJECTS_INL_H_
36#define V8_OBJECTS_INL_H_
37
38#include "objects.h"
39#include "contexts.h"
40#include "conversions-inl.h"
41#include "property.h"
42
43namespace v8 { namespace internal {
44
45PropertyDetails::PropertyDetails(Smi* smi) {
46 value_ = smi->value();
47}
48
49
50Smi* PropertyDetails::AsSmi() {
51 return Smi::FromInt(value_);
52}
53
54
55#define CAST_ACCESSOR(type) \
56 type* type::cast(Object* object) { \
57 ASSERT(object->Is##type()); \
58 return reinterpret_cast<type*>(object); \
59 }
60
61
62#define INT_ACCESSORS(holder, name, offset) \
63 int holder::name() { return READ_INT_FIELD(this, offset); } \
64 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
65
66
67#define ACCESSORS(holder, name, type, offset) \
68 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000069 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000071 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000072 }
73
74
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000075
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076#define SMI_ACCESSORS(holder, name, offset) \
77 int holder::name() { \
78 Object* value = READ_FIELD(this, offset); \
79 return Smi::cast(value)->value(); \
80 } \
81 void holder::set_##name(int value) { \
82 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
83 }
84
85
86#define BOOL_ACCESSORS(holder, field, name, offset) \
87 bool holder::name() { \
88 return BooleanBit::get(field(), offset); \
89 } \
90 void holder::set_##name(bool value) { \
91 set_##field(BooleanBit::set(field(), offset, value)); \
92 }
93
94
95bool Object::IsSmi() {
96 return HAS_SMI_TAG(this);
97}
98
99
100bool Object::IsHeapObject() {
101 return HAS_HEAP_OBJECT_TAG(this);
102}
103
104
105bool Object::IsHeapNumber() {
106 return Object::IsHeapObject()
107 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
108}
109
110
111bool Object::IsString() {
112 return Object::IsHeapObject()
113 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
114}
115
116
117bool Object::IsSeqString() {
118 return IsString()
119 && (String::cast(this)->representation_tag() == kSeqStringTag);
120}
121
122
ager@chromium.org7c537e22008-10-16 08:43:32 +0000123bool Object::IsSeqAsciiString() {
124 return IsSeqString()
125 && String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126}
127
128
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000129bool String::IsSeqAsciiString() {
130 return (this->representation_tag() == kSeqStringTag)
131 && is_ascii_representation();
132}
133
134
ager@chromium.org7c537e22008-10-16 08:43:32 +0000135bool Object::IsSeqTwoByteString() {
136 return IsSeqString()
137 && !String::cast(this)->IsAsciiRepresentation();
138}
139
140
141bool Object::IsAsciiStringRepresentation() {
142 return IsString() && (String::cast(this)->is_ascii_representation());
143}
144
145
146bool Object::IsTwoByteStringRepresentation() {
147 return IsString() && (!String::cast(this)->is_ascii_representation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148}
149
150
151bool Object::IsConsString() {
152 return IsString()
153 && (String::cast(this)->representation_tag() == kConsStringTag);
154}
155
156
157bool Object::IsSlicedString() {
158 return IsString()
159 && (String::cast(this)->representation_tag() == kSlicedStringTag);
160}
161
162
163bool Object::IsExternalString() {
164 return IsString()
165 && (String::cast(this)->representation_tag() == kExternalStringTag);
166}
167
168
169bool Object::IsExternalAsciiString() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000170 return IsExternalString() && (String::cast(this)->is_ascii_representation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000171}
172
173
174bool Object::IsExternalTwoByteString() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000175 return IsExternalString() && (!String::cast(this)->is_ascii_representation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176}
177
178
179bool Object::IsShortString() {
180 return IsString() && (String::cast(this)->size_tag() == kShortStringTag);
181}
182
183
184bool Object::IsMediumString() {
185 return IsString() && (String::cast(this)->size_tag() == kMediumStringTag);
186}
187
188
189bool Object::IsLongString() {
190 return IsString() && (String::cast(this)->size_tag() == kLongStringTag);
191}
192
193
194bool Object::IsSymbol() {
195 return IsString() && (String::cast(this)->is_symbol());
196}
197
198
199bool Object::IsNumber() {
200 return IsSmi() || IsHeapNumber();
201}
202
203
204bool Object::IsByteArray() {
205 return Object::IsHeapObject()
206 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
207}
208
209
210bool Object::IsFailure() {
211 return HAS_FAILURE_TAG(this);
212}
213
214
215bool Object::IsRetryAfterGC() {
216 return HAS_FAILURE_TAG(this)
217 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
218}
219
220
ager@chromium.org7c537e22008-10-16 08:43:32 +0000221bool Object::IsOutOfMemoryFailure() {
222 return HAS_FAILURE_TAG(this)
223 && Failure::cast(this)->IsOutOfMemoryException();
224}
225
226
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000227bool Object::IsException() {
228 return this == Failure::Exception();
229}
230
231
232bool Object::IsJSObject() {
233 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000234 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235}
236
237
238bool Object::IsMap() {
239 return Object::IsHeapObject()
240 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
241}
242
243
244bool Object::IsFixedArray() {
245 return Object::IsHeapObject()
246 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
247}
248
249
250bool Object::IsDescriptorArray() {
251 return IsFixedArray();
252}
253
254
255bool Object::IsContext() {
256 return Object::IsHeapObject()
257 && (HeapObject::cast(this)->map() == Heap::context_map() ||
258 HeapObject::cast(this)->map() == Heap::global_context_map());
259}
260
261
262bool Object::IsGlobalContext() {
263 return Object::IsHeapObject()
264 && HeapObject::cast(this)->map() == Heap::global_context_map();
265}
266
267
268bool Object::IsJSFunction() {
269 return Object::IsHeapObject()
270 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
271}
272
273
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000274template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275 return obj->IsJSFunction();
276}
277
278
279bool Object::IsCode() {
280 return Object::IsHeapObject()
281 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
282}
283
284
285bool Object::IsOddball() {
286 return Object::IsHeapObject()
287 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
288}
289
290
291bool Object::IsSharedFunctionInfo() {
292 return Object::IsHeapObject() &&
293 (HeapObject::cast(this)->map()->instance_type() ==
294 SHARED_FUNCTION_INFO_TYPE);
295}
296
297
298bool Object::IsJSValue() {
299 return Object::IsHeapObject()
300 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
301}
302
303
304bool Object::IsProxy() {
305 return Object::IsHeapObject()
306 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
307}
308
309
310bool Object::IsBoolean() {
311 return IsTrue() || IsFalse();
312}
313
314
315bool Object::IsJSArray() {
316 return Object::IsHeapObject()
317 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
318}
319
320
ager@chromium.org236ad962008-09-25 09:45:57 +0000321bool Object::IsJSRegExp() {
322 return Object::IsHeapObject()
323 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
324}
325
326
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000327template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 return obj->IsJSArray();
329}
330
331
332bool Object::IsHashTable() {
333 return Object::IsHeapObject()
334 && HeapObject::cast(this)->map() == Heap::hash_table_map();
335}
336
337
338bool Object::IsDictionary() {
339 return IsHashTable() && this != Heap::symbol_table();
340}
341
342
343bool Object::IsSymbolTable() {
344 return IsHashTable() && this == Heap::symbol_table();
345}
346
347
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000348bool Object::IsCompilationCacheTable() {
349 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000350}
351
352
ager@chromium.org236ad962008-09-25 09:45:57 +0000353bool Object::IsMapCache() {
354 return IsHashTable();
355}
356
357
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000358bool Object::IsLookupCache() {
359 return IsHashTable();
360}
361
362
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000363bool Object::IsPrimitive() {
364 return IsOddball() || IsNumber() || IsString();
365}
366
367
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000368bool Object::IsJSGlobalProxy() {
369 bool result = IsHeapObject() &&
370 (HeapObject::cast(this)->map()->instance_type() ==
371 JS_GLOBAL_PROXY_TYPE);
372 ASSERT(!result || IsAccessCheckNeeded());
373 return result;
374}
375
376
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000377bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000378 if (!IsHeapObject()) return false;
379
380 InstanceType type = HeapObject::cast(this)->map()->instance_type();
381 return type == JS_GLOBAL_OBJECT_TYPE ||
382 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000383}
384
385
386bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 return IsHeapObject() &&
388 (HeapObject::cast(this)->map()->instance_type() ==
389 JS_GLOBAL_OBJECT_TYPE);
390}
391
392
393bool Object::IsJSBuiltinsObject() {
394 return IsHeapObject() &&
395 (HeapObject::cast(this)->map()->instance_type() ==
396 JS_BUILTINS_OBJECT_TYPE);
397}
398
399
400bool Object::IsUndetectableObject() {
401 return IsHeapObject()
402 && HeapObject::cast(this)->map()->is_undetectable();
403}
404
405
406bool Object::IsAccessCheckNeeded() {
407 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000408 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409}
410
411
412bool Object::IsStruct() {
413 if (!IsHeapObject()) return false;
414 switch (HeapObject::cast(this)->map()->instance_type()) {
415#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
416 STRUCT_LIST(MAKE_STRUCT_CASE)
417#undef MAKE_STRUCT_CASE
418 default: return false;
419 }
420}
421
422
423#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
424 bool Object::Is##Name() { \
425 return Object::IsHeapObject() \
426 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
427 }
428 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
429#undef MAKE_STRUCT_PREDICATE
430
431
432bool Object::IsUndefined() {
433 return this == Heap::undefined_value();
434}
435
436
437bool Object::IsTheHole() {
438 return this == Heap::the_hole_value();
439}
440
441
442bool Object::IsNull() {
443 return this == Heap::null_value();
444}
445
446
447bool Object::IsTrue() {
448 return this == Heap::true_value();
449}
450
451
452bool Object::IsFalse() {
453 return this == Heap::false_value();
454}
455
456
457double Object::Number() {
458 ASSERT(IsNumber());
459 return IsSmi()
460 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
461 : reinterpret_cast<HeapNumber*>(this)->value();
462}
463
464
465
466Object* Object::ToSmi() {
467 if (IsSmi()) return this;
468 if (IsHeapNumber()) {
469 double value = HeapNumber::cast(this)->value();
470 int int_value = FastD2I(value);
471 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
472 return Smi::FromInt(int_value);
473 }
474 }
475 return Failure::Exception();
476}
477
478
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000479bool Object::HasSpecificClassOf(String* name) {
480 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
481}
482
483
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484Object* Object::GetElement(uint32_t index) {
485 return GetElementWithReceiver(this, index);
486}
487
488
489Object* Object::GetProperty(String* key) {
490 PropertyAttributes attributes;
491 return GetPropertyWithReceiver(this, key, &attributes);
492}
493
494
495Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
496 return GetPropertyWithReceiver(this, key, attributes);
497}
498
499
500#define FIELD_ADDR(p, offset) \
501 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
502
503#define READ_FIELD(p, offset) \
504 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
505
506#define WRITE_FIELD(p, offset, value) \
507 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
508
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000509
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510#define WRITE_BARRIER(object, offset) \
511 Heap::RecordWrite(object->address(), offset);
512
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000513// CONITIONAL_WRITE_BARRIER must be issued after the actual
514// write due to the assert validating the written value.
515#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
516 if (mode == UPDATE_WRITE_BARRIER) { \
517 Heap::RecordWrite(object->address(), offset); \
518 } else { \
519 ASSERT(mode == SKIP_WRITE_BARRIER); \
520 ASSERT(Heap::InNewSpace(object) || \
521 !Heap::InNewSpace(READ_FIELD(object, offset))); \
522 }
523
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524#define READ_DOUBLE_FIELD(p, offset) \
525 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
526
527#define WRITE_DOUBLE_FIELD(p, offset, value) \
528 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
529
530#define READ_INT_FIELD(p, offset) \
531 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
532
533#define WRITE_INT_FIELD(p, offset, value) \
534 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
535
ager@chromium.org7c537e22008-10-16 08:43:32 +0000536#define READ_UINT32_FIELD(p, offset) \
537 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
538
539#define WRITE_UINT32_FIELD(p, offset, value) \
540 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
541
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542#define READ_SHORT_FIELD(p, offset) \
543 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
544
545#define WRITE_SHORT_FIELD(p, offset, value) \
546 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
547
548#define READ_BYTE_FIELD(p, offset) \
549 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
550
551#define WRITE_BYTE_FIELD(p, offset, value) \
552 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
553
554
555Object* HeapObject::GetHeapObjectField(HeapObject* obj, int index) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000556 return READ_FIELD(obj, HeapObject::kHeaderSize + kPointerSize * index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557}
558
559
560int Smi::value() {
561 return reinterpret_cast<int>(this) >> kSmiTagSize;
562}
563
564
565Smi* Smi::FromInt(int value) {
566 ASSERT(Smi::IsValid(value));
567 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
568}
569
570
571Failure::Type Failure::type() const {
572 return static_cast<Type>(value() & kFailureTypeTagMask);
573}
574
575
576bool Failure::IsInternalError() const {
577 return type() == INTERNAL_ERROR;
578}
579
580
581bool Failure::IsOutOfMemoryException() const {
582 return type() == OUT_OF_MEMORY_EXCEPTION;
583}
584
585
586int Failure::requested() const {
587 const int kShiftBits =
588 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
589 STATIC_ASSERT(kShiftBits >= 0);
590 ASSERT(type() == RETRY_AFTER_GC);
591 return value() >> kShiftBits;
592}
593
594
595AllocationSpace Failure::allocation_space() const {
596 ASSERT_EQ(RETRY_AFTER_GC, type());
597 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
598 & kSpaceTagMask);
599}
600
601
602Failure* Failure::InternalError() {
603 return Construct(INTERNAL_ERROR);
604}
605
606
607Failure* Failure::Exception() {
608 return Construct(EXCEPTION);
609}
610
611Failure* Failure::OutOfMemoryException() {
612 return Construct(OUT_OF_MEMORY_EXCEPTION);
613}
614
615
616int Failure::value() const {
617 return reinterpret_cast<int>(this) >> kFailureTagSize;
618}
619
620
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000621Failure* Failure::RetryAfterGC(int requested_bytes) {
622 int requested = requested_bytes >> kObjectAlignmentBits;
623 int value = (requested << kSpaceTagSize) | NEW_SPACE;
624 ASSERT(value >> kSpaceTagSize == requested);
625 ASSERT(Smi::IsValid(value));
626 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
627 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
628 return Construct(RETRY_AFTER_GC, value);
629}
630
631
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000632Failure* Failure::Construct(Type type, int value) {
633 int info = (value << kFailureTypeTagSize) | type;
634 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
635 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
636}
637
638
639bool Smi::IsValid(int value) {
640#ifdef DEBUG
641 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
642#endif
643 // To be representable as an tagged small integer, the two
644 // most-significant bits of 'value' must be either 00 or 11 due to
645 // sign-extension. To check this we add 01 to the two
646 // most-significant bits, and check if the most-significant bit is 0
647 //
648 // CAUTION: The original code below:
649 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
650 // may lead to incorrect results according to the C language spec, and
651 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
652 // compiler may produce undefined results in case of signed integer
653 // overflow. The computation must be done w/ unsigned ints.
654 bool result =
655 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
656 ASSERT(result == in_range);
657 return result;
658}
659
660
kasper.lund7276f142008-07-30 08:49:36 +0000661MapWord MapWord::FromMap(Map* map) {
662 return MapWord(reinterpret_cast<uintptr_t>(map));
663}
664
665
666Map* MapWord::ToMap() {
667 return reinterpret_cast<Map*>(value_);
668}
669
670
671bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000672 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000673}
674
675
676MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000677 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
678 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000679}
680
681
682HeapObject* MapWord::ToForwardingAddress() {
683 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000684 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000685}
686
687
688bool MapWord::IsMarked() {
689 return (value_ & kMarkingMask) == 0;
690}
691
692
693void MapWord::SetMark() {
694 value_ &= ~kMarkingMask;
695}
696
697
698void MapWord::ClearMark() {
699 value_ |= kMarkingMask;
700}
701
702
703bool MapWord::IsOverflowed() {
704 return (value_ & kOverflowMask) != 0;
705}
706
707
708void MapWord::SetOverflow() {
709 value_ |= kOverflowMask;
710}
711
712
713void MapWord::ClearOverflow() {
714 value_ &= ~kOverflowMask;
715}
716
717
718MapWord MapWord::EncodeAddress(Address map_address, int offset) {
719 // Offset is the distance in live bytes from the first live object in the
720 // same page. The offset between two objects in the same page should not
721 // exceed the object area size of a page.
722 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
723
724 int compact_offset = offset >> kObjectAlignmentBits;
725 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
726
727 Page* map_page = Page::FromAddress(map_address);
728 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
729
730 int map_page_offset =
731 map_page->Offset(map_address) >> kObjectAlignmentBits;
732
733 uintptr_t encoding =
734 (compact_offset << kForwardingOffsetShift) |
735 (map_page_offset << kMapPageOffsetShift) |
736 (map_page->mc_page_index << kMapPageIndexShift);
737 return MapWord(encoding);
738}
739
740
741Address MapWord::DecodeMapAddress(MapSpace* map_space) {
742 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
743 ASSERT_MAP_PAGE_INDEX(map_page_index);
744
745 int map_page_offset =
746 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
747 << kObjectAlignmentBits;
748
749 return (map_space->PageAddress(map_page_index) + map_page_offset);
750}
751
752
753int MapWord::DecodeOffset() {
754 // The offset field is represented in the kForwardingOffsetBits
755 // most-significant bits.
756 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
757 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
758 return offset;
759}
760
761
762MapWord MapWord::FromEncodedAddress(Address address) {
763 return MapWord(reinterpret_cast<uintptr_t>(address));
764}
765
766
767Address MapWord::ToEncodedAddress() {
768 return reinterpret_cast<Address>(value_);
769}
770
771
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772#ifdef DEBUG
773void HeapObject::VerifyObjectField(int offset) {
774 VerifyPointer(READ_FIELD(this, offset));
775}
776#endif
777
778
779Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000780 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781}
782
783
784void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000785 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000786}
787
788
kasper.lund7276f142008-07-30 08:49:36 +0000789MapWord HeapObject::map_word() {
790 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
791}
792
793
794void HeapObject::set_map_word(MapWord map_word) {
795 // WRITE_FIELD does not update the remembered set, but there is no need
796 // here.
797 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
798}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799
800
801HeapObject* HeapObject::FromAddress(Address address) {
802 ASSERT_TAG_ALIGNED(address);
803 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
804}
805
806
807Address HeapObject::address() {
808 return reinterpret_cast<Address>(this) - kHeapObjectTag;
809}
810
811
812int HeapObject::Size() {
813 return SizeFromMap(map());
814}
815
816
817void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
818 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
819 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
820}
821
822
823void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
824 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
825}
826
827
kasper.lund7276f142008-07-30 08:49:36 +0000828bool HeapObject::IsMarked() {
829 return map_word().IsMarked();
830}
831
832
833void HeapObject::SetMark() {
834 ASSERT(!IsMarked());
835 MapWord first_word = map_word();
836 first_word.SetMark();
837 set_map_word(first_word);
838}
839
840
841void HeapObject::ClearMark() {
842 ASSERT(IsMarked());
843 MapWord first_word = map_word();
844 first_word.ClearMark();
845 set_map_word(first_word);
846}
847
848
849bool HeapObject::IsOverflowed() {
850 return map_word().IsOverflowed();
851}
852
853
854void HeapObject::SetOverflow() {
855 MapWord first_word = map_word();
856 first_word.SetOverflow();
857 set_map_word(first_word);
858}
859
860
861void HeapObject::ClearOverflow() {
862 ASSERT(IsOverflowed());
863 MapWord first_word = map_word();
864 first_word.ClearOverflow();
865 set_map_word(first_word);
866}
867
868
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869double HeapNumber::value() {
870 return READ_DOUBLE_FIELD(this, kValueOffset);
871}
872
873
874void HeapNumber::set_value(double value) {
875 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
876}
877
878
879ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000880ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000881
882
883void JSObject::initialize_properties() {
884 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
885 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
886}
887
888
889void JSObject::initialize_elements() {
890 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
891 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
892}
893
894
895ACCESSORS(Oddball, to_string, String, kToStringOffset)
896ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
897
898
899int JSObject::GetHeaderSize() {
900 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000901 case JS_GLOBAL_PROXY_TYPE:
902 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000903 case JS_GLOBAL_OBJECT_TYPE:
904 return JSGlobalObject::kSize;
905 case JS_BUILTINS_OBJECT_TYPE:
906 return JSBuiltinsObject::kSize;
907 case JS_FUNCTION_TYPE:
908 return JSFunction::kSize;
909 case JS_VALUE_TYPE:
910 return JSValue::kSize;
911 case JS_ARRAY_TYPE:
912 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +0000913 case JS_REGEXP_TYPE:
914 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915 case JS_OBJECT_TYPE:
916 return JSObject::kHeaderSize;
917 default:
918 UNREACHABLE();
919 return 0;
920 }
921}
922
923
924int JSObject::GetInternalFieldCount() {
925 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000926 // Make sure to adjust for the number of in-object properties. These
927 // properties do contribute to the size, but are not internal fields.
928 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
929 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000930}
931
932
933Object* JSObject::GetInternalField(int index) {
934 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000935 // Internal objects do follow immediately after the header, whereas in-object
936 // properties are at the end of the object. Therefore there is no need
937 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000938 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
939}
940
941
942void JSObject::SetInternalField(int index, Object* value) {
943 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000944 // Internal objects do follow immediately after the header, whereas in-object
945 // properties are at the end of the object. Therefore there is no need
946 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000947 int offset = GetHeaderSize() + (kPointerSize * index);
948 WRITE_FIELD(this, offset, value);
949 WRITE_BARRIER(this, offset);
950}
951
952
ager@chromium.org7c537e22008-10-16 08:43:32 +0000953// Access fast-case object properties at index. The use of these routines
954// is needed to correctly distinguish between properties stored in-object and
955// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000956Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000957 // Adjust for the number of properties stored in the object.
958 index -= map()->inobject_properties();
959 if (index < 0) {
960 int offset = map()->instance_size() + (index * kPointerSize);
961 return READ_FIELD(this, offset);
962 } else {
963 ASSERT(index < properties()->length());
964 return properties()->get(index);
965 }
966}
967
968
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000969Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000970 // Adjust for the number of properties stored in the object.
971 index -= map()->inobject_properties();
972 if (index < 0) {
973 int offset = map()->instance_size() + (index * kPointerSize);
974 WRITE_FIELD(this, offset, value);
975 WRITE_BARRIER(this, offset);
976 } else {
977 ASSERT(index < properties()->length());
978 properties()->set(index, value);
979 }
980 return value;
981}
982
983
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000984Object* JSObject::InObjectPropertyAtPut(int index,
985 Object* value,
986 WriteBarrierMode mode) {
987 // Adjust for the number of properties stored in the object.
988 index -= map()->inobject_properties();
989 ASSERT(index < 0);
990 int offset = map()->instance_size() + (index * kPointerSize);
991 WRITE_FIELD(this, offset, value);
992 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
993 return value;
994}
995
996
997
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000998void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000999 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001000 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001001 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001002 }
1003}
1004
1005
1006void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001007 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001008 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001009 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001010 }
1011}
1012
1013
1014bool JSObject::HasFastProperties() {
1015 return !properties()->IsDictionary();
1016}
1017
1018
1019bool Array::IndexFromObject(Object* object, uint32_t* index) {
1020 if (object->IsSmi()) {
1021 int value = Smi::cast(object)->value();
1022 if (value < 0) return false;
1023 *index = value;
1024 return true;
1025 }
1026 if (object->IsHeapNumber()) {
1027 double value = HeapNumber::cast(object)->value();
1028 uint32_t uint_value = static_cast<uint32_t>(value);
1029 if (value == static_cast<double>(uint_value)) {
1030 *index = uint_value;
1031 return true;
1032 }
1033 }
1034 return false;
1035}
1036
1037
1038bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1039 if (!this->IsJSValue()) return false;
1040
1041 JSValue* js_value = JSValue::cast(this);
1042 if (!js_value->value()->IsString()) return false;
1043
1044 String* str = String::cast(js_value->value());
1045 if (index >= (uint32_t)str->length()) return false;
1046
1047 return true;
1048}
1049
1050
1051Object* FixedArray::get(int index) {
1052 ASSERT(index >= 0 && index < this->length());
1053 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1054}
1055
1056
1057void FixedArray::set(int index, Object* value) {
1058 ASSERT(index >= 0 && index < this->length());
1059 int offset = kHeaderSize + index * kPointerSize;
1060 WRITE_FIELD(this, offset, value);
1061 WRITE_BARRIER(this, offset);
1062}
1063
1064
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001065WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001066 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1067 return UPDATE_WRITE_BARRIER;
1068}
1069
1070
1071void FixedArray::set(int index,
1072 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001073 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001074 ASSERT(index >= 0 && index < this->length());
1075 int offset = kHeaderSize + index * kPointerSize;
1076 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001077 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001078}
1079
1080
1081void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1082 ASSERT(index >= 0 && index < array->length());
1083 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1084}
1085
1086
1087void FixedArray::set_undefined(int index) {
1088 ASSERT(index >= 0 && index < this->length());
1089 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1090 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1091 Heap::undefined_value());
1092}
1093
1094
ager@chromium.org236ad962008-09-25 09:45:57 +00001095void FixedArray::set_null(int index) {
1096 ASSERT(index >= 0 && index < this->length());
1097 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1098 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1099}
1100
1101
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001102void FixedArray::set_the_hole(int index) {
1103 ASSERT(index >= 0 && index < this->length());
1104 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1105 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1106}
1107
1108
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001109bool DescriptorArray::IsEmpty() {
1110 ASSERT(this == Heap::empty_descriptor_array() ||
1111 this->length() > 2);
1112 return this == Heap::empty_descriptor_array();
1113}
1114
1115
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001116void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1117 Object* tmp = array->get(first);
1118 fast_set(array, first, array->get(second));
1119 fast_set(array, second, tmp);
1120}
1121
1122
1123int DescriptorArray::Search(String* name) {
1124 SLOW_ASSERT(IsSortedNoDuplicates());
1125
1126 // Check for empty descriptor array.
1127 int nof = number_of_descriptors();
1128 if (nof == 0) return kNotFound;
1129
1130 // Fast case: do linear search for small arrays.
1131 const int kMaxElementsForLinearSearch = 8;
1132 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
1133 for (int number = 0; number < nof; number++) {
1134 if (name == GetKey(number)) return number;
1135 }
1136 return kNotFound;
1137 }
1138
1139 // Slow case: perform binary search.
1140 return BinarySearch(name, 0, nof - 1);
1141}
1142
1143
1144
1145String* DescriptorArray::GetKey(int descriptor_number) {
1146 ASSERT(descriptor_number < number_of_descriptors());
1147 return String::cast(get(ToKeyIndex(descriptor_number)));
1148}
1149
1150
1151Object* DescriptorArray::GetValue(int descriptor_number) {
1152 ASSERT(descriptor_number < number_of_descriptors());
1153 return GetContentArray()->get(ToValueIndex(descriptor_number));
1154}
1155
1156
1157Smi* DescriptorArray::GetDetails(int descriptor_number) {
1158 ASSERT(descriptor_number < number_of_descriptors());
1159 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1160}
1161
1162
1163void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1164 desc->Init(GetKey(descriptor_number),
1165 GetValue(descriptor_number),
1166 GetDetails(descriptor_number));
1167}
1168
1169
1170void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1171 // Range check.
1172 ASSERT(descriptor_number < number_of_descriptors());
1173
1174 // Make sure non of the elements in desc are in new space.
1175 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1176 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1177
1178 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1179 FixedArray* content_array = GetContentArray();
1180 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1181 fast_set(content_array, ToDetailsIndex(descriptor_number),
1182 desc->GetDetails().AsSmi());
1183}
1184
1185
1186void DescriptorArray::Swap(int first, int second) {
1187 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1188 FixedArray* content_array = GetContentArray();
1189 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1190 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1191}
1192
1193
1194bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001195 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001196 if (!max_index_object->IsSmi()) return false;
1197 return 0 !=
1198 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1199}
1200
1201
1202uint32_t Dictionary::max_number_key() {
1203 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001204 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001205 if (!max_index_object->IsSmi()) return 0;
1206 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1207 return value >> kRequiresSlowElementsTagSize;
1208}
1209
1210
1211// ------------------------------------
1212// Cast operations
1213
1214
1215CAST_ACCESSOR(FixedArray)
1216CAST_ACCESSOR(DescriptorArray)
1217CAST_ACCESSOR(Dictionary)
1218CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001219CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001220CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001221CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001222CAST_ACCESSOR(String)
1223CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001224CAST_ACCESSOR(SeqAsciiString)
1225CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001226CAST_ACCESSOR(ConsString)
1227CAST_ACCESSOR(SlicedString)
1228CAST_ACCESSOR(ExternalString)
1229CAST_ACCESSOR(ExternalAsciiString)
1230CAST_ACCESSOR(ExternalTwoByteString)
1231CAST_ACCESSOR(JSObject)
1232CAST_ACCESSOR(Smi)
1233CAST_ACCESSOR(Failure)
1234CAST_ACCESSOR(HeapObject)
1235CAST_ACCESSOR(HeapNumber)
1236CAST_ACCESSOR(Oddball)
1237CAST_ACCESSOR(SharedFunctionInfo)
1238CAST_ACCESSOR(Map)
1239CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001240CAST_ACCESSOR(GlobalObject)
1241CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001242CAST_ACCESSOR(JSGlobalObject)
1243CAST_ACCESSOR(JSBuiltinsObject)
1244CAST_ACCESSOR(Code)
1245CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001246CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001247CAST_ACCESSOR(Proxy)
1248CAST_ACCESSOR(ByteArray)
1249CAST_ACCESSOR(Struct)
1250
1251
1252#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1253 STRUCT_LIST(MAKE_STRUCT_CAST)
1254#undef MAKE_STRUCT_CAST
1255
1256template <int prefix_size, int elem_size>
1257HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1258 Object* obj) {
1259 ASSERT(obj->IsHashTable());
1260 return reinterpret_cast<HashTable*>(obj);
1261}
1262
1263
1264INT_ACCESSORS(Array, length, kLengthOffset)
1265
1266
1267bool String::Equals(String* other) {
1268 if (other == this) return true;
1269 if (IsSymbol() && other->IsSymbol()) return false;
1270 return SlowEquals(other);
1271}
1272
1273
1274int String::length() {
1275 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1276
1277 switch (size_tag()) {
1278 case kShortStringTag:
1279 return len >> kShortLengthShift;
1280 case kMediumStringTag:
1281 return len >> kMediumLengthShift;
1282 case kLongStringTag:
1283 return len >> kLongLengthShift;
1284 default:
1285 break;
1286 }
1287 UNREACHABLE();
1288 return 0;
1289}
1290
1291
1292void String::set_length(int value) {
1293 switch (size_tag()) {
1294 case kShortStringTag:
1295 WRITE_INT_FIELD(this, kLengthOffset, value << kShortLengthShift);
1296 break;
1297 case kMediumStringTag:
1298 WRITE_INT_FIELD(this, kLengthOffset, value << kMediumLengthShift);
1299 break;
1300 case kLongStringTag:
1301 WRITE_INT_FIELD(this, kLengthOffset, value << kLongLengthShift);
1302 break;
1303 default:
1304 UNREACHABLE();
1305 break;
1306 }
1307}
1308
1309
ager@chromium.org7c537e22008-10-16 08:43:32 +00001310uint32_t String::length_field() {
1311 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001312}
1313
1314
ager@chromium.org7c537e22008-10-16 08:43:32 +00001315void String::set_length_field(uint32_t value) {
1316 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001317}
1318
1319
1320void String::TryFlatten() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001321 // We don't need to flatten strings that are already flat. Since this code
1322 // is inlined, it can be helpful in the flat case to not call out to Flatten.
1323 StringRepresentationTag str_type = representation_tag();
1324 if (str_type != kSeqStringTag && str_type != kExternalStringTag) {
1325 Flatten();
1326 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001327}
1328
1329
1330uint16_t String::Get(int index) {
1331 ASSERT(index >= 0 && index < length());
1332 switch (representation_tag()) {
1333 case kSeqStringTag:
ager@chromium.org7c537e22008-10-16 08:43:32 +00001334 return is_ascii_representation()
1335 ? SeqAsciiString::cast(this)->SeqAsciiStringGet(index)
1336 : SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337 case kConsStringTag:
1338 return ConsString::cast(this)->ConsStringGet(index);
1339 case kSlicedStringTag:
1340 return SlicedString::cast(this)->SlicedStringGet(index);
1341 case kExternalStringTag:
ager@chromium.org7c537e22008-10-16 08:43:32 +00001342 return is_ascii_representation()
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001343 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
1344 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1345 default:
1346 break;
1347 }
1348
1349 UNREACHABLE();
1350 return 0;
1351}
1352
1353
1354void String::Set(int index, uint16_t value) {
1355 ASSERT(index >= 0 && index < length());
1356 ASSERT(IsSeqString());
1357
ager@chromium.org7c537e22008-10-16 08:43:32 +00001358 return is_ascii_representation()
1359 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1360 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361}
1362
1363
ager@chromium.org7c537e22008-10-16 08:43:32 +00001364bool String::IsAsciiRepresentation() {
1365 return is_ascii_representation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001366}
1367
1368
1369bool String::StringIsConsString() {
1370 return representation_tag() == kConsStringTag;
1371}
1372
1373
1374bool String::StringIsSlicedString() {
1375 return representation_tag() == kSlicedStringTag;
1376}
1377
1378
1379uint32_t String::size_tag() {
1380 return map_size_tag(map());
1381}
1382
1383
1384uint32_t String::map_size_tag(Map* map) {
1385 return map->instance_type() & kStringSizeMask;
1386}
1387
1388
1389bool String::is_symbol() {
1390 return is_symbol_map(map());
1391}
1392
1393
1394bool String::is_symbol_map(Map* map) {
1395 return (map->instance_type() & kIsSymbolMask) != 0;
1396}
1397
1398
ager@chromium.org7c537e22008-10-16 08:43:32 +00001399bool String::is_ascii_representation() {
1400 return is_ascii_representation_map(map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001401}
1402
1403
ager@chromium.org7c537e22008-10-16 08:43:32 +00001404bool String::is_ascii_representation_map(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405 return (map->instance_type() & kStringEncodingMask) != 0;
1406}
1407
1408
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001409int String::full_representation_tag() {
1410 return map()->instance_type() &
1411 (kStringRepresentationMask | kStringEncodingMask);
1412}
1413
1414
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001415StringRepresentationTag String::representation_tag() {
1416 return map_representation_tag(map());
1417}
1418
1419
1420StringRepresentationTag String::map_representation_tag(Map* map) {
1421 uint32_t tag = map->instance_type() & kStringRepresentationMask;
1422 return static_cast<StringRepresentationTag>(tag);
1423}
1424
1425
1426bool String::IsFlat() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001427 switch (this->representation_tag()) {
1428 case kConsStringTag:
1429 // Only flattened strings have second part empty.
1430 return String::cast(ConsString::cast(this)->second())->length() == 0;
1431 case kSlicedStringTag: {
1432 String* slice = String::cast(SlicedString::cast(this)->buffer());
1433 StringRepresentationTag tag = slice->representation_tag();
1434 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001435 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001436 default:
1437 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001438 }
1439}
1440
1441
ager@chromium.org7c537e22008-10-16 08:43:32 +00001442uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001443 ASSERT(index >= 0 && index < length());
1444 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1445}
1446
1447
ager@chromium.org7c537e22008-10-16 08:43:32 +00001448void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001449 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1450 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1451 static_cast<byte>(value));
1452}
1453
1454
ager@chromium.org7c537e22008-10-16 08:43:32 +00001455Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456 return FIELD_ADDR(this, kHeaderSize);
1457}
1458
1459
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001460char* SeqAsciiString::GetChars() {
1461 return reinterpret_cast<char*>(GetCharsAddress());
1462}
1463
1464
ager@chromium.org7c537e22008-10-16 08:43:32 +00001465Address SeqTwoByteString::GetCharsAddress() {
1466 return FIELD_ADDR(this, kHeaderSize);
1467}
1468
1469
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001470uc16* SeqTwoByteString::GetChars() {
1471 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1472}
1473
1474
ager@chromium.org7c537e22008-10-16 08:43:32 +00001475uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476 ASSERT(index >= 0 && index < length());
1477 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1478}
1479
1480
ager@chromium.org7c537e22008-10-16 08:43:32 +00001481void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001482 ASSERT(index >= 0 && index < length());
1483 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1484}
1485
1486
ager@chromium.org7c537e22008-10-16 08:43:32 +00001487int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001488 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1489
1490 // Use the map (and not 'this') to compute the size tag, since
1491 // TwoByteStringSize is called during GC when maps are encoded.
1492 switch (map_size_tag(map)) {
1493 case kShortStringTag:
1494 length = length >> kShortLengthShift;
1495 break;
1496 case kMediumStringTag:
1497 length = length >> kMediumLengthShift;
1498 break;
1499 case kLongStringTag:
1500 length = length >> kLongLengthShift;
1501 break;
1502 default:
1503 break;
1504 }
1505 return SizeFor(length);
1506}
1507
1508
ager@chromium.org7c537e22008-10-16 08:43:32 +00001509int SeqAsciiString::SeqAsciiStringSize(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1511
1512 // Use the map (and not 'this') to compute the size tag, since
1513 // AsciiStringSize is called during GC when maps are encoded.
1514 switch (map_size_tag(map)) {
1515 case kShortStringTag:
1516 length = length >> kShortLengthShift;
1517 break;
1518 case kMediumStringTag:
1519 length = length >> kMediumLengthShift;
1520 break;
1521 case kLongStringTag:
1522 length = length >> kLongLengthShift;
1523 break;
1524 default:
1525 break;
1526 }
1527
1528 return SizeFor(length);
1529}
1530
1531
1532Object* ConsString::first() {
1533 return READ_FIELD(this, kFirstOffset);
1534}
1535
1536
1537void ConsString::set_first(Object* value) {
1538 WRITE_FIELD(this, kFirstOffset, value);
1539 WRITE_BARRIER(this, kFirstOffset);
1540}
1541
1542
1543Object* ConsString::second() {
1544 return READ_FIELD(this, kSecondOffset);
1545}
1546
1547
1548void ConsString::set_second(Object* value) {
1549 WRITE_FIELD(this, kSecondOffset, value);
1550 WRITE_BARRIER(this, kSecondOffset);
1551}
1552
1553
1554Object* SlicedString::buffer() {
1555 return READ_FIELD(this, kBufferOffset);
1556}
1557
1558
1559void SlicedString::set_buffer(Object* buffer) {
1560 WRITE_FIELD(this, kBufferOffset, buffer);
1561 WRITE_BARRIER(this, kBufferOffset);
1562}
1563
1564
1565int SlicedString::start() {
1566 return READ_INT_FIELD(this, kStartOffset);
1567}
1568
1569
1570void SlicedString::set_start(int start) {
1571 WRITE_INT_FIELD(this, kStartOffset, start);
1572}
1573
1574
1575ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1576 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1577}
1578
1579
1580void ExternalAsciiString::set_resource(
1581 ExternalAsciiString::Resource* resource) {
1582 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1583}
1584
1585
1586ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1587 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1588}
1589
1590
1591void ExternalTwoByteString::set_resource(
1592 ExternalTwoByteString::Resource* resource) {
1593 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1594}
1595
1596
1597byte ByteArray::get(int index) {
1598 ASSERT(index >= 0 && index < this->length());
1599 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1600}
1601
1602
1603void ByteArray::set(int index, byte value) {
1604 ASSERT(index >= 0 && index < this->length());
1605 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1606}
1607
1608
1609int ByteArray::get_int(int index) {
1610 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1611 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1612}
1613
1614
1615ByteArray* ByteArray::FromDataStartAddress(Address address) {
1616 ASSERT_TAG_ALIGNED(address);
1617 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1618}
1619
1620
1621Address ByteArray::GetDataStartAddress() {
1622 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1623}
1624
1625
1626int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001627 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1628}
1629
1630
1631int Map::inobject_properties() {
1632 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633}
1634
1635
1636int HeapObject::SizeFromMap(Map* map) {
1637 InstanceType instance_type = map->instance_type();
1638 // Only inline the two most frequent cases.
1639 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1640 if (instance_type == FIXED_ARRAY_TYPE) {
1641 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1642 }
1643 // Otherwise do the general size computation.
1644 return SlowSizeFromMap(map);
1645}
1646
1647
1648void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001649 ASSERT((value & ~(kPointerSize - 1)) == value);
1650 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001651 ASSERT(0 <= value && value < 256);
1652 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1653}
1654
1655
ager@chromium.org7c537e22008-10-16 08:43:32 +00001656void Map::set_inobject_properties(int value) {
1657 ASSERT(0 <= value && value < 256);
1658 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1659}
1660
1661
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001662InstanceType Map::instance_type() {
1663 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1664}
1665
1666
1667void Map::set_instance_type(InstanceType value) {
1668 ASSERT(0 <= value && value < 256);
1669 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1670}
1671
1672
1673int Map::unused_property_fields() {
1674 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1675}
1676
1677
1678void Map::set_unused_property_fields(int value) {
1679 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1680}
1681
1682
1683byte Map::bit_field() {
1684 return READ_BYTE_FIELD(this, kBitFieldOffset);
1685}
1686
1687
1688void Map::set_bit_field(byte value) {
1689 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1690}
1691
1692
1693void Map::set_non_instance_prototype(bool value) {
1694 if (value) {
1695 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1696 } else {
1697 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1698 }
1699}
1700
1701
1702bool Map::has_non_instance_prototype() {
1703 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1704}
1705
1706
1707Code::Flags Code::flags() {
1708 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1709}
1710
1711
1712void Code::set_flags(Code::Flags flags) {
1713 // Make sure that all call stubs have an arguments count.
1714 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1715 ExtractArgumentsCountFromFlags(flags) >= 0);
1716 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1717}
1718
1719
1720Code::Kind Code::kind() {
1721 return ExtractKindFromFlags(flags());
1722}
1723
1724
kasper.lund7276f142008-07-30 08:49:36 +00001725InlineCacheState Code::ic_state() {
1726 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001727 // Only allow uninitialized or debugger states for non-IC code
1728 // objects. This is used in the debugger to determine whether or not
1729 // a call to code object has been replaced with a debug break call.
1730 ASSERT(is_inline_cache_stub() ||
1731 result == UNINITIALIZED ||
1732 result == DEBUG_BREAK ||
1733 result == DEBUG_PREPARE_STEP_IN);
1734 return result;
1735}
1736
1737
1738PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001739 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001740 return ExtractTypeFromFlags(flags());
1741}
1742
1743
1744int Code::arguments_count() {
1745 ASSERT(is_call_stub() || kind() == STUB);
1746 return ExtractArgumentsCountFromFlags(flags());
1747}
1748
1749
1750CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001751 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001752 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1753 kStubMajorKeyOffset));
1754}
1755
1756
1757void Code::set_major_key(CodeStub::Major major) {
1758 ASSERT(kind() == STUB);
1759 ASSERT(0 <= major && major < 256);
1760 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761}
1762
1763
1764bool Code::is_inline_cache_stub() {
1765 Kind kind = this->kind();
1766 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1767}
1768
1769
1770Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001771 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001772 PropertyType type,
1773 int argc) {
1774 // Compute the bit mask.
1775 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001776 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001777 bits |= type << kFlagsTypeShift;
1778 bits |= argc << kFlagsArgumentsCountShift;
1779 // Cast to flags and validate result before returning it.
1780 Flags result = static_cast<Flags>(bits);
1781 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001782 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001783 ASSERT(ExtractTypeFromFlags(result) == type);
1784 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1785 return result;
1786}
1787
1788
1789Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1790 PropertyType type,
1791 int argc) {
1792 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1793}
1794
1795
1796Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1797 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1798 return static_cast<Kind>(bits);
1799}
1800
1801
kasper.lund7276f142008-07-30 08:49:36 +00001802InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1803 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001804 return static_cast<InlineCacheState>(bits);
1805}
1806
1807
1808PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1809 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1810 return static_cast<PropertyType>(bits);
1811}
1812
1813
1814int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1815 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1816}
1817
1818
1819Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1820 int bits = flags & ~kFlagsTypeMask;
1821 return static_cast<Flags>(bits);
1822}
1823
1824
1825Object* Map::prototype() {
1826 return READ_FIELD(this, kPrototypeOffset);
1827}
1828
1829
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001830void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001831 ASSERT(value->IsNull() || value->IsJSObject());
1832 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001833 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001834}
1835
1836
1837ACCESSORS(Map, instance_descriptors, DescriptorArray,
1838 kInstanceDescriptorsOffset)
1839ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1840ACCESSORS(Map, constructor, Object, kConstructorOffset)
1841
1842ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1843ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1844
1845ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1846ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001847ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001848
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001849ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001850
1851ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1852ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1853ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1854ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1855ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1856
1857ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1858ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1859ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1860
1861ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1862ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1863ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1864ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1865ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1866ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1867
1868ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1869ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1870
1871ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1872ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1873
1874ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1875ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001876ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1877 kPropertyAccessorsOffset)
1878ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1879 kPrototypeTemplateOffset)
1880ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1881ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1882 kNamedPropertyHandlerOffset)
1883ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1884 kIndexedPropertyHandlerOffset)
1885ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1886 kInstanceTemplateOffset)
1887ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1888ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1890 kInstanceCallHandlerOffset)
1891ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1892 kAccessCheckInfoOffset)
1893ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1894
1895ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001896ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1897 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001898
1899ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1900ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1901
1902ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1903
1904ACCESSORS(Script, source, Object, kSourceOffset)
1905ACCESSORS(Script, name, Object, kNameOffset)
1906ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1907ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1908ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1909ACCESSORS(Script, type, Smi, kTypeOffset)
1910
1911ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1912ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1913ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1914ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1915
1916ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1917ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1918ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1919ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1920
1921ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1922ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1923 kInstanceClassNameOffset)
1924ACCESSORS(SharedFunctionInfo, function_data, Object,
1925 kExternalReferenceDataOffset)
1926ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1927ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1928ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1929
1930BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1931 kHiddenPrototypeBit)
1932BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1933BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1934 kNeedsAccessCheckBit)
1935BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1936 kIsExpressionBit)
1937BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1938 kIsTopLevelBit)
1939
1940INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1941INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1942 kFormalParameterCountOffset)
1943INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1944 kExpectedNofPropertiesOffset)
1945INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
1946 kStartPositionAndTypeOffset)
1947INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
1948INT_ACCESSORS(SharedFunctionInfo, function_token_position,
1949 kFunctionTokenPositionOffset)
1950
1951
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001952void SharedFunctionInfo::DontAdaptArguments() {
1953 ASSERT(code()->kind() == Code::BUILTIN);
1954 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
1955}
1956
1957
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001958int SharedFunctionInfo::start_position() {
1959 return start_position_and_type() >> kStartPositionShift;
1960}
1961
1962
1963void SharedFunctionInfo::set_start_position(int start_position) {
1964 set_start_position_and_type((start_position << kStartPositionShift)
1965 | (start_position_and_type() & ~kStartPositionMask));
1966}
1967
1968
1969Code* SharedFunctionInfo::code() {
1970 return Code::cast(READ_FIELD(this, kCodeOffset));
1971}
1972
1973
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001974void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001975 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001976 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001977}
1978
1979
1980bool SharedFunctionInfo::is_compiled() {
1981 // TODO(1242782): Create a code kind for uncompiled code.
1982 return code()->kind() != Code::STUB;
1983}
1984
1985
1986bool JSFunction::IsBoilerplate() {
1987 return map() == Heap::boilerplate_function_map();
1988}
1989
1990
1991bool JSFunction::IsLoaded() {
1992 return shared()->lazy_load_data() == Heap::undefined_value();
1993}
1994
1995
1996Code* JSFunction::code() {
1997 return shared()->code();
1998}
1999
2000
2001void JSFunction::set_code(Code* value) {
2002 shared()->set_code(value);
2003}
2004
2005
2006Context* JSFunction::context() {
2007 return Context::cast(READ_FIELD(this, kContextOffset));
2008}
2009
2010
2011Object* JSFunction::unchecked_context() {
2012 return READ_FIELD(this, kContextOffset);
2013}
2014
2015
2016void JSFunction::set_context(Object* value) {
2017 ASSERT(value == Heap::undefined_value() || value->IsContext());
2018 WRITE_FIELD(this, kContextOffset, value);
2019 WRITE_BARRIER(this, kContextOffset);
2020}
2021
2022ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2023 kPrototypeOrInitialMapOffset)
2024
2025
2026Map* JSFunction::initial_map() {
2027 return Map::cast(prototype_or_initial_map());
2028}
2029
2030
2031void JSFunction::set_initial_map(Map* value) {
2032 set_prototype_or_initial_map(value);
2033}
2034
2035
2036bool JSFunction::has_initial_map() {
2037 return prototype_or_initial_map()->IsMap();
2038}
2039
2040
2041bool JSFunction::has_instance_prototype() {
2042 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2043}
2044
2045
2046bool JSFunction::has_prototype() {
2047 return map()->has_non_instance_prototype() || has_instance_prototype();
2048}
2049
2050
2051Object* JSFunction::instance_prototype() {
2052 ASSERT(has_instance_prototype());
2053 if (has_initial_map()) return initial_map()->prototype();
2054 // When there is no initial map and the prototype is a JSObject, the
2055 // initial map field is used for the prototype field.
2056 return prototype_or_initial_map();
2057}
2058
2059
2060Object* JSFunction::prototype() {
2061 ASSERT(has_prototype());
2062 // If the function's prototype property has been set to a non-JSObject
2063 // value, that value is stored in the constructor field of the map.
2064 if (map()->has_non_instance_prototype()) return map()->constructor();
2065 return instance_prototype();
2066}
2067
2068
2069bool JSFunction::is_compiled() {
2070 return shared()->is_compiled();
2071}
2072
2073
2074Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2075 ASSERT(0 <= id && id < kJSBuiltinsCount);
2076 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2077}
2078
2079
2080void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2081 Object* value) {
2082 ASSERT(0 <= id && id < kJSBuiltinsCount);
2083 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2084 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2085}
2086
2087
2088Address Proxy::proxy() {
2089 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2090}
2091
2092
2093void Proxy::set_proxy(Address value) {
2094 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2095}
2096
2097
2098void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2099 visitor->VisitExternalReference(
2100 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2101}
2102
2103
2104ACCESSORS(JSValue, value, Object, kValueOffset)
2105
2106
2107JSValue* JSValue::cast(Object* obj) {
2108 ASSERT(obj->IsJSValue());
2109 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2110 return reinterpret_cast<JSValue*>(obj);
2111}
2112
2113
2114INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2115INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2116INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2117
2118
2119Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002120 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002121}
2122
2123
2124void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002125 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002126}
2127
2128
2129byte* Code::instruction_start() {
2130 return FIELD_ADDR(this, kHeaderSize);
2131}
2132
2133
2134int Code::body_size() {
2135 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2136}
2137
2138
2139byte* Code::relocation_start() {
2140 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2141}
2142
2143
2144byte* Code::entry() {
2145 return instruction_start();
2146}
2147
2148
2149bool Code::contains(byte* pc) {
2150 return (instruction_start() <= pc) &&
2151 (pc < instruction_start() + instruction_size());
2152}
2153
2154
2155byte* Code::sinfo_start() {
2156 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2157}
2158
2159
2160ACCESSORS(JSArray, length, Object, kLengthOffset)
2161
2162
ager@chromium.org236ad962008-09-25 09:45:57 +00002163ACCESSORS(JSRegExp, data, Object, kDataOffset)
2164ACCESSORS(JSRegExp, type, Object, kTypeOffset)
2165
2166
2167JSRegExp::Type JSRegExp::type_tag() {
2168 return static_cast<JSRegExp::Type>(Smi::cast(type())->value());
2169}
2170
2171
2172void JSRegExp::set_type_tag(JSRegExp::Type value) {
2173 set_type(Smi::FromInt(value));
2174}
2175
2176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002177bool JSObject::HasFastElements() {
2178 return !elements()->IsDictionary();
2179}
2180
2181
2182bool JSObject::HasNamedInterceptor() {
2183 return map()->has_named_interceptor();
2184}
2185
2186
2187bool JSObject::HasIndexedInterceptor() {
2188 return map()->has_indexed_interceptor();
2189}
2190
2191
2192Dictionary* JSObject::property_dictionary() {
2193 ASSERT(!HasFastProperties());
2194 return Dictionary::cast(properties());
2195}
2196
2197
2198Dictionary* JSObject::element_dictionary() {
2199 ASSERT(!HasFastElements());
2200 return Dictionary::cast(elements());
2201}
2202
2203
2204bool String::HasHashCode() {
2205 return (length_field() & kHashComputedMask) != 0;
2206}
2207
2208
2209uint32_t String::Hash() {
2210 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002211 uint32_t field = length_field();
2212 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002213 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002214 return ComputeAndSetHash();
2215}
2216
2217
ager@chromium.org7c537e22008-10-16 08:43:32 +00002218StringHasher::StringHasher(int length)
2219 : length_(length),
2220 raw_running_hash_(0),
2221 array_index_(0),
2222 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2223 is_first_char_(true),
2224 is_valid_(true) { }
2225
2226
2227bool StringHasher::has_trivial_hash() {
2228 return length_ > String::kMaxMediumStringSize;
2229}
2230
2231
2232void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002233 // Use the Jenkins one-at-a-time hash function to update the hash
2234 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002235 raw_running_hash_ += c;
2236 raw_running_hash_ += (raw_running_hash_ << 10);
2237 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002238 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002239 if (is_array_index_) {
2240 if (c < '0' || c > '9') {
2241 is_array_index_ = false;
2242 } else {
2243 int d = c - '0';
2244 if (is_first_char_) {
2245 is_first_char_ = false;
2246 if (c == '0' && length_ > 1) {
2247 is_array_index_ = false;
2248 return;
2249 }
2250 }
2251 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2252 is_array_index_ = false;
2253 } else {
2254 array_index_ = array_index_ * 10 + d;
2255 }
2256 }
2257 }
2258}
2259
2260
2261void StringHasher::AddCharacterNoIndex(uc32 c) {
2262 ASSERT(!is_array_index());
2263 raw_running_hash_ += c;
2264 raw_running_hash_ += (raw_running_hash_ << 10);
2265 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2266}
2267
2268
2269uint32_t StringHasher::GetHash() {
2270 uint32_t result = raw_running_hash_;
2271 result += (result << 3);
2272 result ^= (result >> 11);
2273 result += (result << 15);
2274 return result;
2275}
2276
2277
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002278bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002279 uint32_t field = length_field();
2280 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002281 return SlowAsArrayIndex(index);
2282}
2283
2284
2285Object* JSObject::GetPrototype() {
2286 return JSObject::cast(this)->map()->prototype();
2287}
2288
2289
2290PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2291 return GetPropertyAttributeWithReceiver(this, key);
2292}
2293
2294
2295bool JSObject::HasElement(uint32_t index) {
2296 return HasElementWithReceiver(this, index);
2297}
2298
2299
2300bool AccessorInfo::all_can_read() {
2301 return BooleanBit::get(flag(), kAllCanReadBit);
2302}
2303
2304
2305void AccessorInfo::set_all_can_read(bool value) {
2306 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2307}
2308
2309
2310bool AccessorInfo::all_can_write() {
2311 return BooleanBit::get(flag(), kAllCanWriteBit);
2312}
2313
2314
2315void AccessorInfo::set_all_can_write(bool value) {
2316 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2317}
2318
2319
2320PropertyAttributes AccessorInfo::property_attributes() {
2321 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2322}
2323
2324
2325void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2326 ASSERT(AttributesField::is_valid(attributes));
2327 int rest_value = flag()->value() & ~AttributesField::mask();
2328 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2329}
2330
2331void Dictionary::SetEntry(int entry,
2332 Object* key,
2333 Object* value,
2334 PropertyDetails details) {
2335 ASSERT(!key->IsString() || details.index() > 0);
2336 int index = EntryToIndex(entry);
2337 WriteBarrierMode mode = GetWriteBarrierMode();
2338 set(index, key, mode);
2339 set(index+1, value, mode);
2340 fast_set(this, index+2, details.AsSmi());
2341}
2342
2343
2344void Map::ClearCodeCache() {
2345 // No write barrier is needed since empty_fixed_array is not in new space.
2346 // Please note this function is used during marking:
2347 // - MarkCompactCollector::MarkUnmarkedObject
2348 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2349 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2350}
2351
2352
ager@chromium.org7c537e22008-10-16 08:43:32 +00002353void JSArray::SetContent(FixedArray* storage) {
2354 set_length(Smi::FromInt(storage->length()));
2355 set_elements(storage);
2356}
2357
2358
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002359Object* FixedArray::Copy() {
2360 if (length() == 0) return this;
2361 return Heap::CopyFixedArray(this);
2362}
2363
2364
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002365#undef CAST_ACCESSOR
2366#undef INT_ACCESSORS
2367#undef SMI_ACCESSORS
2368#undef ACCESSORS
2369#undef FIELD_ADDR
2370#undef READ_FIELD
2371#undef WRITE_FIELD
2372#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002373#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002374#undef READ_MEMADDR_FIELD
2375#undef WRITE_MEMADDR_FIELD
2376#undef READ_DOUBLE_FIELD
2377#undef WRITE_DOUBLE_FIELD
2378#undef READ_INT_FIELD
2379#undef WRITE_INT_FIELD
2380#undef READ_SHORT_FIELD
2381#undef WRITE_SHORT_FIELD
2382#undef READ_BYTE_FIELD
2383#undef WRITE_BYTE_FIELD
2384
2385
2386} } // namespace v8::internal
2387
2388#endif // V8_OBJECTS_INL_H_