blob: ff64d65084d3d1d3c7e7e4d29b349aae5afdd542 [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
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001814byte Map::bit_field2() {
1815 return READ_BYTE_FIELD(this, kBitField2Offset);
1816}
1817
1818
1819void Map::set_bit_field2(byte value) {
1820 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1821}
1822
1823
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001824void Map::set_non_instance_prototype(bool value) {
1825 if (value) {
1826 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1827 } else {
1828 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1829 }
1830}
1831
1832
1833bool Map::has_non_instance_prototype() {
1834 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1835}
1836
1837
ager@chromium.org870a0b62008-11-04 11:43:05 +00001838void Map::set_is_access_check_needed(bool access_check_needed) {
1839 if (access_check_needed) {
1840 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1841 } else {
1842 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1843 }
1844}
1845
1846
1847bool Map::is_access_check_needed() {
1848 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1849}
1850
1851
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001852Code::Flags Code::flags() {
1853 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1854}
1855
1856
1857void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001858 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001859 // Make sure that all call stubs have an arguments count.
1860 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1861 ExtractArgumentsCountFromFlags(flags) >= 0);
1862 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1863}
1864
1865
1866Code::Kind Code::kind() {
1867 return ExtractKindFromFlags(flags());
1868}
1869
1870
kasper.lund7276f142008-07-30 08:49:36 +00001871InlineCacheState Code::ic_state() {
1872 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001873 // Only allow uninitialized or debugger states for non-IC code
1874 // objects. This is used in the debugger to determine whether or not
1875 // a call to code object has been replaced with a debug break call.
1876 ASSERT(is_inline_cache_stub() ||
1877 result == UNINITIALIZED ||
1878 result == DEBUG_BREAK ||
1879 result == DEBUG_PREPARE_STEP_IN);
1880 return result;
1881}
1882
1883
1884PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001885 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001886 return ExtractTypeFromFlags(flags());
1887}
1888
1889
1890int Code::arguments_count() {
1891 ASSERT(is_call_stub() || kind() == STUB);
1892 return ExtractArgumentsCountFromFlags(flags());
1893}
1894
1895
1896CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001897 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001898 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1899 kStubMajorKeyOffset));
1900}
1901
1902
1903void Code::set_major_key(CodeStub::Major major) {
1904 ASSERT(kind() == STUB);
1905 ASSERT(0 <= major && major < 256);
1906 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001907}
1908
1909
1910bool Code::is_inline_cache_stub() {
1911 Kind kind = this->kind();
1912 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1913}
1914
1915
1916Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001917 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001918 PropertyType type,
1919 int argc) {
1920 // Compute the bit mask.
1921 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001922 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001923 bits |= type << kFlagsTypeShift;
1924 bits |= argc << kFlagsArgumentsCountShift;
1925 // Cast to flags and validate result before returning it.
1926 Flags result = static_cast<Flags>(bits);
1927 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001928 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001929 ASSERT(ExtractTypeFromFlags(result) == type);
1930 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1931 return result;
1932}
1933
1934
1935Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1936 PropertyType type,
1937 int argc) {
1938 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1939}
1940
1941
1942Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1943 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1944 return static_cast<Kind>(bits);
1945}
1946
1947
kasper.lund7276f142008-07-30 08:49:36 +00001948InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1949 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001950 return static_cast<InlineCacheState>(bits);
1951}
1952
1953
1954PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1955 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1956 return static_cast<PropertyType>(bits);
1957}
1958
1959
1960int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1961 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1962}
1963
1964
1965Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1966 int bits = flags & ~kFlagsTypeMask;
1967 return static_cast<Flags>(bits);
1968}
1969
1970
ager@chromium.org8bb60582008-12-11 12:02:20 +00001971Code* Code::GetCodeFromTargetAddress(Address address) {
1972 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
1973 // GetCodeFromTargetAddress might be called when marking objects during mark
1974 // sweep. reinterpret_cast is therefore used instead of the more appropriate
1975 // Code::cast. Code::cast does not work when the object's map is
1976 // marked.
1977 Code* result = reinterpret_cast<Code*>(code);
1978 return result;
1979}
1980
1981
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001982Object* Map::prototype() {
1983 return READ_FIELD(this, kPrototypeOffset);
1984}
1985
1986
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001987void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001988 ASSERT(value->IsNull() || value->IsJSObject());
1989 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001990 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001991}
1992
1993
1994ACCESSORS(Map, instance_descriptors, DescriptorArray,
1995 kInstanceDescriptorsOffset)
1996ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1997ACCESSORS(Map, constructor, Object, kConstructorOffset)
1998
1999ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2000ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2001
2002ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2003ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002004ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002005
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002006ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002007
2008ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2009ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2010ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2011ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2012ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2013
2014ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2015ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2016ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2017
2018ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2019ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2020ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2021ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2022ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2023ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2024
2025ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2026ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2027
2028ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2029ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2030
2031ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2032ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002033ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2034 kPropertyAccessorsOffset)
2035ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2036 kPrototypeTemplateOffset)
2037ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2038ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2039 kNamedPropertyHandlerOffset)
2040ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2041 kIndexedPropertyHandlerOffset)
2042ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2043 kInstanceTemplateOffset)
2044ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2045ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002046ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2047 kInstanceCallHandlerOffset)
2048ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2049 kAccessCheckInfoOffset)
2050ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2051
2052ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002053ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2054 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002055
2056ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2057ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2058
2059ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2060
2061ACCESSORS(Script, source, Object, kSourceOffset)
2062ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002063ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002064ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2065ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002066ACCESSORS(Script, data, Object, kDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002067ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2068ACCESSORS(Script, type, Smi, kTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002069ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002070
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002071#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002072ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2073ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2074ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2075ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2076
2077ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2078ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2079ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2080ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002081#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002082
2083ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2084ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2085 kInstanceClassNameOffset)
2086ACCESSORS(SharedFunctionInfo, function_data, Object,
2087 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002088ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2089ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002090ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091
2092BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2093 kHiddenPrototypeBit)
2094BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2095BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2096 kNeedsAccessCheckBit)
2097BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2098 kIsExpressionBit)
2099BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2100 kIsTopLevelBit)
2101
2102INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2103INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2104 kFormalParameterCountOffset)
2105INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2106 kExpectedNofPropertiesOffset)
2107INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2108 kStartPositionAndTypeOffset)
2109INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2110INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2111 kFunctionTokenPositionOffset)
2112
2113
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002114void SharedFunctionInfo::DontAdaptArguments() {
2115 ASSERT(code()->kind() == Code::BUILTIN);
2116 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2117}
2118
2119
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002120int SharedFunctionInfo::start_position() {
2121 return start_position_and_type() >> kStartPositionShift;
2122}
2123
2124
2125void SharedFunctionInfo::set_start_position(int start_position) {
2126 set_start_position_and_type((start_position << kStartPositionShift)
2127 | (start_position_and_type() & ~kStartPositionMask));
2128}
2129
2130
2131Code* SharedFunctionInfo::code() {
2132 return Code::cast(READ_FIELD(this, kCodeOffset));
2133}
2134
2135
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002136void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002137 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002138 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002139}
2140
2141
2142bool SharedFunctionInfo::is_compiled() {
2143 // TODO(1242782): Create a code kind for uncompiled code.
2144 return code()->kind() != Code::STUB;
2145}
2146
2147
2148bool JSFunction::IsBoilerplate() {
2149 return map() == Heap::boilerplate_function_map();
2150}
2151
2152
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002153bool JSObject::IsLoaded() {
2154 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002155}
2156
2157
2158Code* JSFunction::code() {
2159 return shared()->code();
2160}
2161
2162
2163void JSFunction::set_code(Code* value) {
2164 shared()->set_code(value);
2165}
2166
2167
2168Context* JSFunction::context() {
2169 return Context::cast(READ_FIELD(this, kContextOffset));
2170}
2171
2172
2173Object* JSFunction::unchecked_context() {
2174 return READ_FIELD(this, kContextOffset);
2175}
2176
2177
2178void JSFunction::set_context(Object* value) {
2179 ASSERT(value == Heap::undefined_value() || value->IsContext());
2180 WRITE_FIELD(this, kContextOffset, value);
2181 WRITE_BARRIER(this, kContextOffset);
2182}
2183
2184ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2185 kPrototypeOrInitialMapOffset)
2186
2187
2188Map* JSFunction::initial_map() {
2189 return Map::cast(prototype_or_initial_map());
2190}
2191
2192
2193void JSFunction::set_initial_map(Map* value) {
2194 set_prototype_or_initial_map(value);
2195}
2196
2197
2198bool JSFunction::has_initial_map() {
2199 return prototype_or_initial_map()->IsMap();
2200}
2201
2202
2203bool JSFunction::has_instance_prototype() {
2204 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2205}
2206
2207
2208bool JSFunction::has_prototype() {
2209 return map()->has_non_instance_prototype() || has_instance_prototype();
2210}
2211
2212
2213Object* JSFunction::instance_prototype() {
2214 ASSERT(has_instance_prototype());
2215 if (has_initial_map()) return initial_map()->prototype();
2216 // When there is no initial map and the prototype is a JSObject, the
2217 // initial map field is used for the prototype field.
2218 return prototype_or_initial_map();
2219}
2220
2221
2222Object* JSFunction::prototype() {
2223 ASSERT(has_prototype());
2224 // If the function's prototype property has been set to a non-JSObject
2225 // value, that value is stored in the constructor field of the map.
2226 if (map()->has_non_instance_prototype()) return map()->constructor();
2227 return instance_prototype();
2228}
2229
2230
2231bool JSFunction::is_compiled() {
2232 return shared()->is_compiled();
2233}
2234
2235
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002236int JSFunction::NumberOfLiterals() {
2237 return literals()->length();
2238}
2239
2240
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002241Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2242 ASSERT(0 <= id && id < kJSBuiltinsCount);
2243 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2244}
2245
2246
2247void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2248 Object* value) {
2249 ASSERT(0 <= id && id < kJSBuiltinsCount);
2250 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2251 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2252}
2253
2254
2255Address Proxy::proxy() {
2256 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2257}
2258
2259
2260void Proxy::set_proxy(Address value) {
2261 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2262}
2263
2264
2265void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2266 visitor->VisitExternalReference(
2267 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2268}
2269
2270
2271ACCESSORS(JSValue, value, Object, kValueOffset)
2272
2273
2274JSValue* JSValue::cast(Object* obj) {
2275 ASSERT(obj->IsJSValue());
2276 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2277 return reinterpret_cast<JSValue*>(obj);
2278}
2279
2280
2281INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2282INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2283INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2284
2285
2286Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002287 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002288}
2289
2290
2291void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002292 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002293}
2294
2295
2296byte* Code::instruction_start() {
2297 return FIELD_ADDR(this, kHeaderSize);
2298}
2299
2300
2301int Code::body_size() {
2302 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2303}
2304
2305
2306byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002307 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002308}
2309
2310
2311byte* Code::entry() {
2312 return instruction_start();
2313}
2314
2315
2316bool Code::contains(byte* pc) {
2317 return (instruction_start() <= pc) &&
2318 (pc < instruction_start() + instruction_size());
2319}
2320
2321
2322byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002323 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002324}
2325
2326
2327ACCESSORS(JSArray, length, Object, kLengthOffset)
2328
2329
ager@chromium.org236ad962008-09-25 09:45:57 +00002330ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002331
2332
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002333JSRegExp::Type JSRegExp::TypeTag() {
2334 Object* data = this->data();
2335 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2336 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2337 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002338}
2339
2340
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002341int JSRegExp::CaptureCount() {
2342 switch (TypeTag()) {
2343 case ATOM:
2344 return 0;
2345 case IRREGEXP:
2346 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2347 default:
2348 UNREACHABLE();
2349 return -1;
2350 }
2351}
2352
2353
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002354JSRegExp::Flags JSRegExp::GetFlags() {
2355 ASSERT(this->data()->IsFixedArray());
2356 Object* data = this->data();
2357 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2358 return Flags(smi->value());
2359}
2360
2361
2362String* JSRegExp::Pattern() {
2363 ASSERT(this->data()->IsFixedArray());
2364 Object* data = this->data();
2365 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2366 return pattern;
2367}
2368
2369
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002370Object* JSRegExp::DataAt(int index) {
2371 ASSERT(TypeTag() != NOT_COMPILED);
2372 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002373}
2374
2375
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002376void JSRegExp::SetDataAt(int index, Object* value) {
2377 ASSERT(TypeTag() != NOT_COMPILED);
2378 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2379 FixedArray::cast(data())->set(index, value);
2380}
2381
2382
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002383bool JSObject::HasFastElements() {
2384 return !elements()->IsDictionary();
2385}
2386
2387
2388bool JSObject::HasNamedInterceptor() {
2389 return map()->has_named_interceptor();
2390}
2391
2392
2393bool JSObject::HasIndexedInterceptor() {
2394 return map()->has_indexed_interceptor();
2395}
2396
2397
2398Dictionary* JSObject::property_dictionary() {
2399 ASSERT(!HasFastProperties());
2400 return Dictionary::cast(properties());
2401}
2402
2403
2404Dictionary* JSObject::element_dictionary() {
2405 ASSERT(!HasFastElements());
2406 return Dictionary::cast(elements());
2407}
2408
2409
2410bool String::HasHashCode() {
2411 return (length_field() & kHashComputedMask) != 0;
2412}
2413
2414
2415uint32_t String::Hash() {
2416 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002417 uint32_t field = length_field();
2418 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002419 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002420 return ComputeAndSetHash();
2421}
2422
2423
ager@chromium.org7c537e22008-10-16 08:43:32 +00002424StringHasher::StringHasher(int length)
2425 : length_(length),
2426 raw_running_hash_(0),
2427 array_index_(0),
2428 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2429 is_first_char_(true),
2430 is_valid_(true) { }
2431
2432
2433bool StringHasher::has_trivial_hash() {
2434 return length_ > String::kMaxMediumStringSize;
2435}
2436
2437
2438void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002439 // Use the Jenkins one-at-a-time hash function to update the hash
2440 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002441 raw_running_hash_ += c;
2442 raw_running_hash_ += (raw_running_hash_ << 10);
2443 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002444 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002445 if (is_array_index_) {
2446 if (c < '0' || c > '9') {
2447 is_array_index_ = false;
2448 } else {
2449 int d = c - '0';
2450 if (is_first_char_) {
2451 is_first_char_ = false;
2452 if (c == '0' && length_ > 1) {
2453 is_array_index_ = false;
2454 return;
2455 }
2456 }
2457 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2458 is_array_index_ = false;
2459 } else {
2460 array_index_ = array_index_ * 10 + d;
2461 }
2462 }
2463 }
2464}
2465
2466
2467void StringHasher::AddCharacterNoIndex(uc32 c) {
2468 ASSERT(!is_array_index());
2469 raw_running_hash_ += c;
2470 raw_running_hash_ += (raw_running_hash_ << 10);
2471 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2472}
2473
2474
2475uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002476 // Get the calculated raw hash value and do some more bit ops to distribute
2477 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002478 uint32_t result = raw_running_hash_;
2479 result += (result << 3);
2480 result ^= (result >> 11);
2481 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002482 if (result == 0) {
2483 result = 27;
2484 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002485 return result;
2486}
2487
2488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002489bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002490 uint32_t field = length_field();
2491 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002492 return SlowAsArrayIndex(index);
2493}
2494
2495
2496Object* JSObject::GetPrototype() {
2497 return JSObject::cast(this)->map()->prototype();
2498}
2499
2500
2501PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2502 return GetPropertyAttributeWithReceiver(this, key);
2503}
2504
2505
2506bool JSObject::HasElement(uint32_t index) {
2507 return HasElementWithReceiver(this, index);
2508}
2509
2510
2511bool AccessorInfo::all_can_read() {
2512 return BooleanBit::get(flag(), kAllCanReadBit);
2513}
2514
2515
2516void AccessorInfo::set_all_can_read(bool value) {
2517 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2518}
2519
2520
2521bool AccessorInfo::all_can_write() {
2522 return BooleanBit::get(flag(), kAllCanWriteBit);
2523}
2524
2525
2526void AccessorInfo::set_all_can_write(bool value) {
2527 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2528}
2529
2530
ager@chromium.org870a0b62008-11-04 11:43:05 +00002531bool AccessorInfo::prohibits_overwriting() {
2532 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2533}
2534
2535
2536void AccessorInfo::set_prohibits_overwriting(bool value) {
2537 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2538}
2539
2540
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002541PropertyAttributes AccessorInfo::property_attributes() {
2542 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2543}
2544
2545
2546void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2547 ASSERT(AttributesField::is_valid(attributes));
2548 int rest_value = flag()->value() & ~AttributesField::mask();
2549 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2550}
2551
2552void Dictionary::SetEntry(int entry,
2553 Object* key,
2554 Object* value,
2555 PropertyDetails details) {
2556 ASSERT(!key->IsString() || details.index() > 0);
2557 int index = EntryToIndex(entry);
2558 WriteBarrierMode mode = GetWriteBarrierMode();
2559 set(index, key, mode);
2560 set(index+1, value, mode);
2561 fast_set(this, index+2, details.AsSmi());
2562}
2563
2564
2565void Map::ClearCodeCache() {
2566 // No write barrier is needed since empty_fixed_array is not in new space.
2567 // Please note this function is used during marking:
2568 // - MarkCompactCollector::MarkUnmarkedObject
2569 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2570 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2571}
2572
2573
ager@chromium.org7c537e22008-10-16 08:43:32 +00002574void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002575 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002576 set_elements(storage);
2577}
2578
2579
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002580Object* FixedArray::Copy() {
2581 if (length() == 0) return this;
2582 return Heap::CopyFixedArray(this);
2583}
2584
2585
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002586#undef CAST_ACCESSOR
2587#undef INT_ACCESSORS
2588#undef SMI_ACCESSORS
2589#undef ACCESSORS
2590#undef FIELD_ADDR
2591#undef READ_FIELD
2592#undef WRITE_FIELD
2593#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002594#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002595#undef READ_MEMADDR_FIELD
2596#undef WRITE_MEMADDR_FIELD
2597#undef READ_DOUBLE_FIELD
2598#undef WRITE_DOUBLE_FIELD
2599#undef READ_INT_FIELD
2600#undef WRITE_INT_FIELD
2601#undef READ_SHORT_FIELD
2602#undef WRITE_SHORT_FIELD
2603#undef READ_BYTE_FIELD
2604#undef WRITE_BYTE_FIELD
2605
2606
2607} } // namespace v8::internal
2608
2609#endif // V8_OBJECTS_INL_H_