blob: 73b9c84943eda2bf788e057530c96b867cf9e346 [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//
ager@chromium.org32912102009-01-16 10:38:43 +000030// - The use of macros in these inline functions may seem superfluous
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000031// 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;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000146 return StringShape(String::cast(this)).IsSequential() &&
147 StringShape(String::cast(this)).IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000148}
149
150
151bool Object::IsSeqTwoByteString() {
152 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000153 return StringShape(String::cast(this)).IsSequential() &&
154 StringShape(String::cast(this)).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;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000166 return StringShape(String::cast(this)).IsExternal() &&
167 StringShape(String::cast(this)).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;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000173 return StringShape(String::cast(this)).IsExternal() &&
174 StringShape(String::cast(this)).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() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000266 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000267}
268
269
270bool StringShape::IsExternalAscii() {
271 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
272}
273
274
275bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000276 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277}
278
279
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000280uc32 FlatStringReader::Get(int index) {
281 ASSERT(0 <= index && index <= length_);
282 if (is_ascii_) {
283 return static_cast<const byte*>(start_)[index];
284 } else {
285 return static_cast<const uc16*>(start_)[index];
286 }
287}
288
289
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000290bool Object::IsNumber() {
291 return IsSmi() || IsHeapNumber();
292}
293
294
295bool Object::IsByteArray() {
296 return Object::IsHeapObject()
297 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
298}
299
300
301bool Object::IsFailure() {
302 return HAS_FAILURE_TAG(this);
303}
304
305
306bool Object::IsRetryAfterGC() {
307 return HAS_FAILURE_TAG(this)
308 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
309}
310
311
ager@chromium.org7c537e22008-10-16 08:43:32 +0000312bool Object::IsOutOfMemoryFailure() {
313 return HAS_FAILURE_TAG(this)
314 && Failure::cast(this)->IsOutOfMemoryException();
315}
316
317
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318bool Object::IsException() {
319 return this == Failure::Exception();
320}
321
322
323bool Object::IsJSObject() {
324 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000325 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000326}
327
328
ager@chromium.org32912102009-01-16 10:38:43 +0000329bool Object::IsJSContextExtensionObject() {
330 return IsHeapObject()
331 && (HeapObject::cast(this)->map()->instance_type() ==
332 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
333}
334
335
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000336bool Object::IsMap() {
337 return Object::IsHeapObject()
338 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
339}
340
341
342bool Object::IsFixedArray() {
343 return Object::IsHeapObject()
344 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
345}
346
347
348bool Object::IsDescriptorArray() {
349 return IsFixedArray();
350}
351
352
353bool Object::IsContext() {
354 return Object::IsHeapObject()
355 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000356 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357 HeapObject::cast(this)->map() == Heap::global_context_map());
358}
359
360
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000361bool Object::IsCatchContext() {
362 return Object::IsHeapObject()
363 && HeapObject::cast(this)->map() == Heap::catch_context_map();
364}
365
366
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000367bool Object::IsGlobalContext() {
368 return Object::IsHeapObject()
369 && HeapObject::cast(this)->map() == Heap::global_context_map();
370}
371
372
373bool Object::IsJSFunction() {
374 return Object::IsHeapObject()
375 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
376}
377
378
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000379template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380 return obj->IsJSFunction();
381}
382
383
384bool Object::IsCode() {
385 return Object::IsHeapObject()
386 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
387}
388
389
390bool Object::IsOddball() {
391 return Object::IsHeapObject()
392 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
393}
394
395
396bool Object::IsSharedFunctionInfo() {
397 return Object::IsHeapObject() &&
398 (HeapObject::cast(this)->map()->instance_type() ==
399 SHARED_FUNCTION_INFO_TYPE);
400}
401
402
403bool Object::IsJSValue() {
404 return Object::IsHeapObject()
405 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
406}
407
408
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000409bool Object::IsStringWrapper() {
410 return IsJSValue() && JSValue::cast(this)->value()->IsString();
411}
412
413
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000414bool Object::IsProxy() {
415 return Object::IsHeapObject()
416 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
417}
418
419
420bool Object::IsBoolean() {
421 return IsTrue() || IsFalse();
422}
423
424
425bool Object::IsJSArray() {
426 return Object::IsHeapObject()
427 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
428}
429
430
ager@chromium.org236ad962008-09-25 09:45:57 +0000431bool Object::IsJSRegExp() {
432 return Object::IsHeapObject()
433 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
434}
435
436
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000437template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000438 return obj->IsJSArray();
439}
440
441
442bool Object::IsHashTable() {
443 return Object::IsHeapObject()
444 && HeapObject::cast(this)->map() == Heap::hash_table_map();
445}
446
447
448bool Object::IsDictionary() {
449 return IsHashTable() && this != Heap::symbol_table();
450}
451
452
453bool Object::IsSymbolTable() {
454 return IsHashTable() && this == Heap::symbol_table();
455}
456
457
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000458bool Object::IsCompilationCacheTable() {
459 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000460}
461
462
ager@chromium.org236ad962008-09-25 09:45:57 +0000463bool Object::IsMapCache() {
464 return IsHashTable();
465}
466
467
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000468bool Object::IsLookupCache() {
469 return IsHashTable();
470}
471
472
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473bool Object::IsPrimitive() {
474 return IsOddball() || IsNumber() || IsString();
475}
476
477
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000478bool Object::IsJSGlobalProxy() {
479 bool result = IsHeapObject() &&
480 (HeapObject::cast(this)->map()->instance_type() ==
481 JS_GLOBAL_PROXY_TYPE);
482 ASSERT(!result || IsAccessCheckNeeded());
483 return result;
484}
485
486
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000488 if (!IsHeapObject()) return false;
489
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000490 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000491 return type == JS_GLOBAL_OBJECT_TYPE ||
492 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493}
494
495
496bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000497 return IsHeapObject() &&
498 (HeapObject::cast(this)->map()->instance_type() ==
499 JS_GLOBAL_OBJECT_TYPE);
500}
501
502
503bool Object::IsJSBuiltinsObject() {
504 return IsHeapObject() &&
505 (HeapObject::cast(this)->map()->instance_type() ==
506 JS_BUILTINS_OBJECT_TYPE);
507}
508
509
510bool Object::IsUndetectableObject() {
511 return IsHeapObject()
512 && HeapObject::cast(this)->map()->is_undetectable();
513}
514
515
516bool Object::IsAccessCheckNeeded() {
517 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000518 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519}
520
521
522bool Object::IsStruct() {
523 if (!IsHeapObject()) return false;
524 switch (HeapObject::cast(this)->map()->instance_type()) {
525#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
526 STRUCT_LIST(MAKE_STRUCT_CASE)
527#undef MAKE_STRUCT_CASE
528 default: return false;
529 }
530}
531
532
533#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
534 bool Object::Is##Name() { \
535 return Object::IsHeapObject() \
536 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
537 }
538 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
539#undef MAKE_STRUCT_PREDICATE
540
541
542bool Object::IsUndefined() {
543 return this == Heap::undefined_value();
544}
545
546
547bool Object::IsTheHole() {
548 return this == Heap::the_hole_value();
549}
550
551
552bool Object::IsNull() {
553 return this == Heap::null_value();
554}
555
556
557bool Object::IsTrue() {
558 return this == Heap::true_value();
559}
560
561
562bool Object::IsFalse() {
563 return this == Heap::false_value();
564}
565
566
567double Object::Number() {
568 ASSERT(IsNumber());
569 return IsSmi()
570 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
571 : reinterpret_cast<HeapNumber*>(this)->value();
572}
573
574
575
576Object* Object::ToSmi() {
577 if (IsSmi()) return this;
578 if (IsHeapNumber()) {
579 double value = HeapNumber::cast(this)->value();
580 int int_value = FastD2I(value);
581 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
582 return Smi::FromInt(int_value);
583 }
584 }
585 return Failure::Exception();
586}
587
588
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000589bool Object::HasSpecificClassOf(String* name) {
590 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
591}
592
593
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000594Object* Object::GetElement(uint32_t index) {
595 return GetElementWithReceiver(this, index);
596}
597
598
599Object* Object::GetProperty(String* key) {
600 PropertyAttributes attributes;
601 return GetPropertyWithReceiver(this, key, &attributes);
602}
603
604
605Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
606 return GetPropertyWithReceiver(this, key, attributes);
607}
608
609
610#define FIELD_ADDR(p, offset) \
611 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
612
613#define READ_FIELD(p, offset) \
614 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
615
616#define WRITE_FIELD(p, offset, value) \
617 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
618
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000619
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000620#define WRITE_BARRIER(object, offset) \
621 Heap::RecordWrite(object->address(), offset);
622
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000623// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000624// write due to the assert validating the written value.
625#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
626 if (mode == UPDATE_WRITE_BARRIER) { \
627 Heap::RecordWrite(object->address(), offset); \
628 } else { \
629 ASSERT(mode == SKIP_WRITE_BARRIER); \
630 ASSERT(Heap::InNewSpace(object) || \
631 !Heap::InNewSpace(READ_FIELD(object, offset))); \
632 }
633
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000634#define READ_DOUBLE_FIELD(p, offset) \
635 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
636
637#define WRITE_DOUBLE_FIELD(p, offset, value) \
638 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
639
640#define READ_INT_FIELD(p, offset) \
641 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
642
643#define WRITE_INT_FIELD(p, offset, value) \
644 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
645
ager@chromium.org7c537e22008-10-16 08:43:32 +0000646#define READ_UINT32_FIELD(p, offset) \
647 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
648
649#define WRITE_UINT32_FIELD(p, offset, value) \
650 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
651
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652#define READ_SHORT_FIELD(p, offset) \
653 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
654
655#define WRITE_SHORT_FIELD(p, offset, value) \
656 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
657
658#define READ_BYTE_FIELD(p, offset) \
659 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
660
661#define WRITE_BYTE_FIELD(p, offset, value) \
662 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
663
664
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000665Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
666 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667}
668
669
670int Smi::value() {
671 return reinterpret_cast<int>(this) >> kSmiTagSize;
672}
673
674
675Smi* Smi::FromInt(int value) {
676 ASSERT(Smi::IsValid(value));
677 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
678}
679
680
681Failure::Type Failure::type() const {
682 return static_cast<Type>(value() & kFailureTypeTagMask);
683}
684
685
686bool Failure::IsInternalError() const {
687 return type() == INTERNAL_ERROR;
688}
689
690
691bool Failure::IsOutOfMemoryException() const {
692 return type() == OUT_OF_MEMORY_EXCEPTION;
693}
694
695
696int Failure::requested() const {
697 const int kShiftBits =
698 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
699 STATIC_ASSERT(kShiftBits >= 0);
700 ASSERT(type() == RETRY_AFTER_GC);
701 return value() >> kShiftBits;
702}
703
704
705AllocationSpace Failure::allocation_space() const {
706 ASSERT_EQ(RETRY_AFTER_GC, type());
707 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
708 & kSpaceTagMask);
709}
710
711
712Failure* Failure::InternalError() {
713 return Construct(INTERNAL_ERROR);
714}
715
716
717Failure* Failure::Exception() {
718 return Construct(EXCEPTION);
719}
720
721Failure* Failure::OutOfMemoryException() {
722 return Construct(OUT_OF_MEMORY_EXCEPTION);
723}
724
725
726int Failure::value() const {
727 return reinterpret_cast<int>(this) >> kFailureTagSize;
728}
729
730
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000731Failure* Failure::RetryAfterGC(int requested_bytes) {
732 int requested = requested_bytes >> kObjectAlignmentBits;
733 int value = (requested << kSpaceTagSize) | NEW_SPACE;
734 ASSERT(value >> kSpaceTagSize == requested);
735 ASSERT(Smi::IsValid(value));
736 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
737 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
738 return Construct(RETRY_AFTER_GC, value);
739}
740
741
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000742Failure* Failure::Construct(Type type, int value) {
743 int info = (value << kFailureTypeTagSize) | type;
744 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
745 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
746}
747
748
749bool Smi::IsValid(int value) {
750#ifdef DEBUG
751 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
752#endif
753 // To be representable as an tagged small integer, the two
754 // most-significant bits of 'value' must be either 00 or 11 due to
755 // sign-extension. To check this we add 01 to the two
756 // most-significant bits, and check if the most-significant bit is 0
757 //
758 // CAUTION: The original code below:
759 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
760 // may lead to incorrect results according to the C language spec, and
761 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
762 // compiler may produce undefined results in case of signed integer
763 // overflow. The computation must be done w/ unsigned ints.
764 bool result =
765 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
766 ASSERT(result == in_range);
767 return result;
768}
769
770
kasper.lund7276f142008-07-30 08:49:36 +0000771MapWord MapWord::FromMap(Map* map) {
772 return MapWord(reinterpret_cast<uintptr_t>(map));
773}
774
775
776Map* MapWord::ToMap() {
777 return reinterpret_cast<Map*>(value_);
778}
779
780
781bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000782 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000783}
784
785
786MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000787 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
788 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000789}
790
791
792HeapObject* MapWord::ToForwardingAddress() {
793 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000794 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000795}
796
797
798bool MapWord::IsMarked() {
799 return (value_ & kMarkingMask) == 0;
800}
801
802
803void MapWord::SetMark() {
804 value_ &= ~kMarkingMask;
805}
806
807
808void MapWord::ClearMark() {
809 value_ |= kMarkingMask;
810}
811
812
813bool MapWord::IsOverflowed() {
814 return (value_ & kOverflowMask) != 0;
815}
816
817
818void MapWord::SetOverflow() {
819 value_ |= kOverflowMask;
820}
821
822
823void MapWord::ClearOverflow() {
824 value_ &= ~kOverflowMask;
825}
826
827
828MapWord MapWord::EncodeAddress(Address map_address, int offset) {
829 // Offset is the distance in live bytes from the first live object in the
830 // same page. The offset between two objects in the same page should not
831 // exceed the object area size of a page.
832 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
833
834 int compact_offset = offset >> kObjectAlignmentBits;
835 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
836
837 Page* map_page = Page::FromAddress(map_address);
838 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
839
840 int map_page_offset =
841 map_page->Offset(map_address) >> kObjectAlignmentBits;
842
843 uintptr_t encoding =
844 (compact_offset << kForwardingOffsetShift) |
845 (map_page_offset << kMapPageOffsetShift) |
846 (map_page->mc_page_index << kMapPageIndexShift);
847 return MapWord(encoding);
848}
849
850
851Address MapWord::DecodeMapAddress(MapSpace* map_space) {
852 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
853 ASSERT_MAP_PAGE_INDEX(map_page_index);
854
855 int map_page_offset =
856 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
857 << kObjectAlignmentBits;
858
859 return (map_space->PageAddress(map_page_index) + map_page_offset);
860}
861
862
863int MapWord::DecodeOffset() {
864 // The offset field is represented in the kForwardingOffsetBits
865 // most-significant bits.
866 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
867 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
868 return offset;
869}
870
871
872MapWord MapWord::FromEncodedAddress(Address address) {
873 return MapWord(reinterpret_cast<uintptr_t>(address));
874}
875
876
877Address MapWord::ToEncodedAddress() {
878 return reinterpret_cast<Address>(value_);
879}
880
881
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882#ifdef DEBUG
883void HeapObject::VerifyObjectField(int offset) {
884 VerifyPointer(READ_FIELD(this, offset));
885}
886#endif
887
888
889Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000890 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000891}
892
893
894void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000895 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896}
897
898
kasper.lund7276f142008-07-30 08:49:36 +0000899MapWord HeapObject::map_word() {
900 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
901}
902
903
904void HeapObject::set_map_word(MapWord map_word) {
905 // WRITE_FIELD does not update the remembered set, but there is no need
906 // here.
907 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
908}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000909
910
911HeapObject* HeapObject::FromAddress(Address address) {
912 ASSERT_TAG_ALIGNED(address);
913 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
914}
915
916
917Address HeapObject::address() {
918 return reinterpret_cast<Address>(this) - kHeapObjectTag;
919}
920
921
922int HeapObject::Size() {
923 return SizeFromMap(map());
924}
925
926
927void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
928 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
929 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
930}
931
932
933void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
934 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
935}
936
937
kasper.lund7276f142008-07-30 08:49:36 +0000938bool HeapObject::IsMarked() {
939 return map_word().IsMarked();
940}
941
942
943void HeapObject::SetMark() {
944 ASSERT(!IsMarked());
945 MapWord first_word = map_word();
946 first_word.SetMark();
947 set_map_word(first_word);
948}
949
950
951void HeapObject::ClearMark() {
952 ASSERT(IsMarked());
953 MapWord first_word = map_word();
954 first_word.ClearMark();
955 set_map_word(first_word);
956}
957
958
959bool HeapObject::IsOverflowed() {
960 return map_word().IsOverflowed();
961}
962
963
964void HeapObject::SetOverflow() {
965 MapWord first_word = map_word();
966 first_word.SetOverflow();
967 set_map_word(first_word);
968}
969
970
971void HeapObject::ClearOverflow() {
972 ASSERT(IsOverflowed());
973 MapWord first_word = map_word();
974 first_word.ClearOverflow();
975 set_map_word(first_word);
976}
977
978
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979double HeapNumber::value() {
980 return READ_DOUBLE_FIELD(this, kValueOffset);
981}
982
983
984void HeapNumber::set_value(double value) {
985 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
986}
987
988
989ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000990ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991
992
993void JSObject::initialize_properties() {
994 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
995 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
996}
997
998
999void JSObject::initialize_elements() {
1000 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1001 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1002}
1003
1004
1005ACCESSORS(Oddball, to_string, String, kToStringOffset)
1006ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1007
1008
1009int JSObject::GetHeaderSize() {
1010 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001011 case JS_GLOBAL_PROXY_TYPE:
1012 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001013 case JS_GLOBAL_OBJECT_TYPE:
1014 return JSGlobalObject::kSize;
1015 case JS_BUILTINS_OBJECT_TYPE:
1016 return JSBuiltinsObject::kSize;
1017 case JS_FUNCTION_TYPE:
1018 return JSFunction::kSize;
1019 case JS_VALUE_TYPE:
1020 return JSValue::kSize;
1021 case JS_ARRAY_TYPE:
1022 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001023 case JS_REGEXP_TYPE:
1024 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001025 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001026 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001027 return JSObject::kHeaderSize;
1028 default:
1029 UNREACHABLE();
1030 return 0;
1031 }
1032}
1033
1034
1035int JSObject::GetInternalFieldCount() {
1036 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001037 // Make sure to adjust for the number of in-object properties. These
1038 // properties do contribute to the size, but are not internal fields.
1039 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1040 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041}
1042
1043
1044Object* JSObject::GetInternalField(int index) {
1045 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001046 // Internal objects do follow immediately after the header, whereas in-object
1047 // properties are at the end of the object. Therefore there is no need
1048 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1050}
1051
1052
1053void JSObject::SetInternalField(int index, Object* value) {
1054 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001055 // Internal objects do follow immediately after the header, whereas in-object
1056 // properties are at the end of the object. Therefore there is no need
1057 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058 int offset = GetHeaderSize() + (kPointerSize * index);
1059 WRITE_FIELD(this, offset, value);
1060 WRITE_BARRIER(this, offset);
1061}
1062
1063
ager@chromium.org7c537e22008-10-16 08:43:32 +00001064// Access fast-case object properties at index. The use of these routines
1065// is needed to correctly distinguish between properties stored in-object and
1066// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001067Object* JSObject::FastPropertyAt(int index) {
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 return READ_FIELD(this, offset);
1073 } else {
1074 ASSERT(index < properties()->length());
1075 return properties()->get(index);
1076 }
1077}
1078
1079
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001080Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001081 // Adjust for the number of properties stored in the object.
1082 index -= map()->inobject_properties();
1083 if (index < 0) {
1084 int offset = map()->instance_size() + (index * kPointerSize);
1085 WRITE_FIELD(this, offset, value);
1086 WRITE_BARRIER(this, offset);
1087 } else {
1088 ASSERT(index < properties()->length());
1089 properties()->set(index, value);
1090 }
1091 return value;
1092}
1093
1094
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001095Object* JSObject::InObjectPropertyAt(int index) {
1096 // Adjust for the number of properties stored in the object.
1097 index -= map()->inobject_properties();
1098 ASSERT(index < 0);
1099 int offset = map()->instance_size() + (index * kPointerSize);
1100 return READ_FIELD(this, offset);
1101}
1102
1103
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001104Object* JSObject::InObjectPropertyAtPut(int index,
1105 Object* value,
1106 WriteBarrierMode mode) {
1107 // Adjust for the number of properties stored in the object.
1108 index -= map()->inobject_properties();
1109 ASSERT(index < 0);
1110 int offset = map()->instance_size() + (index * kPointerSize);
1111 WRITE_FIELD(this, offset, value);
1112 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1113 return value;
1114}
1115
1116
1117
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001118void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001119 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001120 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001121 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001122 }
1123}
1124
1125
1126void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001127 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001128 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001129 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130 }
1131}
1132
1133
1134bool JSObject::HasFastProperties() {
1135 return !properties()->IsDictionary();
1136}
1137
1138
1139bool Array::IndexFromObject(Object* object, uint32_t* index) {
1140 if (object->IsSmi()) {
1141 int value = Smi::cast(object)->value();
1142 if (value < 0) return false;
1143 *index = value;
1144 return true;
1145 }
1146 if (object->IsHeapNumber()) {
1147 double value = HeapNumber::cast(object)->value();
1148 uint32_t uint_value = static_cast<uint32_t>(value);
1149 if (value == static_cast<double>(uint_value)) {
1150 *index = uint_value;
1151 return true;
1152 }
1153 }
1154 return false;
1155}
1156
1157
1158bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1159 if (!this->IsJSValue()) return false;
1160
1161 JSValue* js_value = JSValue::cast(this);
1162 if (!js_value->value()->IsString()) return false;
1163
1164 String* str = String::cast(js_value->value());
1165 if (index >= (uint32_t)str->length()) return false;
1166
1167 return true;
1168}
1169
1170
1171Object* FixedArray::get(int index) {
1172 ASSERT(index >= 0 && index < this->length());
1173 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1174}
1175
1176
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001177void FixedArray::set(int index, Smi* value) {
1178 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1179 int offset = kHeaderSize + index * kPointerSize;
1180 WRITE_FIELD(this, offset, value);
1181}
1182
1183
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001184void FixedArray::set(int index, Object* value) {
1185 ASSERT(index >= 0 && index < this->length());
1186 int offset = kHeaderSize + index * kPointerSize;
1187 WRITE_FIELD(this, offset, value);
1188 WRITE_BARRIER(this, offset);
1189}
1190
1191
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001192WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001193 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1194 return UPDATE_WRITE_BARRIER;
1195}
1196
1197
1198void FixedArray::set(int index,
1199 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001200 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001201 ASSERT(index >= 0 && index < this->length());
1202 int offset = kHeaderSize + index * kPointerSize;
1203 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001204 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001205}
1206
1207
1208void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1209 ASSERT(index >= 0 && index < array->length());
1210 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1211}
1212
1213
1214void FixedArray::set_undefined(int index) {
1215 ASSERT(index >= 0 && index < this->length());
1216 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1217 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1218 Heap::undefined_value());
1219}
1220
1221
ager@chromium.org236ad962008-09-25 09:45:57 +00001222void FixedArray::set_null(int index) {
1223 ASSERT(index >= 0 && index < this->length());
1224 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1225 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1226}
1227
1228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001229void FixedArray::set_the_hole(int index) {
1230 ASSERT(index >= 0 && index < this->length());
1231 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1232 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1233}
1234
1235
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001236bool DescriptorArray::IsEmpty() {
1237 ASSERT(this == Heap::empty_descriptor_array() ||
1238 this->length() > 2);
1239 return this == Heap::empty_descriptor_array();
1240}
1241
1242
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001243void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1244 Object* tmp = array->get(first);
1245 fast_set(array, first, array->get(second));
1246 fast_set(array, second, tmp);
1247}
1248
1249
1250int DescriptorArray::Search(String* name) {
1251 SLOW_ASSERT(IsSortedNoDuplicates());
1252
1253 // Check for empty descriptor array.
1254 int nof = number_of_descriptors();
1255 if (nof == 0) return kNotFound;
1256
1257 // Fast case: do linear search for small arrays.
1258 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001259 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001260 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001261 }
1262
1263 // Slow case: perform binary search.
1264 return BinarySearch(name, 0, nof - 1);
1265}
1266
1267
1268
1269String* DescriptorArray::GetKey(int descriptor_number) {
1270 ASSERT(descriptor_number < number_of_descriptors());
1271 return String::cast(get(ToKeyIndex(descriptor_number)));
1272}
1273
1274
1275Object* DescriptorArray::GetValue(int descriptor_number) {
1276 ASSERT(descriptor_number < number_of_descriptors());
1277 return GetContentArray()->get(ToValueIndex(descriptor_number));
1278}
1279
1280
1281Smi* DescriptorArray::GetDetails(int descriptor_number) {
1282 ASSERT(descriptor_number < number_of_descriptors());
1283 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1284}
1285
1286
1287void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1288 desc->Init(GetKey(descriptor_number),
1289 GetValue(descriptor_number),
1290 GetDetails(descriptor_number));
1291}
1292
1293
1294void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1295 // Range check.
1296 ASSERT(descriptor_number < number_of_descriptors());
1297
1298 // Make sure non of the elements in desc are in new space.
1299 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1300 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1301
1302 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1303 FixedArray* content_array = GetContentArray();
1304 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1305 fast_set(content_array, ToDetailsIndex(descriptor_number),
1306 desc->GetDetails().AsSmi());
1307}
1308
1309
1310void DescriptorArray::Swap(int first, int second) {
1311 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1312 FixedArray* content_array = GetContentArray();
1313 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1314 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1315}
1316
1317
1318bool Dictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001319 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320 if (!max_index_object->IsSmi()) return false;
1321 return 0 !=
1322 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1323}
1324
1325
1326uint32_t Dictionary::max_number_key() {
1327 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001328 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329 if (!max_index_object->IsSmi()) return 0;
1330 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1331 return value >> kRequiresSlowElementsTagSize;
1332}
1333
1334
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001335void Dictionary::set_requires_slow_elements() {
1336 set(kMaxNumberKeyIndex,
1337 Smi::FromInt(kRequiresSlowElementsMask),
1338 SKIP_WRITE_BARRIER);
1339}
1340
1341
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001342// ------------------------------------
1343// Cast operations
1344
1345
1346CAST_ACCESSOR(FixedArray)
1347CAST_ACCESSOR(DescriptorArray)
1348CAST_ACCESSOR(Dictionary)
1349CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001350CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001351CAST_ACCESSOR(MapCache)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001352CAST_ACCESSOR(LookupCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353CAST_ACCESSOR(String)
1354CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001355CAST_ACCESSOR(SeqAsciiString)
1356CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001357CAST_ACCESSOR(ConsString)
1358CAST_ACCESSOR(SlicedString)
1359CAST_ACCESSOR(ExternalString)
1360CAST_ACCESSOR(ExternalAsciiString)
1361CAST_ACCESSOR(ExternalTwoByteString)
1362CAST_ACCESSOR(JSObject)
1363CAST_ACCESSOR(Smi)
1364CAST_ACCESSOR(Failure)
1365CAST_ACCESSOR(HeapObject)
1366CAST_ACCESSOR(HeapNumber)
1367CAST_ACCESSOR(Oddball)
1368CAST_ACCESSOR(SharedFunctionInfo)
1369CAST_ACCESSOR(Map)
1370CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001371CAST_ACCESSOR(GlobalObject)
1372CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001373CAST_ACCESSOR(JSGlobalObject)
1374CAST_ACCESSOR(JSBuiltinsObject)
1375CAST_ACCESSOR(Code)
1376CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001377CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001378CAST_ACCESSOR(Proxy)
1379CAST_ACCESSOR(ByteArray)
1380CAST_ACCESSOR(Struct)
1381
1382
1383#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1384 STRUCT_LIST(MAKE_STRUCT_CAST)
1385#undef MAKE_STRUCT_CAST
1386
1387template <int prefix_size, int elem_size>
1388HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1389 Object* obj) {
1390 ASSERT(obj->IsHashTable());
1391 return reinterpret_cast<HashTable*>(obj);
1392}
1393
1394
1395INT_ACCESSORS(Array, length, kLengthOffset)
1396
1397
1398bool String::Equals(String* other) {
1399 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001400 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1401 return false;
1402 }
1403 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001404}
1405
1406
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001407int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001408 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1409
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001410 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1411 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1412 ASSERT(kLongStringTag == 0);
1413
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001414 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001415}
1416
1417
1418void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001419 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1420 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1421 ASSERT(kLongStringTag == 0);
1422
1423 WRITE_INT_FIELD(this,
1424 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001425 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001426}
1427
1428
ager@chromium.org7c537e22008-10-16 08:43:32 +00001429uint32_t String::length_field() {
1430 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001431}
1432
1433
ager@chromium.org7c537e22008-10-16 08:43:32 +00001434void String::set_length_field(uint32_t value) {
1435 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001436}
1437
1438
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001439Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001440 // We don't need to flatten strings that are already flat. Since this code
1441 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001442 if (!IsFlat()) {
1443 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001444 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001445 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001446}
1447
1448
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001449uint16_t String::Get(int index) {
1450 ASSERT(index >= 0 && index < length());
1451 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001452 case kSeqStringTag | kAsciiStringTag:
1453 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1454 case kSeqStringTag | kTwoByteStringTag:
1455 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1456 case kConsStringTag | kAsciiStringTag:
1457 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001458 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001459 case kSlicedStringTag | kAsciiStringTag:
1460 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001462 case kExternalStringTag | kAsciiStringTag:
1463 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1464 case kExternalStringTag | kTwoByteStringTag:
1465 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001466 default:
1467 break;
1468 }
1469
1470 UNREACHABLE();
1471 return 0;
1472}
1473
1474
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001475void String::Set(int index, uint16_t value) {
1476 ASSERT(index >= 0 && index < length());
1477 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001478
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001479 return StringShape(this).IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001480 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1481 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001482}
1483
1484
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001485bool String::IsFlat() {
1486 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001487 case kConsStringTag: {
1488 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001489 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001490 return second->length() == 0;
1491 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001492 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001493 StringRepresentationTag tag =
1494 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001495 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001496 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001497 default:
1498 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001499 }
1500}
1501
1502
ager@chromium.org7c537e22008-10-16 08:43:32 +00001503uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001504 ASSERT(index >= 0 && index < length());
1505 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1506}
1507
1508
ager@chromium.org7c537e22008-10-16 08:43:32 +00001509void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1511 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1512 static_cast<byte>(value));
1513}
1514
1515
ager@chromium.org7c537e22008-10-16 08:43:32 +00001516Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001517 return FIELD_ADDR(this, kHeaderSize);
1518}
1519
1520
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001521char* SeqAsciiString::GetChars() {
1522 return reinterpret_cast<char*>(GetCharsAddress());
1523}
1524
1525
ager@chromium.org7c537e22008-10-16 08:43:32 +00001526Address SeqTwoByteString::GetCharsAddress() {
1527 return FIELD_ADDR(this, kHeaderSize);
1528}
1529
1530
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001531uc16* SeqTwoByteString::GetChars() {
1532 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1533}
1534
1535
ager@chromium.org7c537e22008-10-16 08:43:32 +00001536uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 ASSERT(index >= 0 && index < length());
1538 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1539}
1540
1541
ager@chromium.org7c537e22008-10-16 08:43:32 +00001542void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543 ASSERT(index >= 0 && index < length());
1544 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1545}
1546
1547
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001548int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1550
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001551 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1552 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1553 ASSERT(kLongStringTag == 0);
1554
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001555 // Use the map (and not 'this') to compute the size tag, since
1556 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001557 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001558
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559 return SizeFor(length);
1560}
1561
1562
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001563int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001564 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1565
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001566 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1567 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1568 ASSERT(kLongStringTag == 0);
1569
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570 // Use the map (and not 'this') to compute the size tag, since
1571 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001572 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001573
1574 return SizeFor(length);
1575}
1576
1577
ager@chromium.org870a0b62008-11-04 11:43:05 +00001578String* ConsString::first() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001579 ASSERT(String::cast(READ_FIELD(this, kSecondOffset))->length() != 0 ||
1580 StringShape(
1581 String::cast(
1582 READ_FIELD(this, kFirstOffset))).IsAsciiRepresentation()
1583 == StringShape(this).IsAsciiRepresentation());
ager@chromium.org870a0b62008-11-04 11:43:05 +00001584 return String::cast(READ_FIELD(this, kFirstOffset));
1585}
1586
1587
1588Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589 return READ_FIELD(this, kFirstOffset);
1590}
1591
1592
ager@chromium.org870a0b62008-11-04 11:43:05 +00001593void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001594 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001595 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001596}
1597
1598
ager@chromium.org870a0b62008-11-04 11:43:05 +00001599String* ConsString::second() {
1600 return String::cast(READ_FIELD(this, kSecondOffset));
1601}
1602
1603
1604Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001605 return READ_FIELD(this, kSecondOffset);
1606}
1607
1608
ager@chromium.org870a0b62008-11-04 11:43:05 +00001609void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001610 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001611 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612}
1613
1614
ager@chromium.org870a0b62008-11-04 11:43:05 +00001615String* SlicedString::buffer() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001616 ASSERT(
1617 StringShape(
1618 String::cast(READ_FIELD(this, kBufferOffset))).IsAsciiRepresentation()
1619 == StringShape(this).IsAsciiRepresentation());
ager@chromium.org870a0b62008-11-04 11:43:05 +00001620 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001621}
1622
1623
ager@chromium.org870a0b62008-11-04 11:43:05 +00001624void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625 WRITE_FIELD(this, kBufferOffset, buffer);
1626 WRITE_BARRIER(this, kBufferOffset);
1627}
1628
1629
1630int SlicedString::start() {
1631 return READ_INT_FIELD(this, kStartOffset);
1632}
1633
1634
1635void SlicedString::set_start(int start) {
1636 WRITE_INT_FIELD(this, kStartOffset, start);
1637}
1638
1639
1640ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1641 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1642}
1643
1644
1645void ExternalAsciiString::set_resource(
1646 ExternalAsciiString::Resource* resource) {
1647 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1648}
1649
1650
ager@chromium.org6f10e412009-02-13 10:11:16 +00001651Map* ExternalAsciiString::StringMap(int length) {
1652 Map* map;
1653 // Number of characters: determines the map.
1654 if (length <= String::kMaxShortStringSize) {
1655 map = Heap::short_external_ascii_string_map();
1656 } else if (length <= String::kMaxMediumStringSize) {
1657 map = Heap::medium_external_ascii_string_map();
1658 } else {
1659 map = Heap::long_external_ascii_string_map();
1660 }
1661 return map;
1662}
1663
1664
1665Map* ExternalAsciiString::SymbolMap(int length) {
1666 Map* map;
1667 // Number of characters: determines the map.
1668 if (length <= String::kMaxShortStringSize) {
1669 map = Heap::short_external_ascii_symbol_map();
1670 } else if (length <= String::kMaxMediumStringSize) {
1671 map = Heap::medium_external_ascii_symbol_map();
1672 } else {
1673 map = Heap::long_external_ascii_symbol_map();
1674 }
1675 return map;
1676}
1677
1678
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001679ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1680 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1681}
1682
1683
1684void ExternalTwoByteString::set_resource(
1685 ExternalTwoByteString::Resource* resource) {
1686 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1687}
1688
1689
ager@chromium.org6f10e412009-02-13 10:11:16 +00001690Map* ExternalTwoByteString::StringMap(int length) {
1691 Map* map;
1692 // Number of characters: determines the map.
1693 if (length <= String::kMaxShortStringSize) {
1694 map = Heap::short_external_string_map();
1695 } else if (length <= String::kMaxMediumStringSize) {
1696 map = Heap::medium_external_string_map();
1697 } else {
1698 map = Heap::long_external_string_map();
1699 }
1700 return map;
1701}
1702
1703
1704Map* ExternalTwoByteString::SymbolMap(int length) {
1705 Map* map;
1706 // Number of characters: determines the map.
1707 if (length <= String::kMaxShortStringSize) {
1708 map = Heap::short_external_symbol_map();
1709 } else if (length <= String::kMaxMediumStringSize) {
1710 map = Heap::medium_external_symbol_map();
1711 } else {
1712 map = Heap::long_external_symbol_map();
1713 }
1714 return map;
1715}
1716
1717
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001718byte ByteArray::get(int index) {
1719 ASSERT(index >= 0 && index < this->length());
1720 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1721}
1722
1723
1724void ByteArray::set(int index, byte value) {
1725 ASSERT(index >= 0 && index < this->length());
1726 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1727}
1728
1729
1730int ByteArray::get_int(int index) {
1731 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1732 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1733}
1734
1735
1736ByteArray* ByteArray::FromDataStartAddress(Address address) {
1737 ASSERT_TAG_ALIGNED(address);
1738 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1739}
1740
1741
1742Address ByteArray::GetDataStartAddress() {
1743 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1744}
1745
1746
1747int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001748 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1749}
1750
1751
1752int Map::inobject_properties() {
1753 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001754}
1755
1756
1757int HeapObject::SizeFromMap(Map* map) {
1758 InstanceType instance_type = map->instance_type();
1759 // Only inline the two most frequent cases.
1760 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1761 if (instance_type == FIXED_ARRAY_TYPE) {
1762 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1763 }
1764 // Otherwise do the general size computation.
1765 return SlowSizeFromMap(map);
1766}
1767
1768
1769void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001770 ASSERT((value & ~(kPointerSize - 1)) == value);
1771 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001772 ASSERT(0 <= value && value < 256);
1773 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1774}
1775
1776
ager@chromium.org7c537e22008-10-16 08:43:32 +00001777void Map::set_inobject_properties(int value) {
1778 ASSERT(0 <= value && value < 256);
1779 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1780}
1781
1782
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001783InstanceType Map::instance_type() {
1784 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1785}
1786
1787
1788void Map::set_instance_type(InstanceType value) {
1789 ASSERT(0 <= value && value < 256);
1790 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1791}
1792
1793
1794int Map::unused_property_fields() {
1795 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1796}
1797
1798
1799void Map::set_unused_property_fields(int value) {
1800 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1801}
1802
1803
1804byte Map::bit_field() {
1805 return READ_BYTE_FIELD(this, kBitFieldOffset);
1806}
1807
1808
1809void Map::set_bit_field(byte value) {
1810 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1811}
1812
1813
1814void Map::set_non_instance_prototype(bool value) {
1815 if (value) {
1816 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1817 } else {
1818 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1819 }
1820}
1821
1822
1823bool Map::has_non_instance_prototype() {
1824 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1825}
1826
1827
ager@chromium.org870a0b62008-11-04 11:43:05 +00001828void Map::set_is_access_check_needed(bool access_check_needed) {
1829 if (access_check_needed) {
1830 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1831 } else {
1832 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1833 }
1834}
1835
1836
1837bool Map::is_access_check_needed() {
1838 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1839}
1840
1841
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001842Code::Flags Code::flags() {
1843 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1844}
1845
1846
1847void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001848 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001849 // Make sure that all call stubs have an arguments count.
1850 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1851 ExtractArgumentsCountFromFlags(flags) >= 0);
1852 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1853}
1854
1855
1856Code::Kind Code::kind() {
1857 return ExtractKindFromFlags(flags());
1858}
1859
1860
kasper.lund7276f142008-07-30 08:49:36 +00001861InlineCacheState Code::ic_state() {
1862 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001863 // Only allow uninitialized or debugger states for non-IC code
1864 // objects. This is used in the debugger to determine whether or not
1865 // a call to code object has been replaced with a debug break call.
1866 ASSERT(is_inline_cache_stub() ||
1867 result == UNINITIALIZED ||
1868 result == DEBUG_BREAK ||
1869 result == DEBUG_PREPARE_STEP_IN);
1870 return result;
1871}
1872
1873
1874PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001875 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001876 return ExtractTypeFromFlags(flags());
1877}
1878
1879
1880int Code::arguments_count() {
1881 ASSERT(is_call_stub() || kind() == STUB);
1882 return ExtractArgumentsCountFromFlags(flags());
1883}
1884
1885
1886CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001887 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001888 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1889 kStubMajorKeyOffset));
1890}
1891
1892
1893void Code::set_major_key(CodeStub::Major major) {
1894 ASSERT(kind() == STUB);
1895 ASSERT(0 <= major && major < 256);
1896 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001897}
1898
1899
1900bool Code::is_inline_cache_stub() {
1901 Kind kind = this->kind();
1902 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1903}
1904
1905
1906Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001907 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001908 PropertyType type,
1909 int argc) {
1910 // Compute the bit mask.
1911 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001912 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001913 bits |= type << kFlagsTypeShift;
1914 bits |= argc << kFlagsArgumentsCountShift;
1915 // Cast to flags and validate result before returning it.
1916 Flags result = static_cast<Flags>(bits);
1917 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001918 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001919 ASSERT(ExtractTypeFromFlags(result) == type);
1920 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1921 return result;
1922}
1923
1924
1925Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1926 PropertyType type,
1927 int argc) {
1928 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1929}
1930
1931
1932Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1933 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1934 return static_cast<Kind>(bits);
1935}
1936
1937
kasper.lund7276f142008-07-30 08:49:36 +00001938InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1939 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001940 return static_cast<InlineCacheState>(bits);
1941}
1942
1943
1944PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1945 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1946 return static_cast<PropertyType>(bits);
1947}
1948
1949
1950int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1951 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1952}
1953
1954
1955Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1956 int bits = flags & ~kFlagsTypeMask;
1957 return static_cast<Flags>(bits);
1958}
1959
1960
ager@chromium.org8bb60582008-12-11 12:02:20 +00001961Code* Code::GetCodeFromTargetAddress(Address address) {
1962 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1963 // GetCodeFromTargetAddress might be called when marking objects during mark
1964 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1965 // Code::cast. Code::cast does not work when the object's map is
1966 // marked.
1967 Code* result = reinterpret_cast<Code*>(code);
1968 return result;
1969}
1970
1971
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001972Object* Map::prototype() {
1973 return READ_FIELD(this, kPrototypeOffset);
1974}
1975
1976
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001977void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001978 ASSERT(value->IsNull() || value->IsJSObject());
1979 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001980 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001981}
1982
1983
1984ACCESSORS(Map, instance_descriptors, DescriptorArray,
1985 kInstanceDescriptorsOffset)
1986ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1987ACCESSORS(Map, constructor, Object, kConstructorOffset)
1988
1989ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1990ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1991
1992ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1993ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001994ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001996ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001997
1998ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1999ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2000ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2001ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2002ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2003
2004ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2005ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2006ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2007
2008ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2009ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2010ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2011ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2012ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2013ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2014
2015ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2016ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2017
2018ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2019ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2020
2021ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2022ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002023ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2024 kPropertyAccessorsOffset)
2025ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2026 kPrototypeTemplateOffset)
2027ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2028ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2029 kNamedPropertyHandlerOffset)
2030ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2031 kIndexedPropertyHandlerOffset)
2032ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2033 kInstanceTemplateOffset)
2034ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2035ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002036ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2037 kInstanceCallHandlerOffset)
2038ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2039 kAccessCheckInfoOffset)
2040ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2041
2042ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002043ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2044 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002045
2046ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2047ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2048
2049ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2050
2051ACCESSORS(Script, source, Object, kSourceOffset)
2052ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002053ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002054ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2055ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002056ACCESSORS(Script, data, Object, kDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002057ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2058ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002059ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002060
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002061#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002062ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2063ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2064ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2065ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2066
2067ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2068ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2069ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2070ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002071#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002072
2073ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2074ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2075 kInstanceClassNameOffset)
2076ACCESSORS(SharedFunctionInfo, function_data, Object,
2077 kExternalReferenceDataOffset)
2078ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
2079ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2080ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002081ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002082
2083BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2084 kHiddenPrototypeBit)
2085BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2086BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2087 kNeedsAccessCheckBit)
2088BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2089 kIsExpressionBit)
2090BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2091 kIsTopLevelBit)
2092
2093INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2094INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2095 kFormalParameterCountOffset)
2096INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2097 kExpectedNofPropertiesOffset)
2098INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2099 kStartPositionAndTypeOffset)
2100INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2101INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2102 kFunctionTokenPositionOffset)
2103
2104
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002105void SharedFunctionInfo::DontAdaptArguments() {
2106 ASSERT(code()->kind() == Code::BUILTIN);
2107 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2108}
2109
2110
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002111int SharedFunctionInfo::start_position() {
2112 return start_position_and_type() >> kStartPositionShift;
2113}
2114
2115
2116void SharedFunctionInfo::set_start_position(int start_position) {
2117 set_start_position_and_type((start_position << kStartPositionShift)
2118 | (start_position_and_type() & ~kStartPositionMask));
2119}
2120
2121
2122Code* SharedFunctionInfo::code() {
2123 return Code::cast(READ_FIELD(this, kCodeOffset));
2124}
2125
2126
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002127void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002129 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002130}
2131
2132
2133bool SharedFunctionInfo::is_compiled() {
2134 // TODO(1242782): Create a code kind for uncompiled code.
2135 return code()->kind() != Code::STUB;
2136}
2137
2138
2139bool JSFunction::IsBoilerplate() {
2140 return map() == Heap::boilerplate_function_map();
2141}
2142
2143
2144bool JSFunction::IsLoaded() {
2145 return shared()->lazy_load_data() == Heap::undefined_value();
2146}
2147
2148
2149Code* JSFunction::code() {
2150 return shared()->code();
2151}
2152
2153
2154void JSFunction::set_code(Code* value) {
2155 shared()->set_code(value);
2156}
2157
2158
2159Context* JSFunction::context() {
2160 return Context::cast(READ_FIELD(this, kContextOffset));
2161}
2162
2163
2164Object* JSFunction::unchecked_context() {
2165 return READ_FIELD(this, kContextOffset);
2166}
2167
2168
2169void JSFunction::set_context(Object* value) {
2170 ASSERT(value == Heap::undefined_value() || value->IsContext());
2171 WRITE_FIELD(this, kContextOffset, value);
2172 WRITE_BARRIER(this, kContextOffset);
2173}
2174
2175ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2176 kPrototypeOrInitialMapOffset)
2177
2178
2179Map* JSFunction::initial_map() {
2180 return Map::cast(prototype_or_initial_map());
2181}
2182
2183
2184void JSFunction::set_initial_map(Map* value) {
2185 set_prototype_or_initial_map(value);
2186}
2187
2188
2189bool JSFunction::has_initial_map() {
2190 return prototype_or_initial_map()->IsMap();
2191}
2192
2193
2194bool JSFunction::has_instance_prototype() {
2195 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2196}
2197
2198
2199bool JSFunction::has_prototype() {
2200 return map()->has_non_instance_prototype() || has_instance_prototype();
2201}
2202
2203
2204Object* JSFunction::instance_prototype() {
2205 ASSERT(has_instance_prototype());
2206 if (has_initial_map()) return initial_map()->prototype();
2207 // When there is no initial map and the prototype is a JSObject, the
2208 // initial map field is used for the prototype field.
2209 return prototype_or_initial_map();
2210}
2211
2212
2213Object* JSFunction::prototype() {
2214 ASSERT(has_prototype());
2215 // If the function's prototype property has been set to a non-JSObject
2216 // value, that value is stored in the constructor field of the map.
2217 if (map()->has_non_instance_prototype()) return map()->constructor();
2218 return instance_prototype();
2219}
2220
2221
2222bool JSFunction::is_compiled() {
2223 return shared()->is_compiled();
2224}
2225
2226
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002227int JSFunction::NumberOfLiterals() {
2228 return literals()->length();
2229}
2230
2231
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002232Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2233 ASSERT(0 <= id && id < kJSBuiltinsCount);
2234 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2235}
2236
2237
2238void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2239 Object* value) {
2240 ASSERT(0 <= id && id < kJSBuiltinsCount);
2241 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2242 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2243}
2244
2245
2246Address Proxy::proxy() {
2247 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2248}
2249
2250
2251void Proxy::set_proxy(Address value) {
2252 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2253}
2254
2255
2256void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2257 visitor->VisitExternalReference(
2258 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2259}
2260
2261
2262ACCESSORS(JSValue, value, Object, kValueOffset)
2263
2264
2265JSValue* JSValue::cast(Object* obj) {
2266 ASSERT(obj->IsJSValue());
2267 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2268 return reinterpret_cast<JSValue*>(obj);
2269}
2270
2271
2272INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2273INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2274INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2275
2276
2277Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002278 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002279}
2280
2281
2282void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002283 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002284}
2285
2286
2287byte* Code::instruction_start() {
2288 return FIELD_ADDR(this, kHeaderSize);
2289}
2290
2291
2292int Code::body_size() {
2293 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2294}
2295
2296
2297byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002298 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002299}
2300
2301
2302byte* Code::entry() {
2303 return instruction_start();
2304}
2305
2306
2307bool Code::contains(byte* pc) {
2308 return (instruction_start() <= pc) &&
2309 (pc < instruction_start() + instruction_size());
2310}
2311
2312
2313byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002314 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002315}
2316
2317
2318ACCESSORS(JSArray, length, Object, kLengthOffset)
2319
2320
ager@chromium.org236ad962008-09-25 09:45:57 +00002321ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002322
2323
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002324JSRegExp::Type JSRegExp::TypeTag() {
2325 Object* data = this->data();
2326 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2327 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2328 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002329}
2330
2331
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002332int JSRegExp::CaptureCount() {
2333 switch (TypeTag()) {
2334 case ATOM:
2335 return 0;
2336 case IRREGEXP:
2337 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2338 default:
2339 UNREACHABLE();
2340 return -1;
2341 }
2342}
2343
2344
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002345JSRegExp::Flags JSRegExp::GetFlags() {
2346 ASSERT(this->data()->IsFixedArray());
2347 Object* data = this->data();
2348 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2349 return Flags(smi->value());
2350}
2351
2352
2353String* JSRegExp::Pattern() {
2354 ASSERT(this->data()->IsFixedArray());
2355 Object* data = this->data();
2356 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2357 return pattern;
2358}
2359
2360
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002361Object* JSRegExp::DataAt(int index) {
2362 ASSERT(TypeTag() != NOT_COMPILED);
2363 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002364}
2365
2366
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002367void JSRegExp::SetDataAt(int index, Object* value) {
2368 ASSERT(TypeTag() != NOT_COMPILED);
2369 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2370 FixedArray::cast(data())->set(index, value);
2371}
2372
2373
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002374bool JSObject::HasFastElements() {
2375 return !elements()->IsDictionary();
2376}
2377
2378
2379bool JSObject::HasNamedInterceptor() {
2380 return map()->has_named_interceptor();
2381}
2382
2383
2384bool JSObject::HasIndexedInterceptor() {
2385 return map()->has_indexed_interceptor();
2386}
2387
2388
2389Dictionary* JSObject::property_dictionary() {
2390 ASSERT(!HasFastProperties());
2391 return Dictionary::cast(properties());
2392}
2393
2394
2395Dictionary* JSObject::element_dictionary() {
2396 ASSERT(!HasFastElements());
2397 return Dictionary::cast(elements());
2398}
2399
2400
2401bool String::HasHashCode() {
2402 return (length_field() & kHashComputedMask) != 0;
2403}
2404
2405
2406uint32_t String::Hash() {
2407 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002408 uint32_t field = length_field();
2409 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002410 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002411 return ComputeAndSetHash();
2412}
2413
2414
ager@chromium.org7c537e22008-10-16 08:43:32 +00002415StringHasher::StringHasher(int length)
2416 : length_(length),
2417 raw_running_hash_(0),
2418 array_index_(0),
2419 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2420 is_first_char_(true),
2421 is_valid_(true) { }
2422
2423
2424bool StringHasher::has_trivial_hash() {
2425 return length_ > String::kMaxMediumStringSize;
2426}
2427
2428
2429void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002430 // Use the Jenkins one-at-a-time hash function to update the hash
2431 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002432 raw_running_hash_ += c;
2433 raw_running_hash_ += (raw_running_hash_ << 10);
2434 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002435 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002436 if (is_array_index_) {
2437 if (c < '0' || c > '9') {
2438 is_array_index_ = false;
2439 } else {
2440 int d = c - '0';
2441 if (is_first_char_) {
2442 is_first_char_ = false;
2443 if (c == '0' && length_ > 1) {
2444 is_array_index_ = false;
2445 return;
2446 }
2447 }
2448 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2449 is_array_index_ = false;
2450 } else {
2451 array_index_ = array_index_ * 10 + d;
2452 }
2453 }
2454 }
2455}
2456
2457
2458void StringHasher::AddCharacterNoIndex(uc32 c) {
2459 ASSERT(!is_array_index());
2460 raw_running_hash_ += c;
2461 raw_running_hash_ += (raw_running_hash_ << 10);
2462 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2463}
2464
2465
2466uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002467 // Get the calculated raw hash value and do some more bit ops to distribute
2468 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002469 uint32_t result = raw_running_hash_;
2470 result += (result << 3);
2471 result ^= (result >> 11);
2472 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002473 if (result == 0) {
2474 result = 27;
2475 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002476 return result;
2477}
2478
2479
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002480bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002481 uint32_t field = length_field();
2482 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002483 return SlowAsArrayIndex(index);
2484}
2485
2486
2487Object* JSObject::GetPrototype() {
2488 return JSObject::cast(this)->map()->prototype();
2489}
2490
2491
2492PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2493 return GetPropertyAttributeWithReceiver(this, key);
2494}
2495
2496
2497bool JSObject::HasElement(uint32_t index) {
2498 return HasElementWithReceiver(this, index);
2499}
2500
2501
2502bool AccessorInfo::all_can_read() {
2503 return BooleanBit::get(flag(), kAllCanReadBit);
2504}
2505
2506
2507void AccessorInfo::set_all_can_read(bool value) {
2508 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2509}
2510
2511
2512bool AccessorInfo::all_can_write() {
2513 return BooleanBit::get(flag(), kAllCanWriteBit);
2514}
2515
2516
2517void AccessorInfo::set_all_can_write(bool value) {
2518 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2519}
2520
2521
ager@chromium.org870a0b62008-11-04 11:43:05 +00002522bool AccessorInfo::prohibits_overwriting() {
2523 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2524}
2525
2526
2527void AccessorInfo::set_prohibits_overwriting(bool value) {
2528 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2529}
2530
2531
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002532PropertyAttributes AccessorInfo::property_attributes() {
2533 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2534}
2535
2536
2537void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2538 ASSERT(AttributesField::is_valid(attributes));
2539 int rest_value = flag()->value() & ~AttributesField::mask();
2540 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2541}
2542
2543void Dictionary::SetEntry(int entry,
2544 Object* key,
2545 Object* value,
2546 PropertyDetails details) {
2547 ASSERT(!key->IsString() || details.index() > 0);
2548 int index = EntryToIndex(entry);
2549 WriteBarrierMode mode = GetWriteBarrierMode();
2550 set(index, key, mode);
2551 set(index+1, value, mode);
2552 fast_set(this, index+2, details.AsSmi());
2553}
2554
2555
2556void Map::ClearCodeCache() {
2557 // No write barrier is needed since empty_fixed_array is not in new space.
2558 // Please note this function is used during marking:
2559 // - MarkCompactCollector::MarkUnmarkedObject
2560 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2561 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2562}
2563
2564
ager@chromium.org7c537e22008-10-16 08:43:32 +00002565void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002566 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002567 set_elements(storage);
2568}
2569
2570
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002571Object* FixedArray::Copy() {
2572 if (length() == 0) return this;
2573 return Heap::CopyFixedArray(this);
2574}
2575
2576
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002577#undef CAST_ACCESSOR
2578#undef INT_ACCESSORS
2579#undef SMI_ACCESSORS
2580#undef ACCESSORS
2581#undef FIELD_ADDR
2582#undef READ_FIELD
2583#undef WRITE_FIELD
2584#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002585#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002586#undef READ_MEMADDR_FIELD
2587#undef WRITE_MEMADDR_FIELD
2588#undef READ_DOUBLE_FIELD
2589#undef WRITE_DOUBLE_FIELD
2590#undef READ_INT_FIELD
2591#undef WRITE_INT_FIELD
2592#undef READ_SHORT_FIELD
2593#undef WRITE_SHORT_FIELD
2594#undef READ_BYTE_FIELD
2595#undef WRITE_BYTE_FIELD
2596
2597
2598} } // namespace v8::internal
2599
2600#endif // V8_OBJECTS_INL_H_