blob: e8c4e9149cb0eb9ca2563ec5575f212834f6100e [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
1880Object* Map::prototype() {
1881 return READ_FIELD(this, kPrototypeOffset);
1882}
1883
1884
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001885void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001886 ASSERT(value->IsNull() || value->IsJSObject());
1887 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001888 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889}
1890
1891
1892ACCESSORS(Map, instance_descriptors, DescriptorArray,
1893 kInstanceDescriptorsOffset)
1894ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1895ACCESSORS(Map, constructor, Object, kConstructorOffset)
1896
1897ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1898ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1899
1900ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1901ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001902ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001903
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001904ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001905
1906ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1907ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1908ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1909ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1910ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1911
1912ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1913ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1914ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1915
1916ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1917ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1918ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1919ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1920ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1921ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1922
1923ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1924ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1925
1926ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1927ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1928
1929ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1930ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001931ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1932 kPropertyAccessorsOffset)
1933ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1934 kPrototypeTemplateOffset)
1935ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1936ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1937 kNamedPropertyHandlerOffset)
1938ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1939 kIndexedPropertyHandlerOffset)
1940ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1941 kInstanceTemplateOffset)
1942ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1943ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001944ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1945 kInstanceCallHandlerOffset)
1946ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1947 kAccessCheckInfoOffset)
1948ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1949
1950ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001951ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1952 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001953
1954ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1955ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1956
1957ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1958
1959ACCESSORS(Script, source, Object, kSourceOffset)
1960ACCESSORS(Script, name, Object, kNameOffset)
1961ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1962ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1963ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1964ACCESSORS(Script, type, Smi, kTypeOffset)
1965
1966ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1967ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1968ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1969ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1970
1971ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1972ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1973ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1974ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1975
1976ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1977ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1978 kInstanceClassNameOffset)
1979ACCESSORS(SharedFunctionInfo, function_data, Object,
1980 kExternalReferenceDataOffset)
1981ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1982ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1983ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1984
1985BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1986 kHiddenPrototypeBit)
1987BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1988BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1989 kNeedsAccessCheckBit)
1990BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1991 kIsExpressionBit)
1992BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1993 kIsTopLevelBit)
1994
1995INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1996INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1997 kFormalParameterCountOffset)
1998INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1999 kExpectedNofPropertiesOffset)
2000INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2001 kStartPositionAndTypeOffset)
2002INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2003INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2004 kFunctionTokenPositionOffset)
2005
2006
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002007void SharedFunctionInfo::DontAdaptArguments() {
2008 ASSERT(code()->kind() == Code::BUILTIN);
2009 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2010}
2011
2012
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002013int SharedFunctionInfo::start_position() {
2014 return start_position_and_type() >> kStartPositionShift;
2015}
2016
2017
2018void SharedFunctionInfo::set_start_position(int start_position) {
2019 set_start_position_and_type((start_position << kStartPositionShift)
2020 | (start_position_and_type() & ~kStartPositionMask));
2021}
2022
2023
2024Code* SharedFunctionInfo::code() {
2025 return Code::cast(READ_FIELD(this, kCodeOffset));
2026}
2027
2028
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002029void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002030 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002031 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002032}
2033
2034
2035bool SharedFunctionInfo::is_compiled() {
2036 // TODO(1242782): Create a code kind for uncompiled code.
2037 return code()->kind() != Code::STUB;
2038}
2039
2040
2041bool JSFunction::IsBoilerplate() {
2042 return map() == Heap::boilerplate_function_map();
2043}
2044
2045
2046bool JSFunction::IsLoaded() {
2047 return shared()->lazy_load_data() == Heap::undefined_value();
2048}
2049
2050
2051Code* JSFunction::code() {
2052 return shared()->code();
2053}
2054
2055
2056void JSFunction::set_code(Code* value) {
2057 shared()->set_code(value);
2058}
2059
2060
2061Context* JSFunction::context() {
2062 return Context::cast(READ_FIELD(this, kContextOffset));
2063}
2064
2065
2066Object* JSFunction::unchecked_context() {
2067 return READ_FIELD(this, kContextOffset);
2068}
2069
2070
2071void JSFunction::set_context(Object* value) {
2072 ASSERT(value == Heap::undefined_value() || value->IsContext());
2073 WRITE_FIELD(this, kContextOffset, value);
2074 WRITE_BARRIER(this, kContextOffset);
2075}
2076
2077ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2078 kPrototypeOrInitialMapOffset)
2079
2080
2081Map* JSFunction::initial_map() {
2082 return Map::cast(prototype_or_initial_map());
2083}
2084
2085
2086void JSFunction::set_initial_map(Map* value) {
2087 set_prototype_or_initial_map(value);
2088}
2089
2090
2091bool JSFunction::has_initial_map() {
2092 return prototype_or_initial_map()->IsMap();
2093}
2094
2095
2096bool JSFunction::has_instance_prototype() {
2097 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2098}
2099
2100
2101bool JSFunction::has_prototype() {
2102 return map()->has_non_instance_prototype() || has_instance_prototype();
2103}
2104
2105
2106Object* JSFunction::instance_prototype() {
2107 ASSERT(has_instance_prototype());
2108 if (has_initial_map()) return initial_map()->prototype();
2109 // When there is no initial map and the prototype is a JSObject, the
2110 // initial map field is used for the prototype field.
2111 return prototype_or_initial_map();
2112}
2113
2114
2115Object* JSFunction::prototype() {
2116 ASSERT(has_prototype());
2117 // If the function's prototype property has been set to a non-JSObject
2118 // value, that value is stored in the constructor field of the map.
2119 if (map()->has_non_instance_prototype()) return map()->constructor();
2120 return instance_prototype();
2121}
2122
2123
2124bool JSFunction::is_compiled() {
2125 return shared()->is_compiled();
2126}
2127
2128
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002129int JSFunction::NumberOfLiterals() {
2130 return literals()->length();
2131}
2132
2133
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002134Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2135 ASSERT(0 <= id && id < kJSBuiltinsCount);
2136 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2137}
2138
2139
2140void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2141 Object* value) {
2142 ASSERT(0 <= id && id < kJSBuiltinsCount);
2143 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2144 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2145}
2146
2147
2148Address Proxy::proxy() {
2149 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2150}
2151
2152
2153void Proxy::set_proxy(Address value) {
2154 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2155}
2156
2157
2158void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2159 visitor->VisitExternalReference(
2160 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2161}
2162
2163
2164ACCESSORS(JSValue, value, Object, kValueOffset)
2165
2166
2167JSValue* JSValue::cast(Object* obj) {
2168 ASSERT(obj->IsJSValue());
2169 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2170 return reinterpret_cast<JSValue*>(obj);
2171}
2172
2173
2174INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2175INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2176INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2177
2178
2179Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002180 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002181}
2182
2183
2184void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002185 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002186}
2187
2188
2189byte* Code::instruction_start() {
2190 return FIELD_ADDR(this, kHeaderSize);
2191}
2192
2193
2194int Code::body_size() {
2195 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2196}
2197
2198
2199byte* Code::relocation_start() {
2200 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2201}
2202
2203
2204byte* Code::entry() {
2205 return instruction_start();
2206}
2207
2208
2209bool Code::contains(byte* pc) {
2210 return (instruction_start() <= pc) &&
2211 (pc < instruction_start() + instruction_size());
2212}
2213
2214
2215byte* Code::sinfo_start() {
2216 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2217}
2218
2219
2220ACCESSORS(JSArray, length, Object, kLengthOffset)
2221
2222
ager@chromium.org236ad962008-09-25 09:45:57 +00002223ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002224
2225
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002226JSRegExp::Type JSRegExp::TypeTag() {
2227 Object* data = this->data();
2228 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2229 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2230 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002231}
2232
2233
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002234JSRegExp::Flags JSRegExp::GetFlags() {
2235 ASSERT(this->data()->IsFixedArray());
2236 Object* data = this->data();
2237 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2238 return Flags(smi->value());
2239}
2240
2241
2242String* JSRegExp::Pattern() {
2243 ASSERT(this->data()->IsFixedArray());
2244 Object* data = this->data();
2245 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2246 return pattern;
2247}
2248
2249
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002250Object* JSRegExp::DataAt(int index) {
2251 ASSERT(TypeTag() != NOT_COMPILED);
2252 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002253}
2254
2255
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002256bool JSObject::HasFastElements() {
2257 return !elements()->IsDictionary();
2258}
2259
2260
2261bool JSObject::HasNamedInterceptor() {
2262 return map()->has_named_interceptor();
2263}
2264
2265
2266bool JSObject::HasIndexedInterceptor() {
2267 return map()->has_indexed_interceptor();
2268}
2269
2270
2271Dictionary* JSObject::property_dictionary() {
2272 ASSERT(!HasFastProperties());
2273 return Dictionary::cast(properties());
2274}
2275
2276
2277Dictionary* JSObject::element_dictionary() {
2278 ASSERT(!HasFastElements());
2279 return Dictionary::cast(elements());
2280}
2281
2282
2283bool String::HasHashCode() {
2284 return (length_field() & kHashComputedMask) != 0;
2285}
2286
2287
2288uint32_t String::Hash() {
2289 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002290 uint32_t field = length_field();
2291 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002292 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002293 return ComputeAndSetHash();
2294}
2295
2296
ager@chromium.org7c537e22008-10-16 08:43:32 +00002297StringHasher::StringHasher(int length)
2298 : length_(length),
2299 raw_running_hash_(0),
2300 array_index_(0),
2301 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2302 is_first_char_(true),
2303 is_valid_(true) { }
2304
2305
2306bool StringHasher::has_trivial_hash() {
2307 return length_ > String::kMaxMediumStringSize;
2308}
2309
2310
2311void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002312 // Use the Jenkins one-at-a-time hash function to update the hash
2313 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002314 raw_running_hash_ += c;
2315 raw_running_hash_ += (raw_running_hash_ << 10);
2316 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002317 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002318 if (is_array_index_) {
2319 if (c < '0' || c > '9') {
2320 is_array_index_ = false;
2321 } else {
2322 int d = c - '0';
2323 if (is_first_char_) {
2324 is_first_char_ = false;
2325 if (c == '0' && length_ > 1) {
2326 is_array_index_ = false;
2327 return;
2328 }
2329 }
2330 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2331 is_array_index_ = false;
2332 } else {
2333 array_index_ = array_index_ * 10 + d;
2334 }
2335 }
2336 }
2337}
2338
2339
2340void StringHasher::AddCharacterNoIndex(uc32 c) {
2341 ASSERT(!is_array_index());
2342 raw_running_hash_ += c;
2343 raw_running_hash_ += (raw_running_hash_ << 10);
2344 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2345}
2346
2347
2348uint32_t StringHasher::GetHash() {
2349 uint32_t result = raw_running_hash_;
2350 result += (result << 3);
2351 result ^= (result >> 11);
2352 result += (result << 15);
2353 return result;
2354}
2355
2356
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002357bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002358 uint32_t field = length_field();
2359 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002360 return SlowAsArrayIndex(index);
2361}
2362
2363
2364Object* JSObject::GetPrototype() {
2365 return JSObject::cast(this)->map()->prototype();
2366}
2367
2368
2369PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2370 return GetPropertyAttributeWithReceiver(this, key);
2371}
2372
2373
2374bool JSObject::HasElement(uint32_t index) {
2375 return HasElementWithReceiver(this, index);
2376}
2377
2378
2379bool AccessorInfo::all_can_read() {
2380 return BooleanBit::get(flag(), kAllCanReadBit);
2381}
2382
2383
2384void AccessorInfo::set_all_can_read(bool value) {
2385 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2386}
2387
2388
2389bool AccessorInfo::all_can_write() {
2390 return BooleanBit::get(flag(), kAllCanWriteBit);
2391}
2392
2393
2394void AccessorInfo::set_all_can_write(bool value) {
2395 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2396}
2397
2398
ager@chromium.org870a0b62008-11-04 11:43:05 +00002399bool AccessorInfo::prohibits_overwriting() {
2400 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2401}
2402
2403
2404void AccessorInfo::set_prohibits_overwriting(bool value) {
2405 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2406}
2407
2408
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002409PropertyAttributes AccessorInfo::property_attributes() {
2410 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2411}
2412
2413
2414void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2415 ASSERT(AttributesField::is_valid(attributes));
2416 int rest_value = flag()->value() & ~AttributesField::mask();
2417 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2418}
2419
2420void Dictionary::SetEntry(int entry,
2421 Object* key,
2422 Object* value,
2423 PropertyDetails details) {
2424 ASSERT(!key->IsString() || details.index() > 0);
2425 int index = EntryToIndex(entry);
2426 WriteBarrierMode mode = GetWriteBarrierMode();
2427 set(index, key, mode);
2428 set(index+1, value, mode);
2429 fast_set(this, index+2, details.AsSmi());
2430}
2431
2432
2433void Map::ClearCodeCache() {
2434 // No write barrier is needed since empty_fixed_array is not in new space.
2435 // Please note this function is used during marking:
2436 // - MarkCompactCollector::MarkUnmarkedObject
2437 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2438 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2439}
2440
2441
ager@chromium.org7c537e22008-10-16 08:43:32 +00002442void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002443 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002444 set_elements(storage);
2445}
2446
2447
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002448Object* FixedArray::Copy() {
2449 if (length() == 0) return this;
2450 return Heap::CopyFixedArray(this);
2451}
2452
2453
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002454#undef CAST_ACCESSOR
2455#undef INT_ACCESSORS
2456#undef SMI_ACCESSORS
2457#undef ACCESSORS
2458#undef FIELD_ADDR
2459#undef READ_FIELD
2460#undef WRITE_FIELD
2461#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002462#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002463#undef READ_MEMADDR_FIELD
2464#undef WRITE_MEMADDR_FIELD
2465#undef READ_DOUBLE_FIELD
2466#undef WRITE_DOUBLE_FIELD
2467#undef READ_INT_FIELD
2468#undef WRITE_INT_FIELD
2469#undef READ_SHORT_FIELD
2470#undef WRITE_SHORT_FIELD
2471#undef READ_BYTE_FIELD
2472#undef WRITE_BYTE_FIELD
2473
2474
2475} } // namespace v8::internal
2476
2477#endif // V8_OBJECTS_INL_H_