blob: 5c70463ac5f8fb98873b4879c2757b101d075ff6 [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
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000282uc32 FlatStringReader::Get(int index) {
283 ASSERT(0 <= index && index <= length_);
284 if (is_ascii_) {
285 return static_cast<const byte*>(start_)[index];
286 } else {
287 return static_cast<const uc16*>(start_)[index];
288 }
289}
290
291
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292bool Object::IsNumber() {
293 return IsSmi() || IsHeapNumber();
294}
295
296
297bool Object::IsByteArray() {
298 return Object::IsHeapObject()
299 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
300}
301
302
303bool Object::IsFailure() {
304 return HAS_FAILURE_TAG(this);
305}
306
307
308bool Object::IsRetryAfterGC() {
309 return HAS_FAILURE_TAG(this)
310 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
311}
312
313
ager@chromium.org7c537e22008-10-16 08:43:32 +0000314bool Object::IsOutOfMemoryFailure() {
315 return HAS_FAILURE_TAG(this)
316 && Failure::cast(this)->IsOutOfMemoryException();
317}
318
319
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320bool Object::IsException() {
321 return this == Failure::Exception();
322}
323
324
325bool Object::IsJSObject() {
326 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000327 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328}
329
330
331bool Object::IsMap() {
332 return Object::IsHeapObject()
333 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
334}
335
336
337bool Object::IsFixedArray() {
338 return Object::IsHeapObject()
339 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
340}
341
342
343bool Object::IsDescriptorArray() {
344 return IsFixedArray();
345}
346
347
348bool Object::IsContext() {
349 return Object::IsHeapObject()
350 && (HeapObject::cast(this)->map() == Heap::context_map() ||
351 HeapObject::cast(this)->map() == Heap::global_context_map());
352}
353
354
355bool Object::IsGlobalContext() {
356 return Object::IsHeapObject()
357 && HeapObject::cast(this)->map() == Heap::global_context_map();
358}
359
360
361bool Object::IsJSFunction() {
362 return Object::IsHeapObject()
363 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
364}
365
366
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000367template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 return obj->IsJSFunction();
369}
370
371
372bool Object::IsCode() {
373 return Object::IsHeapObject()
374 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
375}
376
377
378bool Object::IsOddball() {
379 return Object::IsHeapObject()
380 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
381}
382
383
384bool Object::IsSharedFunctionInfo() {
385 return Object::IsHeapObject() &&
386 (HeapObject::cast(this)->map()->instance_type() ==
387 SHARED_FUNCTION_INFO_TYPE);
388}
389
390
391bool Object::IsJSValue() {
392 return Object::IsHeapObject()
393 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
394}
395
396
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000397bool Object::IsStringWrapper() {
398 return IsJSValue() && JSValue::cast(this)->value()->IsString();
399}
400
401
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000402bool Object::IsProxy() {
403 return Object::IsHeapObject()
404 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
405}
406
407
408bool Object::IsBoolean() {
409 return IsTrue() || IsFalse();
410}
411
412
413bool Object::IsJSArray() {
414 return Object::IsHeapObject()
415 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
416}
417
418
ager@chromium.org236ad962008-09-25 09:45:57 +0000419bool Object::IsJSRegExp() {
420 return Object::IsHeapObject()
421 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
422}
423
424
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000425template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000426 return obj->IsJSArray();
427}
428
429
430bool Object::IsHashTable() {
431 return Object::IsHeapObject()
432 && HeapObject::cast(this)->map() == Heap::hash_table_map();
433}
434
435
436bool Object::IsDictionary() {
437 return IsHashTable() && this != Heap::symbol_table();
438}
439
440
441bool Object::IsSymbolTable() {
442 return IsHashTable() && this == Heap::symbol_table();
443}
444
445
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000446bool Object::IsCompilationCacheTable() {
447 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000448}
449
450
ager@chromium.org236ad962008-09-25 09:45:57 +0000451bool Object::IsMapCache() {
452 return IsHashTable();
453}
454
455
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000456bool Object::IsLookupCache() {
457 return IsHashTable();
458}
459
460
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461bool Object::IsPrimitive() {
462 return IsOddball() || IsNumber() || IsString();
463}
464
465
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000466bool Object::IsJSGlobalProxy() {
467 bool result = IsHeapObject() &&
468 (HeapObject::cast(this)->map()->instance_type() ==
469 JS_GLOBAL_PROXY_TYPE);
470 ASSERT(!result || IsAccessCheckNeeded());
471 return result;
472}
473
474
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000476 if (!IsHeapObject()) return false;
477
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000478 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000479 return type == JS_GLOBAL_OBJECT_TYPE ||
480 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000481}
482
483
484bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000485 return IsHeapObject() &&
486 (HeapObject::cast(this)->map()->instance_type() ==
487 JS_GLOBAL_OBJECT_TYPE);
488}
489
490
491bool Object::IsJSBuiltinsObject() {
492 return IsHeapObject() &&
493 (HeapObject::cast(this)->map()->instance_type() ==
494 JS_BUILTINS_OBJECT_TYPE);
495}
496
497
498bool Object::IsUndetectableObject() {
499 return IsHeapObject()
500 && HeapObject::cast(this)->map()->is_undetectable();
501}
502
503
504bool Object::IsAccessCheckNeeded() {
505 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000506 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507}
508
509
510bool Object::IsStruct() {
511 if (!IsHeapObject()) return false;
512 switch (HeapObject::cast(this)->map()->instance_type()) {
513#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
514 STRUCT_LIST(MAKE_STRUCT_CASE)
515#undef MAKE_STRUCT_CASE
516 default: return false;
517 }
518}
519
520
521#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
522 bool Object::Is##Name() { \
523 return Object::IsHeapObject() \
524 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
525 }
526 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
527#undef MAKE_STRUCT_PREDICATE
528
529
530bool Object::IsUndefined() {
531 return this == Heap::undefined_value();
532}
533
534
535bool Object::IsTheHole() {
536 return this == Heap::the_hole_value();
537}
538
539
540bool Object::IsNull() {
541 return this == Heap::null_value();
542}
543
544
545bool Object::IsTrue() {
546 return this == Heap::true_value();
547}
548
549
550bool Object::IsFalse() {
551 return this == Heap::false_value();
552}
553
554
555double Object::Number() {
556 ASSERT(IsNumber());
557 return IsSmi()
558 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
559 : reinterpret_cast<HeapNumber*>(this)->value();
560}
561
562
563
564Object* Object::ToSmi() {
565 if (IsSmi()) return this;
566 if (IsHeapNumber()) {
567 double value = HeapNumber::cast(this)->value();
568 int int_value = FastD2I(value);
569 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
570 return Smi::FromInt(int_value);
571 }
572 }
573 return Failure::Exception();
574}
575
576
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000577bool Object::HasSpecificClassOf(String* name) {
578 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
579}
580
581
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000582Object* Object::GetElement(uint32_t index) {
583 return GetElementWithReceiver(this, index);
584}
585
586
587Object* Object::GetProperty(String* key) {
588 PropertyAttributes attributes;
589 return GetPropertyWithReceiver(this, key, &attributes);
590}
591
592
593Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
594 return GetPropertyWithReceiver(this, key, attributes);
595}
596
597
598#define FIELD_ADDR(p, offset) \
599 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
600
601#define READ_FIELD(p, offset) \
602 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
603
604#define WRITE_FIELD(p, offset, value) \
605 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
606
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000607
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000608#define WRITE_BARRIER(object, offset) \
609 Heap::RecordWrite(object->address(), offset);
610
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000611// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000612// write due to the assert validating the written value.
613#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
614 if (mode == UPDATE_WRITE_BARRIER) { \
615 Heap::RecordWrite(object->address(), offset); \
616 } else { \
617 ASSERT(mode == SKIP_WRITE_BARRIER); \
618 ASSERT(Heap::InNewSpace(object) || \
619 !Heap::InNewSpace(READ_FIELD(object, offset))); \
620 }
621
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000622#define READ_DOUBLE_FIELD(p, offset) \
623 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
624
625#define WRITE_DOUBLE_FIELD(p, offset, value) \
626 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
627
628#define READ_INT_FIELD(p, offset) \
629 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
630
631#define WRITE_INT_FIELD(p, offset, value) \
632 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
633
ager@chromium.org7c537e22008-10-16 08:43:32 +0000634#define READ_UINT32_FIELD(p, offset) \
635 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
636
637#define WRITE_UINT32_FIELD(p, offset, value) \
638 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
639
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000640#define READ_SHORT_FIELD(p, offset) \
641 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
642
643#define WRITE_SHORT_FIELD(p, offset, value) \
644 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
645
646#define READ_BYTE_FIELD(p, offset) \
647 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
648
649#define WRITE_BYTE_FIELD(p, offset, value) \
650 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
651
652
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000653Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
654 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655}
656
657
658int Smi::value() {
659 return reinterpret_cast<int>(this) >> kSmiTagSize;
660}
661
662
663Smi* Smi::FromInt(int value) {
664 ASSERT(Smi::IsValid(value));
665 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
666}
667
668
669Failure::Type Failure::type() const {
670 return static_cast<Type>(value() & kFailureTypeTagMask);
671}
672
673
674bool Failure::IsInternalError() const {
675 return type() == INTERNAL_ERROR;
676}
677
678
679bool Failure::IsOutOfMemoryException() const {
680 return type() == OUT_OF_MEMORY_EXCEPTION;
681}
682
683
684int Failure::requested() const {
685 const int kShiftBits =
686 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
687 STATIC_ASSERT(kShiftBits >= 0);
688 ASSERT(type() == RETRY_AFTER_GC);
689 return value() >> kShiftBits;
690}
691
692
693AllocationSpace Failure::allocation_space() const {
694 ASSERT_EQ(RETRY_AFTER_GC, type());
695 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
696 & kSpaceTagMask);
697}
698
699
700Failure* Failure::InternalError() {
701 return Construct(INTERNAL_ERROR);
702}
703
704
705Failure* Failure::Exception() {
706 return Construct(EXCEPTION);
707}
708
709Failure* Failure::OutOfMemoryException() {
710 return Construct(OUT_OF_MEMORY_EXCEPTION);
711}
712
713
714int Failure::value() const {
715 return reinterpret_cast<int>(this) >> kFailureTagSize;
716}
717
718
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000719Failure* Failure::RetryAfterGC(int requested_bytes) {
720 int requested = requested_bytes >> kObjectAlignmentBits;
721 int value = (requested << kSpaceTagSize) | NEW_SPACE;
722 ASSERT(value >> kSpaceTagSize == requested);
723 ASSERT(Smi::IsValid(value));
724 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
725 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
726 return Construct(RETRY_AFTER_GC, value);
727}
728
729
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000730Failure* Failure::Construct(Type type, int value) {
731 int info = (value << kFailureTypeTagSize) | type;
732 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
733 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
734}
735
736
737bool Smi::IsValid(int value) {
738#ifdef DEBUG
739 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
740#endif
741 // To be representable as an tagged small integer, the two
742 // most-significant bits of 'value' must be either 00 or 11 due to
743 // sign-extension. To check this we add 01 to the two
744 // most-significant bits, and check if the most-significant bit is 0
745 //
746 // CAUTION: The original code below:
747 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
748 // may lead to incorrect results according to the C language spec, and
749 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
750 // compiler may produce undefined results in case of signed integer
751 // overflow. The computation must be done w/ unsigned ints.
752 bool result =
753 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
754 ASSERT(result == in_range);
755 return result;
756}
757
758
kasper.lund7276f142008-07-30 08:49:36 +0000759MapWord MapWord::FromMap(Map* map) {
760 return MapWord(reinterpret_cast<uintptr_t>(map));
761}
762
763
764Map* MapWord::ToMap() {
765 return reinterpret_cast<Map*>(value_);
766}
767
768
769bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000770 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000771}
772
773
774MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000775 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
776 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000777}
778
779
780HeapObject* MapWord::ToForwardingAddress() {
781 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000782 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000783}
784
785
786bool MapWord::IsMarked() {
787 return (value_ & kMarkingMask) == 0;
788}
789
790
791void MapWord::SetMark() {
792 value_ &= ~kMarkingMask;
793}
794
795
796void MapWord::ClearMark() {
797 value_ |= kMarkingMask;
798}
799
800
801bool MapWord::IsOverflowed() {
802 return (value_ & kOverflowMask) != 0;
803}
804
805
806void MapWord::SetOverflow() {
807 value_ |= kOverflowMask;
808}
809
810
811void MapWord::ClearOverflow() {
812 value_ &= ~kOverflowMask;
813}
814
815
816MapWord MapWord::EncodeAddress(Address map_address, int offset) {
817 // Offset is the distance in live bytes from the first live object in the
818 // same page. The offset between two objects in the same page should not
819 // exceed the object area size of a page.
820 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
821
822 int compact_offset = offset >> kObjectAlignmentBits;
823 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
824
825 Page* map_page = Page::FromAddress(map_address);
826 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
827
828 int map_page_offset =
829 map_page->Offset(map_address) >> kObjectAlignmentBits;
830
831 uintptr_t encoding =
832 (compact_offset << kForwardingOffsetShift) |
833 (map_page_offset << kMapPageOffsetShift) |
834 (map_page->mc_page_index << kMapPageIndexShift);
835 return MapWord(encoding);
836}
837
838
839Address MapWord::DecodeMapAddress(MapSpace* map_space) {
840 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
841 ASSERT_MAP_PAGE_INDEX(map_page_index);
842
843 int map_page_offset =
844 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
845 << kObjectAlignmentBits;
846
847 return (map_space->PageAddress(map_page_index) + map_page_offset);
848}
849
850
851int MapWord::DecodeOffset() {
852 // The offset field is represented in the kForwardingOffsetBits
853 // most-significant bits.
854 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
855 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
856 return offset;
857}
858
859
860MapWord MapWord::FromEncodedAddress(Address address) {
861 return MapWord(reinterpret_cast<uintptr_t>(address));
862}
863
864
865Address MapWord::ToEncodedAddress() {
866 return reinterpret_cast<Address>(value_);
867}
868
869
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870#ifdef DEBUG
871void HeapObject::VerifyObjectField(int offset) {
872 VerifyPointer(READ_FIELD(this, offset));
873}
874#endif
875
876
877Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000878 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879}
880
881
882void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000883 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000884}
885
886
kasper.lund7276f142008-07-30 08:49:36 +0000887MapWord HeapObject::map_word() {
888 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
889}
890
891
892void HeapObject::set_map_word(MapWord map_word) {
893 // WRITE_FIELD does not update the remembered set, but there is no need
894 // here.
895 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
896}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000897
898
899HeapObject* HeapObject::FromAddress(Address address) {
900 ASSERT_TAG_ALIGNED(address);
901 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
902}
903
904
905Address HeapObject::address() {
906 return reinterpret_cast<Address>(this) - kHeapObjectTag;
907}
908
909
910int HeapObject::Size() {
911 return SizeFromMap(map());
912}
913
914
915void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
916 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
917 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
918}
919
920
921void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
922 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
923}
924
925
kasper.lund7276f142008-07-30 08:49:36 +0000926bool HeapObject::IsMarked() {
927 return map_word().IsMarked();
928}
929
930
931void HeapObject::SetMark() {
932 ASSERT(!IsMarked());
933 MapWord first_word = map_word();
934 first_word.SetMark();
935 set_map_word(first_word);
936}
937
938
939void HeapObject::ClearMark() {
940 ASSERT(IsMarked());
941 MapWord first_word = map_word();
942 first_word.ClearMark();
943 set_map_word(first_word);
944}
945
946
947bool HeapObject::IsOverflowed() {
948 return map_word().IsOverflowed();
949}
950
951
952void HeapObject::SetOverflow() {
953 MapWord first_word = map_word();
954 first_word.SetOverflow();
955 set_map_word(first_word);
956}
957
958
959void HeapObject::ClearOverflow() {
960 ASSERT(IsOverflowed());
961 MapWord first_word = map_word();
962 first_word.ClearOverflow();
963 set_map_word(first_word);
964}
965
966
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000967double HeapNumber::value() {
968 return READ_DOUBLE_FIELD(this, kValueOffset);
969}
970
971
972void HeapNumber::set_value(double value) {
973 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
974}
975
976
977ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000978ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979
980
981void JSObject::initialize_properties() {
982 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
983 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
984}
985
986
987void JSObject::initialize_elements() {
988 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
989 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
990}
991
992
993ACCESSORS(Oddball, to_string, String, kToStringOffset)
994ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
995
996
997int JSObject::GetHeaderSize() {
998 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000999 case JS_GLOBAL_PROXY_TYPE:
1000 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001001 case JS_GLOBAL_OBJECT_TYPE:
1002 return JSGlobalObject::kSize;
1003 case JS_BUILTINS_OBJECT_TYPE:
1004 return JSBuiltinsObject::kSize;
1005 case JS_FUNCTION_TYPE:
1006 return JSFunction::kSize;
1007 case JS_VALUE_TYPE:
1008 return JSValue::kSize;
1009 case JS_ARRAY_TYPE:
1010 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001011 case JS_REGEXP_TYPE:
1012 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001013 case JS_OBJECT_TYPE:
1014 return JSObject::kHeaderSize;
1015 default:
1016 UNREACHABLE();
1017 return 0;
1018 }
1019}
1020
1021
1022int JSObject::GetInternalFieldCount() {
1023 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001024 // Make sure to adjust for the number of in-object properties. These
1025 // properties do contribute to the size, but are not internal fields.
1026 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1027 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001028}
1029
1030
1031Object* JSObject::GetInternalField(int index) {
1032 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001033 // Internal objects do follow immediately after the header, whereas in-object
1034 // properties are at the end of the object. Therefore there is no need
1035 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001036 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1037}
1038
1039
1040void JSObject::SetInternalField(int index, Object* value) {
1041 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001042 // Internal objects do follow immediately after the header, whereas in-object
1043 // properties are at the end of the object. Therefore there is no need
1044 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045 int offset = GetHeaderSize() + (kPointerSize * index);
1046 WRITE_FIELD(this, offset, value);
1047 WRITE_BARRIER(this, offset);
1048}
1049
1050
ager@chromium.org7c537e22008-10-16 08:43:32 +00001051// Access fast-case object properties at index. The use of these routines
1052// is needed to correctly distinguish between properties stored in-object and
1053// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001054Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001055 // Adjust for the number of properties stored in the object.
1056 index -= map()->inobject_properties();
1057 if (index < 0) {
1058 int offset = map()->instance_size() + (index * kPointerSize);
1059 return READ_FIELD(this, offset);
1060 } else {
1061 ASSERT(index < properties()->length());
1062 return properties()->get(index);
1063 }
1064}
1065
1066
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001067Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001068 // Adjust for the number of properties stored in the object.
1069 index -= map()->inobject_properties();
1070 if (index < 0) {
1071 int offset = map()->instance_size() + (index * kPointerSize);
1072 WRITE_FIELD(this, offset, value);
1073 WRITE_BARRIER(this, offset);
1074 } else {
1075 ASSERT(index < properties()->length());
1076 properties()->set(index, value);
1077 }
1078 return value;
1079}
1080
1081
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001082Object* JSObject::InObjectPropertyAtPut(int index,
1083 Object* value,
1084 WriteBarrierMode mode) {
1085 // Adjust for the number of properties stored in the object.
1086 index -= map()->inobject_properties();
1087 ASSERT(index < 0);
1088 int offset = map()->instance_size() + (index * kPointerSize);
1089 WRITE_FIELD(this, offset, value);
1090 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1091 return value;
1092}
1093
1094
1095
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001096void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001097 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001098 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001099 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001100 }
1101}
1102
1103
1104void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001105 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001106 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001107 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001108 }
1109}
1110
1111
1112bool JSObject::HasFastProperties() {
1113 return !properties()->IsDictionary();
1114}
1115
1116
1117bool Array::IndexFromObject(Object* object, uint32_t* index) {
1118 if (object->IsSmi()) {
1119 int value = Smi::cast(object)->value();
1120 if (value < 0) return false;
1121 *index = value;
1122 return true;
1123 }
1124 if (object->IsHeapNumber()) {
1125 double value = HeapNumber::cast(object)->value();
1126 uint32_t uint_value = static_cast<uint32_t>(value);
1127 if (value == static_cast<double>(uint_value)) {
1128 *index = uint_value;
1129 return true;
1130 }
1131 }
1132 return false;
1133}
1134
1135
1136bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1137 if (!this->IsJSValue()) return false;
1138
1139 JSValue* js_value = JSValue::cast(this);
1140 if (!js_value->value()->IsString()) return false;
1141
1142 String* str = String::cast(js_value->value());
1143 if (index >= (uint32_t)str->length()) return false;
1144
1145 return true;
1146}
1147
1148
1149Object* FixedArray::get(int index) {
1150 ASSERT(index >= 0 && index < this->length());
1151 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1152}
1153
1154
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001155void FixedArray::set(int index, Smi* value) {
1156 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1157 int offset = kHeaderSize + index * kPointerSize;
1158 WRITE_FIELD(this, offset, value);
1159}
1160
1161
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162void FixedArray::set(int index, Object* value) {
1163 ASSERT(index >= 0 && index < this->length());
1164 int offset = kHeaderSize + index * kPointerSize;
1165 WRITE_FIELD(this, offset, value);
1166 WRITE_BARRIER(this, offset);
1167}
1168
1169
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001170WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001171 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1172 return UPDATE_WRITE_BARRIER;
1173}
1174
1175
1176void FixedArray::set(int index,
1177 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001178 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001179 ASSERT(index >= 0 && index < this->length());
1180 int offset = kHeaderSize + index * kPointerSize;
1181 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001182 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001183}
1184
1185
1186void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1187 ASSERT(index >= 0 && index < array->length());
1188 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1189}
1190
1191
1192void FixedArray::set_undefined(int index) {
1193 ASSERT(index >= 0 && index < this->length());
1194 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1195 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1196 Heap::undefined_value());
1197}
1198
1199
ager@chromium.org236ad962008-09-25 09:45:57 +00001200void FixedArray::set_null(int index) {
1201 ASSERT(index >= 0 && index < this->length());
1202 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1203 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1204}
1205
1206
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001207void FixedArray::set_the_hole(int index) {
1208 ASSERT(index >= 0 && index < this->length());
1209 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1210 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1211}
1212
1213
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001214bool DescriptorArray::IsEmpty() {
1215 ASSERT(this == Heap::empty_descriptor_array() ||
1216 this->length() > 2);
1217 return this == Heap::empty_descriptor_array();
1218}
1219
1220
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001221void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1222 Object* tmp = array->get(first);
1223 fast_set(array, first, array->get(second));
1224 fast_set(array, second, tmp);
1225}
1226
1227
1228int DescriptorArray::Search(String* name) {
1229 SLOW_ASSERT(IsSortedNoDuplicates());
1230
ager@chromium.org870a0b62008-11-04 11:43:05 +00001231 StringShape shape(name);
1232
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001233 // Check for empty descriptor array.
1234 int nof = number_of_descriptors();
1235 if (nof == 0) return kNotFound;
1236
1237 // Fast case: do linear search for small arrays.
1238 const int kMaxElementsForLinearSearch = 8;
ager@chromium.org870a0b62008-11-04 11:43:05 +00001239 if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001240 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001241 }
1242
1243 // Slow case: perform binary search.
1244 return BinarySearch(name, 0, nof - 1);
1245}
1246
1247
1248
1249String* DescriptorArray::GetKey(int descriptor_number) {
1250 ASSERT(descriptor_number < number_of_descriptors());
1251 return String::cast(get(ToKeyIndex(descriptor_number)));
1252}
1253
1254
1255Object* DescriptorArray::GetValue(int descriptor_number) {
1256 ASSERT(descriptor_number < number_of_descriptors());
1257 return GetContentArray()->get(ToValueIndex(descriptor_number));
1258}
1259
1260
1261Smi* DescriptorArray::GetDetails(int descriptor_number) {
1262 ASSERT(descriptor_number < number_of_descriptors());
1263 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1264}
1265
1266
1267void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1268 desc->Init(GetKey(descriptor_number),
1269 GetValue(descriptor_number),
1270 GetDetails(descriptor_number));
1271}
1272
1273
1274void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1275 // Range check.
1276 ASSERT(descriptor_number < number_of_descriptors());
1277
1278 // Make sure non of the elements in desc are in new space.
1279 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1280 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1281
1282 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1283 FixedArray* content_array = GetContentArray();
1284 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1285 fast_set(content_array, ToDetailsIndex(descriptor_number),
1286 desc->GetDetails().AsSmi());
1287}
1288
1289
1290void DescriptorArray::Swap(int first, int second) {
1291 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1292 FixedArray* content_array = GetContentArray();
1293 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1294 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1295}
1296
1297
1298bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001299 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 if (!max_index_object->IsSmi()) return false;
1301 return 0 !=
1302 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1303}
1304
1305
1306uint32_t Dictionary::max_number_key() {
1307 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001308 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309 if (!max_index_object->IsSmi()) return 0;
1310 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1311 return value >> kRequiresSlowElementsTagSize;
1312}
1313
1314
1315// ------------------------------------
1316// Cast operations
1317
1318
1319CAST_ACCESSOR(FixedArray)
1320CAST_ACCESSOR(DescriptorArray)
1321CAST_ACCESSOR(Dictionary)
1322CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001323CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001324CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001325CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001326CAST_ACCESSOR(String)
1327CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001328CAST_ACCESSOR(SeqAsciiString)
1329CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001330CAST_ACCESSOR(ConsString)
1331CAST_ACCESSOR(SlicedString)
1332CAST_ACCESSOR(ExternalString)
1333CAST_ACCESSOR(ExternalAsciiString)
1334CAST_ACCESSOR(ExternalTwoByteString)
1335CAST_ACCESSOR(JSObject)
1336CAST_ACCESSOR(Smi)
1337CAST_ACCESSOR(Failure)
1338CAST_ACCESSOR(HeapObject)
1339CAST_ACCESSOR(HeapNumber)
1340CAST_ACCESSOR(Oddball)
1341CAST_ACCESSOR(SharedFunctionInfo)
1342CAST_ACCESSOR(Map)
1343CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001344CAST_ACCESSOR(GlobalObject)
1345CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001346CAST_ACCESSOR(JSGlobalObject)
1347CAST_ACCESSOR(JSBuiltinsObject)
1348CAST_ACCESSOR(Code)
1349CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001350CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001351CAST_ACCESSOR(Proxy)
1352CAST_ACCESSOR(ByteArray)
1353CAST_ACCESSOR(Struct)
1354
1355
1356#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1357 STRUCT_LIST(MAKE_STRUCT_CAST)
1358#undef MAKE_STRUCT_CAST
1359
1360template <int prefix_size, int elem_size>
1361HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1362 Object* obj) {
1363 ASSERT(obj->IsHashTable());
1364 return reinterpret_cast<HashTable*>(obj);
1365}
1366
1367
1368INT_ACCESSORS(Array, length, kLengthOffset)
1369
1370
1371bool String::Equals(String* other) {
1372 if (other == this) return true;
ager@chromium.org870a0b62008-11-04 11:43:05 +00001373 StringShape this_shape(this);
1374 StringShape other_shape(other);
1375 if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false;
1376 return SlowEquals(this_shape, other, other_shape);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001377}
1378
1379
ager@chromium.org870a0b62008-11-04 11:43:05 +00001380int String::length(StringShape shape) {
1381 ASSERT(shape.type() == StringShape(this).type());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001382 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1383
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001384 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1385 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1386 ASSERT(kLongStringTag == 0);
1387
ager@chromium.org870a0b62008-11-04 11:43:05 +00001388 return len >> (shape.size_tag() + kLongLengthShift);
1389}
1390
1391
1392int String::length() {
1393 return length(StringShape(this));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394}
1395
1396
1397void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001398 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1399 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1400 ASSERT(kLongStringTag == 0);
1401
ager@chromium.org870a0b62008-11-04 11:43:05 +00001402 StringShape shape(this);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001403 WRITE_INT_FIELD(this,
1404 kLengthOffset,
ager@chromium.org870a0b62008-11-04 11:43:05 +00001405 value << (shape.size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001406}
1407
1408
ager@chromium.org7c537e22008-10-16 08:43:32 +00001409uint32_t String::length_field() {
1410 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001411}
1412
1413
ager@chromium.org7c537e22008-10-16 08:43:32 +00001414void String::set_length_field(uint32_t value) {
1415 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001416}
1417
1418
ager@chromium.org870a0b62008-11-04 11:43:05 +00001419void String::TryFlatten(StringShape shape) {
1420 ASSERT(shape.type() == StringShape(this).type());
ager@chromium.org236ad962008-09-25 09:45:57 +00001421 // We don't need to flatten strings that are already flat. Since this code
1422 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001423 if (!IsFlat(shape)) {
1424 Flatten(shape);
ager@chromium.org236ad962008-09-25 09:45:57 +00001425 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001426}
1427
1428
ager@chromium.org870a0b62008-11-04 11:43:05 +00001429uint16_t String::Get(StringShape shape, int index) {
1430 ASSERT(shape.type() == StringShape(this).type());
1431 ASSERT(index >= 0 && index < length(shape));
1432 switch (shape.full_representation_tag()) {
1433 case kSeqStringTag | kAsciiStringTag:
1434 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1435 case kSeqStringTag | kTwoByteStringTag:
1436 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1437 case kConsStringTag | kAsciiStringTag:
1438 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001439 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001440 case kSlicedStringTag | kAsciiStringTag:
1441 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001442 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001443 case kExternalStringTag | kAsciiStringTag:
1444 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1445 case kExternalStringTag | kTwoByteStringTag:
1446 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001447 default:
1448 break;
1449 }
1450
1451 UNREACHABLE();
1452 return 0;
1453}
1454
1455
ager@chromium.org870a0b62008-11-04 11:43:05 +00001456void String::Set(StringShape shape, int index, uint16_t value) {
1457 ASSERT(shape.type() == StringShape(this).type());
1458 ASSERT(shape.type() == StringShape(this).type());
1459 ASSERT(index >= 0 && index < length(shape));
1460 ASSERT(shape.IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461
ager@chromium.org870a0b62008-11-04 11:43:05 +00001462 return shape.IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001463 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1464 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001465}
1466
1467
ager@chromium.org870a0b62008-11-04 11:43:05 +00001468bool String::IsFlat(StringShape shape) {
1469 ASSERT(shape.type() == StringShape(this).type());
1470 switch (shape.representation_tag()) {
1471 case kConsStringTag: {
1472 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001473 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001474 return second->length() == 0;
1475 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001476 case kSlicedStringTag: {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001477 StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer());
1478 StringRepresentationTag tag = slice_shape.representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001479 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001480 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001481 default:
1482 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001483 }
1484}
1485
1486
ager@chromium.org7c537e22008-10-16 08:43:32 +00001487uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001488 ASSERT(index >= 0 && index < length());
1489 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1490}
1491
1492
ager@chromium.org7c537e22008-10-16 08:43:32 +00001493void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1495 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1496 static_cast<byte>(value));
1497}
1498
1499
ager@chromium.org7c537e22008-10-16 08:43:32 +00001500Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001501 return FIELD_ADDR(this, kHeaderSize);
1502}
1503
1504
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001505char* SeqAsciiString::GetChars() {
1506 return reinterpret_cast<char*>(GetCharsAddress());
1507}
1508
1509
ager@chromium.org7c537e22008-10-16 08:43:32 +00001510Address SeqTwoByteString::GetCharsAddress() {
1511 return FIELD_ADDR(this, kHeaderSize);
1512}
1513
1514
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001515uc16* SeqTwoByteString::GetChars() {
1516 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1517}
1518
1519
ager@chromium.org7c537e22008-10-16 08:43:32 +00001520uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001521 ASSERT(index >= 0 && index < length());
1522 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1523}
1524
1525
ager@chromium.org7c537e22008-10-16 08:43:32 +00001526void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001527 ASSERT(index >= 0 && index < length());
1528 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1529}
1530
1531
ager@chromium.org870a0b62008-11-04 11:43:05 +00001532int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001533 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1534
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001535 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1536 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1537 ASSERT(kLongStringTag == 0);
1538
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001539 // Use the map (and not 'this') to compute the size tag, since
1540 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001541 length >>= shape.size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001542
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543 return SizeFor(length);
1544}
1545
1546
ager@chromium.org870a0b62008-11-04 11:43:05 +00001547int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001548 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1549
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001550 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1551 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1552 ASSERT(kLongStringTag == 0);
1553
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001554 // Use the map (and not 'this') to compute the size tag, since
1555 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001556 length >>= shape.size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557
1558 return SizeFor(length);
1559}
1560
1561
ager@chromium.org870a0b62008-11-04 11:43:05 +00001562String* ConsString::first() {
1563 return String::cast(READ_FIELD(this, kFirstOffset));
1564}
1565
1566
1567Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001568 return READ_FIELD(this, kFirstOffset);
1569}
1570
1571
ager@chromium.org870a0b62008-11-04 11:43:05 +00001572void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001573 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001574 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001575}
1576
1577
ager@chromium.org870a0b62008-11-04 11:43:05 +00001578String* ConsString::second() {
1579 return String::cast(READ_FIELD(this, kSecondOffset));
1580}
1581
1582
1583Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001584 return READ_FIELD(this, kSecondOffset);
1585}
1586
1587
ager@chromium.org870a0b62008-11-04 11:43:05 +00001588void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001590 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001591}
1592
1593
ager@chromium.org870a0b62008-11-04 11:43:05 +00001594String* SlicedString::buffer() {
1595 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001596}
1597
1598
ager@chromium.org870a0b62008-11-04 11:43:05 +00001599void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 WRITE_FIELD(this, kBufferOffset, buffer);
1601 WRITE_BARRIER(this, kBufferOffset);
1602}
1603
1604
1605int SlicedString::start() {
1606 return READ_INT_FIELD(this, kStartOffset);
1607}
1608
1609
1610void SlicedString::set_start(int start) {
1611 WRITE_INT_FIELD(this, kStartOffset, start);
1612}
1613
1614
1615ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1616 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1617}
1618
1619
1620void ExternalAsciiString::set_resource(
1621 ExternalAsciiString::Resource* resource) {
1622 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1623}
1624
1625
1626ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1627 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1628}
1629
1630
1631void ExternalTwoByteString::set_resource(
1632 ExternalTwoByteString::Resource* resource) {
1633 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1634}
1635
1636
1637byte ByteArray::get(int index) {
1638 ASSERT(index >= 0 && index < this->length());
1639 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1640}
1641
1642
1643void ByteArray::set(int index, byte value) {
1644 ASSERT(index >= 0 && index < this->length());
1645 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1646}
1647
1648
1649int ByteArray::get_int(int index) {
1650 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1651 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1652}
1653
1654
1655ByteArray* ByteArray::FromDataStartAddress(Address address) {
1656 ASSERT_TAG_ALIGNED(address);
1657 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1658}
1659
1660
1661Address ByteArray::GetDataStartAddress() {
1662 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1663}
1664
1665
1666int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001667 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1668}
1669
1670
1671int Map::inobject_properties() {
1672 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001673}
1674
1675
1676int HeapObject::SizeFromMap(Map* map) {
1677 InstanceType instance_type = map->instance_type();
1678 // Only inline the two most frequent cases.
1679 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1680 if (instance_type == FIXED_ARRAY_TYPE) {
1681 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1682 }
1683 // Otherwise do the general size computation.
1684 return SlowSizeFromMap(map);
1685}
1686
1687
1688void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001689 ASSERT((value & ~(kPointerSize - 1)) == value);
1690 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001691 ASSERT(0 <= value && value < 256);
1692 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1693}
1694
1695
ager@chromium.org7c537e22008-10-16 08:43:32 +00001696void Map::set_inobject_properties(int value) {
1697 ASSERT(0 <= value && value < 256);
1698 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1699}
1700
1701
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001702InstanceType Map::instance_type() {
1703 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1704}
1705
1706
1707void Map::set_instance_type(InstanceType value) {
1708 ASSERT(0 <= value && value < 256);
1709 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1710}
1711
1712
1713int Map::unused_property_fields() {
1714 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1715}
1716
1717
1718void Map::set_unused_property_fields(int value) {
1719 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1720}
1721
1722
1723byte Map::bit_field() {
1724 return READ_BYTE_FIELD(this, kBitFieldOffset);
1725}
1726
1727
1728void Map::set_bit_field(byte value) {
1729 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1730}
1731
1732
1733void Map::set_non_instance_prototype(bool value) {
1734 if (value) {
1735 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1736 } else {
1737 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1738 }
1739}
1740
1741
1742bool Map::has_non_instance_prototype() {
1743 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1744}
1745
1746
ager@chromium.org870a0b62008-11-04 11:43:05 +00001747void Map::set_is_access_check_needed(bool access_check_needed) {
1748 if (access_check_needed) {
1749 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1750 } else {
1751 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1752 }
1753}
1754
1755
1756bool Map::is_access_check_needed() {
1757 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1758}
1759
1760
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761Code::Flags Code::flags() {
1762 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1763}
1764
1765
1766void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001767 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001768 // Make sure that all call stubs have an arguments count.
1769 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1770 ExtractArgumentsCountFromFlags(flags) >= 0);
1771 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1772}
1773
1774
1775Code::Kind Code::kind() {
1776 return ExtractKindFromFlags(flags());
1777}
1778
1779
kasper.lund7276f142008-07-30 08:49:36 +00001780InlineCacheState Code::ic_state() {
1781 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001782 // Only allow uninitialized or debugger states for non-IC code
1783 // objects. This is used in the debugger to determine whether or not
1784 // a call to code object has been replaced with a debug break call.
1785 ASSERT(is_inline_cache_stub() ||
1786 result == UNINITIALIZED ||
1787 result == DEBUG_BREAK ||
1788 result == DEBUG_PREPARE_STEP_IN);
1789 return result;
1790}
1791
1792
1793PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001794 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001795 return ExtractTypeFromFlags(flags());
1796}
1797
1798
1799int Code::arguments_count() {
1800 ASSERT(is_call_stub() || kind() == STUB);
1801 return ExtractArgumentsCountFromFlags(flags());
1802}
1803
1804
1805CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001806 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001807 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1808 kStubMajorKeyOffset));
1809}
1810
1811
1812void Code::set_major_key(CodeStub::Major major) {
1813 ASSERT(kind() == STUB);
1814 ASSERT(0 <= major && major < 256);
1815 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001816}
1817
1818
1819bool Code::is_inline_cache_stub() {
1820 Kind kind = this->kind();
1821 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1822}
1823
1824
1825Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001826 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001827 PropertyType type,
1828 int argc) {
1829 // Compute the bit mask.
1830 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001831 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001832 bits |= type << kFlagsTypeShift;
1833 bits |= argc << kFlagsArgumentsCountShift;
1834 // Cast to flags and validate result before returning it.
1835 Flags result = static_cast<Flags>(bits);
1836 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001837 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001838 ASSERT(ExtractTypeFromFlags(result) == type);
1839 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1840 return result;
1841}
1842
1843
1844Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1845 PropertyType type,
1846 int argc) {
1847 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1848}
1849
1850
1851Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1852 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1853 return static_cast<Kind>(bits);
1854}
1855
1856
kasper.lund7276f142008-07-30 08:49:36 +00001857InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1858 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001859 return static_cast<InlineCacheState>(bits);
1860}
1861
1862
1863PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1864 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1865 return static_cast<PropertyType>(bits);
1866}
1867
1868
1869int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1870 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1871}
1872
1873
1874Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1875 int bits = flags & ~kFlagsTypeMask;
1876 return static_cast<Flags>(bits);
1877}
1878
1879
ager@chromium.org8bb60582008-12-11 12:02:20 +00001880Code* Code::GetCodeFromTargetAddress(Address address) {
1881 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1882 // GetCodeFromTargetAddress might be called when marking objects during mark
1883 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1884 // Code::cast. Code::cast does not work when the object's map is
1885 // marked.
1886 Code* result = reinterpret_cast<Code*>(code);
1887 return result;
1888}
1889
1890
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001891Object* Map::prototype() {
1892 return READ_FIELD(this, kPrototypeOffset);
1893}
1894
1895
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001896void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001897 ASSERT(value->IsNull() || value->IsJSObject());
1898 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001899 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001900}
1901
1902
1903ACCESSORS(Map, instance_descriptors, DescriptorArray,
1904 kInstanceDescriptorsOffset)
1905ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1906ACCESSORS(Map, constructor, Object, kConstructorOffset)
1907
1908ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1909ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1910
1911ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1912ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001913ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001914
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001915ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001916
1917ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1918ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1919ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1920ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1921ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1922
1923ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1924ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1925ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1926
1927ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1928ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1929ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1930ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1931ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1932ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1933
1934ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1935ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1936
1937ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1938ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1939
1940ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1941ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1943 kPropertyAccessorsOffset)
1944ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1945 kPrototypeTemplateOffset)
1946ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1947ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1948 kNamedPropertyHandlerOffset)
1949ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1950 kIndexedPropertyHandlerOffset)
1951ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1952 kInstanceTemplateOffset)
1953ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1954ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001955ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1956 kInstanceCallHandlerOffset)
1957ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1958 kAccessCheckInfoOffset)
1959ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1960
1961ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001962ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1963 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001964
1965ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1966ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1967
1968ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1969
1970ACCESSORS(Script, source, Object, kSourceOffset)
1971ACCESSORS(Script, name, Object, kNameOffset)
1972ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1973ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1974ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1975ACCESSORS(Script, type, Smi, kTypeOffset)
1976
1977ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1978ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1979ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1980ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1981
1982ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1983ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1984ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1985ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1986
1987ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1988ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1989 kInstanceClassNameOffset)
1990ACCESSORS(SharedFunctionInfo, function_data, Object,
1991 kExternalReferenceDataOffset)
1992ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1993ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1994ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1995
1996BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1997 kHiddenPrototypeBit)
1998BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1999BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2000 kNeedsAccessCheckBit)
2001BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2002 kIsExpressionBit)
2003BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2004 kIsTopLevelBit)
2005
2006INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2007INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2008 kFormalParameterCountOffset)
2009INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2010 kExpectedNofPropertiesOffset)
2011INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2012 kStartPositionAndTypeOffset)
2013INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2014INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2015 kFunctionTokenPositionOffset)
2016
2017
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002018void SharedFunctionInfo::DontAdaptArguments() {
2019 ASSERT(code()->kind() == Code::BUILTIN);
2020 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2021}
2022
2023
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002024int SharedFunctionInfo::start_position() {
2025 return start_position_and_type() >> kStartPositionShift;
2026}
2027
2028
2029void SharedFunctionInfo::set_start_position(int start_position) {
2030 set_start_position_and_type((start_position << kStartPositionShift)
2031 | (start_position_and_type() & ~kStartPositionMask));
2032}
2033
2034
2035Code* SharedFunctionInfo::code() {
2036 return Code::cast(READ_FIELD(this, kCodeOffset));
2037}
2038
2039
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002040void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002041 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002042 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002043}
2044
2045
2046bool SharedFunctionInfo::is_compiled() {
2047 // TODO(1242782): Create a code kind for uncompiled code.
2048 return code()->kind() != Code::STUB;
2049}
2050
2051
2052bool JSFunction::IsBoilerplate() {
2053 return map() == Heap::boilerplate_function_map();
2054}
2055
2056
2057bool JSFunction::IsLoaded() {
2058 return shared()->lazy_load_data() == Heap::undefined_value();
2059}
2060
2061
2062Code* JSFunction::code() {
2063 return shared()->code();
2064}
2065
2066
2067void JSFunction::set_code(Code* value) {
2068 shared()->set_code(value);
2069}
2070
2071
2072Context* JSFunction::context() {
2073 return Context::cast(READ_FIELD(this, kContextOffset));
2074}
2075
2076
2077Object* JSFunction::unchecked_context() {
2078 return READ_FIELD(this, kContextOffset);
2079}
2080
2081
2082void JSFunction::set_context(Object* value) {
2083 ASSERT(value == Heap::undefined_value() || value->IsContext());
2084 WRITE_FIELD(this, kContextOffset, value);
2085 WRITE_BARRIER(this, kContextOffset);
2086}
2087
2088ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2089 kPrototypeOrInitialMapOffset)
2090
2091
2092Map* JSFunction::initial_map() {
2093 return Map::cast(prototype_or_initial_map());
2094}
2095
2096
2097void JSFunction::set_initial_map(Map* value) {
2098 set_prototype_or_initial_map(value);
2099}
2100
2101
2102bool JSFunction::has_initial_map() {
2103 return prototype_or_initial_map()->IsMap();
2104}
2105
2106
2107bool JSFunction::has_instance_prototype() {
2108 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2109}
2110
2111
2112bool JSFunction::has_prototype() {
2113 return map()->has_non_instance_prototype() || has_instance_prototype();
2114}
2115
2116
2117Object* JSFunction::instance_prototype() {
2118 ASSERT(has_instance_prototype());
2119 if (has_initial_map()) return initial_map()->prototype();
2120 // When there is no initial map and the prototype is a JSObject, the
2121 // initial map field is used for the prototype field.
2122 return prototype_or_initial_map();
2123}
2124
2125
2126Object* JSFunction::prototype() {
2127 ASSERT(has_prototype());
2128 // If the function's prototype property has been set to a non-JSObject
2129 // value, that value is stored in the constructor field of the map.
2130 if (map()->has_non_instance_prototype()) return map()->constructor();
2131 return instance_prototype();
2132}
2133
2134
2135bool JSFunction::is_compiled() {
2136 return shared()->is_compiled();
2137}
2138
2139
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002140int JSFunction::NumberOfLiterals() {
2141 return literals()->length();
2142}
2143
2144
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002145Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2146 ASSERT(0 <= id && id < kJSBuiltinsCount);
2147 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2148}
2149
2150
2151void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2152 Object* value) {
2153 ASSERT(0 <= id && id < kJSBuiltinsCount);
2154 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2155 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2156}
2157
2158
2159Address Proxy::proxy() {
2160 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2161}
2162
2163
2164void Proxy::set_proxy(Address value) {
2165 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2166}
2167
2168
2169void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2170 visitor->VisitExternalReference(
2171 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2172}
2173
2174
2175ACCESSORS(JSValue, value, Object, kValueOffset)
2176
2177
2178JSValue* JSValue::cast(Object* obj) {
2179 ASSERT(obj->IsJSValue());
2180 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2181 return reinterpret_cast<JSValue*>(obj);
2182}
2183
2184
2185INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2186INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2187INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2188
2189
2190Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002191 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192}
2193
2194
2195void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002196 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002197}
2198
2199
2200byte* Code::instruction_start() {
2201 return FIELD_ADDR(this, kHeaderSize);
2202}
2203
2204
2205int Code::body_size() {
2206 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2207}
2208
2209
2210byte* Code::relocation_start() {
2211 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2212}
2213
2214
2215byte* Code::entry() {
2216 return instruction_start();
2217}
2218
2219
2220bool Code::contains(byte* pc) {
2221 return (instruction_start() <= pc) &&
2222 (pc < instruction_start() + instruction_size());
2223}
2224
2225
2226byte* Code::sinfo_start() {
2227 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2228}
2229
2230
2231ACCESSORS(JSArray, length, Object, kLengthOffset)
2232
2233
ager@chromium.org236ad962008-09-25 09:45:57 +00002234ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002235
2236
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002237JSRegExp::Type JSRegExp::TypeTag() {
2238 Object* data = this->data();
2239 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2240 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2241 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002242}
2243
2244
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002245JSRegExp::Flags JSRegExp::GetFlags() {
2246 ASSERT(this->data()->IsFixedArray());
2247 Object* data = this->data();
2248 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2249 return Flags(smi->value());
2250}
2251
2252
2253String* JSRegExp::Pattern() {
2254 ASSERT(this->data()->IsFixedArray());
2255 Object* data = this->data();
2256 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2257 return pattern;
2258}
2259
2260
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002261Object* JSRegExp::DataAt(int index) {
2262 ASSERT(TypeTag() != NOT_COMPILED);
2263 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002264}
2265
2266
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002267bool JSObject::HasFastElements() {
2268 return !elements()->IsDictionary();
2269}
2270
2271
2272bool JSObject::HasNamedInterceptor() {
2273 return map()->has_named_interceptor();
2274}
2275
2276
2277bool JSObject::HasIndexedInterceptor() {
2278 return map()->has_indexed_interceptor();
2279}
2280
2281
2282Dictionary* JSObject::property_dictionary() {
2283 ASSERT(!HasFastProperties());
2284 return Dictionary::cast(properties());
2285}
2286
2287
2288Dictionary* JSObject::element_dictionary() {
2289 ASSERT(!HasFastElements());
2290 return Dictionary::cast(elements());
2291}
2292
2293
2294bool String::HasHashCode() {
2295 return (length_field() & kHashComputedMask) != 0;
2296}
2297
2298
2299uint32_t String::Hash() {
2300 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002301 uint32_t field = length_field();
2302 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002303 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002304 return ComputeAndSetHash();
2305}
2306
2307
ager@chromium.org7c537e22008-10-16 08:43:32 +00002308StringHasher::StringHasher(int length)
2309 : length_(length),
2310 raw_running_hash_(0),
2311 array_index_(0),
2312 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2313 is_first_char_(true),
2314 is_valid_(true) { }
2315
2316
2317bool StringHasher::has_trivial_hash() {
2318 return length_ > String::kMaxMediumStringSize;
2319}
2320
2321
2322void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002323 // Use the Jenkins one-at-a-time hash function to update the hash
2324 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002325 raw_running_hash_ += c;
2326 raw_running_hash_ += (raw_running_hash_ << 10);
2327 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002328 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002329 if (is_array_index_) {
2330 if (c < '0' || c > '9') {
2331 is_array_index_ = false;
2332 } else {
2333 int d = c - '0';
2334 if (is_first_char_) {
2335 is_first_char_ = false;
2336 if (c == '0' && length_ > 1) {
2337 is_array_index_ = false;
2338 return;
2339 }
2340 }
2341 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2342 is_array_index_ = false;
2343 } else {
2344 array_index_ = array_index_ * 10 + d;
2345 }
2346 }
2347 }
2348}
2349
2350
2351void StringHasher::AddCharacterNoIndex(uc32 c) {
2352 ASSERT(!is_array_index());
2353 raw_running_hash_ += c;
2354 raw_running_hash_ += (raw_running_hash_ << 10);
2355 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2356}
2357
2358
2359uint32_t StringHasher::GetHash() {
2360 uint32_t result = raw_running_hash_;
2361 result += (result << 3);
2362 result ^= (result >> 11);
2363 result += (result << 15);
2364 return result;
2365}
2366
2367
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002368bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002369 uint32_t field = length_field();
2370 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002371 return SlowAsArrayIndex(index);
2372}
2373
2374
2375Object* JSObject::GetPrototype() {
2376 return JSObject::cast(this)->map()->prototype();
2377}
2378
2379
2380PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2381 return GetPropertyAttributeWithReceiver(this, key);
2382}
2383
2384
2385bool JSObject::HasElement(uint32_t index) {
2386 return HasElementWithReceiver(this, index);
2387}
2388
2389
2390bool AccessorInfo::all_can_read() {
2391 return BooleanBit::get(flag(), kAllCanReadBit);
2392}
2393
2394
2395void AccessorInfo::set_all_can_read(bool value) {
2396 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2397}
2398
2399
2400bool AccessorInfo::all_can_write() {
2401 return BooleanBit::get(flag(), kAllCanWriteBit);
2402}
2403
2404
2405void AccessorInfo::set_all_can_write(bool value) {
2406 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2407}
2408
2409
ager@chromium.org870a0b62008-11-04 11:43:05 +00002410bool AccessorInfo::prohibits_overwriting() {
2411 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2412}
2413
2414
2415void AccessorInfo::set_prohibits_overwriting(bool value) {
2416 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2417}
2418
2419
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002420PropertyAttributes AccessorInfo::property_attributes() {
2421 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2422}
2423
2424
2425void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2426 ASSERT(AttributesField::is_valid(attributes));
2427 int rest_value = flag()->value() & ~AttributesField::mask();
2428 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2429}
2430
2431void Dictionary::SetEntry(int entry,
2432 Object* key,
2433 Object* value,
2434 PropertyDetails details) {
2435 ASSERT(!key->IsString() || details.index() > 0);
2436 int index = EntryToIndex(entry);
2437 WriteBarrierMode mode = GetWriteBarrierMode();
2438 set(index, key, mode);
2439 set(index+1, value, mode);
2440 fast_set(this, index+2, details.AsSmi());
2441}
2442
2443
2444void Map::ClearCodeCache() {
2445 // No write barrier is needed since empty_fixed_array is not in new space.
2446 // Please note this function is used during marking:
2447 // - MarkCompactCollector::MarkUnmarkedObject
2448 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2449 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2450}
2451
2452
ager@chromium.org7c537e22008-10-16 08:43:32 +00002453void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002454 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002455 set_elements(storage);
2456}
2457
2458
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002459Object* FixedArray::Copy() {
2460 if (length() == 0) return this;
2461 return Heap::CopyFixedArray(this);
2462}
2463
2464
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002465#undef CAST_ACCESSOR
2466#undef INT_ACCESSORS
2467#undef SMI_ACCESSORS
2468#undef ACCESSORS
2469#undef FIELD_ADDR
2470#undef READ_FIELD
2471#undef WRITE_FIELD
2472#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002473#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002474#undef READ_MEMADDR_FIELD
2475#undef WRITE_MEMADDR_FIELD
2476#undef READ_DOUBLE_FIELD
2477#undef WRITE_DOUBLE_FIELD
2478#undef READ_INT_FIELD
2479#undef WRITE_INT_FIELD
2480#undef READ_SHORT_FIELD
2481#undef WRITE_SHORT_FIELD
2482#undef READ_BYTE_FIELD
2483#undef WRITE_BYTE_FIELD
2484
2485
2486} } // namespace v8::internal
2487
2488#endif // V8_OBJECTS_INL_H_