blob: beb6c0e1a46553cc9f231593246159a8a40beb14 [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
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000304bool Object::IsStringWrapper() {
305 return IsJSValue() && JSValue::cast(this)->value()->IsString();
306}
307
308
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000309bool Object::IsProxy() {
310 return Object::IsHeapObject()
311 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
312}
313
314
315bool Object::IsBoolean() {
316 return IsTrue() || IsFalse();
317}
318
319
320bool Object::IsJSArray() {
321 return Object::IsHeapObject()
322 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
323}
324
325
ager@chromium.org236ad962008-09-25 09:45:57 +0000326bool Object::IsJSRegExp() {
327 return Object::IsHeapObject()
328 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
329}
330
331
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000332template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000333 return obj->IsJSArray();
334}
335
336
337bool Object::IsHashTable() {
338 return Object::IsHeapObject()
339 && HeapObject::cast(this)->map() == Heap::hash_table_map();
340}
341
342
343bool Object::IsDictionary() {
344 return IsHashTable() && this != Heap::symbol_table();
345}
346
347
348bool Object::IsSymbolTable() {
349 return IsHashTable() && this == Heap::symbol_table();
350}
351
352
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000353bool Object::IsCompilationCacheTable() {
354 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000355}
356
357
ager@chromium.org236ad962008-09-25 09:45:57 +0000358bool Object::IsMapCache() {
359 return IsHashTable();
360}
361
362
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000363bool Object::IsLookupCache() {
364 return IsHashTable();
365}
366
367
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368bool Object::IsPrimitive() {
369 return IsOddball() || IsNumber() || IsString();
370}
371
372
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000373bool Object::IsJSGlobalProxy() {
374 bool result = IsHeapObject() &&
375 (HeapObject::cast(this)->map()->instance_type() ==
376 JS_GLOBAL_PROXY_TYPE);
377 ASSERT(!result || IsAccessCheckNeeded());
378 return result;
379}
380
381
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000382bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000383 if (!IsHeapObject()) return false;
384
385 InstanceType type = HeapObject::cast(this)->map()->instance_type();
386 return type == JS_GLOBAL_OBJECT_TYPE ||
387 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388}
389
390
391bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392 return IsHeapObject() &&
393 (HeapObject::cast(this)->map()->instance_type() ==
394 JS_GLOBAL_OBJECT_TYPE);
395}
396
397
398bool Object::IsJSBuiltinsObject() {
399 return IsHeapObject() &&
400 (HeapObject::cast(this)->map()->instance_type() ==
401 JS_BUILTINS_OBJECT_TYPE);
402}
403
404
405bool Object::IsUndetectableObject() {
406 return IsHeapObject()
407 && HeapObject::cast(this)->map()->is_undetectable();
408}
409
410
411bool Object::IsAccessCheckNeeded() {
412 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000413 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000414}
415
416
417bool Object::IsStruct() {
418 if (!IsHeapObject()) return false;
419 switch (HeapObject::cast(this)->map()->instance_type()) {
420#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
421 STRUCT_LIST(MAKE_STRUCT_CASE)
422#undef MAKE_STRUCT_CASE
423 default: return false;
424 }
425}
426
427
428#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
429 bool Object::Is##Name() { \
430 return Object::IsHeapObject() \
431 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
432 }
433 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
434#undef MAKE_STRUCT_PREDICATE
435
436
437bool Object::IsUndefined() {
438 return this == Heap::undefined_value();
439}
440
441
442bool Object::IsTheHole() {
443 return this == Heap::the_hole_value();
444}
445
446
447bool Object::IsNull() {
448 return this == Heap::null_value();
449}
450
451
452bool Object::IsTrue() {
453 return this == Heap::true_value();
454}
455
456
457bool Object::IsFalse() {
458 return this == Heap::false_value();
459}
460
461
462double Object::Number() {
463 ASSERT(IsNumber());
464 return IsSmi()
465 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
466 : reinterpret_cast<HeapNumber*>(this)->value();
467}
468
469
470
471Object* Object::ToSmi() {
472 if (IsSmi()) return this;
473 if (IsHeapNumber()) {
474 double value = HeapNumber::cast(this)->value();
475 int int_value = FastD2I(value);
476 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
477 return Smi::FromInt(int_value);
478 }
479 }
480 return Failure::Exception();
481}
482
483
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000484bool Object::HasSpecificClassOf(String* name) {
485 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
486}
487
488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489Object* Object::GetElement(uint32_t index) {
490 return GetElementWithReceiver(this, index);
491}
492
493
494Object* Object::GetProperty(String* key) {
495 PropertyAttributes attributes;
496 return GetPropertyWithReceiver(this, key, &attributes);
497}
498
499
500Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
501 return GetPropertyWithReceiver(this, key, attributes);
502}
503
504
505#define FIELD_ADDR(p, offset) \
506 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
507
508#define READ_FIELD(p, offset) \
509 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
510
511#define WRITE_FIELD(p, offset, value) \
512 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
513
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000514
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515#define WRITE_BARRIER(object, offset) \
516 Heap::RecordWrite(object->address(), offset);
517
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000518// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000519// write due to the assert validating the written value.
520#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
521 if (mode == UPDATE_WRITE_BARRIER) { \
522 Heap::RecordWrite(object->address(), offset); \
523 } else { \
524 ASSERT(mode == SKIP_WRITE_BARRIER); \
525 ASSERT(Heap::InNewSpace(object) || \
526 !Heap::InNewSpace(READ_FIELD(object, offset))); \
527 }
528
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529#define READ_DOUBLE_FIELD(p, offset) \
530 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
531
532#define WRITE_DOUBLE_FIELD(p, offset, value) \
533 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
534
535#define READ_INT_FIELD(p, offset) \
536 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
537
538#define WRITE_INT_FIELD(p, offset, value) \
539 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
540
ager@chromium.org7c537e22008-10-16 08:43:32 +0000541#define READ_UINT32_FIELD(p, offset) \
542 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
543
544#define WRITE_UINT32_FIELD(p, offset, value) \
545 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
546
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000547#define READ_SHORT_FIELD(p, offset) \
548 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
549
550#define WRITE_SHORT_FIELD(p, offset, value) \
551 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
552
553#define READ_BYTE_FIELD(p, offset) \
554 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
555
556#define WRITE_BYTE_FIELD(p, offset, value) \
557 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
558
559
560Object* HeapObject::GetHeapObjectField(HeapObject* obj, int index) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000561 return READ_FIELD(obj, HeapObject::kHeaderSize + kPointerSize * index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562}
563
564
565int Smi::value() {
566 return reinterpret_cast<int>(this) >> kSmiTagSize;
567}
568
569
570Smi* Smi::FromInt(int value) {
571 ASSERT(Smi::IsValid(value));
572 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
573}
574
575
576Failure::Type Failure::type() const {
577 return static_cast<Type>(value() & kFailureTypeTagMask);
578}
579
580
581bool Failure::IsInternalError() const {
582 return type() == INTERNAL_ERROR;
583}
584
585
586bool Failure::IsOutOfMemoryException() const {
587 return type() == OUT_OF_MEMORY_EXCEPTION;
588}
589
590
591int Failure::requested() const {
592 const int kShiftBits =
593 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
594 STATIC_ASSERT(kShiftBits >= 0);
595 ASSERT(type() == RETRY_AFTER_GC);
596 return value() >> kShiftBits;
597}
598
599
600AllocationSpace Failure::allocation_space() const {
601 ASSERT_EQ(RETRY_AFTER_GC, type());
602 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
603 & kSpaceTagMask);
604}
605
606
607Failure* Failure::InternalError() {
608 return Construct(INTERNAL_ERROR);
609}
610
611
612Failure* Failure::Exception() {
613 return Construct(EXCEPTION);
614}
615
616Failure* Failure::OutOfMemoryException() {
617 return Construct(OUT_OF_MEMORY_EXCEPTION);
618}
619
620
621int Failure::value() const {
622 return reinterpret_cast<int>(this) >> kFailureTagSize;
623}
624
625
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000626Failure* Failure::RetryAfterGC(int requested_bytes) {
627 int requested = requested_bytes >> kObjectAlignmentBits;
628 int value = (requested << kSpaceTagSize) | NEW_SPACE;
629 ASSERT(value >> kSpaceTagSize == requested);
630 ASSERT(Smi::IsValid(value));
631 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
632 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
633 return Construct(RETRY_AFTER_GC, value);
634}
635
636
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000637Failure* Failure::Construct(Type type, int value) {
638 int info = (value << kFailureTypeTagSize) | type;
639 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
640 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
641}
642
643
644bool Smi::IsValid(int value) {
645#ifdef DEBUG
646 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
647#endif
648 // To be representable as an tagged small integer, the two
649 // most-significant bits of 'value' must be either 00 or 11 due to
650 // sign-extension. To check this we add 01 to the two
651 // most-significant bits, and check if the most-significant bit is 0
652 //
653 // CAUTION: The original code below:
654 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
655 // may lead to incorrect results according to the C language spec, and
656 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
657 // compiler may produce undefined results in case of signed integer
658 // overflow. The computation must be done w/ unsigned ints.
659 bool result =
660 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
661 ASSERT(result == in_range);
662 return result;
663}
664
665
kasper.lund7276f142008-07-30 08:49:36 +0000666MapWord MapWord::FromMap(Map* map) {
667 return MapWord(reinterpret_cast<uintptr_t>(map));
668}
669
670
671Map* MapWord::ToMap() {
672 return reinterpret_cast<Map*>(value_);
673}
674
675
676bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000677 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000678}
679
680
681MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000682 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
683 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000684}
685
686
687HeapObject* MapWord::ToForwardingAddress() {
688 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000689 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000690}
691
692
693bool MapWord::IsMarked() {
694 return (value_ & kMarkingMask) == 0;
695}
696
697
698void MapWord::SetMark() {
699 value_ &= ~kMarkingMask;
700}
701
702
703void MapWord::ClearMark() {
704 value_ |= kMarkingMask;
705}
706
707
708bool MapWord::IsOverflowed() {
709 return (value_ & kOverflowMask) != 0;
710}
711
712
713void MapWord::SetOverflow() {
714 value_ |= kOverflowMask;
715}
716
717
718void MapWord::ClearOverflow() {
719 value_ &= ~kOverflowMask;
720}
721
722
723MapWord MapWord::EncodeAddress(Address map_address, int offset) {
724 // Offset is the distance in live bytes from the first live object in the
725 // same page. The offset between two objects in the same page should not
726 // exceed the object area size of a page.
727 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
728
729 int compact_offset = offset >> kObjectAlignmentBits;
730 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
731
732 Page* map_page = Page::FromAddress(map_address);
733 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
734
735 int map_page_offset =
736 map_page->Offset(map_address) >> kObjectAlignmentBits;
737
738 uintptr_t encoding =
739 (compact_offset << kForwardingOffsetShift) |
740 (map_page_offset << kMapPageOffsetShift) |
741 (map_page->mc_page_index << kMapPageIndexShift);
742 return MapWord(encoding);
743}
744
745
746Address MapWord::DecodeMapAddress(MapSpace* map_space) {
747 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
748 ASSERT_MAP_PAGE_INDEX(map_page_index);
749
750 int map_page_offset =
751 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
752 << kObjectAlignmentBits;
753
754 return (map_space->PageAddress(map_page_index) + map_page_offset);
755}
756
757
758int MapWord::DecodeOffset() {
759 // The offset field is represented in the kForwardingOffsetBits
760 // most-significant bits.
761 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
762 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
763 return offset;
764}
765
766
767MapWord MapWord::FromEncodedAddress(Address address) {
768 return MapWord(reinterpret_cast<uintptr_t>(address));
769}
770
771
772Address MapWord::ToEncodedAddress() {
773 return reinterpret_cast<Address>(value_);
774}
775
776
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000777#ifdef DEBUG
778void HeapObject::VerifyObjectField(int offset) {
779 VerifyPointer(READ_FIELD(this, offset));
780}
781#endif
782
783
784Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000785 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000786}
787
788
789void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000790 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791}
792
793
kasper.lund7276f142008-07-30 08:49:36 +0000794MapWord HeapObject::map_word() {
795 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
796}
797
798
799void HeapObject::set_map_word(MapWord map_word) {
800 // WRITE_FIELD does not update the remembered set, but there is no need
801 // here.
802 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
803}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000804
805
806HeapObject* HeapObject::FromAddress(Address address) {
807 ASSERT_TAG_ALIGNED(address);
808 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
809}
810
811
812Address HeapObject::address() {
813 return reinterpret_cast<Address>(this) - kHeapObjectTag;
814}
815
816
817int HeapObject::Size() {
818 return SizeFromMap(map());
819}
820
821
822void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
823 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
824 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
825}
826
827
828void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
829 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
830}
831
832
kasper.lund7276f142008-07-30 08:49:36 +0000833bool HeapObject::IsMarked() {
834 return map_word().IsMarked();
835}
836
837
838void HeapObject::SetMark() {
839 ASSERT(!IsMarked());
840 MapWord first_word = map_word();
841 first_word.SetMark();
842 set_map_word(first_word);
843}
844
845
846void HeapObject::ClearMark() {
847 ASSERT(IsMarked());
848 MapWord first_word = map_word();
849 first_word.ClearMark();
850 set_map_word(first_word);
851}
852
853
854bool HeapObject::IsOverflowed() {
855 return map_word().IsOverflowed();
856}
857
858
859void HeapObject::SetOverflow() {
860 MapWord first_word = map_word();
861 first_word.SetOverflow();
862 set_map_word(first_word);
863}
864
865
866void HeapObject::ClearOverflow() {
867 ASSERT(IsOverflowed());
868 MapWord first_word = map_word();
869 first_word.ClearOverflow();
870 set_map_word(first_word);
871}
872
873
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874double HeapNumber::value() {
875 return READ_DOUBLE_FIELD(this, kValueOffset);
876}
877
878
879void HeapNumber::set_value(double value) {
880 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
881}
882
883
884ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000885ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000886
887
888void JSObject::initialize_properties() {
889 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
890 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
891}
892
893
894void JSObject::initialize_elements() {
895 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
896 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
897}
898
899
900ACCESSORS(Oddball, to_string, String, kToStringOffset)
901ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
902
903
904int JSObject::GetHeaderSize() {
905 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000906 case JS_GLOBAL_PROXY_TYPE:
907 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000908 case JS_GLOBAL_OBJECT_TYPE:
909 return JSGlobalObject::kSize;
910 case JS_BUILTINS_OBJECT_TYPE:
911 return JSBuiltinsObject::kSize;
912 case JS_FUNCTION_TYPE:
913 return JSFunction::kSize;
914 case JS_VALUE_TYPE:
915 return JSValue::kSize;
916 case JS_ARRAY_TYPE:
917 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +0000918 case JS_REGEXP_TYPE:
919 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000920 case JS_OBJECT_TYPE:
921 return JSObject::kHeaderSize;
922 default:
923 UNREACHABLE();
924 return 0;
925 }
926}
927
928
929int JSObject::GetInternalFieldCount() {
930 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000931 // Make sure to adjust for the number of in-object properties. These
932 // properties do contribute to the size, but are not internal fields.
933 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
934 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000935}
936
937
938Object* JSObject::GetInternalField(int index) {
939 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000940 // Internal objects do follow immediately after the header, whereas in-object
941 // properties are at the end of the object. Therefore there is no need
942 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000943 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
944}
945
946
947void JSObject::SetInternalField(int index, Object* value) {
948 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000949 // Internal objects do follow immediately after the header, whereas in-object
950 // properties are at the end of the object. Therefore there is no need
951 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000952 int offset = GetHeaderSize() + (kPointerSize * index);
953 WRITE_FIELD(this, offset, value);
954 WRITE_BARRIER(this, offset);
955}
956
957
ager@chromium.org7c537e22008-10-16 08:43:32 +0000958// Access fast-case object properties at index. The use of these routines
959// is needed to correctly distinguish between properties stored in-object and
960// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000961Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000962 // Adjust for the number of properties stored in the object.
963 index -= map()->inobject_properties();
964 if (index < 0) {
965 int offset = map()->instance_size() + (index * kPointerSize);
966 return READ_FIELD(this, offset);
967 } else {
968 ASSERT(index < properties()->length());
969 return properties()->get(index);
970 }
971}
972
973
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000974Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000975 // Adjust for the number of properties stored in the object.
976 index -= map()->inobject_properties();
977 if (index < 0) {
978 int offset = map()->instance_size() + (index * kPointerSize);
979 WRITE_FIELD(this, offset, value);
980 WRITE_BARRIER(this, offset);
981 } else {
982 ASSERT(index < properties()->length());
983 properties()->set(index, value);
984 }
985 return value;
986}
987
988
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000989Object* JSObject::InObjectPropertyAtPut(int index,
990 Object* value,
991 WriteBarrierMode mode) {
992 // Adjust for the number of properties stored in the object.
993 index -= map()->inobject_properties();
994 ASSERT(index < 0);
995 int offset = map()->instance_size() + (index * kPointerSize);
996 WRITE_FIELD(this, offset, value);
997 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
998 return value;
999}
1000
1001
1002
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001003void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001004 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001005 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001006 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001007 }
1008}
1009
1010
1011void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001012 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001013 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001014 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001015 }
1016}
1017
1018
1019bool JSObject::HasFastProperties() {
1020 return !properties()->IsDictionary();
1021}
1022
1023
1024bool Array::IndexFromObject(Object* object, uint32_t* index) {
1025 if (object->IsSmi()) {
1026 int value = Smi::cast(object)->value();
1027 if (value < 0) return false;
1028 *index = value;
1029 return true;
1030 }
1031 if (object->IsHeapNumber()) {
1032 double value = HeapNumber::cast(object)->value();
1033 uint32_t uint_value = static_cast<uint32_t>(value);
1034 if (value == static_cast<double>(uint_value)) {
1035 *index = uint_value;
1036 return true;
1037 }
1038 }
1039 return false;
1040}
1041
1042
1043bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1044 if (!this->IsJSValue()) return false;
1045
1046 JSValue* js_value = JSValue::cast(this);
1047 if (!js_value->value()->IsString()) return false;
1048
1049 String* str = String::cast(js_value->value());
1050 if (index >= (uint32_t)str->length()) return false;
1051
1052 return true;
1053}
1054
1055
1056Object* FixedArray::get(int index) {
1057 ASSERT(index >= 0 && index < this->length());
1058 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1059}
1060
1061
1062void FixedArray::set(int index, Object* value) {
1063 ASSERT(index >= 0 && index < this->length());
1064 int offset = kHeaderSize + index * kPointerSize;
1065 WRITE_FIELD(this, offset, value);
1066 WRITE_BARRIER(this, offset);
1067}
1068
1069
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001070WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1072 return UPDATE_WRITE_BARRIER;
1073}
1074
1075
1076void FixedArray::set(int index,
1077 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001078 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001079 ASSERT(index >= 0 && index < this->length());
1080 int offset = kHeaderSize + index * kPointerSize;
1081 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001082 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001083}
1084
1085
1086void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1087 ASSERT(index >= 0 && index < array->length());
1088 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1089}
1090
1091
1092void FixedArray::set_undefined(int index) {
1093 ASSERT(index >= 0 && index < this->length());
1094 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1095 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1096 Heap::undefined_value());
1097}
1098
1099
ager@chromium.org236ad962008-09-25 09:45:57 +00001100void FixedArray::set_null(int index) {
1101 ASSERT(index >= 0 && index < this->length());
1102 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1103 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1104}
1105
1106
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001107void FixedArray::set_the_hole(int index) {
1108 ASSERT(index >= 0 && index < this->length());
1109 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1110 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1111}
1112
1113
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001114bool DescriptorArray::IsEmpty() {
1115 ASSERT(this == Heap::empty_descriptor_array() ||
1116 this->length() > 2);
1117 return this == Heap::empty_descriptor_array();
1118}
1119
1120
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1122 Object* tmp = array->get(first);
1123 fast_set(array, first, array->get(second));
1124 fast_set(array, second, tmp);
1125}
1126
1127
1128int DescriptorArray::Search(String* name) {
1129 SLOW_ASSERT(IsSortedNoDuplicates());
1130
1131 // Check for empty descriptor array.
1132 int nof = number_of_descriptors();
1133 if (nof == 0) return kNotFound;
1134
1135 // Fast case: do linear search for small arrays.
1136 const int kMaxElementsForLinearSearch = 8;
1137 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001138 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001139 }
1140
1141 // Slow case: perform binary search.
1142 return BinarySearch(name, 0, nof - 1);
1143}
1144
1145
1146
1147String* DescriptorArray::GetKey(int descriptor_number) {
1148 ASSERT(descriptor_number < number_of_descriptors());
1149 return String::cast(get(ToKeyIndex(descriptor_number)));
1150}
1151
1152
1153Object* DescriptorArray::GetValue(int descriptor_number) {
1154 ASSERT(descriptor_number < number_of_descriptors());
1155 return GetContentArray()->get(ToValueIndex(descriptor_number));
1156}
1157
1158
1159Smi* DescriptorArray::GetDetails(int descriptor_number) {
1160 ASSERT(descriptor_number < number_of_descriptors());
1161 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1162}
1163
1164
1165void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1166 desc->Init(GetKey(descriptor_number),
1167 GetValue(descriptor_number),
1168 GetDetails(descriptor_number));
1169}
1170
1171
1172void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1173 // Range check.
1174 ASSERT(descriptor_number < number_of_descriptors());
1175
1176 // Make sure non of the elements in desc are in new space.
1177 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1178 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1179
1180 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1181 FixedArray* content_array = GetContentArray();
1182 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1183 fast_set(content_array, ToDetailsIndex(descriptor_number),
1184 desc->GetDetails().AsSmi());
1185}
1186
1187
1188void DescriptorArray::Swap(int first, int second) {
1189 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1190 FixedArray* content_array = GetContentArray();
1191 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1192 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1193}
1194
1195
1196bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001197 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001198 if (!max_index_object->IsSmi()) return false;
1199 return 0 !=
1200 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1201}
1202
1203
1204uint32_t Dictionary::max_number_key() {
1205 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001206 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001207 if (!max_index_object->IsSmi()) return 0;
1208 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1209 return value >> kRequiresSlowElementsTagSize;
1210}
1211
1212
1213// ------------------------------------
1214// Cast operations
1215
1216
1217CAST_ACCESSOR(FixedArray)
1218CAST_ACCESSOR(DescriptorArray)
1219CAST_ACCESSOR(Dictionary)
1220CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001221CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001222CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001223CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001224CAST_ACCESSOR(String)
1225CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001226CAST_ACCESSOR(SeqAsciiString)
1227CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001228CAST_ACCESSOR(ConsString)
1229CAST_ACCESSOR(SlicedString)
1230CAST_ACCESSOR(ExternalString)
1231CAST_ACCESSOR(ExternalAsciiString)
1232CAST_ACCESSOR(ExternalTwoByteString)
1233CAST_ACCESSOR(JSObject)
1234CAST_ACCESSOR(Smi)
1235CAST_ACCESSOR(Failure)
1236CAST_ACCESSOR(HeapObject)
1237CAST_ACCESSOR(HeapNumber)
1238CAST_ACCESSOR(Oddball)
1239CAST_ACCESSOR(SharedFunctionInfo)
1240CAST_ACCESSOR(Map)
1241CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001242CAST_ACCESSOR(GlobalObject)
1243CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001244CAST_ACCESSOR(JSGlobalObject)
1245CAST_ACCESSOR(JSBuiltinsObject)
1246CAST_ACCESSOR(Code)
1247CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001248CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249CAST_ACCESSOR(Proxy)
1250CAST_ACCESSOR(ByteArray)
1251CAST_ACCESSOR(Struct)
1252
1253
1254#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1255 STRUCT_LIST(MAKE_STRUCT_CAST)
1256#undef MAKE_STRUCT_CAST
1257
1258template <int prefix_size, int elem_size>
1259HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1260 Object* obj) {
1261 ASSERT(obj->IsHashTable());
1262 return reinterpret_cast<HashTable*>(obj);
1263}
1264
1265
1266INT_ACCESSORS(Array, length, kLengthOffset)
1267
1268
1269bool String::Equals(String* other) {
1270 if (other == this) return true;
1271 if (IsSymbol() && other->IsSymbol()) return false;
1272 return SlowEquals(other);
1273}
1274
1275
1276int String::length() {
1277 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1278
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001279 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1280 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1281 ASSERT(kLongStringTag == 0);
1282
1283 return len >> (size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284}
1285
1286
1287void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001288 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1289 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1290 ASSERT(kLongStringTag == 0);
1291
1292 WRITE_INT_FIELD(this,
1293 kLengthOffset,
1294 value << (size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001295}
1296
1297
ager@chromium.org7c537e22008-10-16 08:43:32 +00001298uint32_t String::length_field() {
1299 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300}
1301
1302
ager@chromium.org7c537e22008-10-16 08:43:32 +00001303void String::set_length_field(uint32_t value) {
1304 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001305}
1306
1307
1308void String::TryFlatten() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001309 // We don't need to flatten strings that are already flat. Since this code
1310 // is inlined, it can be helpful in the flat case to not call out to Flatten.
1311 StringRepresentationTag str_type = representation_tag();
1312 if (str_type != kSeqStringTag && str_type != kExternalStringTag) {
1313 Flatten();
1314 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315}
1316
1317
1318uint16_t String::Get(int index) {
1319 ASSERT(index >= 0 && index < length());
1320 switch (representation_tag()) {
1321 case kSeqStringTag:
ager@chromium.org7c537e22008-10-16 08:43:32 +00001322 return is_ascii_representation()
1323 ? SeqAsciiString::cast(this)->SeqAsciiStringGet(index)
1324 : SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001325 case kConsStringTag:
1326 return ConsString::cast(this)->ConsStringGet(index);
1327 case kSlicedStringTag:
1328 return SlicedString::cast(this)->SlicedStringGet(index);
1329 case kExternalStringTag:
ager@chromium.org7c537e22008-10-16 08:43:32 +00001330 return is_ascii_representation()
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
1332 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1333 default:
1334 break;
1335 }
1336
1337 UNREACHABLE();
1338 return 0;
1339}
1340
1341
1342void String::Set(int index, uint16_t value) {
1343 ASSERT(index >= 0 && index < length());
1344 ASSERT(IsSeqString());
1345
ager@chromium.org7c537e22008-10-16 08:43:32 +00001346 return is_ascii_representation()
1347 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1348 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001349}
1350
1351
ager@chromium.org7c537e22008-10-16 08:43:32 +00001352bool String::IsAsciiRepresentation() {
1353 return is_ascii_representation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354}
1355
1356
1357bool String::StringIsConsString() {
1358 return representation_tag() == kConsStringTag;
1359}
1360
1361
1362bool String::StringIsSlicedString() {
1363 return representation_tag() == kSlicedStringTag;
1364}
1365
1366
1367uint32_t String::size_tag() {
1368 return map_size_tag(map());
1369}
1370
1371
1372uint32_t String::map_size_tag(Map* map) {
1373 return map->instance_type() & kStringSizeMask;
1374}
1375
1376
1377bool String::is_symbol() {
1378 return is_symbol_map(map());
1379}
1380
1381
1382bool String::is_symbol_map(Map* map) {
1383 return (map->instance_type() & kIsSymbolMask) != 0;
1384}
1385
1386
ager@chromium.org7c537e22008-10-16 08:43:32 +00001387bool String::is_ascii_representation() {
1388 return is_ascii_representation_map(map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389}
1390
1391
ager@chromium.org7c537e22008-10-16 08:43:32 +00001392bool String::is_ascii_representation_map(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001393 return (map->instance_type() & kStringEncodingMask) != 0;
1394}
1395
1396
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001397int String::full_representation_tag() {
1398 return map()->instance_type() &
1399 (kStringRepresentationMask | kStringEncodingMask);
1400}
1401
1402
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001403StringRepresentationTag String::representation_tag() {
1404 return map_representation_tag(map());
1405}
1406
1407
1408StringRepresentationTag String::map_representation_tag(Map* map) {
1409 uint32_t tag = map->instance_type() & kStringRepresentationMask;
1410 return static_cast<StringRepresentationTag>(tag);
1411}
1412
1413
1414bool String::IsFlat() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001415 switch (this->representation_tag()) {
1416 case kConsStringTag:
1417 // Only flattened strings have second part empty.
1418 return String::cast(ConsString::cast(this)->second())->length() == 0;
1419 case kSlicedStringTag: {
1420 String* slice = String::cast(SlicedString::cast(this)->buffer());
1421 StringRepresentationTag tag = slice->representation_tag();
1422 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001424 default:
1425 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001426 }
1427}
1428
1429
ager@chromium.org7c537e22008-10-16 08:43:32 +00001430uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001431 ASSERT(index >= 0 && index < length());
1432 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1433}
1434
1435
ager@chromium.org7c537e22008-10-16 08:43:32 +00001436void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001437 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1438 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1439 static_cast<byte>(value));
1440}
1441
1442
ager@chromium.org7c537e22008-10-16 08:43:32 +00001443Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001444 return FIELD_ADDR(this, kHeaderSize);
1445}
1446
1447
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001448char* SeqAsciiString::GetChars() {
1449 return reinterpret_cast<char*>(GetCharsAddress());
1450}
1451
1452
ager@chromium.org7c537e22008-10-16 08:43:32 +00001453Address SeqTwoByteString::GetCharsAddress() {
1454 return FIELD_ADDR(this, kHeaderSize);
1455}
1456
1457
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001458uc16* SeqTwoByteString::GetChars() {
1459 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1460}
1461
1462
ager@chromium.org7c537e22008-10-16 08:43:32 +00001463uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001464 ASSERT(index >= 0 && index < length());
1465 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1466}
1467
1468
ager@chromium.org7c537e22008-10-16 08:43:32 +00001469void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001470 ASSERT(index >= 0 && index < length());
1471 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1472}
1473
1474
ager@chromium.org7c537e22008-10-16 08:43:32 +00001475int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1477
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001478 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1479 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1480 ASSERT(kLongStringTag == 0);
1481
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001482 // Use the map (and not 'this') to compute the size tag, since
1483 // TwoByteStringSize is called during GC when maps are encoded.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001484 length >>= map_size_tag(map) + kLongLengthShift;
1485
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001486 return SizeFor(length);
1487}
1488
1489
ager@chromium.org7c537e22008-10-16 08:43:32 +00001490int SeqAsciiString::SeqAsciiStringSize(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001491 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1492
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001493 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1494 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1495 ASSERT(kLongStringTag == 0);
1496
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001497 // Use the map (and not 'this') to compute the size tag, since
1498 // AsciiStringSize is called during GC when maps are encoded.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001499 length >>= map_size_tag(map) + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001500
1501 return SizeFor(length);
1502}
1503
1504
1505Object* ConsString::first() {
1506 return READ_FIELD(this, kFirstOffset);
1507}
1508
1509
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001510void ConsString::set_first(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001511 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001512 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001513}
1514
1515
1516Object* ConsString::second() {
1517 return READ_FIELD(this, kSecondOffset);
1518}
1519
1520
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001521void ConsString::set_second(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001522 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001523 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001524}
1525
1526
1527Object* SlicedString::buffer() {
1528 return READ_FIELD(this, kBufferOffset);
1529}
1530
1531
1532void SlicedString::set_buffer(Object* buffer) {
1533 WRITE_FIELD(this, kBufferOffset, buffer);
1534 WRITE_BARRIER(this, kBufferOffset);
1535}
1536
1537
1538int SlicedString::start() {
1539 return READ_INT_FIELD(this, kStartOffset);
1540}
1541
1542
1543void SlicedString::set_start(int start) {
1544 WRITE_INT_FIELD(this, kStartOffset, start);
1545}
1546
1547
1548ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1549 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1550}
1551
1552
1553void ExternalAsciiString::set_resource(
1554 ExternalAsciiString::Resource* resource) {
1555 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1556}
1557
1558
1559ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1560 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1561}
1562
1563
1564void ExternalTwoByteString::set_resource(
1565 ExternalTwoByteString::Resource* resource) {
1566 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1567}
1568
1569
1570byte ByteArray::get(int index) {
1571 ASSERT(index >= 0 && index < this->length());
1572 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1573}
1574
1575
1576void ByteArray::set(int index, byte value) {
1577 ASSERT(index >= 0 && index < this->length());
1578 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1579}
1580
1581
1582int ByteArray::get_int(int index) {
1583 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1584 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1585}
1586
1587
1588ByteArray* ByteArray::FromDataStartAddress(Address address) {
1589 ASSERT_TAG_ALIGNED(address);
1590 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1591}
1592
1593
1594Address ByteArray::GetDataStartAddress() {
1595 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1596}
1597
1598
1599int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001600 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1601}
1602
1603
1604int Map::inobject_properties() {
1605 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001606}
1607
1608
1609int HeapObject::SizeFromMap(Map* map) {
1610 InstanceType instance_type = map->instance_type();
1611 // Only inline the two most frequent cases.
1612 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1613 if (instance_type == FIXED_ARRAY_TYPE) {
1614 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1615 }
1616 // Otherwise do the general size computation.
1617 return SlowSizeFromMap(map);
1618}
1619
1620
1621void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001622 ASSERT((value & ~(kPointerSize - 1)) == value);
1623 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001624 ASSERT(0 <= value && value < 256);
1625 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1626}
1627
1628
ager@chromium.org7c537e22008-10-16 08:43:32 +00001629void Map::set_inobject_properties(int value) {
1630 ASSERT(0 <= value && value < 256);
1631 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1632}
1633
1634
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001635InstanceType Map::instance_type() {
1636 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1637}
1638
1639
1640void Map::set_instance_type(InstanceType value) {
1641 ASSERT(0 <= value && value < 256);
1642 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1643}
1644
1645
1646int Map::unused_property_fields() {
1647 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1648}
1649
1650
1651void Map::set_unused_property_fields(int value) {
1652 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1653}
1654
1655
1656byte Map::bit_field() {
1657 return READ_BYTE_FIELD(this, kBitFieldOffset);
1658}
1659
1660
1661void Map::set_bit_field(byte value) {
1662 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1663}
1664
1665
1666void Map::set_non_instance_prototype(bool value) {
1667 if (value) {
1668 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1669 } else {
1670 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1671 }
1672}
1673
1674
1675bool Map::has_non_instance_prototype() {
1676 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1677}
1678
1679
1680Code::Flags Code::flags() {
1681 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1682}
1683
1684
1685void Code::set_flags(Code::Flags flags) {
1686 // Make sure that all call stubs have an arguments count.
1687 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1688 ExtractArgumentsCountFromFlags(flags) >= 0);
1689 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1690}
1691
1692
1693Code::Kind Code::kind() {
1694 return ExtractKindFromFlags(flags());
1695}
1696
1697
kasper.lund7276f142008-07-30 08:49:36 +00001698InlineCacheState Code::ic_state() {
1699 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001700 // Only allow uninitialized or debugger states for non-IC code
1701 // objects. This is used in the debugger to determine whether or not
1702 // a call to code object has been replaced with a debug break call.
1703 ASSERT(is_inline_cache_stub() ||
1704 result == UNINITIALIZED ||
1705 result == DEBUG_BREAK ||
1706 result == DEBUG_PREPARE_STEP_IN);
1707 return result;
1708}
1709
1710
1711PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001712 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001713 return ExtractTypeFromFlags(flags());
1714}
1715
1716
1717int Code::arguments_count() {
1718 ASSERT(is_call_stub() || kind() == STUB);
1719 return ExtractArgumentsCountFromFlags(flags());
1720}
1721
1722
1723CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001724 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001725 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1726 kStubMajorKeyOffset));
1727}
1728
1729
1730void Code::set_major_key(CodeStub::Major major) {
1731 ASSERT(kind() == STUB);
1732 ASSERT(0 <= major && major < 256);
1733 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001734}
1735
1736
1737bool Code::is_inline_cache_stub() {
1738 Kind kind = this->kind();
1739 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1740}
1741
1742
1743Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001744 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745 PropertyType type,
1746 int argc) {
1747 // Compute the bit mask.
1748 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001749 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001750 bits |= type << kFlagsTypeShift;
1751 bits |= argc << kFlagsArgumentsCountShift;
1752 // Cast to flags and validate result before returning it.
1753 Flags result = static_cast<Flags>(bits);
1754 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001755 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756 ASSERT(ExtractTypeFromFlags(result) == type);
1757 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1758 return result;
1759}
1760
1761
1762Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1763 PropertyType type,
1764 int argc) {
1765 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1766}
1767
1768
1769Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1770 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1771 return static_cast<Kind>(bits);
1772}
1773
1774
kasper.lund7276f142008-07-30 08:49:36 +00001775InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1776 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001777 return static_cast<InlineCacheState>(bits);
1778}
1779
1780
1781PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1782 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1783 return static_cast<PropertyType>(bits);
1784}
1785
1786
1787int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1788 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1789}
1790
1791
1792Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1793 int bits = flags & ~kFlagsTypeMask;
1794 return static_cast<Flags>(bits);
1795}
1796
1797
1798Object* Map::prototype() {
1799 return READ_FIELD(this, kPrototypeOffset);
1800}
1801
1802
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001803void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001804 ASSERT(value->IsNull() || value->IsJSObject());
1805 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001806 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001807}
1808
1809
1810ACCESSORS(Map, instance_descriptors, DescriptorArray,
1811 kInstanceDescriptorsOffset)
1812ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1813ACCESSORS(Map, constructor, Object, kConstructorOffset)
1814
1815ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1816ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1817
1818ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1819ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001820ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001821
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001822ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001823
1824ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1825ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1826ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1827ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1828ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1829
1830ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1831ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1832ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1833
1834ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1835ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1836ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1837ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1838ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1839ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1840
1841ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1842ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1843
1844ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1845ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1846
1847ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1848ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001849ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1850 kPropertyAccessorsOffset)
1851ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1852 kPrototypeTemplateOffset)
1853ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1854ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1855 kNamedPropertyHandlerOffset)
1856ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1857 kIndexedPropertyHandlerOffset)
1858ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1859 kInstanceTemplateOffset)
1860ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1861ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001862ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1863 kInstanceCallHandlerOffset)
1864ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1865 kAccessCheckInfoOffset)
1866ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1867
1868ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001869ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1870 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001871
1872ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1873ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1874
1875ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1876
1877ACCESSORS(Script, source, Object, kSourceOffset)
1878ACCESSORS(Script, name, Object, kNameOffset)
1879ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1880ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1881ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1882ACCESSORS(Script, type, Smi, kTypeOffset)
1883
1884ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1885ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1886ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1887ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1888
1889ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1890ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1891ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1892ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1893
1894ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1895ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1896 kInstanceClassNameOffset)
1897ACCESSORS(SharedFunctionInfo, function_data, Object,
1898 kExternalReferenceDataOffset)
1899ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1900ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1901ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1902
1903BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1904 kHiddenPrototypeBit)
1905BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1906BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1907 kNeedsAccessCheckBit)
1908BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1909 kIsExpressionBit)
1910BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1911 kIsTopLevelBit)
1912
1913INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1914INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1915 kFormalParameterCountOffset)
1916INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1917 kExpectedNofPropertiesOffset)
1918INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
1919 kStartPositionAndTypeOffset)
1920INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
1921INT_ACCESSORS(SharedFunctionInfo, function_token_position,
1922 kFunctionTokenPositionOffset)
1923
1924
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001925void SharedFunctionInfo::DontAdaptArguments() {
1926 ASSERT(code()->kind() == Code::BUILTIN);
1927 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
1928}
1929
1930
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001931int SharedFunctionInfo::start_position() {
1932 return start_position_and_type() >> kStartPositionShift;
1933}
1934
1935
1936void SharedFunctionInfo::set_start_position(int start_position) {
1937 set_start_position_and_type((start_position << kStartPositionShift)
1938 | (start_position_and_type() & ~kStartPositionMask));
1939}
1940
1941
1942Code* SharedFunctionInfo::code() {
1943 return Code::cast(READ_FIELD(this, kCodeOffset));
1944}
1945
1946
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001947void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001948 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001949 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001950}
1951
1952
1953bool SharedFunctionInfo::is_compiled() {
1954 // TODO(1242782): Create a code kind for uncompiled code.
1955 return code()->kind() != Code::STUB;
1956}
1957
1958
1959bool JSFunction::IsBoilerplate() {
1960 return map() == Heap::boilerplate_function_map();
1961}
1962
1963
1964bool JSFunction::IsLoaded() {
1965 return shared()->lazy_load_data() == Heap::undefined_value();
1966}
1967
1968
1969Code* JSFunction::code() {
1970 return shared()->code();
1971}
1972
1973
1974void JSFunction::set_code(Code* value) {
1975 shared()->set_code(value);
1976}
1977
1978
1979Context* JSFunction::context() {
1980 return Context::cast(READ_FIELD(this, kContextOffset));
1981}
1982
1983
1984Object* JSFunction::unchecked_context() {
1985 return READ_FIELD(this, kContextOffset);
1986}
1987
1988
1989void JSFunction::set_context(Object* value) {
1990 ASSERT(value == Heap::undefined_value() || value->IsContext());
1991 WRITE_FIELD(this, kContextOffset, value);
1992 WRITE_BARRIER(this, kContextOffset);
1993}
1994
1995ACCESSORS(JSFunction, prototype_or_initial_map, Object,
1996 kPrototypeOrInitialMapOffset)
1997
1998
1999Map* JSFunction::initial_map() {
2000 return Map::cast(prototype_or_initial_map());
2001}
2002
2003
2004void JSFunction::set_initial_map(Map* value) {
2005 set_prototype_or_initial_map(value);
2006}
2007
2008
2009bool JSFunction::has_initial_map() {
2010 return prototype_or_initial_map()->IsMap();
2011}
2012
2013
2014bool JSFunction::has_instance_prototype() {
2015 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2016}
2017
2018
2019bool JSFunction::has_prototype() {
2020 return map()->has_non_instance_prototype() || has_instance_prototype();
2021}
2022
2023
2024Object* JSFunction::instance_prototype() {
2025 ASSERT(has_instance_prototype());
2026 if (has_initial_map()) return initial_map()->prototype();
2027 // When there is no initial map and the prototype is a JSObject, the
2028 // initial map field is used for the prototype field.
2029 return prototype_or_initial_map();
2030}
2031
2032
2033Object* JSFunction::prototype() {
2034 ASSERT(has_prototype());
2035 // If the function's prototype property has been set to a non-JSObject
2036 // value, that value is stored in the constructor field of the map.
2037 if (map()->has_non_instance_prototype()) return map()->constructor();
2038 return instance_prototype();
2039}
2040
2041
2042bool JSFunction::is_compiled() {
2043 return shared()->is_compiled();
2044}
2045
2046
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002047int JSFunction::NumberOfLiterals() {
2048 return literals()->length();
2049}
2050
2051
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002052Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2053 ASSERT(0 <= id && id < kJSBuiltinsCount);
2054 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2055}
2056
2057
2058void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2059 Object* value) {
2060 ASSERT(0 <= id && id < kJSBuiltinsCount);
2061 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2062 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2063}
2064
2065
2066Address Proxy::proxy() {
2067 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2068}
2069
2070
2071void Proxy::set_proxy(Address value) {
2072 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2073}
2074
2075
2076void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2077 visitor->VisitExternalReference(
2078 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2079}
2080
2081
2082ACCESSORS(JSValue, value, Object, kValueOffset)
2083
2084
2085JSValue* JSValue::cast(Object* obj) {
2086 ASSERT(obj->IsJSValue());
2087 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2088 return reinterpret_cast<JSValue*>(obj);
2089}
2090
2091
2092INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2093INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2094INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2095
2096
2097Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002098 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002099}
2100
2101
2102void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002103 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002104}
2105
2106
2107byte* Code::instruction_start() {
2108 return FIELD_ADDR(this, kHeaderSize);
2109}
2110
2111
2112int Code::body_size() {
2113 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2114}
2115
2116
2117byte* Code::relocation_start() {
2118 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2119}
2120
2121
2122byte* Code::entry() {
2123 return instruction_start();
2124}
2125
2126
2127bool Code::contains(byte* pc) {
2128 return (instruction_start() <= pc) &&
2129 (pc < instruction_start() + instruction_size());
2130}
2131
2132
2133byte* Code::sinfo_start() {
2134 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2135}
2136
2137
2138ACCESSORS(JSArray, length, Object, kLengthOffset)
2139
2140
ager@chromium.org236ad962008-09-25 09:45:57 +00002141ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002142
2143
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002144JSRegExp::Type JSRegExp::TypeTag() {
2145 Object* data = this->data();
2146 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2147 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2148 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002149}
2150
2151
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002152Object* JSRegExp::DataAt(int index) {
2153 ASSERT(TypeTag() != NOT_COMPILED);
2154 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002155}
2156
2157
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002158bool JSObject::HasFastElements() {
2159 return !elements()->IsDictionary();
2160}
2161
2162
2163bool JSObject::HasNamedInterceptor() {
2164 return map()->has_named_interceptor();
2165}
2166
2167
2168bool JSObject::HasIndexedInterceptor() {
2169 return map()->has_indexed_interceptor();
2170}
2171
2172
2173Dictionary* JSObject::property_dictionary() {
2174 ASSERT(!HasFastProperties());
2175 return Dictionary::cast(properties());
2176}
2177
2178
2179Dictionary* JSObject::element_dictionary() {
2180 ASSERT(!HasFastElements());
2181 return Dictionary::cast(elements());
2182}
2183
2184
2185bool String::HasHashCode() {
2186 return (length_field() & kHashComputedMask) != 0;
2187}
2188
2189
2190uint32_t String::Hash() {
2191 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002192 uint32_t field = length_field();
2193 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002194 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002195 return ComputeAndSetHash();
2196}
2197
2198
ager@chromium.org7c537e22008-10-16 08:43:32 +00002199StringHasher::StringHasher(int length)
2200 : length_(length),
2201 raw_running_hash_(0),
2202 array_index_(0),
2203 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2204 is_first_char_(true),
2205 is_valid_(true) { }
2206
2207
2208bool StringHasher::has_trivial_hash() {
2209 return length_ > String::kMaxMediumStringSize;
2210}
2211
2212
2213void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002214 // Use the Jenkins one-at-a-time hash function to update the hash
2215 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002216 raw_running_hash_ += c;
2217 raw_running_hash_ += (raw_running_hash_ << 10);
2218 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002219 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002220 if (is_array_index_) {
2221 if (c < '0' || c > '9') {
2222 is_array_index_ = false;
2223 } else {
2224 int d = c - '0';
2225 if (is_first_char_) {
2226 is_first_char_ = false;
2227 if (c == '0' && length_ > 1) {
2228 is_array_index_ = false;
2229 return;
2230 }
2231 }
2232 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2233 is_array_index_ = false;
2234 } else {
2235 array_index_ = array_index_ * 10 + d;
2236 }
2237 }
2238 }
2239}
2240
2241
2242void StringHasher::AddCharacterNoIndex(uc32 c) {
2243 ASSERT(!is_array_index());
2244 raw_running_hash_ += c;
2245 raw_running_hash_ += (raw_running_hash_ << 10);
2246 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2247}
2248
2249
2250uint32_t StringHasher::GetHash() {
2251 uint32_t result = raw_running_hash_;
2252 result += (result << 3);
2253 result ^= (result >> 11);
2254 result += (result << 15);
2255 return result;
2256}
2257
2258
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002260 uint32_t field = length_field();
2261 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002262 return SlowAsArrayIndex(index);
2263}
2264
2265
2266Object* JSObject::GetPrototype() {
2267 return JSObject::cast(this)->map()->prototype();
2268}
2269
2270
2271PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2272 return GetPropertyAttributeWithReceiver(this, key);
2273}
2274
2275
2276bool JSObject::HasElement(uint32_t index) {
2277 return HasElementWithReceiver(this, index);
2278}
2279
2280
2281bool AccessorInfo::all_can_read() {
2282 return BooleanBit::get(flag(), kAllCanReadBit);
2283}
2284
2285
2286void AccessorInfo::set_all_can_read(bool value) {
2287 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2288}
2289
2290
2291bool AccessorInfo::all_can_write() {
2292 return BooleanBit::get(flag(), kAllCanWriteBit);
2293}
2294
2295
2296void AccessorInfo::set_all_can_write(bool value) {
2297 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2298}
2299
2300
2301PropertyAttributes AccessorInfo::property_attributes() {
2302 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2303}
2304
2305
2306void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2307 ASSERT(AttributesField::is_valid(attributes));
2308 int rest_value = flag()->value() & ~AttributesField::mask();
2309 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2310}
2311
2312void Dictionary::SetEntry(int entry,
2313 Object* key,
2314 Object* value,
2315 PropertyDetails details) {
2316 ASSERT(!key->IsString() || details.index() > 0);
2317 int index = EntryToIndex(entry);
2318 WriteBarrierMode mode = GetWriteBarrierMode();
2319 set(index, key, mode);
2320 set(index+1, value, mode);
2321 fast_set(this, index+2, details.AsSmi());
2322}
2323
2324
2325void Map::ClearCodeCache() {
2326 // No write barrier is needed since empty_fixed_array is not in new space.
2327 // Please note this function is used during marking:
2328 // - MarkCompactCollector::MarkUnmarkedObject
2329 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2330 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2331}
2332
2333
ager@chromium.org7c537e22008-10-16 08:43:32 +00002334void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002335 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002336 set_elements(storage);
2337}
2338
2339
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002340Object* FixedArray::Copy() {
2341 if (length() == 0) return this;
2342 return Heap::CopyFixedArray(this);
2343}
2344
2345
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002346#undef CAST_ACCESSOR
2347#undef INT_ACCESSORS
2348#undef SMI_ACCESSORS
2349#undef ACCESSORS
2350#undef FIELD_ADDR
2351#undef READ_FIELD
2352#undef WRITE_FIELD
2353#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002354#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002355#undef READ_MEMADDR_FIELD
2356#undef WRITE_MEMADDR_FIELD
2357#undef READ_DOUBLE_FIELD
2358#undef WRITE_DOUBLE_FIELD
2359#undef READ_INT_FIELD
2360#undef WRITE_INT_FIELD
2361#undef READ_SHORT_FIELD
2362#undef WRITE_SHORT_FIELD
2363#undef READ_BYTE_FIELD
2364#undef WRITE_BYTE_FIELD
2365
2366
2367} } // namespace v8::internal
2368
2369#endif // V8_OBJECTS_INL_H_