blob: a3bd3ce1ca6360626e6d2f4839eb552214238c05 [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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48}
49
50
51Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53}
54
55
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000056PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60}
61
62
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063#define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70#define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75#define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000077 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000079 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 }
81
82
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000083
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084#define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
94#define BOOL_ACCESSORS(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98 void holder::set_##name(bool value) { \
99 set_##field(BooleanBit::set(field(), offset, value)); \
100 }
101
102
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000103bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
104 // There is a constraint on the object; check.
105 if (!this->IsJSObject()) return false;
106 // Fetch the constructor function of the object.
107 Object* cons_obj = JSObject::cast(this)->map()->constructor();
108 if (!cons_obj->IsJSFunction()) return false;
109 JSFunction* fun = JSFunction::cast(cons_obj);
110 // Iterate through the chain of inheriting function templates to
111 // see if the required one occurs.
112 for (Object* type = fun->shared()->function_data();
113 type->IsFunctionTemplateInfo();
114 type = FunctionTemplateInfo::cast(type)->parent_template()) {
115 if (type == expected) return true;
116 }
117 // Didn't find the required type in the inheritance chain.
118 return false;
119}
120
121
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122bool Object::IsSmi() {
123 return HAS_SMI_TAG(this);
124}
125
126
127bool Object::IsHeapObject() {
128 return HAS_HEAP_OBJECT_TAG(this);
129}
130
131
132bool Object::IsHeapNumber() {
133 return Object::IsHeapObject()
134 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
135}
136
137
138bool Object::IsString() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
141}
142
143
ager@chromium.org870a0b62008-11-04 11:43:05 +0000144bool Object::IsSymbol() {
145 if (!this->IsHeapObject()) return false;
146 uint32_t type = HeapObject::cast(this)->map()->instance_type();
147 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
148 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149}
150
151
152bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000153 if (!this->IsHeapObject()) return false;
154 uint32_t type = HeapObject::cast(this)->map()->instance_type();
155 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
156 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157}
158
159
ager@chromium.org870a0b62008-11-04 11:43:05 +0000160#ifdef DEBUG
161// These are for cast checks. If you need one of these in release
162// mode you should consider using a StringShape before moving it out
163// of the ifdef
164
165bool Object::IsSeqString() {
166 if (!IsString()) return false;
167 return StringShape(String::cast(this)).IsSequential();
168}
169
170
171bool Object::IsSeqAsciiString() {
172 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000173 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000174 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000175}
176
177
178bool Object::IsSeqTwoByteString() {
179 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000180 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000181 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182}
183
184
185bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000186 if (!IsString()) return false;
187 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188}
189
190
191bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000192 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000193 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000194 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195}
196
197
198bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000199 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000200 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000201 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202}
203
204
ager@chromium.org870a0b62008-11-04 11:43:05 +0000205bool Object::IsSlicedString() {
206 if (!IsString()) return false;
207 return StringShape(String::cast(this)).IsSliced();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208}
209
210
ager@chromium.org870a0b62008-11-04 11:43:05 +0000211#endif // DEBUG
212
213
214StringShape::StringShape(String* str)
215 : type_(str->map()->instance_type()) {
216 set_valid();
217 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218}
219
220
ager@chromium.org870a0b62008-11-04 11:43:05 +0000221StringShape::StringShape(Map* map)
222 : type_(map->instance_type()) {
223 set_valid();
224 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000225}
226
227
ager@chromium.org870a0b62008-11-04 11:43:05 +0000228StringShape::StringShape(InstanceType t)
229 : type_(static_cast<uint32_t>(t)) {
230 set_valid();
231 ASSERT((type_ & kIsNotStringMask) == kStringTag);
232}
233
234
235bool StringShape::IsSymbol() {
236 ASSERT(valid());
237 return (type_ & kIsSymbolMask) == kSymbolTag;
238}
239
240
ager@chromium.org5ec48922009-05-05 07:25:34 +0000241bool String::IsAsciiRepresentation() {
242 uint32_t type = map()->instance_type();
243 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
244 return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
245 }
246 if ((type & kStringRepresentationMask) == kConsStringTag &&
247 ConsString::cast(this)->second()->length() == 0) {
248 return ConsString::cast(this)->first()->IsAsciiRepresentation();
249 }
250 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000251}
252
253
ager@chromium.org5ec48922009-05-05 07:25:34 +0000254bool String::IsTwoByteRepresentation() {
255 uint32_t type = map()->instance_type();
256 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
257 return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
258 } else if ((type & kStringRepresentationMask) == kConsStringTag &&
259 ConsString::cast(this)->second()->length() == 0) {
260 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
261 }
262 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000263}
264
265
266bool StringShape::IsCons() {
267 return (type_ & kStringRepresentationMask) == kConsStringTag;
268}
269
270
271bool StringShape::IsSliced() {
272 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
273}
274
275
276bool StringShape::IsExternal() {
277 return (type_ & kStringRepresentationMask) == kExternalStringTag;
278}
279
280
281bool StringShape::IsSequential() {
282 return (type_ & kStringRepresentationMask) == kSeqStringTag;
283}
284
285
286StringRepresentationTag StringShape::representation_tag() {
287 uint32_t tag = (type_ & kStringRepresentationMask);
288 return static_cast<StringRepresentationTag>(tag);
289}
290
291
292uint32_t StringShape::full_representation_tag() {
293 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
294}
295
296
297uint32_t StringShape::size_tag() {
298 return (type_ & kStringSizeMask);
299}
300
301
302bool StringShape::IsSequentialAscii() {
303 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
304}
305
306
307bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000308 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000309}
310
311
312bool StringShape::IsExternalAscii() {
313 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
314}
315
316
317bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000318 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000319}
320
321
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000322uc32 FlatStringReader::Get(int index) {
323 ASSERT(0 <= index && index <= length_);
324 if (is_ascii_) {
325 return static_cast<const byte*>(start_)[index];
326 } else {
327 return static_cast<const uc16*>(start_)[index];
328 }
329}
330
331
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332bool Object::IsNumber() {
333 return IsSmi() || IsHeapNumber();
334}
335
336
337bool Object::IsByteArray() {
338 return Object::IsHeapObject()
339 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
340}
341
342
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000343bool Object::IsPixelArray() {
344 return Object::IsHeapObject() &&
345 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
346}
347
348
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349bool Object::IsFailure() {
350 return HAS_FAILURE_TAG(this);
351}
352
353
354bool Object::IsRetryAfterGC() {
355 return HAS_FAILURE_TAG(this)
356 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
357}
358
359
ager@chromium.org7c537e22008-10-16 08:43:32 +0000360bool Object::IsOutOfMemoryFailure() {
361 return HAS_FAILURE_TAG(this)
362 && Failure::cast(this)->IsOutOfMemoryException();
363}
364
365
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000366bool Object::IsException() {
367 return this == Failure::Exception();
368}
369
370
371bool Object::IsJSObject() {
372 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000373 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000374}
375
376
ager@chromium.org32912102009-01-16 10:38:43 +0000377bool Object::IsJSContextExtensionObject() {
378 return IsHeapObject()
379 && (HeapObject::cast(this)->map()->instance_type() ==
380 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
381}
382
383
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384bool Object::IsMap() {
385 return Object::IsHeapObject()
386 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
387}
388
389
390bool Object::IsFixedArray() {
391 return Object::IsHeapObject()
392 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
393}
394
395
396bool Object::IsDescriptorArray() {
397 return IsFixedArray();
398}
399
400
401bool Object::IsContext() {
402 return Object::IsHeapObject()
403 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000404 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000405 HeapObject::cast(this)->map() == Heap::global_context_map());
406}
407
408
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000409bool Object::IsCatchContext() {
410 return Object::IsHeapObject()
411 && HeapObject::cast(this)->map() == Heap::catch_context_map();
412}
413
414
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415bool Object::IsGlobalContext() {
416 return Object::IsHeapObject()
417 && HeapObject::cast(this)->map() == Heap::global_context_map();
418}
419
420
421bool Object::IsJSFunction() {
422 return Object::IsHeapObject()
423 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
424}
425
426
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000427template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000428 return obj->IsJSFunction();
429}
430
431
432bool Object::IsCode() {
433 return Object::IsHeapObject()
434 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
435}
436
437
438bool Object::IsOddball() {
439 return Object::IsHeapObject()
440 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
441}
442
443
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000444bool Object::IsJSGlobalPropertyCell() {
445 return Object::IsHeapObject()
446 && HeapObject::cast(this)->map()->instance_type()
447 == JS_GLOBAL_PROPERTY_CELL_TYPE;
448}
449
450
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451bool Object::IsSharedFunctionInfo() {
452 return Object::IsHeapObject() &&
453 (HeapObject::cast(this)->map()->instance_type() ==
454 SHARED_FUNCTION_INFO_TYPE);
455}
456
457
458bool Object::IsJSValue() {
459 return Object::IsHeapObject()
460 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
461}
462
463
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000464bool Object::IsStringWrapper() {
465 return IsJSValue() && JSValue::cast(this)->value()->IsString();
466}
467
468
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469bool Object::IsProxy() {
470 return Object::IsHeapObject()
471 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
472}
473
474
475bool Object::IsBoolean() {
476 return IsTrue() || IsFalse();
477}
478
479
480bool Object::IsJSArray() {
481 return Object::IsHeapObject()
482 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
483}
484
485
ager@chromium.org236ad962008-09-25 09:45:57 +0000486bool Object::IsJSRegExp() {
487 return Object::IsHeapObject()
488 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
489}
490
491
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000492template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493 return obj->IsJSArray();
494}
495
496
497bool Object::IsHashTable() {
498 return Object::IsHeapObject()
499 && HeapObject::cast(this)->map() == Heap::hash_table_map();
500}
501
502
503bool Object::IsDictionary() {
504 return IsHashTable() && this != Heap::symbol_table();
505}
506
507
508bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000509 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510}
511
512
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000513bool Object::IsCompilationCacheTable() {
514 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000515}
516
517
ager@chromium.org236ad962008-09-25 09:45:57 +0000518bool Object::IsMapCache() {
519 return IsHashTable();
520}
521
522
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000523bool Object::IsPrimitive() {
524 return IsOddball() || IsNumber() || IsString();
525}
526
527
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000528bool Object::IsJSGlobalProxy() {
529 bool result = IsHeapObject() &&
530 (HeapObject::cast(this)->map()->instance_type() ==
531 JS_GLOBAL_PROXY_TYPE);
532 ASSERT(!result || IsAccessCheckNeeded());
533 return result;
534}
535
536
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000538 if (!IsHeapObject()) return false;
539
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000540 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000541 return type == JS_GLOBAL_OBJECT_TYPE ||
542 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543}
544
545
546bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000547 return IsHeapObject() &&
548 (HeapObject::cast(this)->map()->instance_type() ==
549 JS_GLOBAL_OBJECT_TYPE);
550}
551
552
553bool Object::IsJSBuiltinsObject() {
554 return IsHeapObject() &&
555 (HeapObject::cast(this)->map()->instance_type() ==
556 JS_BUILTINS_OBJECT_TYPE);
557}
558
559
560bool Object::IsUndetectableObject() {
561 return IsHeapObject()
562 && HeapObject::cast(this)->map()->is_undetectable();
563}
564
565
566bool Object::IsAccessCheckNeeded() {
567 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000568 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000569}
570
571
572bool Object::IsStruct() {
573 if (!IsHeapObject()) return false;
574 switch (HeapObject::cast(this)->map()->instance_type()) {
575#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
576 STRUCT_LIST(MAKE_STRUCT_CASE)
577#undef MAKE_STRUCT_CASE
578 default: return false;
579 }
580}
581
582
583#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
584 bool Object::Is##Name() { \
585 return Object::IsHeapObject() \
586 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
587 }
588 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
589#undef MAKE_STRUCT_PREDICATE
590
591
592bool Object::IsUndefined() {
593 return this == Heap::undefined_value();
594}
595
596
597bool Object::IsTheHole() {
598 return this == Heap::the_hole_value();
599}
600
601
602bool Object::IsNull() {
603 return this == Heap::null_value();
604}
605
606
607bool Object::IsTrue() {
608 return this == Heap::true_value();
609}
610
611
612bool Object::IsFalse() {
613 return this == Heap::false_value();
614}
615
616
617double Object::Number() {
618 ASSERT(IsNumber());
619 return IsSmi()
620 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
621 : reinterpret_cast<HeapNumber*>(this)->value();
622}
623
624
625
626Object* Object::ToSmi() {
627 if (IsSmi()) return this;
628 if (IsHeapNumber()) {
629 double value = HeapNumber::cast(this)->value();
630 int int_value = FastD2I(value);
631 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
632 return Smi::FromInt(int_value);
633 }
634 }
635 return Failure::Exception();
636}
637
638
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000639bool Object::HasSpecificClassOf(String* name) {
640 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
641}
642
643
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644Object* Object::GetElement(uint32_t index) {
645 return GetElementWithReceiver(this, index);
646}
647
648
649Object* Object::GetProperty(String* key) {
650 PropertyAttributes attributes;
651 return GetPropertyWithReceiver(this, key, &attributes);
652}
653
654
655Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
656 return GetPropertyWithReceiver(this, key, attributes);
657}
658
659
660#define FIELD_ADDR(p, offset) \
661 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
662
663#define READ_FIELD(p, offset) \
664 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
665
666#define WRITE_FIELD(p, offset, value) \
667 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
668
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000669
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670#define WRITE_BARRIER(object, offset) \
671 Heap::RecordWrite(object->address(), offset);
672
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000673// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000674// write due to the assert validating the written value.
675#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
676 if (mode == UPDATE_WRITE_BARRIER) { \
677 Heap::RecordWrite(object->address(), offset); \
678 } else { \
679 ASSERT(mode == SKIP_WRITE_BARRIER); \
680 ASSERT(Heap::InNewSpace(object) || \
681 !Heap::InNewSpace(READ_FIELD(object, offset))); \
682 }
683
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684#define READ_DOUBLE_FIELD(p, offset) \
685 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
686
687#define WRITE_DOUBLE_FIELD(p, offset, value) \
688 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
689
690#define READ_INT_FIELD(p, offset) \
691 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
692
693#define WRITE_INT_FIELD(p, offset, value) \
694 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
695
ager@chromium.org3e875802009-06-29 08:26:34 +0000696#define READ_INTPTR_FIELD(p, offset) \
697 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
698
699#define WRITE_INTPTR_FIELD(p, offset, value) \
700 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
701
ager@chromium.org7c537e22008-10-16 08:43:32 +0000702#define READ_UINT32_FIELD(p, offset) \
703 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
704
705#define WRITE_UINT32_FIELD(p, offset, value) \
706 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
707
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000708#define READ_SHORT_FIELD(p, offset) \
709 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
710
711#define WRITE_SHORT_FIELD(p, offset, value) \
712 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
713
714#define READ_BYTE_FIELD(p, offset) \
715 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
716
717#define WRITE_BYTE_FIELD(p, offset, value) \
718 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
719
720
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000721Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
722 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000723}
724
725
726int Smi::value() {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000727 return static_cast<int>(reinterpret_cast<intptr_t>(this)) >> kSmiTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728}
729
730
731Smi* Smi::FromInt(int value) {
732 ASSERT(Smi::IsValid(value));
ager@chromium.org9085a012009-05-11 19:22:57 +0000733 intptr_t tagged_value =
734 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
735 return reinterpret_cast<Smi*>(tagged_value);
736}
737
738
739Smi* Smi::FromIntptr(intptr_t value) {
740 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000741 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
742}
743
744
745Failure::Type Failure::type() const {
746 return static_cast<Type>(value() & kFailureTypeTagMask);
747}
748
749
750bool Failure::IsInternalError() const {
751 return type() == INTERNAL_ERROR;
752}
753
754
755bool Failure::IsOutOfMemoryException() const {
756 return type() == OUT_OF_MEMORY_EXCEPTION;
757}
758
759
760int Failure::requested() const {
761 const int kShiftBits =
762 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
763 STATIC_ASSERT(kShiftBits >= 0);
764 ASSERT(type() == RETRY_AFTER_GC);
765 return value() >> kShiftBits;
766}
767
768
769AllocationSpace Failure::allocation_space() const {
770 ASSERT_EQ(RETRY_AFTER_GC, type());
771 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
772 & kSpaceTagMask);
773}
774
775
776Failure* Failure::InternalError() {
777 return Construct(INTERNAL_ERROR);
778}
779
780
781Failure* Failure::Exception() {
782 return Construct(EXCEPTION);
783}
784
785Failure* Failure::OutOfMemoryException() {
786 return Construct(OUT_OF_MEMORY_EXCEPTION);
787}
788
789
790int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000791 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792}
793
794
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000795Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000796 // Assert that the space encoding fits in the three bytes allotted for it.
797 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000798 int requested = requested_bytes >> kObjectAlignmentBits;
799 int value = (requested << kSpaceTagSize) | NEW_SPACE;
800 ASSERT(value >> kSpaceTagSize == requested);
801 ASSERT(Smi::IsValid(value));
802 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
803 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
804 return Construct(RETRY_AFTER_GC, value);
805}
806
807
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808Failure* Failure::Construct(Type type, int value) {
809 int info = (value << kFailureTypeTagSize) | type;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000810 // TODO(X64): Stop using Smi validation for non-smi checks, even if they
811 // happen to be identical at the moment.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000813 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000814 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815}
816
817
818bool Smi::IsValid(int value) {
819#ifdef DEBUG
820 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
821#endif
822 // To be representable as an tagged small integer, the two
823 // most-significant bits of 'value' must be either 00 or 11 due to
824 // sign-extension. To check this we add 01 to the two
825 // most-significant bits, and check if the most-significant bit is 0
826 //
827 // CAUTION: The original code below:
828 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
829 // may lead to incorrect results according to the C language spec, and
830 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
831 // compiler may produce undefined results in case of signed integer
832 // overflow. The computation must be done w/ unsigned ints.
833 bool result =
834 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
835 ASSERT(result == in_range);
836 return result;
837}
838
839
ager@chromium.org9085a012009-05-11 19:22:57 +0000840bool Smi::IsIntptrValid(intptr_t value) {
841#ifdef DEBUG
842 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
843#endif
844 // See Smi::IsValid(int) for description.
845 bool result =
846 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
847 ASSERT(result == in_range);
848 return result;
849}
850
851
kasper.lund7276f142008-07-30 08:49:36 +0000852MapWord MapWord::FromMap(Map* map) {
853 return MapWord(reinterpret_cast<uintptr_t>(map));
854}
855
856
857Map* MapWord::ToMap() {
858 return reinterpret_cast<Map*>(value_);
859}
860
861
862bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000863 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000864}
865
866
867MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000868 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
869 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000870}
871
872
873HeapObject* MapWord::ToForwardingAddress() {
874 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000875 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000876}
877
878
879bool MapWord::IsMarked() {
880 return (value_ & kMarkingMask) == 0;
881}
882
883
884void MapWord::SetMark() {
885 value_ &= ~kMarkingMask;
886}
887
888
889void MapWord::ClearMark() {
890 value_ |= kMarkingMask;
891}
892
893
894bool MapWord::IsOverflowed() {
895 return (value_ & kOverflowMask) != 0;
896}
897
898
899void MapWord::SetOverflow() {
900 value_ |= kOverflowMask;
901}
902
903
904void MapWord::ClearOverflow() {
905 value_ &= ~kOverflowMask;
906}
907
908
909MapWord MapWord::EncodeAddress(Address map_address, int offset) {
910 // Offset is the distance in live bytes from the first live object in the
911 // same page. The offset between two objects in the same page should not
912 // exceed the object area size of a page.
913 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
914
915 int compact_offset = offset >> kObjectAlignmentBits;
916 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
917
918 Page* map_page = Page::FromAddress(map_address);
919 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
920
921 int map_page_offset =
922 map_page->Offset(map_address) >> kObjectAlignmentBits;
923
924 uintptr_t encoding =
925 (compact_offset << kForwardingOffsetShift) |
926 (map_page_offset << kMapPageOffsetShift) |
927 (map_page->mc_page_index << kMapPageIndexShift);
928 return MapWord(encoding);
929}
930
931
932Address MapWord::DecodeMapAddress(MapSpace* map_space) {
933 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
934 ASSERT_MAP_PAGE_INDEX(map_page_index);
935
936 int map_page_offset =
937 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
938 << kObjectAlignmentBits;
939
940 return (map_space->PageAddress(map_page_index) + map_page_offset);
941}
942
943
944int MapWord::DecodeOffset() {
945 // The offset field is represented in the kForwardingOffsetBits
946 // most-significant bits.
947 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
948 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
949 return offset;
950}
951
952
953MapWord MapWord::FromEncodedAddress(Address address) {
954 return MapWord(reinterpret_cast<uintptr_t>(address));
955}
956
957
958Address MapWord::ToEncodedAddress() {
959 return reinterpret_cast<Address>(value_);
960}
961
962
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000963#ifdef DEBUG
964void HeapObject::VerifyObjectField(int offset) {
965 VerifyPointer(READ_FIELD(this, offset));
966}
967#endif
968
969
970Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000971 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000972}
973
974
975void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000976 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000977}
978
979
kasper.lund7276f142008-07-30 08:49:36 +0000980MapWord HeapObject::map_word() {
981 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
982}
983
984
985void HeapObject::set_map_word(MapWord map_word) {
986 // WRITE_FIELD does not update the remembered set, but there is no need
987 // here.
988 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
989}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000990
991
992HeapObject* HeapObject::FromAddress(Address address) {
993 ASSERT_TAG_ALIGNED(address);
994 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
995}
996
997
998Address HeapObject::address() {
999 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1000}
1001
1002
1003int HeapObject::Size() {
1004 return SizeFromMap(map());
1005}
1006
1007
1008void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1009 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1010 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1011}
1012
1013
1014void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1015 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1016}
1017
1018
kasper.lund7276f142008-07-30 08:49:36 +00001019bool HeapObject::IsMarked() {
1020 return map_word().IsMarked();
1021}
1022
1023
1024void HeapObject::SetMark() {
1025 ASSERT(!IsMarked());
1026 MapWord first_word = map_word();
1027 first_word.SetMark();
1028 set_map_word(first_word);
1029}
1030
1031
1032void HeapObject::ClearMark() {
1033 ASSERT(IsMarked());
1034 MapWord first_word = map_word();
1035 first_word.ClearMark();
1036 set_map_word(first_word);
1037}
1038
1039
1040bool HeapObject::IsOverflowed() {
1041 return map_word().IsOverflowed();
1042}
1043
1044
1045void HeapObject::SetOverflow() {
1046 MapWord first_word = map_word();
1047 first_word.SetOverflow();
1048 set_map_word(first_word);
1049}
1050
1051
1052void HeapObject::ClearOverflow() {
1053 ASSERT(IsOverflowed());
1054 MapWord first_word = map_word();
1055 first_word.ClearOverflow();
1056 set_map_word(first_word);
1057}
1058
1059
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001060double HeapNumber::value() {
1061 return READ_DOUBLE_FIELD(this, kValueOffset);
1062}
1063
1064
1065void HeapNumber::set_value(double value) {
1066 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1067}
1068
1069
1070ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001071
1072
1073Array* JSObject::elements() {
1074 Object* array = READ_FIELD(this, kElementsOffset);
1075 // In the assert below Dictionary is covered under FixedArray.
1076 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1077 return reinterpret_cast<Array*>(array);
1078}
1079
1080
1081void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1082 // In the assert below Dictionary is covered under FixedArray.
1083 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1084 WRITE_FIELD(this, kElementsOffset, value);
1085 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1086}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001087
1088
1089void JSObject::initialize_properties() {
1090 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1091 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1092}
1093
1094
1095void JSObject::initialize_elements() {
1096 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1097 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1098}
1099
1100
1101ACCESSORS(Oddball, to_string, String, kToStringOffset)
1102ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1103
1104
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001105Object* JSGlobalPropertyCell::value() {
1106 return READ_FIELD(this, kValueOffset);
1107}
1108
1109
1110void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1111 // The write barrier is not used for global property cells.
1112 ASSERT(!val->IsJSGlobalPropertyCell());
1113 WRITE_FIELD(this, kValueOffset, val);
1114}
1115
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001116
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001117int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001118 InstanceType type = map()->instance_type();
1119 // Check for the most common kind of JavaScript object before
1120 // falling into the generic switch. This speeds up the internal
1121 // field operations considerably on average.
1122 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1123 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001124 case JS_GLOBAL_PROXY_TYPE:
1125 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001126 case JS_GLOBAL_OBJECT_TYPE:
1127 return JSGlobalObject::kSize;
1128 case JS_BUILTINS_OBJECT_TYPE:
1129 return JSBuiltinsObject::kSize;
1130 case JS_FUNCTION_TYPE:
1131 return JSFunction::kSize;
1132 case JS_VALUE_TYPE:
1133 return JSValue::kSize;
1134 case JS_ARRAY_TYPE:
1135 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001136 case JS_REGEXP_TYPE:
1137 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001138 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001139 return JSObject::kHeaderSize;
1140 default:
1141 UNREACHABLE();
1142 return 0;
1143 }
1144}
1145
1146
1147int JSObject::GetInternalFieldCount() {
1148 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001149 // Make sure to adjust for the number of in-object properties. These
1150 // properties do contribute to the size, but are not internal fields.
1151 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1152 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001153}
1154
1155
1156Object* JSObject::GetInternalField(int index) {
1157 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001158 // Internal objects do follow immediately after the header, whereas in-object
1159 // properties are at the end of the object. Therefore there is no need
1160 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001161 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1162}
1163
1164
1165void JSObject::SetInternalField(int index, Object* value) {
1166 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001167 // Internal objects do follow immediately after the header, whereas in-object
1168 // properties are at the end of the object. Therefore there is no need
1169 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001170 int offset = GetHeaderSize() + (kPointerSize * index);
1171 WRITE_FIELD(this, offset, value);
1172 WRITE_BARRIER(this, offset);
1173}
1174
1175
ager@chromium.org7c537e22008-10-16 08:43:32 +00001176// Access fast-case object properties at index. The use of these routines
1177// is needed to correctly distinguish between properties stored in-object and
1178// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001179Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001180 // Adjust for the number of properties stored in the object.
1181 index -= map()->inobject_properties();
1182 if (index < 0) {
1183 int offset = map()->instance_size() + (index * kPointerSize);
1184 return READ_FIELD(this, offset);
1185 } else {
1186 ASSERT(index < properties()->length());
1187 return properties()->get(index);
1188 }
1189}
1190
1191
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001192Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001193 // Adjust for the number of properties stored in the object.
1194 index -= map()->inobject_properties();
1195 if (index < 0) {
1196 int offset = map()->instance_size() + (index * kPointerSize);
1197 WRITE_FIELD(this, offset, value);
1198 WRITE_BARRIER(this, offset);
1199 } else {
1200 ASSERT(index < properties()->length());
1201 properties()->set(index, value);
1202 }
1203 return value;
1204}
1205
1206
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001207Object* JSObject::InObjectPropertyAt(int index) {
1208 // Adjust for the number of properties stored in the object.
1209 index -= map()->inobject_properties();
1210 ASSERT(index < 0);
1211 int offset = map()->instance_size() + (index * kPointerSize);
1212 return READ_FIELD(this, offset);
1213}
1214
1215
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001216Object* JSObject::InObjectPropertyAtPut(int index,
1217 Object* value,
1218 WriteBarrierMode mode) {
1219 // Adjust for the number of properties stored in the object.
1220 index -= map()->inobject_properties();
1221 ASSERT(index < 0);
1222 int offset = map()->instance_size() + (index * kPointerSize);
1223 WRITE_FIELD(this, offset, value);
1224 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1225 return value;
1226}
1227
1228
1229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001230void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001231 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001232 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001233 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001234 }
1235}
1236
1237
1238void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001239 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001240 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001241 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001242 }
1243}
1244
1245
1246bool JSObject::HasFastProperties() {
1247 return !properties()->IsDictionary();
1248}
1249
1250
1251bool Array::IndexFromObject(Object* object, uint32_t* index) {
1252 if (object->IsSmi()) {
1253 int value = Smi::cast(object)->value();
1254 if (value < 0) return false;
1255 *index = value;
1256 return true;
1257 }
1258 if (object->IsHeapNumber()) {
1259 double value = HeapNumber::cast(object)->value();
1260 uint32_t uint_value = static_cast<uint32_t>(value);
1261 if (value == static_cast<double>(uint_value)) {
1262 *index = uint_value;
1263 return true;
1264 }
1265 }
1266 return false;
1267}
1268
1269
1270bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1271 if (!this->IsJSValue()) return false;
1272
1273 JSValue* js_value = JSValue::cast(this);
1274 if (!js_value->value()->IsString()) return false;
1275
1276 String* str = String::cast(js_value->value());
1277 if (index >= (uint32_t)str->length()) return false;
1278
1279 return true;
1280}
1281
1282
1283Object* FixedArray::get(int index) {
1284 ASSERT(index >= 0 && index < this->length());
1285 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1286}
1287
1288
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001289void FixedArray::set(int index, Smi* value) {
1290 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1291 int offset = kHeaderSize + index * kPointerSize;
1292 WRITE_FIELD(this, offset, value);
1293}
1294
1295
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001296void FixedArray::set(int index, Object* value) {
1297 ASSERT(index >= 0 && index < this->length());
1298 int offset = kHeaderSize + index * kPointerSize;
1299 WRITE_FIELD(this, offset, value);
1300 WRITE_BARRIER(this, offset);
1301}
1302
1303
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001304WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001305 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1306 return UPDATE_WRITE_BARRIER;
1307}
1308
1309
1310void FixedArray::set(int index,
1311 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001312 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001313 ASSERT(index >= 0 && index < this->length());
1314 int offset = kHeaderSize + index * kPointerSize;
1315 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001316 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001317}
1318
1319
1320void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1321 ASSERT(index >= 0 && index < array->length());
1322 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1323}
1324
1325
1326void FixedArray::set_undefined(int index) {
1327 ASSERT(index >= 0 && index < this->length());
1328 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1329 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1330 Heap::undefined_value());
1331}
1332
1333
ager@chromium.org236ad962008-09-25 09:45:57 +00001334void FixedArray::set_null(int index) {
1335 ASSERT(index >= 0 && index < this->length());
1336 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1337 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1338}
1339
1340
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001341void FixedArray::set_the_hole(int index) {
1342 ASSERT(index >= 0 && index < this->length());
1343 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1344 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1345}
1346
1347
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001348bool DescriptorArray::IsEmpty() {
1349 ASSERT(this == Heap::empty_descriptor_array() ||
1350 this->length() > 2);
1351 return this == Heap::empty_descriptor_array();
1352}
1353
1354
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001355void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1356 Object* tmp = array->get(first);
1357 fast_set(array, first, array->get(second));
1358 fast_set(array, second, tmp);
1359}
1360
1361
1362int DescriptorArray::Search(String* name) {
1363 SLOW_ASSERT(IsSortedNoDuplicates());
1364
1365 // Check for empty descriptor array.
1366 int nof = number_of_descriptors();
1367 if (nof == 0) return kNotFound;
1368
1369 // Fast case: do linear search for small arrays.
1370 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001371 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001372 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001373 }
1374
1375 // Slow case: perform binary search.
1376 return BinarySearch(name, 0, nof - 1);
1377}
1378
1379
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380String* DescriptorArray::GetKey(int descriptor_number) {
1381 ASSERT(descriptor_number < number_of_descriptors());
1382 return String::cast(get(ToKeyIndex(descriptor_number)));
1383}
1384
1385
1386Object* DescriptorArray::GetValue(int descriptor_number) {
1387 ASSERT(descriptor_number < number_of_descriptors());
1388 return GetContentArray()->get(ToValueIndex(descriptor_number));
1389}
1390
1391
1392Smi* DescriptorArray::GetDetails(int descriptor_number) {
1393 ASSERT(descriptor_number < number_of_descriptors());
1394 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1395}
1396
1397
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001398PropertyType DescriptorArray::GetType(int descriptor_number) {
1399 ASSERT(descriptor_number < number_of_descriptors());
1400 return PropertyDetails(GetDetails(descriptor_number)).type();
1401}
1402
1403
1404int DescriptorArray::GetFieldIndex(int descriptor_number) {
1405 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1406}
1407
1408
1409JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1410 return JSFunction::cast(GetValue(descriptor_number));
1411}
1412
1413
1414Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1415 ASSERT(GetType(descriptor_number) == CALLBACKS);
1416 return GetValue(descriptor_number);
1417}
1418
1419
1420AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1421 ASSERT(GetType(descriptor_number) == CALLBACKS);
1422 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1423 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1424}
1425
1426
1427bool DescriptorArray::IsProperty(int descriptor_number) {
1428 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1429}
1430
1431
1432bool DescriptorArray::IsTransition(int descriptor_number) {
1433 PropertyType t = GetType(descriptor_number);
1434 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1435}
1436
1437
1438bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1439 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1440}
1441
1442
1443bool DescriptorArray::IsDontEnum(int descriptor_number) {
1444 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1445}
1446
1447
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001448void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1449 desc->Init(GetKey(descriptor_number),
1450 GetValue(descriptor_number),
1451 GetDetails(descriptor_number));
1452}
1453
1454
1455void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1456 // Range check.
1457 ASSERT(descriptor_number < number_of_descriptors());
1458
1459 // Make sure non of the elements in desc are in new space.
1460 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1461 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1462
1463 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1464 FixedArray* content_array = GetContentArray();
1465 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1466 fast_set(content_array, ToDetailsIndex(descriptor_number),
1467 desc->GetDetails().AsSmi());
1468}
1469
1470
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001471void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1472 Descriptor desc;
1473 src->Get(src_index, &desc);
1474 Set(index, &desc);
1475}
1476
1477
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001478void DescriptorArray::Swap(int first, int second) {
1479 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1480 FixedArray* content_array = GetContentArray();
1481 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1482 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1483}
1484
1485
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001486bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001487 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001488 if (!max_index_object->IsSmi()) return false;
1489 return 0 !=
1490 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1491}
1492
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001493uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001495 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001496 if (!max_index_object->IsSmi()) return 0;
1497 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1498 return value >> kRequiresSlowElementsTagSize;
1499}
1500
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001501void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001502 set(kMaxNumberKeyIndex,
1503 Smi::FromInt(kRequiresSlowElementsMask),
1504 SKIP_WRITE_BARRIER);
1505}
1506
1507
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001508// ------------------------------------
1509// Cast operations
1510
1511
1512CAST_ACCESSOR(FixedArray)
1513CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001515CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001516CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001517CAST_ACCESSOR(String)
1518CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001519CAST_ACCESSOR(SeqAsciiString)
1520CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001521CAST_ACCESSOR(ConsString)
1522CAST_ACCESSOR(SlicedString)
1523CAST_ACCESSOR(ExternalString)
1524CAST_ACCESSOR(ExternalAsciiString)
1525CAST_ACCESSOR(ExternalTwoByteString)
1526CAST_ACCESSOR(JSObject)
1527CAST_ACCESSOR(Smi)
1528CAST_ACCESSOR(Failure)
1529CAST_ACCESSOR(HeapObject)
1530CAST_ACCESSOR(HeapNumber)
1531CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001532CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001533CAST_ACCESSOR(SharedFunctionInfo)
1534CAST_ACCESSOR(Map)
1535CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001536CAST_ACCESSOR(GlobalObject)
1537CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001538CAST_ACCESSOR(JSGlobalObject)
1539CAST_ACCESSOR(JSBuiltinsObject)
1540CAST_ACCESSOR(Code)
1541CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001542CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543CAST_ACCESSOR(Proxy)
1544CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001545CAST_ACCESSOR(PixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001546CAST_ACCESSOR(Struct)
1547
1548
1549#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1550 STRUCT_LIST(MAKE_STRUCT_CAST)
1551#undef MAKE_STRUCT_CAST
1552
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001553
1554template <typename Shape, typename Key>
1555HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556 ASSERT(obj->IsHashTable());
1557 return reinterpret_cast<HashTable*>(obj);
1558}
1559
1560
1561INT_ACCESSORS(Array, length, kLengthOffset)
1562
1563
1564bool String::Equals(String* other) {
1565 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001566 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1567 return false;
1568 }
1569 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570}
1571
1572
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001573int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001574 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1575
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001576 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1577 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1578 ASSERT(kLongStringTag == 0);
1579
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001580 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001581}
1582
1583
1584void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001585 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1586 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1587 ASSERT(kLongStringTag == 0);
1588
1589 WRITE_INT_FIELD(this,
1590 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001591 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001592}
1593
1594
ager@chromium.org7c537e22008-10-16 08:43:32 +00001595uint32_t String::length_field() {
1596 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001597}
1598
1599
ager@chromium.org7c537e22008-10-16 08:43:32 +00001600void String::set_length_field(uint32_t value) {
1601 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001602}
1603
1604
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001605Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001606 // We don't need to flatten strings that are already flat. Since this code
1607 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001608 if (!IsFlat()) {
1609 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001610 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001611 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612}
1613
1614
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001615uint16_t String::Get(int index) {
1616 ASSERT(index >= 0 && index < length());
1617 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001618 case kSeqStringTag | kAsciiStringTag:
1619 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1620 case kSeqStringTag | kTwoByteStringTag:
1621 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1622 case kConsStringTag | kAsciiStringTag:
1623 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001624 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001625 case kSlicedStringTag | kAsciiStringTag:
1626 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001628 case kExternalStringTag | kAsciiStringTag:
1629 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1630 case kExternalStringTag | kTwoByteStringTag:
1631 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001632 default:
1633 break;
1634 }
1635
1636 UNREACHABLE();
1637 return 0;
1638}
1639
1640
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001641void String::Set(int index, uint16_t value) {
1642 ASSERT(index >= 0 && index < length());
1643 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001644
ager@chromium.org5ec48922009-05-05 07:25:34 +00001645 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001646 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1647 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648}
1649
1650
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001651bool String::IsFlat() {
1652 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001653 case kConsStringTag: {
1654 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001655 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001656 return second->length() == 0;
1657 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001658 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001659 StringRepresentationTag tag =
1660 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001661 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001662 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001663 default:
1664 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001665 }
1666}
1667
1668
ager@chromium.org7c537e22008-10-16 08:43:32 +00001669uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001670 ASSERT(index >= 0 && index < length());
1671 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1672}
1673
1674
ager@chromium.org7c537e22008-10-16 08:43:32 +00001675void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1677 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1678 static_cast<byte>(value));
1679}
1680
1681
ager@chromium.org7c537e22008-10-16 08:43:32 +00001682Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001683 return FIELD_ADDR(this, kHeaderSize);
1684}
1685
1686
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001687char* SeqAsciiString::GetChars() {
1688 return reinterpret_cast<char*>(GetCharsAddress());
1689}
1690
1691
ager@chromium.org7c537e22008-10-16 08:43:32 +00001692Address SeqTwoByteString::GetCharsAddress() {
1693 return FIELD_ADDR(this, kHeaderSize);
1694}
1695
1696
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001697uc16* SeqTwoByteString::GetChars() {
1698 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1699}
1700
1701
ager@chromium.org7c537e22008-10-16 08:43:32 +00001702uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703 ASSERT(index >= 0 && index < length());
1704 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1705}
1706
1707
ager@chromium.org7c537e22008-10-16 08:43:32 +00001708void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001709 ASSERT(index >= 0 && index < length());
1710 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1711}
1712
1713
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001714int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001715 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1716
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001717 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1718 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1719 ASSERT(kLongStringTag == 0);
1720
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001721 // Use the map (and not 'this') to compute the size tag, since
1722 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001723 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001724
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725 return SizeFor(length);
1726}
1727
1728
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001729int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1731
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001732 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1733 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1734 ASSERT(kLongStringTag == 0);
1735
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001736 // Use the map (and not 'this') to compute the size tag, since
1737 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001738 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739
1740 return SizeFor(length);
1741}
1742
1743
ager@chromium.org870a0b62008-11-04 11:43:05 +00001744String* ConsString::first() {
1745 return String::cast(READ_FIELD(this, kFirstOffset));
1746}
1747
1748
1749Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001750 return READ_FIELD(this, kFirstOffset);
1751}
1752
1753
ager@chromium.org870a0b62008-11-04 11:43:05 +00001754void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001755 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001756 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001757}
1758
1759
ager@chromium.org870a0b62008-11-04 11:43:05 +00001760String* ConsString::second() {
1761 return String::cast(READ_FIELD(this, kSecondOffset));
1762}
1763
1764
1765Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001766 return READ_FIELD(this, kSecondOffset);
1767}
1768
1769
ager@chromium.org870a0b62008-11-04 11:43:05 +00001770void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001771 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001772 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001773}
1774
1775
ager@chromium.org870a0b62008-11-04 11:43:05 +00001776String* SlicedString::buffer() {
1777 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001778}
1779
1780
ager@chromium.org870a0b62008-11-04 11:43:05 +00001781void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001782 WRITE_FIELD(this, kBufferOffset, buffer);
1783 WRITE_BARRIER(this, kBufferOffset);
1784}
1785
1786
1787int SlicedString::start() {
1788 return READ_INT_FIELD(this, kStartOffset);
1789}
1790
1791
1792void SlicedString::set_start(int start) {
1793 WRITE_INT_FIELD(this, kStartOffset, start);
1794}
1795
1796
1797ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1798 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1799}
1800
1801
1802void ExternalAsciiString::set_resource(
1803 ExternalAsciiString::Resource* resource) {
1804 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1805}
1806
1807
ager@chromium.org6f10e412009-02-13 10:11:16 +00001808Map* ExternalAsciiString::StringMap(int length) {
1809 Map* map;
1810 // Number of characters: determines the map.
1811 if (length <= String::kMaxShortStringSize) {
1812 map = Heap::short_external_ascii_string_map();
1813 } else if (length <= String::kMaxMediumStringSize) {
1814 map = Heap::medium_external_ascii_string_map();
1815 } else {
1816 map = Heap::long_external_ascii_string_map();
1817 }
1818 return map;
1819}
1820
1821
1822Map* ExternalAsciiString::SymbolMap(int length) {
1823 Map* map;
1824 // Number of characters: determines the map.
1825 if (length <= String::kMaxShortStringSize) {
1826 map = Heap::short_external_ascii_symbol_map();
1827 } else if (length <= String::kMaxMediumStringSize) {
1828 map = Heap::medium_external_ascii_symbol_map();
1829 } else {
1830 map = Heap::long_external_ascii_symbol_map();
1831 }
1832 return map;
1833}
1834
1835
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001836ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1837 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1838}
1839
1840
1841void ExternalTwoByteString::set_resource(
1842 ExternalTwoByteString::Resource* resource) {
1843 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1844}
1845
1846
ager@chromium.org6f10e412009-02-13 10:11:16 +00001847Map* ExternalTwoByteString::StringMap(int length) {
1848 Map* map;
1849 // Number of characters: determines the map.
1850 if (length <= String::kMaxShortStringSize) {
1851 map = Heap::short_external_string_map();
1852 } else if (length <= String::kMaxMediumStringSize) {
1853 map = Heap::medium_external_string_map();
1854 } else {
1855 map = Heap::long_external_string_map();
1856 }
1857 return map;
1858}
1859
1860
1861Map* ExternalTwoByteString::SymbolMap(int length) {
1862 Map* map;
1863 // Number of characters: determines the map.
1864 if (length <= String::kMaxShortStringSize) {
1865 map = Heap::short_external_symbol_map();
1866 } else if (length <= String::kMaxMediumStringSize) {
1867 map = Heap::medium_external_symbol_map();
1868 } else {
1869 map = Heap::long_external_symbol_map();
1870 }
1871 return map;
1872}
1873
1874
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001875byte ByteArray::get(int index) {
1876 ASSERT(index >= 0 && index < this->length());
1877 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1878}
1879
1880
1881void ByteArray::set(int index, byte value) {
1882 ASSERT(index >= 0 && index < this->length());
1883 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1884}
1885
1886
1887int ByteArray::get_int(int index) {
1888 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1889 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1890}
1891
1892
1893ByteArray* ByteArray::FromDataStartAddress(Address address) {
1894 ASSERT_TAG_ALIGNED(address);
1895 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1896}
1897
1898
1899Address ByteArray::GetDataStartAddress() {
1900 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1901}
1902
1903
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001904uint8_t* PixelArray::external_pointer() {
1905 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1906 return reinterpret_cast<uint8_t*>(ptr);
1907}
1908
1909
1910void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1911 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1912 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1913}
1914
1915
1916uint8_t PixelArray::get(int index) {
1917 ASSERT((index >= 0) && (index < this->length()));
1918 uint8_t* ptr = external_pointer();
1919 return ptr[index];
1920}
1921
1922
1923void PixelArray::set(int index, uint8_t value) {
1924 ASSERT((index >= 0) && (index < this->length()));
1925 uint8_t* ptr = external_pointer();
1926 ptr[index] = value;
1927}
1928
1929
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001930int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001931 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1932}
1933
1934
1935int Map::inobject_properties() {
1936 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001937}
1938
1939
1940int HeapObject::SizeFromMap(Map* map) {
1941 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001942 // Only inline the most frequent cases.
1943 if (instance_type == JS_OBJECT_TYPE ||
1944 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1945 (kStringTag | kConsStringTag) ||
1946 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001947 if (instance_type == FIXED_ARRAY_TYPE) {
1948 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1949 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001950 if (instance_type == BYTE_ARRAY_TYPE) {
1951 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1952 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001953 // Otherwise do the general size computation.
1954 return SlowSizeFromMap(map);
1955}
1956
1957
1958void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001959 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001960 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001961 ASSERT(0 <= value && value < 256);
1962 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1963}
1964
1965
ager@chromium.org7c537e22008-10-16 08:43:32 +00001966void Map::set_inobject_properties(int value) {
1967 ASSERT(0 <= value && value < 256);
1968 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1969}
1970
1971
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001972InstanceType Map::instance_type() {
1973 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1974}
1975
1976
1977void Map::set_instance_type(InstanceType value) {
1978 ASSERT(0 <= value && value < 256);
1979 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1980}
1981
1982
1983int Map::unused_property_fields() {
1984 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1985}
1986
1987
1988void Map::set_unused_property_fields(int value) {
1989 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1990}
1991
1992
1993byte Map::bit_field() {
1994 return READ_BYTE_FIELD(this, kBitFieldOffset);
1995}
1996
1997
1998void Map::set_bit_field(byte value) {
1999 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2000}
2001
2002
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002003byte Map::bit_field2() {
2004 return READ_BYTE_FIELD(this, kBitField2Offset);
2005}
2006
2007
2008void Map::set_bit_field2(byte value) {
2009 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2010}
2011
2012
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002013void Map::set_non_instance_prototype(bool value) {
2014 if (value) {
2015 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2016 } else {
2017 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2018 }
2019}
2020
2021
2022bool Map::has_non_instance_prototype() {
2023 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2024}
2025
2026
ager@chromium.org870a0b62008-11-04 11:43:05 +00002027void Map::set_is_access_check_needed(bool access_check_needed) {
2028 if (access_check_needed) {
2029 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2030 } else {
2031 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2032 }
2033}
2034
2035
2036bool Map::is_access_check_needed() {
2037 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2038}
2039
2040
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002041Code::Flags Code::flags() {
2042 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2043}
2044
2045
2046void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002047 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002048 // Make sure that all call stubs have an arguments count.
2049 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2050 ExtractArgumentsCountFromFlags(flags) >= 0);
2051 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2052}
2053
2054
2055Code::Kind Code::kind() {
2056 return ExtractKindFromFlags(flags());
2057}
2058
2059
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002060InLoopFlag Code::ic_in_loop() {
2061 return ExtractICInLoopFromFlags(flags());
2062}
2063
2064
kasper.lund7276f142008-07-30 08:49:36 +00002065InlineCacheState Code::ic_state() {
2066 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002067 // Only allow uninitialized or debugger states for non-IC code
2068 // objects. This is used in the debugger to determine whether or not
2069 // a call to code object has been replaced with a debug break call.
2070 ASSERT(is_inline_cache_stub() ||
2071 result == UNINITIALIZED ||
2072 result == DEBUG_BREAK ||
2073 result == DEBUG_PREPARE_STEP_IN);
2074 return result;
2075}
2076
2077
2078PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002079 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002080 return ExtractTypeFromFlags(flags());
2081}
2082
2083
2084int Code::arguments_count() {
2085 ASSERT(is_call_stub() || kind() == STUB);
2086 return ExtractArgumentsCountFromFlags(flags());
2087}
2088
2089
2090CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002092 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2093 kStubMajorKeyOffset));
2094}
2095
2096
2097void Code::set_major_key(CodeStub::Major major) {
2098 ASSERT(kind() == STUB);
2099 ASSERT(0 <= major && major < 256);
2100 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002101}
2102
2103
2104bool Code::is_inline_cache_stub() {
2105 Kind kind = this->kind();
2106 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2107}
2108
2109
2110Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002111 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002112 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002113 PropertyType type,
2114 int argc) {
2115 // Compute the bit mask.
2116 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002117 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002118 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002119 bits |= type << kFlagsTypeShift;
2120 bits |= argc << kFlagsArgumentsCountShift;
2121 // Cast to flags and validate result before returning it.
2122 Flags result = static_cast<Flags>(bits);
2123 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002124 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002125 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002126 ASSERT(ExtractTypeFromFlags(result) == type);
2127 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2128 return result;
2129}
2130
2131
2132Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2133 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002134 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002135 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002136 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002137}
2138
2139
2140Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2141 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2142 return static_cast<Kind>(bits);
2143}
2144
2145
kasper.lund7276f142008-07-30 08:49:36 +00002146InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2147 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002148 return static_cast<InlineCacheState>(bits);
2149}
2150
2151
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002152InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2153 int bits = (flags & kFlagsICInLoopMask);
2154 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2155}
2156
2157
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002158PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2159 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2160 return static_cast<PropertyType>(bits);
2161}
2162
2163
2164int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2165 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2166}
2167
2168
2169Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2170 int bits = flags & ~kFlagsTypeMask;
2171 return static_cast<Flags>(bits);
2172}
2173
2174
ager@chromium.org8bb60582008-12-11 12:02:20 +00002175Code* Code::GetCodeFromTargetAddress(Address address) {
2176 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2177 // GetCodeFromTargetAddress might be called when marking objects during mark
2178 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2179 // Code::cast. Code::cast does not work when the object's map is
2180 // marked.
2181 Code* result = reinterpret_cast<Code*>(code);
2182 return result;
2183}
2184
2185
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002186Object* Map::prototype() {
2187 return READ_FIELD(this, kPrototypeOffset);
2188}
2189
2190
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002191void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192 ASSERT(value->IsNull() || value->IsJSObject());
2193 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002194 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002195}
2196
2197
2198ACCESSORS(Map, instance_descriptors, DescriptorArray,
2199 kInstanceDescriptorsOffset)
2200ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2201ACCESSORS(Map, constructor, Object, kConstructorOffset)
2202
2203ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2204ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2205
2206ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2207ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002208ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002209
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002210ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002211
2212ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2213ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2214ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2215ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2216ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2217
2218ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2219ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2220ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2221
2222ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2223ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2224ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2225ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2226ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2227ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2228
2229ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2230ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2231
2232ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2233ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2234
2235ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2236ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002237ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2238 kPropertyAccessorsOffset)
2239ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2240 kPrototypeTemplateOffset)
2241ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2242ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2243 kNamedPropertyHandlerOffset)
2244ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2245 kIndexedPropertyHandlerOffset)
2246ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2247 kInstanceTemplateOffset)
2248ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2249ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002250ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2251 kInstanceCallHandlerOffset)
2252ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2253 kAccessCheckInfoOffset)
2254ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2255
2256ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002257ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2258 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259
2260ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2261ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2262
2263ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2264
2265ACCESSORS(Script, source, Object, kSourceOffset)
2266ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002267ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002268ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2269ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002270ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002271ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002272ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2273ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002274ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002275ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002276ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2277ACCESSORS(Script, eval_from_instructions_offset, Smi,
2278 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002279
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002280#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002281ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2282ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2283ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2284ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2285
2286ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2287ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2288ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2289ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002290#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002291
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002292ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002293ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2294ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2295 kInstanceClassNameOffset)
2296ACCESSORS(SharedFunctionInfo, function_data, Object,
2297 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002298ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2299ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002300ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002301
2302BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2303 kHiddenPrototypeBit)
2304BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2305BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2306 kNeedsAccessCheckBit)
2307BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2308 kIsExpressionBit)
2309BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2310 kIsTopLevelBit)
2311
2312INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2313INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2314 kFormalParameterCountOffset)
2315INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2316 kExpectedNofPropertiesOffset)
2317INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2318 kStartPositionAndTypeOffset)
2319INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2320INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2321 kFunctionTokenPositionOffset)
2322
2323
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002324void SharedFunctionInfo::DontAdaptArguments() {
2325 ASSERT(code()->kind() == Code::BUILTIN);
2326 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2327}
2328
2329
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002330int SharedFunctionInfo::start_position() {
2331 return start_position_and_type() >> kStartPositionShift;
2332}
2333
2334
2335void SharedFunctionInfo::set_start_position(int start_position) {
2336 set_start_position_and_type((start_position << kStartPositionShift)
2337 | (start_position_and_type() & ~kStartPositionMask));
2338}
2339
2340
2341Code* SharedFunctionInfo::code() {
2342 return Code::cast(READ_FIELD(this, kCodeOffset));
2343}
2344
2345
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002346void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002347 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002348 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002349}
2350
2351
2352bool SharedFunctionInfo::is_compiled() {
2353 // TODO(1242782): Create a code kind for uncompiled code.
2354 return code()->kind() != Code::STUB;
2355}
2356
2357
2358bool JSFunction::IsBoilerplate() {
2359 return map() == Heap::boilerplate_function_map();
2360}
2361
2362
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002363bool JSFunction::IsBuiltin() {
2364 return context()->global()->IsJSBuiltinsObject();
2365}
2366
2367
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002368bool JSObject::IsLoaded() {
2369 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002370}
2371
2372
2373Code* JSFunction::code() {
2374 return shared()->code();
2375}
2376
2377
2378void JSFunction::set_code(Code* value) {
2379 shared()->set_code(value);
2380}
2381
2382
2383Context* JSFunction::context() {
2384 return Context::cast(READ_FIELD(this, kContextOffset));
2385}
2386
2387
2388Object* JSFunction::unchecked_context() {
2389 return READ_FIELD(this, kContextOffset);
2390}
2391
2392
2393void JSFunction::set_context(Object* value) {
2394 ASSERT(value == Heap::undefined_value() || value->IsContext());
2395 WRITE_FIELD(this, kContextOffset, value);
2396 WRITE_BARRIER(this, kContextOffset);
2397}
2398
2399ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2400 kPrototypeOrInitialMapOffset)
2401
2402
2403Map* JSFunction::initial_map() {
2404 return Map::cast(prototype_or_initial_map());
2405}
2406
2407
2408void JSFunction::set_initial_map(Map* value) {
2409 set_prototype_or_initial_map(value);
2410}
2411
2412
2413bool JSFunction::has_initial_map() {
2414 return prototype_or_initial_map()->IsMap();
2415}
2416
2417
2418bool JSFunction::has_instance_prototype() {
2419 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2420}
2421
2422
2423bool JSFunction::has_prototype() {
2424 return map()->has_non_instance_prototype() || has_instance_prototype();
2425}
2426
2427
2428Object* JSFunction::instance_prototype() {
2429 ASSERT(has_instance_prototype());
2430 if (has_initial_map()) return initial_map()->prototype();
2431 // When there is no initial map and the prototype is a JSObject, the
2432 // initial map field is used for the prototype field.
2433 return prototype_or_initial_map();
2434}
2435
2436
2437Object* JSFunction::prototype() {
2438 ASSERT(has_prototype());
2439 // If the function's prototype property has been set to a non-JSObject
2440 // value, that value is stored in the constructor field of the map.
2441 if (map()->has_non_instance_prototype()) return map()->constructor();
2442 return instance_prototype();
2443}
2444
2445
2446bool JSFunction::is_compiled() {
2447 return shared()->is_compiled();
2448}
2449
2450
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002451int JSFunction::NumberOfLiterals() {
2452 return literals()->length();
2453}
2454
2455
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002456Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2457 ASSERT(0 <= id && id < kJSBuiltinsCount);
2458 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2459}
2460
2461
2462void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2463 Object* value) {
2464 ASSERT(0 <= id && id < kJSBuiltinsCount);
2465 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2466 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2467}
2468
2469
2470Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002471 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002472}
2473
2474
2475void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002476 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002477}
2478
2479
2480void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2481 visitor->VisitExternalReference(
2482 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2483}
2484
2485
2486ACCESSORS(JSValue, value, Object, kValueOffset)
2487
2488
2489JSValue* JSValue::cast(Object* obj) {
2490 ASSERT(obj->IsJSValue());
2491 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2492 return reinterpret_cast<JSValue*>(obj);
2493}
2494
2495
2496INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2497INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2498INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2499
2500
2501Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002502 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002503}
2504
2505
2506void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002507 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002508}
2509
2510
2511byte* Code::instruction_start() {
2512 return FIELD_ADDR(this, kHeaderSize);
2513}
2514
2515
2516int Code::body_size() {
2517 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2518}
2519
2520
2521byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002522 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002523}
2524
2525
2526byte* Code::entry() {
2527 return instruction_start();
2528}
2529
2530
2531bool Code::contains(byte* pc) {
2532 return (instruction_start() <= pc) &&
2533 (pc < instruction_start() + instruction_size());
2534}
2535
2536
2537byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002538 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002539}
2540
2541
2542ACCESSORS(JSArray, length, Object, kLengthOffset)
2543
2544
ager@chromium.org236ad962008-09-25 09:45:57 +00002545ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002546
2547
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002548JSRegExp::Type JSRegExp::TypeTag() {
2549 Object* data = this->data();
2550 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2551 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2552 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002553}
2554
2555
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002556int JSRegExp::CaptureCount() {
2557 switch (TypeTag()) {
2558 case ATOM:
2559 return 0;
2560 case IRREGEXP:
2561 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2562 default:
2563 UNREACHABLE();
2564 return -1;
2565 }
2566}
2567
2568
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002569JSRegExp::Flags JSRegExp::GetFlags() {
2570 ASSERT(this->data()->IsFixedArray());
2571 Object* data = this->data();
2572 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2573 return Flags(smi->value());
2574}
2575
2576
2577String* JSRegExp::Pattern() {
2578 ASSERT(this->data()->IsFixedArray());
2579 Object* data = this->data();
2580 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2581 return pattern;
2582}
2583
2584
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002585Object* JSRegExp::DataAt(int index) {
2586 ASSERT(TypeTag() != NOT_COMPILED);
2587 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002588}
2589
2590
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002591void JSRegExp::SetDataAt(int index, Object* value) {
2592 ASSERT(TypeTag() != NOT_COMPILED);
2593 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2594 FixedArray::cast(data())->set(index, value);
2595}
2596
2597
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002598JSObject::ElementsKind JSObject::GetElementsKind() {
2599 Array* array = elements();
2600 if (array->IsFixedArray()) {
2601 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2602 if (array->map() == Heap::fixed_array_map()) {
2603 return FAST_ELEMENTS;
2604 }
2605 ASSERT(array->IsDictionary());
2606 return DICTIONARY_ELEMENTS;
2607 }
2608 ASSERT(array->IsPixelArray());
2609 return PIXEL_ELEMENTS;
2610}
2611
2612
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002613bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002614 return GetElementsKind() == FAST_ELEMENTS;
2615}
2616
2617
2618bool JSObject::HasDictionaryElements() {
2619 return GetElementsKind() == DICTIONARY_ELEMENTS;
2620}
2621
2622
2623bool JSObject::HasPixelElements() {
2624 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002625}
2626
2627
2628bool JSObject::HasNamedInterceptor() {
2629 return map()->has_named_interceptor();
2630}
2631
2632
2633bool JSObject::HasIndexedInterceptor() {
2634 return map()->has_indexed_interceptor();
2635}
2636
2637
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002638StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002639 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002640 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002641}
2642
2643
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002644NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002645 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002646 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002647}
2648
2649
2650bool String::HasHashCode() {
2651 return (length_field() & kHashComputedMask) != 0;
2652}
2653
2654
2655uint32_t String::Hash() {
2656 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002657 uint32_t field = length_field();
2658 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002659 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002660 return ComputeAndSetHash();
2661}
2662
2663
ager@chromium.org7c537e22008-10-16 08:43:32 +00002664StringHasher::StringHasher(int length)
2665 : length_(length),
2666 raw_running_hash_(0),
2667 array_index_(0),
2668 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2669 is_first_char_(true),
2670 is_valid_(true) { }
2671
2672
2673bool StringHasher::has_trivial_hash() {
2674 return length_ > String::kMaxMediumStringSize;
2675}
2676
2677
2678void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002679 // Use the Jenkins one-at-a-time hash function to update the hash
2680 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002681 raw_running_hash_ += c;
2682 raw_running_hash_ += (raw_running_hash_ << 10);
2683 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002684 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002685 if (is_array_index_) {
2686 if (c < '0' || c > '9') {
2687 is_array_index_ = false;
2688 } else {
2689 int d = c - '0';
2690 if (is_first_char_) {
2691 is_first_char_ = false;
2692 if (c == '0' && length_ > 1) {
2693 is_array_index_ = false;
2694 return;
2695 }
2696 }
2697 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2698 is_array_index_ = false;
2699 } else {
2700 array_index_ = array_index_ * 10 + d;
2701 }
2702 }
2703 }
2704}
2705
2706
2707void StringHasher::AddCharacterNoIndex(uc32 c) {
2708 ASSERT(!is_array_index());
2709 raw_running_hash_ += c;
2710 raw_running_hash_ += (raw_running_hash_ << 10);
2711 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2712}
2713
2714
2715uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002716 // Get the calculated raw hash value and do some more bit ops to distribute
2717 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002718 uint32_t result = raw_running_hash_;
2719 result += (result << 3);
2720 result ^= (result >> 11);
2721 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002722 if (result == 0) {
2723 result = 27;
2724 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002725 return result;
2726}
2727
2728
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002729bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002730 uint32_t field = length_field();
2731 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002732 return SlowAsArrayIndex(index);
2733}
2734
2735
2736Object* JSObject::GetPrototype() {
2737 return JSObject::cast(this)->map()->prototype();
2738}
2739
2740
2741PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2742 return GetPropertyAttributeWithReceiver(this, key);
2743}
2744
2745
2746bool JSObject::HasElement(uint32_t index) {
2747 return HasElementWithReceiver(this, index);
2748}
2749
2750
2751bool AccessorInfo::all_can_read() {
2752 return BooleanBit::get(flag(), kAllCanReadBit);
2753}
2754
2755
2756void AccessorInfo::set_all_can_read(bool value) {
2757 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2758}
2759
2760
2761bool AccessorInfo::all_can_write() {
2762 return BooleanBit::get(flag(), kAllCanWriteBit);
2763}
2764
2765
2766void AccessorInfo::set_all_can_write(bool value) {
2767 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2768}
2769
2770
ager@chromium.org870a0b62008-11-04 11:43:05 +00002771bool AccessorInfo::prohibits_overwriting() {
2772 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2773}
2774
2775
2776void AccessorInfo::set_prohibits_overwriting(bool value) {
2777 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2778}
2779
2780
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781PropertyAttributes AccessorInfo::property_attributes() {
2782 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2783}
2784
2785
2786void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2787 ASSERT(AttributesField::is_valid(attributes));
2788 int rest_value = flag()->value() & ~AttributesField::mask();
2789 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2790}
2791
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002792template<typename Shape, typename Key>
2793void Dictionary<Shape, Key>::SetEntry(int entry,
2794 Object* key,
2795 Object* value,
2796 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002797 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002798 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2799 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2800 FixedArray::set(index, key, mode);
2801 FixedArray::set(index+1, value, mode);
2802 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002803}
2804
2805
2806void Map::ClearCodeCache() {
2807 // No write barrier is needed since empty_fixed_array is not in new space.
2808 // Please note this function is used during marking:
2809 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002810 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2811 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002812}
2813
2814
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002815void JSArray::EnsureSize(int required_size) {
2816 ASSERT(HasFastElements());
2817 if (elements()->length() >= required_size) return;
2818 Expand(required_size);
2819}
2820
2821
ager@chromium.org7c537e22008-10-16 08:43:32 +00002822void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002823 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002824 set_elements(storage);
2825}
2826
2827
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002828Object* FixedArray::Copy() {
2829 if (length() == 0) return this;
2830 return Heap::CopyFixedArray(this);
2831}
2832
2833
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002834#undef CAST_ACCESSOR
2835#undef INT_ACCESSORS
2836#undef SMI_ACCESSORS
2837#undef ACCESSORS
2838#undef FIELD_ADDR
2839#undef READ_FIELD
2840#undef WRITE_FIELD
2841#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002842#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002843#undef READ_MEMADDR_FIELD
2844#undef WRITE_MEMADDR_FIELD
2845#undef READ_DOUBLE_FIELD
2846#undef WRITE_DOUBLE_FIELD
2847#undef READ_INT_FIELD
2848#undef WRITE_INT_FIELD
2849#undef READ_SHORT_FIELD
2850#undef WRITE_SHORT_FIELD
2851#undef READ_BYTE_FIELD
2852#undef WRITE_BYTE_FIELD
2853
2854
2855} } // namespace v8::internal
2856
2857#endif // V8_OBJECTS_INL_H_