blob: 97c68198ca1d2085da6d69e41891a39212307ec5 [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
ager@chromium.org870a0b62008-11-04 11:43:05 +0000117bool Object::IsSymbol() {
118 if (!this->IsHeapObject()) return false;
119 uint32_t type = HeapObject::cast(this)->map()->instance_type();
120 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
121 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122}
123
124
125bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000126 if (!this->IsHeapObject()) return false;
127 uint32_t type = HeapObject::cast(this)->map()->instance_type();
128 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
129 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130}
131
132
ager@chromium.org870a0b62008-11-04 11:43:05 +0000133#ifdef DEBUG
134// These are for cast checks. If you need one of these in release
135// mode you should consider using a StringShape before moving it out
136// of the ifdef
137
138bool Object::IsSeqString() {
139 if (!IsString()) return false;
140 return StringShape(String::cast(this)).IsSequential();
141}
142
143
144bool Object::IsSeqAsciiString() {
145 if (!IsString()) return false;
146 StringShape shape(String::cast(this));
147 return shape.IsSequential() && shape.IsAsciiRepresentation();
148}
149
150
151bool Object::IsSeqTwoByteString() {
152 if (!IsString()) return false;
153 StringShape shape(String::cast(this));
154 return shape.IsSequential() && shape.IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155}
156
157
158bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000159 if (!IsString()) return false;
160 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161}
162
163
164bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000165 if (!IsString()) return false;
166 StringShape shape(String::cast(this));
167 return shape.IsExternal() && shape.IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000168}
169
170
171bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000172 if (!IsString()) return false;
173 StringShape shape(String::cast(this));
174 return shape.IsExternal() && shape.IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000175}
176
177
ager@chromium.org870a0b62008-11-04 11:43:05 +0000178bool Object::IsSlicedString() {
179 if (!IsString()) return false;
180 return StringShape(String::cast(this)).IsSliced();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181}
182
183
ager@chromium.org870a0b62008-11-04 11:43:05 +0000184#endif // DEBUG
185
186
187StringShape::StringShape(String* str)
188 : type_(str->map()->instance_type()) {
189 set_valid();
190 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191}
192
193
ager@chromium.org870a0b62008-11-04 11:43:05 +0000194StringShape::StringShape(Map* map)
195 : type_(map->instance_type()) {
196 set_valid();
197 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198}
199
200
ager@chromium.org870a0b62008-11-04 11:43:05 +0000201StringShape::StringShape(InstanceType t)
202 : type_(static_cast<uint32_t>(t)) {
203 set_valid();
204 ASSERT((type_ & kIsNotStringMask) == kStringTag);
205}
206
207
208bool StringShape::IsSymbol() {
209 ASSERT(valid());
210 return (type_ & kIsSymbolMask) == kSymbolTag;
211}
212
213
214bool StringShape::IsAsciiRepresentation() {
215 return (type_ & kStringEncodingMask) == kAsciiStringTag;
216}
217
218
219bool StringShape::IsTwoByteRepresentation() {
220 return (type_ & kStringEncodingMask) == kTwoByteStringTag;
221}
222
223
224bool StringShape::IsCons() {
225 return (type_ & kStringRepresentationMask) == kConsStringTag;
226}
227
228
229bool StringShape::IsSliced() {
230 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
231}
232
233
234bool StringShape::IsExternal() {
235 return (type_ & kStringRepresentationMask) == kExternalStringTag;
236}
237
238
239bool StringShape::IsSequential() {
240 return (type_ & kStringRepresentationMask) == kSeqStringTag;
241}
242
243
244StringRepresentationTag StringShape::representation_tag() {
245 uint32_t tag = (type_ & kStringRepresentationMask);
246 return static_cast<StringRepresentationTag>(tag);
247}
248
249
250uint32_t StringShape::full_representation_tag() {
251 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
252}
253
254
255uint32_t StringShape::size_tag() {
256 return (type_ & kStringSizeMask);
257}
258
259
260bool StringShape::IsSequentialAscii() {
261 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
262}
263
264
265bool StringShape::IsSequentialTwoByte() {
266 return (type_ & (kStringRepresentationMask | kStringEncodingMask)) ==
267 (kSeqStringTag | kTwoByteStringTag);
268}
269
270
271bool StringShape::IsExternalAscii() {
272 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
273}
274
275
276bool StringShape::IsExternalTwoByte() {
277 return (type_ & (kStringRepresentationMask | kStringEncodingMask)) ==
278 (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279}
280
281
282bool Object::IsNumber() {
283 return IsSmi() || IsHeapNumber();
284}
285
286
287bool Object::IsByteArray() {
288 return Object::IsHeapObject()
289 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
290}
291
292
293bool Object::IsFailure() {
294 return HAS_FAILURE_TAG(this);
295}
296
297
298bool Object::IsRetryAfterGC() {
299 return HAS_FAILURE_TAG(this)
300 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
301}
302
303
ager@chromium.org7c537e22008-10-16 08:43:32 +0000304bool Object::IsOutOfMemoryFailure() {
305 return HAS_FAILURE_TAG(this)
306 && Failure::cast(this)->IsOutOfMemoryException();
307}
308
309
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000310bool Object::IsException() {
311 return this == Failure::Exception();
312}
313
314
315bool Object::IsJSObject() {
316 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000317 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318}
319
320
321bool Object::IsMap() {
322 return Object::IsHeapObject()
323 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
324}
325
326
327bool Object::IsFixedArray() {
328 return Object::IsHeapObject()
329 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
330}
331
332
333bool Object::IsDescriptorArray() {
334 return IsFixedArray();
335}
336
337
338bool Object::IsContext() {
339 return Object::IsHeapObject()
340 && (HeapObject::cast(this)->map() == Heap::context_map() ||
341 HeapObject::cast(this)->map() == Heap::global_context_map());
342}
343
344
345bool Object::IsGlobalContext() {
346 return Object::IsHeapObject()
347 && HeapObject::cast(this)->map() == Heap::global_context_map();
348}
349
350
351bool Object::IsJSFunction() {
352 return Object::IsHeapObject()
353 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
354}
355
356
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000357template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000358 return obj->IsJSFunction();
359}
360
361
362bool Object::IsCode() {
363 return Object::IsHeapObject()
364 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
365}
366
367
368bool Object::IsOddball() {
369 return Object::IsHeapObject()
370 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
371}
372
373
374bool Object::IsSharedFunctionInfo() {
375 return Object::IsHeapObject() &&
376 (HeapObject::cast(this)->map()->instance_type() ==
377 SHARED_FUNCTION_INFO_TYPE);
378}
379
380
381bool Object::IsJSValue() {
382 return Object::IsHeapObject()
383 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
384}
385
386
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000387bool Object::IsStringWrapper() {
388 return IsJSValue() && JSValue::cast(this)->value()->IsString();
389}
390
391
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392bool Object::IsProxy() {
393 return Object::IsHeapObject()
394 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
395}
396
397
398bool Object::IsBoolean() {
399 return IsTrue() || IsFalse();
400}
401
402
403bool Object::IsJSArray() {
404 return Object::IsHeapObject()
405 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
406}
407
408
ager@chromium.org236ad962008-09-25 09:45:57 +0000409bool Object::IsJSRegExp() {
410 return Object::IsHeapObject()
411 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
412}
413
414
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000415template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416 return obj->IsJSArray();
417}
418
419
420bool Object::IsHashTable() {
421 return Object::IsHeapObject()
422 && HeapObject::cast(this)->map() == Heap::hash_table_map();
423}
424
425
426bool Object::IsDictionary() {
427 return IsHashTable() && this != Heap::symbol_table();
428}
429
430
431bool Object::IsSymbolTable() {
432 return IsHashTable() && this == Heap::symbol_table();
433}
434
435
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000436bool Object::IsCompilationCacheTable() {
437 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000438}
439
440
ager@chromium.org236ad962008-09-25 09:45:57 +0000441bool Object::IsMapCache() {
442 return IsHashTable();
443}
444
445
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000446bool Object::IsLookupCache() {
447 return IsHashTable();
448}
449
450
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451bool Object::IsPrimitive() {
452 return IsOddball() || IsNumber() || IsString();
453}
454
455
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000456bool Object::IsJSGlobalProxy() {
457 bool result = IsHeapObject() &&
458 (HeapObject::cast(this)->map()->instance_type() ==
459 JS_GLOBAL_PROXY_TYPE);
460 ASSERT(!result || IsAccessCheckNeeded());
461 return result;
462}
463
464
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000465bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000466 if (!IsHeapObject()) return false;
467
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000468 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000469 return type == JS_GLOBAL_OBJECT_TYPE ||
470 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000471}
472
473
474bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475 return IsHeapObject() &&
476 (HeapObject::cast(this)->map()->instance_type() ==
477 JS_GLOBAL_OBJECT_TYPE);
478}
479
480
481bool Object::IsJSBuiltinsObject() {
482 return IsHeapObject() &&
483 (HeapObject::cast(this)->map()->instance_type() ==
484 JS_BUILTINS_OBJECT_TYPE);
485}
486
487
488bool Object::IsUndetectableObject() {
489 return IsHeapObject()
490 && HeapObject::cast(this)->map()->is_undetectable();
491}
492
493
494bool Object::IsAccessCheckNeeded() {
495 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000496 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000497}
498
499
500bool Object::IsStruct() {
501 if (!IsHeapObject()) return false;
502 switch (HeapObject::cast(this)->map()->instance_type()) {
503#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
504 STRUCT_LIST(MAKE_STRUCT_CASE)
505#undef MAKE_STRUCT_CASE
506 default: return false;
507 }
508}
509
510
511#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
512 bool Object::Is##Name() { \
513 return Object::IsHeapObject() \
514 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
515 }
516 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
517#undef MAKE_STRUCT_PREDICATE
518
519
520bool Object::IsUndefined() {
521 return this == Heap::undefined_value();
522}
523
524
525bool Object::IsTheHole() {
526 return this == Heap::the_hole_value();
527}
528
529
530bool Object::IsNull() {
531 return this == Heap::null_value();
532}
533
534
535bool Object::IsTrue() {
536 return this == Heap::true_value();
537}
538
539
540bool Object::IsFalse() {
541 return this == Heap::false_value();
542}
543
544
545double Object::Number() {
546 ASSERT(IsNumber());
547 return IsSmi()
548 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
549 : reinterpret_cast<HeapNumber*>(this)->value();
550}
551
552
553
554Object* Object::ToSmi() {
555 if (IsSmi()) return this;
556 if (IsHeapNumber()) {
557 double value = HeapNumber::cast(this)->value();
558 int int_value = FastD2I(value);
559 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
560 return Smi::FromInt(int_value);
561 }
562 }
563 return Failure::Exception();
564}
565
566
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000567bool Object::HasSpecificClassOf(String* name) {
568 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
569}
570
571
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572Object* Object::GetElement(uint32_t index) {
573 return GetElementWithReceiver(this, index);
574}
575
576
577Object* Object::GetProperty(String* key) {
578 PropertyAttributes attributes;
579 return GetPropertyWithReceiver(this, key, &attributes);
580}
581
582
583Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
584 return GetPropertyWithReceiver(this, key, attributes);
585}
586
587
588#define FIELD_ADDR(p, offset) \
589 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
590
591#define READ_FIELD(p, offset) \
592 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
593
594#define WRITE_FIELD(p, offset, value) \
595 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
596
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598#define WRITE_BARRIER(object, offset) \
599 Heap::RecordWrite(object->address(), offset);
600
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000601// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000602// write due to the assert validating the written value.
603#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
604 if (mode == UPDATE_WRITE_BARRIER) { \
605 Heap::RecordWrite(object->address(), offset); \
606 } else { \
607 ASSERT(mode == SKIP_WRITE_BARRIER); \
608 ASSERT(Heap::InNewSpace(object) || \
609 !Heap::InNewSpace(READ_FIELD(object, offset))); \
610 }
611
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612#define READ_DOUBLE_FIELD(p, offset) \
613 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
614
615#define WRITE_DOUBLE_FIELD(p, offset, value) \
616 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
617
618#define READ_INT_FIELD(p, offset) \
619 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
620
621#define WRITE_INT_FIELD(p, offset, value) \
622 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
623
ager@chromium.org7c537e22008-10-16 08:43:32 +0000624#define READ_UINT32_FIELD(p, offset) \
625 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
626
627#define WRITE_UINT32_FIELD(p, offset, value) \
628 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
629
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630#define READ_SHORT_FIELD(p, offset) \
631 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
632
633#define WRITE_SHORT_FIELD(p, offset, value) \
634 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
635
636#define READ_BYTE_FIELD(p, offset) \
637 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
638
639#define WRITE_BYTE_FIELD(p, offset, value) \
640 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
641
642
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000643Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
644 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000645}
646
647
648int Smi::value() {
649 return reinterpret_cast<int>(this) >> kSmiTagSize;
650}
651
652
653Smi* Smi::FromInt(int value) {
654 ASSERT(Smi::IsValid(value));
655 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
656}
657
658
659Failure::Type Failure::type() const {
660 return static_cast<Type>(value() & kFailureTypeTagMask);
661}
662
663
664bool Failure::IsInternalError() const {
665 return type() == INTERNAL_ERROR;
666}
667
668
669bool Failure::IsOutOfMemoryException() const {
670 return type() == OUT_OF_MEMORY_EXCEPTION;
671}
672
673
674int Failure::requested() const {
675 const int kShiftBits =
676 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
677 STATIC_ASSERT(kShiftBits >= 0);
678 ASSERT(type() == RETRY_AFTER_GC);
679 return value() >> kShiftBits;
680}
681
682
683AllocationSpace Failure::allocation_space() const {
684 ASSERT_EQ(RETRY_AFTER_GC, type());
685 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
686 & kSpaceTagMask);
687}
688
689
690Failure* Failure::InternalError() {
691 return Construct(INTERNAL_ERROR);
692}
693
694
695Failure* Failure::Exception() {
696 return Construct(EXCEPTION);
697}
698
699Failure* Failure::OutOfMemoryException() {
700 return Construct(OUT_OF_MEMORY_EXCEPTION);
701}
702
703
704int Failure::value() const {
705 return reinterpret_cast<int>(this) >> kFailureTagSize;
706}
707
708
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000709Failure* Failure::RetryAfterGC(int requested_bytes) {
710 int requested = requested_bytes >> kObjectAlignmentBits;
711 int value = (requested << kSpaceTagSize) | NEW_SPACE;
712 ASSERT(value >> kSpaceTagSize == requested);
713 ASSERT(Smi::IsValid(value));
714 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
715 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
716 return Construct(RETRY_AFTER_GC, value);
717}
718
719
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000720Failure* Failure::Construct(Type type, int value) {
721 int info = (value << kFailureTypeTagSize) | type;
722 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
723 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
724}
725
726
727bool Smi::IsValid(int value) {
728#ifdef DEBUG
729 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
730#endif
731 // To be representable as an tagged small integer, the two
732 // most-significant bits of 'value' must be either 00 or 11 due to
733 // sign-extension. To check this we add 01 to the two
734 // most-significant bits, and check if the most-significant bit is 0
735 //
736 // CAUTION: The original code below:
737 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
738 // may lead to incorrect results according to the C language spec, and
739 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
740 // compiler may produce undefined results in case of signed integer
741 // overflow. The computation must be done w/ unsigned ints.
742 bool result =
743 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
744 ASSERT(result == in_range);
745 return result;
746}
747
748
kasper.lund7276f142008-07-30 08:49:36 +0000749MapWord MapWord::FromMap(Map* map) {
750 return MapWord(reinterpret_cast<uintptr_t>(map));
751}
752
753
754Map* MapWord::ToMap() {
755 return reinterpret_cast<Map*>(value_);
756}
757
758
759bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000760 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000761}
762
763
764MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000765 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
766 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000767}
768
769
770HeapObject* MapWord::ToForwardingAddress() {
771 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000772 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000773}
774
775
776bool MapWord::IsMarked() {
777 return (value_ & kMarkingMask) == 0;
778}
779
780
781void MapWord::SetMark() {
782 value_ &= ~kMarkingMask;
783}
784
785
786void MapWord::ClearMark() {
787 value_ |= kMarkingMask;
788}
789
790
791bool MapWord::IsOverflowed() {
792 return (value_ & kOverflowMask) != 0;
793}
794
795
796void MapWord::SetOverflow() {
797 value_ |= kOverflowMask;
798}
799
800
801void MapWord::ClearOverflow() {
802 value_ &= ~kOverflowMask;
803}
804
805
806MapWord MapWord::EncodeAddress(Address map_address, int offset) {
807 // Offset is the distance in live bytes from the first live object in the
808 // same page. The offset between two objects in the same page should not
809 // exceed the object area size of a page.
810 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
811
812 int compact_offset = offset >> kObjectAlignmentBits;
813 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
814
815 Page* map_page = Page::FromAddress(map_address);
816 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
817
818 int map_page_offset =
819 map_page->Offset(map_address) >> kObjectAlignmentBits;
820
821 uintptr_t encoding =
822 (compact_offset << kForwardingOffsetShift) |
823 (map_page_offset << kMapPageOffsetShift) |
824 (map_page->mc_page_index << kMapPageIndexShift);
825 return MapWord(encoding);
826}
827
828
829Address MapWord::DecodeMapAddress(MapSpace* map_space) {
830 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
831 ASSERT_MAP_PAGE_INDEX(map_page_index);
832
833 int map_page_offset =
834 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
835 << kObjectAlignmentBits;
836
837 return (map_space->PageAddress(map_page_index) + map_page_offset);
838}
839
840
841int MapWord::DecodeOffset() {
842 // The offset field is represented in the kForwardingOffsetBits
843 // most-significant bits.
844 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
845 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
846 return offset;
847}
848
849
850MapWord MapWord::FromEncodedAddress(Address address) {
851 return MapWord(reinterpret_cast<uintptr_t>(address));
852}
853
854
855Address MapWord::ToEncodedAddress() {
856 return reinterpret_cast<Address>(value_);
857}
858
859
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000860#ifdef DEBUG
861void HeapObject::VerifyObjectField(int offset) {
862 VerifyPointer(READ_FIELD(this, offset));
863}
864#endif
865
866
867Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000868 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869}
870
871
872void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000873 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874}
875
876
kasper.lund7276f142008-07-30 08:49:36 +0000877MapWord HeapObject::map_word() {
878 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
879}
880
881
882void HeapObject::set_map_word(MapWord map_word) {
883 // WRITE_FIELD does not update the remembered set, but there is no need
884 // here.
885 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
886}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887
888
889HeapObject* HeapObject::FromAddress(Address address) {
890 ASSERT_TAG_ALIGNED(address);
891 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
892}
893
894
895Address HeapObject::address() {
896 return reinterpret_cast<Address>(this) - kHeapObjectTag;
897}
898
899
900int HeapObject::Size() {
901 return SizeFromMap(map());
902}
903
904
905void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
906 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
907 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
908}
909
910
911void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
912 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
913}
914
915
kasper.lund7276f142008-07-30 08:49:36 +0000916bool HeapObject::IsMarked() {
917 return map_word().IsMarked();
918}
919
920
921void HeapObject::SetMark() {
922 ASSERT(!IsMarked());
923 MapWord first_word = map_word();
924 first_word.SetMark();
925 set_map_word(first_word);
926}
927
928
929void HeapObject::ClearMark() {
930 ASSERT(IsMarked());
931 MapWord first_word = map_word();
932 first_word.ClearMark();
933 set_map_word(first_word);
934}
935
936
937bool HeapObject::IsOverflowed() {
938 return map_word().IsOverflowed();
939}
940
941
942void HeapObject::SetOverflow() {
943 MapWord first_word = map_word();
944 first_word.SetOverflow();
945 set_map_word(first_word);
946}
947
948
949void HeapObject::ClearOverflow() {
950 ASSERT(IsOverflowed());
951 MapWord first_word = map_word();
952 first_word.ClearOverflow();
953 set_map_word(first_word);
954}
955
956
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000957double HeapNumber::value() {
958 return READ_DOUBLE_FIELD(this, kValueOffset);
959}
960
961
962void HeapNumber::set_value(double value) {
963 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
964}
965
966
967ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000968ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000969
970
971void JSObject::initialize_properties() {
972 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
973 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
974}
975
976
977void JSObject::initialize_elements() {
978 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
979 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
980}
981
982
983ACCESSORS(Oddball, to_string, String, kToStringOffset)
984ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
985
986
987int JSObject::GetHeaderSize() {
988 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000989 case JS_GLOBAL_PROXY_TYPE:
990 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991 case JS_GLOBAL_OBJECT_TYPE:
992 return JSGlobalObject::kSize;
993 case JS_BUILTINS_OBJECT_TYPE:
994 return JSBuiltinsObject::kSize;
995 case JS_FUNCTION_TYPE:
996 return JSFunction::kSize;
997 case JS_VALUE_TYPE:
998 return JSValue::kSize;
999 case JS_ARRAY_TYPE:
1000 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001001 case JS_REGEXP_TYPE:
1002 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001003 case JS_OBJECT_TYPE:
1004 return JSObject::kHeaderSize;
1005 default:
1006 UNREACHABLE();
1007 return 0;
1008 }
1009}
1010
1011
1012int JSObject::GetInternalFieldCount() {
1013 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001014 // Make sure to adjust for the number of in-object properties. These
1015 // properties do contribute to the size, but are not internal fields.
1016 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1017 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018}
1019
1020
1021Object* JSObject::GetInternalField(int index) {
1022 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001023 // Internal objects do follow immediately after the header, whereas in-object
1024 // properties are at the end of the object. Therefore there is no need
1025 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001026 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1027}
1028
1029
1030void JSObject::SetInternalField(int index, Object* value) {
1031 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001032 // Internal objects do follow immediately after the header, whereas in-object
1033 // properties are at the end of the object. Therefore there is no need
1034 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001035 int offset = GetHeaderSize() + (kPointerSize * index);
1036 WRITE_FIELD(this, offset, value);
1037 WRITE_BARRIER(this, offset);
1038}
1039
1040
ager@chromium.org7c537e22008-10-16 08:43:32 +00001041// Access fast-case object properties at index. The use of these routines
1042// is needed to correctly distinguish between properties stored in-object and
1043// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001044Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001045 // Adjust for the number of properties stored in the object.
1046 index -= map()->inobject_properties();
1047 if (index < 0) {
1048 int offset = map()->instance_size() + (index * kPointerSize);
1049 return READ_FIELD(this, offset);
1050 } else {
1051 ASSERT(index < properties()->length());
1052 return properties()->get(index);
1053 }
1054}
1055
1056
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001057Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001058 // Adjust for the number of properties stored in the object.
1059 index -= map()->inobject_properties();
1060 if (index < 0) {
1061 int offset = map()->instance_size() + (index * kPointerSize);
1062 WRITE_FIELD(this, offset, value);
1063 WRITE_BARRIER(this, offset);
1064 } else {
1065 ASSERT(index < properties()->length());
1066 properties()->set(index, value);
1067 }
1068 return value;
1069}
1070
1071
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001072Object* JSObject::InObjectPropertyAtPut(int index,
1073 Object* value,
1074 WriteBarrierMode mode) {
1075 // Adjust for the number of properties stored in the object.
1076 index -= map()->inobject_properties();
1077 ASSERT(index < 0);
1078 int offset = map()->instance_size() + (index * kPointerSize);
1079 WRITE_FIELD(this, offset, value);
1080 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1081 return value;
1082}
1083
1084
1085
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001087 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001089 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001090 }
1091}
1092
1093
1094void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001095 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001096 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001097 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001098 }
1099}
1100
1101
1102bool JSObject::HasFastProperties() {
1103 return !properties()->IsDictionary();
1104}
1105
1106
1107bool Array::IndexFromObject(Object* object, uint32_t* index) {
1108 if (object->IsSmi()) {
1109 int value = Smi::cast(object)->value();
1110 if (value < 0) return false;
1111 *index = value;
1112 return true;
1113 }
1114 if (object->IsHeapNumber()) {
1115 double value = HeapNumber::cast(object)->value();
1116 uint32_t uint_value = static_cast<uint32_t>(value);
1117 if (value == static_cast<double>(uint_value)) {
1118 *index = uint_value;
1119 return true;
1120 }
1121 }
1122 return false;
1123}
1124
1125
1126bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1127 if (!this->IsJSValue()) return false;
1128
1129 JSValue* js_value = JSValue::cast(this);
1130 if (!js_value->value()->IsString()) return false;
1131
1132 String* str = String::cast(js_value->value());
1133 if (index >= (uint32_t)str->length()) return false;
1134
1135 return true;
1136}
1137
1138
1139Object* FixedArray::get(int index) {
1140 ASSERT(index >= 0 && index < this->length());
1141 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1142}
1143
1144
1145void FixedArray::set(int index, Object* value) {
1146 ASSERT(index >= 0 && index < this->length());
1147 int offset = kHeaderSize + index * kPointerSize;
1148 WRITE_FIELD(this, offset, value);
1149 WRITE_BARRIER(this, offset);
1150}
1151
1152
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001153WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001154 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1155 return UPDATE_WRITE_BARRIER;
1156}
1157
1158
1159void FixedArray::set(int index,
1160 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001161 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162 ASSERT(index >= 0 && index < this->length());
1163 int offset = kHeaderSize + index * kPointerSize;
1164 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001165 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001166}
1167
1168
1169void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1170 ASSERT(index >= 0 && index < array->length());
1171 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1172}
1173
1174
1175void FixedArray::set_undefined(int index) {
1176 ASSERT(index >= 0 && index < this->length());
1177 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1178 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1179 Heap::undefined_value());
1180}
1181
1182
ager@chromium.org236ad962008-09-25 09:45:57 +00001183void FixedArray::set_null(int index) {
1184 ASSERT(index >= 0 && index < this->length());
1185 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1186 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1187}
1188
1189
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001190void FixedArray::set_the_hole(int index) {
1191 ASSERT(index >= 0 && index < this->length());
1192 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1193 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1194}
1195
1196
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001197bool DescriptorArray::IsEmpty() {
1198 ASSERT(this == Heap::empty_descriptor_array() ||
1199 this->length() > 2);
1200 return this == Heap::empty_descriptor_array();
1201}
1202
1203
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001204void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1205 Object* tmp = array->get(first);
1206 fast_set(array, first, array->get(second));
1207 fast_set(array, second, tmp);
1208}
1209
1210
1211int DescriptorArray::Search(String* name) {
1212 SLOW_ASSERT(IsSortedNoDuplicates());
1213
ager@chromium.org870a0b62008-11-04 11:43:05 +00001214 StringShape shape(name);
1215
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001216 // Check for empty descriptor array.
1217 int nof = number_of_descriptors();
1218 if (nof == 0) return kNotFound;
1219
1220 // Fast case: do linear search for small arrays.
1221 const int kMaxElementsForLinearSearch = 8;
ager@chromium.org870a0b62008-11-04 11:43:05 +00001222 if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001223 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001224 }
1225
1226 // Slow case: perform binary search.
1227 return BinarySearch(name, 0, nof - 1);
1228}
1229
1230
1231
1232String* DescriptorArray::GetKey(int descriptor_number) {
1233 ASSERT(descriptor_number < number_of_descriptors());
1234 return String::cast(get(ToKeyIndex(descriptor_number)));
1235}
1236
1237
1238Object* DescriptorArray::GetValue(int descriptor_number) {
1239 ASSERT(descriptor_number < number_of_descriptors());
1240 return GetContentArray()->get(ToValueIndex(descriptor_number));
1241}
1242
1243
1244Smi* DescriptorArray::GetDetails(int descriptor_number) {
1245 ASSERT(descriptor_number < number_of_descriptors());
1246 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1247}
1248
1249
1250void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1251 desc->Init(GetKey(descriptor_number),
1252 GetValue(descriptor_number),
1253 GetDetails(descriptor_number));
1254}
1255
1256
1257void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1258 // Range check.
1259 ASSERT(descriptor_number < number_of_descriptors());
1260
1261 // Make sure non of the elements in desc are in new space.
1262 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1263 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1264
1265 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1266 FixedArray* content_array = GetContentArray();
1267 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1268 fast_set(content_array, ToDetailsIndex(descriptor_number),
1269 desc->GetDetails().AsSmi());
1270}
1271
1272
1273void DescriptorArray::Swap(int first, int second) {
1274 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1275 FixedArray* content_array = GetContentArray();
1276 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1277 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1278}
1279
1280
1281bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001282 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001283 if (!max_index_object->IsSmi()) return false;
1284 return 0 !=
1285 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1286}
1287
1288
1289uint32_t Dictionary::max_number_key() {
1290 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001291 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001292 if (!max_index_object->IsSmi()) return 0;
1293 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1294 return value >> kRequiresSlowElementsTagSize;
1295}
1296
1297
1298// ------------------------------------
1299// Cast operations
1300
1301
1302CAST_ACCESSOR(FixedArray)
1303CAST_ACCESSOR(DescriptorArray)
1304CAST_ACCESSOR(Dictionary)
1305CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001306CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001307CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001308CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309CAST_ACCESSOR(String)
1310CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001311CAST_ACCESSOR(SeqAsciiString)
1312CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001313CAST_ACCESSOR(ConsString)
1314CAST_ACCESSOR(SlicedString)
1315CAST_ACCESSOR(ExternalString)
1316CAST_ACCESSOR(ExternalAsciiString)
1317CAST_ACCESSOR(ExternalTwoByteString)
1318CAST_ACCESSOR(JSObject)
1319CAST_ACCESSOR(Smi)
1320CAST_ACCESSOR(Failure)
1321CAST_ACCESSOR(HeapObject)
1322CAST_ACCESSOR(HeapNumber)
1323CAST_ACCESSOR(Oddball)
1324CAST_ACCESSOR(SharedFunctionInfo)
1325CAST_ACCESSOR(Map)
1326CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001327CAST_ACCESSOR(GlobalObject)
1328CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329CAST_ACCESSOR(JSGlobalObject)
1330CAST_ACCESSOR(JSBuiltinsObject)
1331CAST_ACCESSOR(Code)
1332CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001333CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001334CAST_ACCESSOR(Proxy)
1335CAST_ACCESSOR(ByteArray)
1336CAST_ACCESSOR(Struct)
1337
1338
1339#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1340 STRUCT_LIST(MAKE_STRUCT_CAST)
1341#undef MAKE_STRUCT_CAST
1342
1343template <int prefix_size, int elem_size>
1344HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1345 Object* obj) {
1346 ASSERT(obj->IsHashTable());
1347 return reinterpret_cast<HashTable*>(obj);
1348}
1349
1350
1351INT_ACCESSORS(Array, length, kLengthOffset)
1352
1353
1354bool String::Equals(String* other) {
1355 if (other == this) return true;
ager@chromium.org870a0b62008-11-04 11:43:05 +00001356 StringShape this_shape(this);
1357 StringShape other_shape(other);
1358 if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false;
1359 return SlowEquals(this_shape, other, other_shape);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001360}
1361
1362
ager@chromium.org870a0b62008-11-04 11:43:05 +00001363int String::length(StringShape shape) {
1364 ASSERT(shape.type() == StringShape(this).type());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1366
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001367 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1368 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1369 ASSERT(kLongStringTag == 0);
1370
ager@chromium.org870a0b62008-11-04 11:43:05 +00001371 return len >> (shape.size_tag() + kLongLengthShift);
1372}
1373
1374
1375int String::length() {
1376 return length(StringShape(this));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001377}
1378
1379
1380void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001381 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1382 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1383 ASSERT(kLongStringTag == 0);
1384
ager@chromium.org870a0b62008-11-04 11:43:05 +00001385 StringShape shape(this);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001386 WRITE_INT_FIELD(this,
1387 kLengthOffset,
ager@chromium.org870a0b62008-11-04 11:43:05 +00001388 value << (shape.size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389}
1390
1391
ager@chromium.org7c537e22008-10-16 08:43:32 +00001392uint32_t String::length_field() {
1393 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394}
1395
1396
ager@chromium.org7c537e22008-10-16 08:43:32 +00001397void String::set_length_field(uint32_t value) {
1398 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001399}
1400
1401
ager@chromium.org870a0b62008-11-04 11:43:05 +00001402void String::TryFlatten(StringShape shape) {
1403 ASSERT(shape.type() == StringShape(this).type());
ager@chromium.org236ad962008-09-25 09:45:57 +00001404 // We don't need to flatten strings that are already flat. Since this code
1405 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001406 if (!IsFlat(shape)) {
1407 Flatten(shape);
ager@chromium.org236ad962008-09-25 09:45:57 +00001408 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001409}
1410
1411
ager@chromium.org870a0b62008-11-04 11:43:05 +00001412uint16_t String::Get(StringShape shape, int index) {
1413 ASSERT(shape.type() == StringShape(this).type());
1414 ASSERT(index >= 0 && index < length(shape));
1415 switch (shape.full_representation_tag()) {
1416 case kSeqStringTag | kAsciiStringTag:
1417 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1418 case kSeqStringTag | kTwoByteStringTag:
1419 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1420 case kConsStringTag | kAsciiStringTag:
1421 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001422 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001423 case kSlicedStringTag | kAsciiStringTag:
1424 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001425 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001426 case kExternalStringTag | kAsciiStringTag:
1427 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1428 case kExternalStringTag | kTwoByteStringTag:
1429 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001430 default:
1431 break;
1432 }
1433
1434 UNREACHABLE();
1435 return 0;
1436}
1437
1438
ager@chromium.org870a0b62008-11-04 11:43:05 +00001439void String::Set(StringShape shape, int index, uint16_t value) {
1440 ASSERT(shape.type() == StringShape(this).type());
1441 ASSERT(shape.type() == StringShape(this).type());
1442 ASSERT(index >= 0 && index < length(shape));
1443 ASSERT(shape.IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001444
ager@chromium.org870a0b62008-11-04 11:43:05 +00001445 return shape.IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001446 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1447 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001448}
1449
1450
ager@chromium.org870a0b62008-11-04 11:43:05 +00001451bool String::IsFlat(StringShape shape) {
1452 ASSERT(shape.type() == StringShape(this).type());
1453 switch (shape.representation_tag()) {
1454 case kConsStringTag: {
1455 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001456 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001457 return second->length() == 0;
1458 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001459 case kSlicedStringTag: {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001460 StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer());
1461 StringRepresentationTag tag = slice_shape.representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001462 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001463 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001464 default:
1465 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001466 }
1467}
1468
1469
ager@chromium.org7c537e22008-10-16 08:43:32 +00001470uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001471 ASSERT(index >= 0 && index < length());
1472 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1473}
1474
1475
ager@chromium.org7c537e22008-10-16 08:43:32 +00001476void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001477 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1478 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1479 static_cast<byte>(value));
1480}
1481
1482
ager@chromium.org7c537e22008-10-16 08:43:32 +00001483Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001484 return FIELD_ADDR(this, kHeaderSize);
1485}
1486
1487
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001488char* SeqAsciiString::GetChars() {
1489 return reinterpret_cast<char*>(GetCharsAddress());
1490}
1491
1492
ager@chromium.org7c537e22008-10-16 08:43:32 +00001493Address SeqTwoByteString::GetCharsAddress() {
1494 return FIELD_ADDR(this, kHeaderSize);
1495}
1496
1497
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001498uc16* SeqTwoByteString::GetChars() {
1499 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1500}
1501
1502
ager@chromium.org7c537e22008-10-16 08:43:32 +00001503uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001504 ASSERT(index >= 0 && index < length());
1505 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1506}
1507
1508
ager@chromium.org7c537e22008-10-16 08:43:32 +00001509void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 ASSERT(index >= 0 && index < length());
1511 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1512}
1513
1514
ager@chromium.org870a0b62008-11-04 11:43:05 +00001515int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001516 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1517
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001518 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1519 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1520 ASSERT(kLongStringTag == 0);
1521
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001522 // Use the map (and not 'this') to compute the size tag, since
1523 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001524 length >>= shape.size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001525
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001526 return SizeFor(length);
1527}
1528
1529
ager@chromium.org870a0b62008-11-04 11:43:05 +00001530int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001531 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1532
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001533 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1534 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1535 ASSERT(kLongStringTag == 0);
1536
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 // Use the map (and not 'this') to compute the size tag, since
1538 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001539 length >>= shape.size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540
1541 return SizeFor(length);
1542}
1543
1544
ager@chromium.org870a0b62008-11-04 11:43:05 +00001545String* ConsString::first() {
1546 return String::cast(READ_FIELD(this, kFirstOffset));
1547}
1548
1549
1550Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551 return READ_FIELD(this, kFirstOffset);
1552}
1553
1554
ager@chromium.org870a0b62008-11-04 11:43:05 +00001555void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001557 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001558}
1559
1560
ager@chromium.org870a0b62008-11-04 11:43:05 +00001561String* ConsString::second() {
1562 return String::cast(READ_FIELD(this, kSecondOffset));
1563}
1564
1565
1566Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001567 return READ_FIELD(this, kSecondOffset);
1568}
1569
1570
ager@chromium.org870a0b62008-11-04 11:43:05 +00001571void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001572 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001573 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001574}
1575
1576
ager@chromium.org870a0b62008-11-04 11:43:05 +00001577String* SlicedString::buffer() {
1578 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579}
1580
1581
ager@chromium.org870a0b62008-11-04 11:43:05 +00001582void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583 WRITE_FIELD(this, kBufferOffset, buffer);
1584 WRITE_BARRIER(this, kBufferOffset);
1585}
1586
1587
1588int SlicedString::start() {
1589 return READ_INT_FIELD(this, kStartOffset);
1590}
1591
1592
1593void SlicedString::set_start(int start) {
1594 WRITE_INT_FIELD(this, kStartOffset, start);
1595}
1596
1597
1598ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1599 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1600}
1601
1602
1603void ExternalAsciiString::set_resource(
1604 ExternalAsciiString::Resource* resource) {
1605 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1606}
1607
1608
1609ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1610 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1611}
1612
1613
1614void ExternalTwoByteString::set_resource(
1615 ExternalTwoByteString::Resource* resource) {
1616 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1617}
1618
1619
1620byte ByteArray::get(int index) {
1621 ASSERT(index >= 0 && index < this->length());
1622 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1623}
1624
1625
1626void ByteArray::set(int index, byte value) {
1627 ASSERT(index >= 0 && index < this->length());
1628 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1629}
1630
1631
1632int ByteArray::get_int(int index) {
1633 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1634 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1635}
1636
1637
1638ByteArray* ByteArray::FromDataStartAddress(Address address) {
1639 ASSERT_TAG_ALIGNED(address);
1640 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1641}
1642
1643
1644Address ByteArray::GetDataStartAddress() {
1645 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1646}
1647
1648
1649int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001650 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1651}
1652
1653
1654int Map::inobject_properties() {
1655 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001656}
1657
1658
1659int HeapObject::SizeFromMap(Map* map) {
1660 InstanceType instance_type = map->instance_type();
1661 // Only inline the two most frequent cases.
1662 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1663 if (instance_type == FIXED_ARRAY_TYPE) {
1664 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1665 }
1666 // Otherwise do the general size computation.
1667 return SlowSizeFromMap(map);
1668}
1669
1670
1671void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001672 ASSERT((value & ~(kPointerSize - 1)) == value);
1673 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001674 ASSERT(0 <= value && value < 256);
1675 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1676}
1677
1678
ager@chromium.org7c537e22008-10-16 08:43:32 +00001679void Map::set_inobject_properties(int value) {
1680 ASSERT(0 <= value && value < 256);
1681 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1682}
1683
1684
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001685InstanceType Map::instance_type() {
1686 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1687}
1688
1689
1690void Map::set_instance_type(InstanceType value) {
1691 ASSERT(0 <= value && value < 256);
1692 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1693}
1694
1695
1696int Map::unused_property_fields() {
1697 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1698}
1699
1700
1701void Map::set_unused_property_fields(int value) {
1702 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1703}
1704
1705
1706byte Map::bit_field() {
1707 return READ_BYTE_FIELD(this, kBitFieldOffset);
1708}
1709
1710
1711void Map::set_bit_field(byte value) {
1712 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1713}
1714
1715
1716void Map::set_non_instance_prototype(bool value) {
1717 if (value) {
1718 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1719 } else {
1720 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1721 }
1722}
1723
1724
1725bool Map::has_non_instance_prototype() {
1726 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1727}
1728
1729
ager@chromium.org870a0b62008-11-04 11:43:05 +00001730void Map::set_is_access_check_needed(bool access_check_needed) {
1731 if (access_check_needed) {
1732 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1733 } else {
1734 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1735 }
1736}
1737
1738
1739bool Map::is_access_check_needed() {
1740 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1741}
1742
1743
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744Code::Flags Code::flags() {
1745 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1746}
1747
1748
1749void Code::set_flags(Code::Flags flags) {
1750 // Make sure that all call stubs have an arguments count.
1751 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1752 ExtractArgumentsCountFromFlags(flags) >= 0);
1753 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1754}
1755
1756
1757Code::Kind Code::kind() {
1758 return ExtractKindFromFlags(flags());
1759}
1760
1761
kasper.lund7276f142008-07-30 08:49:36 +00001762InlineCacheState Code::ic_state() {
1763 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001764 // Only allow uninitialized or debugger states for non-IC code
1765 // objects. This is used in the debugger to determine whether or not
1766 // a call to code object has been replaced with a debug break call.
1767 ASSERT(is_inline_cache_stub() ||
1768 result == UNINITIALIZED ||
1769 result == DEBUG_BREAK ||
1770 result == DEBUG_PREPARE_STEP_IN);
1771 return result;
1772}
1773
1774
1775PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001776 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001777 return ExtractTypeFromFlags(flags());
1778}
1779
1780
1781int Code::arguments_count() {
1782 ASSERT(is_call_stub() || kind() == STUB);
1783 return ExtractArgumentsCountFromFlags(flags());
1784}
1785
1786
1787CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001788 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001789 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1790 kStubMajorKeyOffset));
1791}
1792
1793
1794void Code::set_major_key(CodeStub::Major major) {
1795 ASSERT(kind() == STUB);
1796 ASSERT(0 <= major && major < 256);
1797 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001798}
1799
1800
1801bool Code::is_inline_cache_stub() {
1802 Kind kind = this->kind();
1803 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1804}
1805
1806
1807Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001808 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001809 PropertyType type,
1810 int argc) {
1811 // Compute the bit mask.
1812 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001813 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001814 bits |= type << kFlagsTypeShift;
1815 bits |= argc << kFlagsArgumentsCountShift;
1816 // Cast to flags and validate result before returning it.
1817 Flags result = static_cast<Flags>(bits);
1818 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001819 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001820 ASSERT(ExtractTypeFromFlags(result) == type);
1821 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1822 return result;
1823}
1824
1825
1826Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1827 PropertyType type,
1828 int argc) {
1829 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1830}
1831
1832
1833Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1834 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1835 return static_cast<Kind>(bits);
1836}
1837
1838
kasper.lund7276f142008-07-30 08:49:36 +00001839InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1840 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001841 return static_cast<InlineCacheState>(bits);
1842}
1843
1844
1845PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1846 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1847 return static_cast<PropertyType>(bits);
1848}
1849
1850
1851int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1852 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1853}
1854
1855
1856Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1857 int bits = flags & ~kFlagsTypeMask;
1858 return static_cast<Flags>(bits);
1859}
1860
1861
1862Object* Map::prototype() {
1863 return READ_FIELD(this, kPrototypeOffset);
1864}
1865
1866
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001867void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001868 ASSERT(value->IsNull() || value->IsJSObject());
1869 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001870 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001871}
1872
1873
1874ACCESSORS(Map, instance_descriptors, DescriptorArray,
1875 kInstanceDescriptorsOffset)
1876ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1877ACCESSORS(Map, constructor, Object, kConstructorOffset)
1878
1879ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1880ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1881
1882ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1883ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001884ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001885
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001886ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001887
1888ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1889ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1890ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1891ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1892ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1893
1894ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1895ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1896ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1897
1898ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1899ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1900ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1901ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1902ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1903ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1904
1905ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1906ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1907
1908ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1909ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1910
1911ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1912ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001913ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1914 kPropertyAccessorsOffset)
1915ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1916 kPrototypeTemplateOffset)
1917ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1918ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1919 kNamedPropertyHandlerOffset)
1920ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1921 kIndexedPropertyHandlerOffset)
1922ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1923 kInstanceTemplateOffset)
1924ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1925ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001926ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1927 kInstanceCallHandlerOffset)
1928ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1929 kAccessCheckInfoOffset)
1930ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1931
1932ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001933ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1934 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001935
1936ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1937ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1938
1939ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1940
1941ACCESSORS(Script, source, Object, kSourceOffset)
1942ACCESSORS(Script, name, Object, kNameOffset)
1943ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1944ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1945ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1946ACCESSORS(Script, type, Smi, kTypeOffset)
1947
1948ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1949ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1950ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1951ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1952
1953ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1954ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1955ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1956ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1957
1958ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1959ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1960 kInstanceClassNameOffset)
1961ACCESSORS(SharedFunctionInfo, function_data, Object,
1962 kExternalReferenceDataOffset)
1963ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1964ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1965ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1966
1967BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1968 kHiddenPrototypeBit)
1969BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1970BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1971 kNeedsAccessCheckBit)
1972BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1973 kIsExpressionBit)
1974BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1975 kIsTopLevelBit)
1976
1977INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1978INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1979 kFormalParameterCountOffset)
1980INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1981 kExpectedNofPropertiesOffset)
1982INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
1983 kStartPositionAndTypeOffset)
1984INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
1985INT_ACCESSORS(SharedFunctionInfo, function_token_position,
1986 kFunctionTokenPositionOffset)
1987
1988
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001989void SharedFunctionInfo::DontAdaptArguments() {
1990 ASSERT(code()->kind() == Code::BUILTIN);
1991 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
1992}
1993
1994
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995int SharedFunctionInfo::start_position() {
1996 return start_position_and_type() >> kStartPositionShift;
1997}
1998
1999
2000void SharedFunctionInfo::set_start_position(int start_position) {
2001 set_start_position_and_type((start_position << kStartPositionShift)
2002 | (start_position_and_type() & ~kStartPositionMask));
2003}
2004
2005
2006Code* SharedFunctionInfo::code() {
2007 return Code::cast(READ_FIELD(this, kCodeOffset));
2008}
2009
2010
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002011void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002012 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002013 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002014}
2015
2016
2017bool SharedFunctionInfo::is_compiled() {
2018 // TODO(1242782): Create a code kind for uncompiled code.
2019 return code()->kind() != Code::STUB;
2020}
2021
2022
2023bool JSFunction::IsBoilerplate() {
2024 return map() == Heap::boilerplate_function_map();
2025}
2026
2027
2028bool JSFunction::IsLoaded() {
2029 return shared()->lazy_load_data() == Heap::undefined_value();
2030}
2031
2032
2033Code* JSFunction::code() {
2034 return shared()->code();
2035}
2036
2037
2038void JSFunction::set_code(Code* value) {
2039 shared()->set_code(value);
2040}
2041
2042
2043Context* JSFunction::context() {
2044 return Context::cast(READ_FIELD(this, kContextOffset));
2045}
2046
2047
2048Object* JSFunction::unchecked_context() {
2049 return READ_FIELD(this, kContextOffset);
2050}
2051
2052
2053void JSFunction::set_context(Object* value) {
2054 ASSERT(value == Heap::undefined_value() || value->IsContext());
2055 WRITE_FIELD(this, kContextOffset, value);
2056 WRITE_BARRIER(this, kContextOffset);
2057}
2058
2059ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2060 kPrototypeOrInitialMapOffset)
2061
2062
2063Map* JSFunction::initial_map() {
2064 return Map::cast(prototype_or_initial_map());
2065}
2066
2067
2068void JSFunction::set_initial_map(Map* value) {
2069 set_prototype_or_initial_map(value);
2070}
2071
2072
2073bool JSFunction::has_initial_map() {
2074 return prototype_or_initial_map()->IsMap();
2075}
2076
2077
2078bool JSFunction::has_instance_prototype() {
2079 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2080}
2081
2082
2083bool JSFunction::has_prototype() {
2084 return map()->has_non_instance_prototype() || has_instance_prototype();
2085}
2086
2087
2088Object* JSFunction::instance_prototype() {
2089 ASSERT(has_instance_prototype());
2090 if (has_initial_map()) return initial_map()->prototype();
2091 // When there is no initial map and the prototype is a JSObject, the
2092 // initial map field is used for the prototype field.
2093 return prototype_or_initial_map();
2094}
2095
2096
2097Object* JSFunction::prototype() {
2098 ASSERT(has_prototype());
2099 // If the function's prototype property has been set to a non-JSObject
2100 // value, that value is stored in the constructor field of the map.
2101 if (map()->has_non_instance_prototype()) return map()->constructor();
2102 return instance_prototype();
2103}
2104
2105
2106bool JSFunction::is_compiled() {
2107 return shared()->is_compiled();
2108}
2109
2110
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002111int JSFunction::NumberOfLiterals() {
2112 return literals()->length();
2113}
2114
2115
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002116Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2117 ASSERT(0 <= id && id < kJSBuiltinsCount);
2118 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2119}
2120
2121
2122void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2123 Object* value) {
2124 ASSERT(0 <= id && id < kJSBuiltinsCount);
2125 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2126 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2127}
2128
2129
2130Address Proxy::proxy() {
2131 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2132}
2133
2134
2135void Proxy::set_proxy(Address value) {
2136 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2137}
2138
2139
2140void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2141 visitor->VisitExternalReference(
2142 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2143}
2144
2145
2146ACCESSORS(JSValue, value, Object, kValueOffset)
2147
2148
2149JSValue* JSValue::cast(Object* obj) {
2150 ASSERT(obj->IsJSValue());
2151 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2152 return reinterpret_cast<JSValue*>(obj);
2153}
2154
2155
2156INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2157INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2158INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2159
2160
2161Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002162 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002163}
2164
2165
2166void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002167 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002168}
2169
2170
2171byte* Code::instruction_start() {
2172 return FIELD_ADDR(this, kHeaderSize);
2173}
2174
2175
2176int Code::body_size() {
2177 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2178}
2179
2180
2181byte* Code::relocation_start() {
2182 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2183}
2184
2185
2186byte* Code::entry() {
2187 return instruction_start();
2188}
2189
2190
2191bool Code::contains(byte* pc) {
2192 return (instruction_start() <= pc) &&
2193 (pc < instruction_start() + instruction_size());
2194}
2195
2196
2197byte* Code::sinfo_start() {
2198 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2199}
2200
2201
2202ACCESSORS(JSArray, length, Object, kLengthOffset)
2203
2204
ager@chromium.org236ad962008-09-25 09:45:57 +00002205ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002206
2207
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002208JSRegExp::Type JSRegExp::TypeTag() {
2209 Object* data = this->data();
2210 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2211 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2212 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002213}
2214
2215
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002216Object* JSRegExp::DataAt(int index) {
2217 ASSERT(TypeTag() != NOT_COMPILED);
2218 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002219}
2220
2221
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002222bool JSObject::HasFastElements() {
2223 return !elements()->IsDictionary();
2224}
2225
2226
2227bool JSObject::HasNamedInterceptor() {
2228 return map()->has_named_interceptor();
2229}
2230
2231
2232bool JSObject::HasIndexedInterceptor() {
2233 return map()->has_indexed_interceptor();
2234}
2235
2236
2237Dictionary* JSObject::property_dictionary() {
2238 ASSERT(!HasFastProperties());
2239 return Dictionary::cast(properties());
2240}
2241
2242
2243Dictionary* JSObject::element_dictionary() {
2244 ASSERT(!HasFastElements());
2245 return Dictionary::cast(elements());
2246}
2247
2248
2249bool String::HasHashCode() {
2250 return (length_field() & kHashComputedMask) != 0;
2251}
2252
2253
2254uint32_t String::Hash() {
2255 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002256 uint32_t field = length_field();
2257 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002258 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259 return ComputeAndSetHash();
2260}
2261
2262
ager@chromium.org7c537e22008-10-16 08:43:32 +00002263StringHasher::StringHasher(int length)
2264 : length_(length),
2265 raw_running_hash_(0),
2266 array_index_(0),
2267 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2268 is_first_char_(true),
2269 is_valid_(true) { }
2270
2271
2272bool StringHasher::has_trivial_hash() {
2273 return length_ > String::kMaxMediumStringSize;
2274}
2275
2276
2277void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002278 // Use the Jenkins one-at-a-time hash function to update the hash
2279 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002280 raw_running_hash_ += c;
2281 raw_running_hash_ += (raw_running_hash_ << 10);
2282 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002283 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002284 if (is_array_index_) {
2285 if (c < '0' || c > '9') {
2286 is_array_index_ = false;
2287 } else {
2288 int d = c - '0';
2289 if (is_first_char_) {
2290 is_first_char_ = false;
2291 if (c == '0' && length_ > 1) {
2292 is_array_index_ = false;
2293 return;
2294 }
2295 }
2296 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2297 is_array_index_ = false;
2298 } else {
2299 array_index_ = array_index_ * 10 + d;
2300 }
2301 }
2302 }
2303}
2304
2305
2306void StringHasher::AddCharacterNoIndex(uc32 c) {
2307 ASSERT(!is_array_index());
2308 raw_running_hash_ += c;
2309 raw_running_hash_ += (raw_running_hash_ << 10);
2310 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2311}
2312
2313
2314uint32_t StringHasher::GetHash() {
2315 uint32_t result = raw_running_hash_;
2316 result += (result << 3);
2317 result ^= (result >> 11);
2318 result += (result << 15);
2319 return result;
2320}
2321
2322
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002323bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002324 uint32_t field = length_field();
2325 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002326 return SlowAsArrayIndex(index);
2327}
2328
2329
2330Object* JSObject::GetPrototype() {
2331 return JSObject::cast(this)->map()->prototype();
2332}
2333
2334
2335PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2336 return GetPropertyAttributeWithReceiver(this, key);
2337}
2338
2339
2340bool JSObject::HasElement(uint32_t index) {
2341 return HasElementWithReceiver(this, index);
2342}
2343
2344
2345bool AccessorInfo::all_can_read() {
2346 return BooleanBit::get(flag(), kAllCanReadBit);
2347}
2348
2349
2350void AccessorInfo::set_all_can_read(bool value) {
2351 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2352}
2353
2354
2355bool AccessorInfo::all_can_write() {
2356 return BooleanBit::get(flag(), kAllCanWriteBit);
2357}
2358
2359
2360void AccessorInfo::set_all_can_write(bool value) {
2361 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2362}
2363
2364
ager@chromium.org870a0b62008-11-04 11:43:05 +00002365bool AccessorInfo::prohibits_overwriting() {
2366 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2367}
2368
2369
2370void AccessorInfo::set_prohibits_overwriting(bool value) {
2371 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2372}
2373
2374
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002375PropertyAttributes AccessorInfo::property_attributes() {
2376 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2377}
2378
2379
2380void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2381 ASSERT(AttributesField::is_valid(attributes));
2382 int rest_value = flag()->value() & ~AttributesField::mask();
2383 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2384}
2385
2386void Dictionary::SetEntry(int entry,
2387 Object* key,
2388 Object* value,
2389 PropertyDetails details) {
2390 ASSERT(!key->IsString() || details.index() > 0);
2391 int index = EntryToIndex(entry);
2392 WriteBarrierMode mode = GetWriteBarrierMode();
2393 set(index, key, mode);
2394 set(index+1, value, mode);
2395 fast_set(this, index+2, details.AsSmi());
2396}
2397
2398
2399void Map::ClearCodeCache() {
2400 // No write barrier is needed since empty_fixed_array is not in new space.
2401 // Please note this function is used during marking:
2402 // - MarkCompactCollector::MarkUnmarkedObject
2403 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2404 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2405}
2406
2407
ager@chromium.org7c537e22008-10-16 08:43:32 +00002408void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002409 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002410 set_elements(storage);
2411}
2412
2413
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002414Object* FixedArray::Copy() {
2415 if (length() == 0) return this;
2416 return Heap::CopyFixedArray(this);
2417}
2418
2419
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002420#undef CAST_ACCESSOR
2421#undef INT_ACCESSORS
2422#undef SMI_ACCESSORS
2423#undef ACCESSORS
2424#undef FIELD_ADDR
2425#undef READ_FIELD
2426#undef WRITE_FIELD
2427#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002428#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002429#undef READ_MEMADDR_FIELD
2430#undef WRITE_MEMADDR_FIELD
2431#undef READ_DOUBLE_FIELD
2432#undef WRITE_DOUBLE_FIELD
2433#undef READ_INT_FIELD
2434#undef WRITE_INT_FIELD
2435#undef READ_SHORT_FIELD
2436#undef WRITE_SHORT_FIELD
2437#undef READ_BYTE_FIELD
2438#undef WRITE_BYTE_FIELD
2439
2440
2441} } // namespace v8::internal
2442
2443#endif // V8_OBJECTS_INL_H_