blob: 7f3628d8dbb778eeeba66c41f56f3757e94621e1 [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
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000094#define BOOL_GETTER(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98
99
100#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101 bool holder::name() { \
102 return BooleanBit::get(field(), offset); \
103 } \
104 void holder::set_##name(bool value) { \
105 set_##field(BooleanBit::set(field(), offset, value)); \
106 }
107
108
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000109bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110 // There is a constraint on the object; check.
111 if (!this->IsJSObject()) return false;
112 // Fetch the constructor function of the object.
113 Object* cons_obj = JSObject::cast(this)->map()->constructor();
114 if (!cons_obj->IsJSFunction()) return false;
115 JSFunction* fun = JSFunction::cast(cons_obj);
116 // Iterate through the chain of inheriting function templates to
117 // see if the required one occurs.
118 for (Object* type = fun->shared()->function_data();
119 type->IsFunctionTemplateInfo();
120 type = FunctionTemplateInfo::cast(type)->parent_template()) {
121 if (type == expected) return true;
122 }
123 // Didn't find the required type in the inheritance chain.
124 return false;
125}
126
127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128bool Object::IsSmi() {
129 return HAS_SMI_TAG(this);
130}
131
132
133bool Object::IsHeapObject() {
134 return HAS_HEAP_OBJECT_TAG(this);
135}
136
137
138bool Object::IsHeapNumber() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141}
142
143
144bool Object::IsString() {
145 return Object::IsHeapObject()
146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147}
148
149
ager@chromium.org870a0b62008-11-04 11:43:05 +0000150bool Object::IsSymbol() {
151 if (!this->IsHeapObject()) return false;
152 uint32_t type = HeapObject::cast(this)->map()->instance_type();
153 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
154 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155}
156
157
158bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000159 if (!this->IsHeapObject()) return false;
160 uint32_t type = HeapObject::cast(this)->map()->instance_type();
161 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
162 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000163}
164
165
ager@chromium.org870a0b62008-11-04 11:43:05 +0000166#ifdef DEBUG
167// These are for cast checks. If you need one of these in release
168// mode you should consider using a StringShape before moving it out
169// of the ifdef
170
171bool Object::IsSeqString() {
172 if (!IsString()) return false;
173 return StringShape(String::cast(this)).IsSequential();
174}
175
176
177bool Object::IsSeqAsciiString() {
178 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000179 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000180 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000181}
182
183
184bool Object::IsSeqTwoByteString() {
185 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000186 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000187 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188}
189
190
191bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000192 if (!IsString()) return false;
193 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194}
195
196
197bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000198 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000199 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000200 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201}
202
203
204bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000205 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000206 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000207 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208}
209
210
ager@chromium.org870a0b62008-11-04 11:43:05 +0000211bool Object::IsSlicedString() {
212 if (!IsString()) return false;
213 return StringShape(String::cast(this)).IsSliced();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214}
215
216
ager@chromium.org870a0b62008-11-04 11:43:05 +0000217#endif // DEBUG
218
219
220StringShape::StringShape(String* str)
221 : type_(str->map()->instance_type()) {
222 set_valid();
223 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224}
225
226
ager@chromium.org870a0b62008-11-04 11:43:05 +0000227StringShape::StringShape(Map* map)
228 : type_(map->instance_type()) {
229 set_valid();
230 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231}
232
233
ager@chromium.org870a0b62008-11-04 11:43:05 +0000234StringShape::StringShape(InstanceType t)
235 : type_(static_cast<uint32_t>(t)) {
236 set_valid();
237 ASSERT((type_ & kIsNotStringMask) == kStringTag);
238}
239
240
241bool StringShape::IsSymbol() {
242 ASSERT(valid());
243 return (type_ & kIsSymbolMask) == kSymbolTag;
244}
245
246
ager@chromium.org5ec48922009-05-05 07:25:34 +0000247bool String::IsAsciiRepresentation() {
248 uint32_t type = map()->instance_type();
249 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
250 return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
251 }
252 if ((type & kStringRepresentationMask) == kConsStringTag &&
253 ConsString::cast(this)->second()->length() == 0) {
254 return ConsString::cast(this)->first()->IsAsciiRepresentation();
255 }
256 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000257}
258
259
ager@chromium.org5ec48922009-05-05 07:25:34 +0000260bool String::IsTwoByteRepresentation() {
261 uint32_t type = map()->instance_type();
262 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
263 return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
264 } else if ((type & kStringRepresentationMask) == kConsStringTag &&
265 ConsString::cast(this)->second()->length() == 0) {
266 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
267 }
268 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000269}
270
271
272bool StringShape::IsCons() {
273 return (type_ & kStringRepresentationMask) == kConsStringTag;
274}
275
276
277bool StringShape::IsSliced() {
278 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
279}
280
281
282bool StringShape::IsExternal() {
283 return (type_ & kStringRepresentationMask) == kExternalStringTag;
284}
285
286
287bool StringShape::IsSequential() {
288 return (type_ & kStringRepresentationMask) == kSeqStringTag;
289}
290
291
292StringRepresentationTag StringShape::representation_tag() {
293 uint32_t tag = (type_ & kStringRepresentationMask);
294 return static_cast<StringRepresentationTag>(tag);
295}
296
297
298uint32_t StringShape::full_representation_tag() {
299 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
300}
301
302
303uint32_t StringShape::size_tag() {
304 return (type_ & kStringSizeMask);
305}
306
307
308bool StringShape::IsSequentialAscii() {
309 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
310}
311
312
313bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000314 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000315}
316
317
318bool StringShape::IsExternalAscii() {
319 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
320}
321
322
323bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000324 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000325}
326
327
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000328uc32 FlatStringReader::Get(int index) {
329 ASSERT(0 <= index && index <= length_);
330 if (is_ascii_) {
331 return static_cast<const byte*>(start_)[index];
332 } else {
333 return static_cast<const uc16*>(start_)[index];
334 }
335}
336
337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338bool Object::IsNumber() {
339 return IsSmi() || IsHeapNumber();
340}
341
342
343bool Object::IsByteArray() {
344 return Object::IsHeapObject()
345 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
346}
347
348
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000349bool Object::IsPixelArray() {
350 return Object::IsHeapObject() &&
351 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
352}
353
354
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355bool Object::IsFailure() {
356 return HAS_FAILURE_TAG(this);
357}
358
359
360bool Object::IsRetryAfterGC() {
361 return HAS_FAILURE_TAG(this)
362 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
363}
364
365
ager@chromium.org7c537e22008-10-16 08:43:32 +0000366bool Object::IsOutOfMemoryFailure() {
367 return HAS_FAILURE_TAG(this)
368 && Failure::cast(this)->IsOutOfMemoryException();
369}
370
371
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000372bool Object::IsException() {
373 return this == Failure::Exception();
374}
375
376
377bool Object::IsJSObject() {
378 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000379 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380}
381
382
ager@chromium.org32912102009-01-16 10:38:43 +0000383bool Object::IsJSContextExtensionObject() {
384 return IsHeapObject()
385 && (HeapObject::cast(this)->map()->instance_type() ==
386 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
387}
388
389
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390bool Object::IsMap() {
391 return Object::IsHeapObject()
392 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
393}
394
395
396bool Object::IsFixedArray() {
397 return Object::IsHeapObject()
398 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
399}
400
401
402bool Object::IsDescriptorArray() {
403 return IsFixedArray();
404}
405
406
407bool Object::IsContext() {
408 return Object::IsHeapObject()
409 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000410 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000411 HeapObject::cast(this)->map() == Heap::global_context_map());
412}
413
414
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000415bool Object::IsCatchContext() {
416 return Object::IsHeapObject()
417 && HeapObject::cast(this)->map() == Heap::catch_context_map();
418}
419
420
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000421bool Object::IsGlobalContext() {
422 return Object::IsHeapObject()
423 && HeapObject::cast(this)->map() == Heap::global_context_map();
424}
425
426
427bool Object::IsJSFunction() {
428 return Object::IsHeapObject()
429 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
430}
431
432
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000433template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000434 return obj->IsJSFunction();
435}
436
437
438bool Object::IsCode() {
439 return Object::IsHeapObject()
440 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
441}
442
443
444bool Object::IsOddball() {
445 return Object::IsHeapObject()
446 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
447}
448
449
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000450bool Object::IsJSGlobalPropertyCell() {
451 return Object::IsHeapObject()
452 && HeapObject::cast(this)->map()->instance_type()
453 == JS_GLOBAL_PROPERTY_CELL_TYPE;
454}
455
456
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000457bool Object::IsSharedFunctionInfo() {
458 return Object::IsHeapObject() &&
459 (HeapObject::cast(this)->map()->instance_type() ==
460 SHARED_FUNCTION_INFO_TYPE);
461}
462
463
464bool Object::IsJSValue() {
465 return Object::IsHeapObject()
466 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
467}
468
469
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000470bool Object::IsStringWrapper() {
471 return IsJSValue() && JSValue::cast(this)->value()->IsString();
472}
473
474
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475bool Object::IsProxy() {
476 return Object::IsHeapObject()
477 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
478}
479
480
481bool Object::IsBoolean() {
482 return IsTrue() || IsFalse();
483}
484
485
486bool Object::IsJSArray() {
487 return Object::IsHeapObject()
488 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
489}
490
491
ager@chromium.org236ad962008-09-25 09:45:57 +0000492bool Object::IsJSRegExp() {
493 return Object::IsHeapObject()
494 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
495}
496
497
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000498template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499 return obj->IsJSArray();
500}
501
502
503bool Object::IsHashTable() {
504 return Object::IsHeapObject()
505 && HeapObject::cast(this)->map() == Heap::hash_table_map();
506}
507
508
509bool Object::IsDictionary() {
510 return IsHashTable() && this != Heap::symbol_table();
511}
512
513
514bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000515 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000516}
517
518
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000519bool Object::IsCompilationCacheTable() {
520 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000521}
522
523
ager@chromium.org236ad962008-09-25 09:45:57 +0000524bool Object::IsMapCache() {
525 return IsHashTable();
526}
527
528
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529bool Object::IsPrimitive() {
530 return IsOddball() || IsNumber() || IsString();
531}
532
533
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000534bool Object::IsJSGlobalProxy() {
535 bool result = IsHeapObject() &&
536 (HeapObject::cast(this)->map()->instance_type() ==
537 JS_GLOBAL_PROXY_TYPE);
538 ASSERT(!result || IsAccessCheckNeeded());
539 return result;
540}
541
542
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000544 if (!IsHeapObject()) return false;
545
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000546 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000547 return type == JS_GLOBAL_OBJECT_TYPE ||
548 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000549}
550
551
552bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553 return IsHeapObject() &&
554 (HeapObject::cast(this)->map()->instance_type() ==
555 JS_GLOBAL_OBJECT_TYPE);
556}
557
558
559bool Object::IsJSBuiltinsObject() {
560 return IsHeapObject() &&
561 (HeapObject::cast(this)->map()->instance_type() ==
562 JS_BUILTINS_OBJECT_TYPE);
563}
564
565
566bool Object::IsUndetectableObject() {
567 return IsHeapObject()
568 && HeapObject::cast(this)->map()->is_undetectable();
569}
570
571
572bool Object::IsAccessCheckNeeded() {
573 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000574 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000575}
576
577
578bool Object::IsStruct() {
579 if (!IsHeapObject()) return false;
580 switch (HeapObject::cast(this)->map()->instance_type()) {
581#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
582 STRUCT_LIST(MAKE_STRUCT_CASE)
583#undef MAKE_STRUCT_CASE
584 default: return false;
585 }
586}
587
588
589#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
590 bool Object::Is##Name() { \
591 return Object::IsHeapObject() \
592 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
593 }
594 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
595#undef MAKE_STRUCT_PREDICATE
596
597
598bool Object::IsUndefined() {
599 return this == Heap::undefined_value();
600}
601
602
603bool Object::IsTheHole() {
604 return this == Heap::the_hole_value();
605}
606
607
608bool Object::IsNull() {
609 return this == Heap::null_value();
610}
611
612
613bool Object::IsTrue() {
614 return this == Heap::true_value();
615}
616
617
618bool Object::IsFalse() {
619 return this == Heap::false_value();
620}
621
622
623double Object::Number() {
624 ASSERT(IsNumber());
625 return IsSmi()
626 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
627 : reinterpret_cast<HeapNumber*>(this)->value();
628}
629
630
631
632Object* Object::ToSmi() {
633 if (IsSmi()) return this;
634 if (IsHeapNumber()) {
635 double value = HeapNumber::cast(this)->value();
636 int int_value = FastD2I(value);
637 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
638 return Smi::FromInt(int_value);
639 }
640 }
641 return Failure::Exception();
642}
643
644
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000645bool Object::HasSpecificClassOf(String* name) {
646 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
647}
648
649
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650Object* Object::GetElement(uint32_t index) {
651 return GetElementWithReceiver(this, index);
652}
653
654
655Object* Object::GetProperty(String* key) {
656 PropertyAttributes attributes;
657 return GetPropertyWithReceiver(this, key, &attributes);
658}
659
660
661Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
662 return GetPropertyWithReceiver(this, key, attributes);
663}
664
665
666#define FIELD_ADDR(p, offset) \
667 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
668
669#define READ_FIELD(p, offset) \
670 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
671
672#define WRITE_FIELD(p, offset, value) \
673 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
674
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000675
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676#define WRITE_BARRIER(object, offset) \
677 Heap::RecordWrite(object->address(), offset);
678
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000679// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000680// write due to the assert validating the written value.
681#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
682 if (mode == UPDATE_WRITE_BARRIER) { \
683 Heap::RecordWrite(object->address(), offset); \
684 } else { \
685 ASSERT(mode == SKIP_WRITE_BARRIER); \
686 ASSERT(Heap::InNewSpace(object) || \
687 !Heap::InNewSpace(READ_FIELD(object, offset))); \
688 }
689
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690#define READ_DOUBLE_FIELD(p, offset) \
691 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
692
693#define WRITE_DOUBLE_FIELD(p, offset, value) \
694 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
695
696#define READ_INT_FIELD(p, offset) \
697 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
698
699#define WRITE_INT_FIELD(p, offset, value) \
700 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
701
ager@chromium.org3e875802009-06-29 08:26:34 +0000702#define READ_INTPTR_FIELD(p, offset) \
703 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
704
705#define WRITE_INTPTR_FIELD(p, offset, value) \
706 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
707
ager@chromium.org7c537e22008-10-16 08:43:32 +0000708#define READ_UINT32_FIELD(p, offset) \
709 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
710
711#define WRITE_UINT32_FIELD(p, offset, value) \
712 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
713
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000714#define READ_SHORT_FIELD(p, offset) \
715 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
716
717#define WRITE_SHORT_FIELD(p, offset, value) \
718 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
719
720#define READ_BYTE_FIELD(p, offset) \
721 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
722
723#define WRITE_BYTE_FIELD(p, offset, value) \
724 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
725
726
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000727Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
728 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000729}
730
731
732int Smi::value() {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000733 return static_cast<int>(reinterpret_cast<intptr_t>(this)) >> kSmiTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000734}
735
736
737Smi* Smi::FromInt(int value) {
738 ASSERT(Smi::IsValid(value));
ager@chromium.org9085a012009-05-11 19:22:57 +0000739 intptr_t tagged_value =
740 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
741 return reinterpret_cast<Smi*>(tagged_value);
742}
743
744
745Smi* Smi::FromIntptr(intptr_t value) {
746 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000747 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
748}
749
750
751Failure::Type Failure::type() const {
752 return static_cast<Type>(value() & kFailureTypeTagMask);
753}
754
755
756bool Failure::IsInternalError() const {
757 return type() == INTERNAL_ERROR;
758}
759
760
761bool Failure::IsOutOfMemoryException() const {
762 return type() == OUT_OF_MEMORY_EXCEPTION;
763}
764
765
766int Failure::requested() const {
767 const int kShiftBits =
768 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
769 STATIC_ASSERT(kShiftBits >= 0);
770 ASSERT(type() == RETRY_AFTER_GC);
771 return value() >> kShiftBits;
772}
773
774
775AllocationSpace Failure::allocation_space() const {
776 ASSERT_EQ(RETRY_AFTER_GC, type());
777 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
778 & kSpaceTagMask);
779}
780
781
782Failure* Failure::InternalError() {
783 return Construct(INTERNAL_ERROR);
784}
785
786
787Failure* Failure::Exception() {
788 return Construct(EXCEPTION);
789}
790
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000791
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792Failure* Failure::OutOfMemoryException() {
793 return Construct(OUT_OF_MEMORY_EXCEPTION);
794}
795
796
797int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000798 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799}
800
801
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000802Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000803 // Assert that the space encoding fits in the three bytes allotted for it.
804 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000805 int requested = requested_bytes >> kObjectAlignmentBits;
806 int value = (requested << kSpaceTagSize) | NEW_SPACE;
807 ASSERT(value >> kSpaceTagSize == requested);
808 ASSERT(Smi::IsValid(value));
809 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
810 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
811 return Construct(RETRY_AFTER_GC, value);
812}
813
814
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815Failure* Failure::Construct(Type type, int value) {
816 int info = (value << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000817 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
ager@chromium.org5ec48922009-05-05 07:25:34 +0000818 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000819 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000820}
821
822
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000823bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824#ifdef DEBUG
825 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
826#endif
827 // To be representable as an tagged small integer, the two
828 // most-significant bits of 'value' must be either 00 or 11 due to
829 // sign-extension. To check this we add 01 to the two
830 // most-significant bits, and check if the most-significant bit is 0
831 //
832 // CAUTION: The original code below:
833 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
834 // may lead to incorrect results according to the C language spec, and
835 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
836 // compiler may produce undefined results in case of signed integer
837 // overflow. The computation must be done w/ unsigned ints.
838 bool result =
839 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
840 ASSERT(result == in_range);
841 return result;
842}
843
844
ager@chromium.org9085a012009-05-11 19:22:57 +0000845bool Smi::IsIntptrValid(intptr_t value) {
846#ifdef DEBUG
847 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
848#endif
849 // See Smi::IsValid(int) for description.
850 bool result =
851 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
852 ASSERT(result == in_range);
853 return result;
854}
855
856
kasper.lund7276f142008-07-30 08:49:36 +0000857MapWord MapWord::FromMap(Map* map) {
858 return MapWord(reinterpret_cast<uintptr_t>(map));
859}
860
861
862Map* MapWord::ToMap() {
863 return reinterpret_cast<Map*>(value_);
864}
865
866
867bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000868 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000869}
870
871
872MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000873 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
874 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000875}
876
877
878HeapObject* MapWord::ToForwardingAddress() {
879 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000880 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000881}
882
883
884bool MapWord::IsMarked() {
885 return (value_ & kMarkingMask) == 0;
886}
887
888
889void MapWord::SetMark() {
890 value_ &= ~kMarkingMask;
891}
892
893
894void MapWord::ClearMark() {
895 value_ |= kMarkingMask;
896}
897
898
899bool MapWord::IsOverflowed() {
900 return (value_ & kOverflowMask) != 0;
901}
902
903
904void MapWord::SetOverflow() {
905 value_ |= kOverflowMask;
906}
907
908
909void MapWord::ClearOverflow() {
910 value_ &= ~kOverflowMask;
911}
912
913
914MapWord MapWord::EncodeAddress(Address map_address, int offset) {
915 // Offset is the distance in live bytes from the first live object in the
916 // same page. The offset between two objects in the same page should not
917 // exceed the object area size of a page.
918 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
919
920 int compact_offset = offset >> kObjectAlignmentBits;
921 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
922
923 Page* map_page = Page::FromAddress(map_address);
924 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
925
926 int map_page_offset =
927 map_page->Offset(map_address) >> kObjectAlignmentBits;
928
929 uintptr_t encoding =
930 (compact_offset << kForwardingOffsetShift) |
931 (map_page_offset << kMapPageOffsetShift) |
932 (map_page->mc_page_index << kMapPageIndexShift);
933 return MapWord(encoding);
934}
935
936
937Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000938 int map_page_index =
939 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +0000940 ASSERT_MAP_PAGE_INDEX(map_page_index);
941
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000942 int map_page_offset = static_cast<int>(
kasper.lund7276f142008-07-30 08:49:36 +0000943 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000944 << kObjectAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +0000945
946 return (map_space->PageAddress(map_page_index) + map_page_offset);
947}
948
949
950int MapWord::DecodeOffset() {
951 // The offset field is represented in the kForwardingOffsetBits
952 // most-significant bits.
953 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
954 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
955 return offset;
956}
957
958
959MapWord MapWord::FromEncodedAddress(Address address) {
960 return MapWord(reinterpret_cast<uintptr_t>(address));
961}
962
963
964Address MapWord::ToEncodedAddress() {
965 return reinterpret_cast<Address>(value_);
966}
967
968
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000969#ifdef DEBUG
970void HeapObject::VerifyObjectField(int offset) {
971 VerifyPointer(READ_FIELD(this, offset));
972}
973#endif
974
975
976Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000977 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000978}
979
980
981void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000982 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000983}
984
985
kasper.lund7276f142008-07-30 08:49:36 +0000986MapWord HeapObject::map_word() {
987 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
988}
989
990
991void HeapObject::set_map_word(MapWord map_word) {
992 // WRITE_FIELD does not update the remembered set, but there is no need
993 // here.
994 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
995}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000996
997
998HeapObject* HeapObject::FromAddress(Address address) {
999 ASSERT_TAG_ALIGNED(address);
1000 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1001}
1002
1003
1004Address HeapObject::address() {
1005 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1006}
1007
1008
1009int HeapObject::Size() {
1010 return SizeFromMap(map());
1011}
1012
1013
1014void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1015 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1016 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1017}
1018
1019
1020void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1021 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1022}
1023
1024
kasper.lund7276f142008-07-30 08:49:36 +00001025bool HeapObject::IsMarked() {
1026 return map_word().IsMarked();
1027}
1028
1029
1030void HeapObject::SetMark() {
1031 ASSERT(!IsMarked());
1032 MapWord first_word = map_word();
1033 first_word.SetMark();
1034 set_map_word(first_word);
1035}
1036
1037
1038void HeapObject::ClearMark() {
1039 ASSERT(IsMarked());
1040 MapWord first_word = map_word();
1041 first_word.ClearMark();
1042 set_map_word(first_word);
1043}
1044
1045
1046bool HeapObject::IsOverflowed() {
1047 return map_word().IsOverflowed();
1048}
1049
1050
1051void HeapObject::SetOverflow() {
1052 MapWord first_word = map_word();
1053 first_word.SetOverflow();
1054 set_map_word(first_word);
1055}
1056
1057
1058void HeapObject::ClearOverflow() {
1059 ASSERT(IsOverflowed());
1060 MapWord first_word = map_word();
1061 first_word.ClearOverflow();
1062 set_map_word(first_word);
1063}
1064
1065
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001066double HeapNumber::value() {
1067 return READ_DOUBLE_FIELD(this, kValueOffset);
1068}
1069
1070
1071void HeapNumber::set_value(double value) {
1072 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1073}
1074
1075
1076ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001077
1078
1079Array* JSObject::elements() {
1080 Object* array = READ_FIELD(this, kElementsOffset);
1081 // In the assert below Dictionary is covered under FixedArray.
1082 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1083 return reinterpret_cast<Array*>(array);
1084}
1085
1086
1087void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1088 // In the assert below Dictionary is covered under FixedArray.
1089 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1090 WRITE_FIELD(this, kElementsOffset, value);
1091 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1092}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001093
1094
1095void JSObject::initialize_properties() {
1096 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1097 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1098}
1099
1100
1101void JSObject::initialize_elements() {
1102 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1103 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1104}
1105
1106
1107ACCESSORS(Oddball, to_string, String, kToStringOffset)
1108ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1109
1110
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001111Object* JSGlobalPropertyCell::value() {
1112 return READ_FIELD(this, kValueOffset);
1113}
1114
1115
1116void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1117 // The write barrier is not used for global property cells.
1118 ASSERT(!val->IsJSGlobalPropertyCell());
1119 WRITE_FIELD(this, kValueOffset, val);
1120}
1121
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001124 InstanceType type = map()->instance_type();
1125 // Check for the most common kind of JavaScript object before
1126 // falling into the generic switch. This speeds up the internal
1127 // field operations considerably on average.
1128 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1129 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001130 case JS_GLOBAL_PROXY_TYPE:
1131 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001132 case JS_GLOBAL_OBJECT_TYPE:
1133 return JSGlobalObject::kSize;
1134 case JS_BUILTINS_OBJECT_TYPE:
1135 return JSBuiltinsObject::kSize;
1136 case JS_FUNCTION_TYPE:
1137 return JSFunction::kSize;
1138 case JS_VALUE_TYPE:
1139 return JSValue::kSize;
1140 case JS_ARRAY_TYPE:
1141 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001142 case JS_REGEXP_TYPE:
1143 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001144 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001145 return JSObject::kHeaderSize;
1146 default:
1147 UNREACHABLE();
1148 return 0;
1149 }
1150}
1151
1152
1153int JSObject::GetInternalFieldCount() {
1154 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001155 // Make sure to adjust for the number of in-object properties. These
1156 // properties do contribute to the size, but are not internal fields.
1157 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1158 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001159}
1160
1161
1162Object* JSObject::GetInternalField(int index) {
1163 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001164 // Internal objects do follow immediately after the header, whereas in-object
1165 // properties are at the end of the object. Therefore there is no need
1166 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001167 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1168}
1169
1170
1171void JSObject::SetInternalField(int index, Object* value) {
1172 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001173 // Internal objects do follow immediately after the header, whereas in-object
1174 // properties are at the end of the object. Therefore there is no need
1175 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001176 int offset = GetHeaderSize() + (kPointerSize * index);
1177 WRITE_FIELD(this, offset, value);
1178 WRITE_BARRIER(this, offset);
1179}
1180
1181
ager@chromium.org7c537e22008-10-16 08:43:32 +00001182// Access fast-case object properties at index. The use of these routines
1183// is needed to correctly distinguish between properties stored in-object and
1184// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001185Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001186 // Adjust for the number of properties stored in the object.
1187 index -= map()->inobject_properties();
1188 if (index < 0) {
1189 int offset = map()->instance_size() + (index * kPointerSize);
1190 return READ_FIELD(this, offset);
1191 } else {
1192 ASSERT(index < properties()->length());
1193 return properties()->get(index);
1194 }
1195}
1196
1197
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001198Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001199 // Adjust for the number of properties stored in the object.
1200 index -= map()->inobject_properties();
1201 if (index < 0) {
1202 int offset = map()->instance_size() + (index * kPointerSize);
1203 WRITE_FIELD(this, offset, value);
1204 WRITE_BARRIER(this, offset);
1205 } else {
1206 ASSERT(index < properties()->length());
1207 properties()->set(index, value);
1208 }
1209 return value;
1210}
1211
1212
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001213Object* JSObject::InObjectPropertyAt(int index) {
1214 // Adjust for the number of properties stored in the object.
1215 index -= map()->inobject_properties();
1216 ASSERT(index < 0);
1217 int offset = map()->instance_size() + (index * kPointerSize);
1218 return READ_FIELD(this, offset);
1219}
1220
1221
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001222Object* JSObject::InObjectPropertyAtPut(int index,
1223 Object* value,
1224 WriteBarrierMode mode) {
1225 // Adjust for the number of properties stored in the object.
1226 index -= map()->inobject_properties();
1227 ASSERT(index < 0);
1228 int offset = map()->instance_size() + (index * kPointerSize);
1229 WRITE_FIELD(this, offset, value);
1230 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1231 return value;
1232}
1233
1234
1235
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001236void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001237 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001238 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001239 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240 }
1241}
1242
1243
1244void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001245 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001246 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001247 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001248 }
1249}
1250
1251
1252bool JSObject::HasFastProperties() {
1253 return !properties()->IsDictionary();
1254}
1255
1256
1257bool Array::IndexFromObject(Object* object, uint32_t* index) {
1258 if (object->IsSmi()) {
1259 int value = Smi::cast(object)->value();
1260 if (value < 0) return false;
1261 *index = value;
1262 return true;
1263 }
1264 if (object->IsHeapNumber()) {
1265 double value = HeapNumber::cast(object)->value();
1266 uint32_t uint_value = static_cast<uint32_t>(value);
1267 if (value == static_cast<double>(uint_value)) {
1268 *index = uint_value;
1269 return true;
1270 }
1271 }
1272 return false;
1273}
1274
1275
1276bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1277 if (!this->IsJSValue()) return false;
1278
1279 JSValue* js_value = JSValue::cast(this);
1280 if (!js_value->value()->IsString()) return false;
1281
1282 String* str = String::cast(js_value->value());
1283 if (index >= (uint32_t)str->length()) return false;
1284
1285 return true;
1286}
1287
1288
1289Object* FixedArray::get(int index) {
1290 ASSERT(index >= 0 && index < this->length());
1291 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1292}
1293
1294
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001295void FixedArray::set(int index, Smi* value) {
1296 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1297 int offset = kHeaderSize + index * kPointerSize;
1298 WRITE_FIELD(this, offset, value);
1299}
1300
1301
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001302void FixedArray::set(int index, Object* value) {
1303 ASSERT(index >= 0 && index < this->length());
1304 int offset = kHeaderSize + index * kPointerSize;
1305 WRITE_FIELD(this, offset, value);
1306 WRITE_BARRIER(this, offset);
1307}
1308
1309
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001310WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001311 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1312 return UPDATE_WRITE_BARRIER;
1313}
1314
1315
1316void FixedArray::set(int index,
1317 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001318 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001319 ASSERT(index >= 0 && index < this->length());
1320 int offset = kHeaderSize + index * kPointerSize;
1321 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001322 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001323}
1324
1325
1326void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1327 ASSERT(index >= 0 && index < array->length());
1328 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1329}
1330
1331
1332void FixedArray::set_undefined(int index) {
1333 ASSERT(index >= 0 && index < this->length());
1334 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1335 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1336 Heap::undefined_value());
1337}
1338
1339
ager@chromium.org236ad962008-09-25 09:45:57 +00001340void FixedArray::set_null(int index) {
1341 ASSERT(index >= 0 && index < this->length());
1342 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1343 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1344}
1345
1346
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001347void FixedArray::set_the_hole(int index) {
1348 ASSERT(index >= 0 && index < this->length());
1349 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1350 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1351}
1352
1353
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001354bool DescriptorArray::IsEmpty() {
1355 ASSERT(this == Heap::empty_descriptor_array() ||
1356 this->length() > 2);
1357 return this == Heap::empty_descriptor_array();
1358}
1359
1360
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1362 Object* tmp = array->get(first);
1363 fast_set(array, first, array->get(second));
1364 fast_set(array, second, tmp);
1365}
1366
1367
1368int DescriptorArray::Search(String* name) {
1369 SLOW_ASSERT(IsSortedNoDuplicates());
1370
1371 // Check for empty descriptor array.
1372 int nof = number_of_descriptors();
1373 if (nof == 0) return kNotFound;
1374
1375 // Fast case: do linear search for small arrays.
1376 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001377 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001378 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001379 }
1380
1381 // Slow case: perform binary search.
1382 return BinarySearch(name, 0, nof - 1);
1383}
1384
1385
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001386String* DescriptorArray::GetKey(int descriptor_number) {
1387 ASSERT(descriptor_number < number_of_descriptors());
1388 return String::cast(get(ToKeyIndex(descriptor_number)));
1389}
1390
1391
1392Object* DescriptorArray::GetValue(int descriptor_number) {
1393 ASSERT(descriptor_number < number_of_descriptors());
1394 return GetContentArray()->get(ToValueIndex(descriptor_number));
1395}
1396
1397
1398Smi* DescriptorArray::GetDetails(int descriptor_number) {
1399 ASSERT(descriptor_number < number_of_descriptors());
1400 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1401}
1402
1403
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001404PropertyType DescriptorArray::GetType(int descriptor_number) {
1405 ASSERT(descriptor_number < number_of_descriptors());
1406 return PropertyDetails(GetDetails(descriptor_number)).type();
1407}
1408
1409
1410int DescriptorArray::GetFieldIndex(int descriptor_number) {
1411 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1412}
1413
1414
1415JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1416 return JSFunction::cast(GetValue(descriptor_number));
1417}
1418
1419
1420Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1421 ASSERT(GetType(descriptor_number) == CALLBACKS);
1422 return GetValue(descriptor_number);
1423}
1424
1425
1426AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1427 ASSERT(GetType(descriptor_number) == CALLBACKS);
1428 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1429 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1430}
1431
1432
1433bool DescriptorArray::IsProperty(int descriptor_number) {
1434 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1435}
1436
1437
1438bool DescriptorArray::IsTransition(int descriptor_number) {
1439 PropertyType t = GetType(descriptor_number);
1440 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1441}
1442
1443
1444bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1445 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1446}
1447
1448
1449bool DescriptorArray::IsDontEnum(int descriptor_number) {
1450 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1451}
1452
1453
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001454void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1455 desc->Init(GetKey(descriptor_number),
1456 GetValue(descriptor_number),
1457 GetDetails(descriptor_number));
1458}
1459
1460
1461void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1462 // Range check.
1463 ASSERT(descriptor_number < number_of_descriptors());
1464
1465 // Make sure non of the elements in desc are in new space.
1466 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1467 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1468
1469 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1470 FixedArray* content_array = GetContentArray();
1471 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1472 fast_set(content_array, ToDetailsIndex(descriptor_number),
1473 desc->GetDetails().AsSmi());
1474}
1475
1476
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001477void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1478 Descriptor desc;
1479 src->Get(src_index, &desc);
1480 Set(index, &desc);
1481}
1482
1483
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001484void DescriptorArray::Swap(int first, int second) {
1485 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1486 FixedArray* content_array = GetContentArray();
1487 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1488 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1489}
1490
1491
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001492bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001493 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494 if (!max_index_object->IsSmi()) return false;
1495 return 0 !=
1496 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1497}
1498
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001499uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001500 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001501 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502 if (!max_index_object->IsSmi()) return 0;
1503 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1504 return value >> kRequiresSlowElementsTagSize;
1505}
1506
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001507void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001508 set(kMaxNumberKeyIndex,
1509 Smi::FromInt(kRequiresSlowElementsMask),
1510 SKIP_WRITE_BARRIER);
1511}
1512
1513
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514// ------------------------------------
1515// Cast operations
1516
1517
1518CAST_ACCESSOR(FixedArray)
1519CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001520CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001521CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001522CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001523CAST_ACCESSOR(String)
1524CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001525CAST_ACCESSOR(SeqAsciiString)
1526CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001527CAST_ACCESSOR(ConsString)
1528CAST_ACCESSOR(SlicedString)
1529CAST_ACCESSOR(ExternalString)
1530CAST_ACCESSOR(ExternalAsciiString)
1531CAST_ACCESSOR(ExternalTwoByteString)
1532CAST_ACCESSOR(JSObject)
1533CAST_ACCESSOR(Smi)
1534CAST_ACCESSOR(Failure)
1535CAST_ACCESSOR(HeapObject)
1536CAST_ACCESSOR(HeapNumber)
1537CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001538CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001539CAST_ACCESSOR(SharedFunctionInfo)
1540CAST_ACCESSOR(Map)
1541CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001542CAST_ACCESSOR(GlobalObject)
1543CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001544CAST_ACCESSOR(JSGlobalObject)
1545CAST_ACCESSOR(JSBuiltinsObject)
1546CAST_ACCESSOR(Code)
1547CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001548CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549CAST_ACCESSOR(Proxy)
1550CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001551CAST_ACCESSOR(PixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552CAST_ACCESSOR(Struct)
1553
1554
1555#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1556 STRUCT_LIST(MAKE_STRUCT_CAST)
1557#undef MAKE_STRUCT_CAST
1558
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001559
1560template <typename Shape, typename Key>
1561HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001562 ASSERT(obj->IsHashTable());
1563 return reinterpret_cast<HashTable*>(obj);
1564}
1565
1566
1567INT_ACCESSORS(Array, length, kLengthOffset)
1568
1569
1570bool String::Equals(String* other) {
1571 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001572 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1573 return false;
1574 }
1575 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001576}
1577
1578
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001579int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1581
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001582 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1583 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1584 ASSERT(kLongStringTag == 0);
1585
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001586 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001587}
1588
1589
1590void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001591 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1592 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1593 ASSERT(kLongStringTag == 0);
1594
1595 WRITE_INT_FIELD(this,
1596 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001597 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001598}
1599
1600
ager@chromium.org7c537e22008-10-16 08:43:32 +00001601uint32_t String::length_field() {
1602 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001603}
1604
1605
ager@chromium.org7c537e22008-10-16 08:43:32 +00001606void String::set_length_field(uint32_t value) {
1607 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001608}
1609
1610
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001611Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001612 // We don't need to flatten strings that are already flat. Since this code
1613 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001614 if (!IsFlat()) {
1615 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001616 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001617 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001618}
1619
1620
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001621uint16_t String::Get(int index) {
1622 ASSERT(index >= 0 && index < length());
1623 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001624 case kSeqStringTag | kAsciiStringTag:
1625 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1626 case kSeqStringTag | kTwoByteStringTag:
1627 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1628 case kConsStringTag | kAsciiStringTag:
1629 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001630 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001631 case kSlicedStringTag | kAsciiStringTag:
1632 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001634 case kExternalStringTag | kAsciiStringTag:
1635 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1636 case kExternalStringTag | kTwoByteStringTag:
1637 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638 default:
1639 break;
1640 }
1641
1642 UNREACHABLE();
1643 return 0;
1644}
1645
1646
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001647void String::Set(int index, uint16_t value) {
1648 ASSERT(index >= 0 && index < length());
1649 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001650
ager@chromium.org5ec48922009-05-05 07:25:34 +00001651 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001652 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1653 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001654}
1655
1656
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001657bool String::IsFlat() {
1658 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001659 case kConsStringTag: {
1660 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001661 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001662 return second->length() == 0;
1663 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001664 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001665 StringRepresentationTag tag =
1666 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001667 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001669 default:
1670 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001671 }
1672}
1673
1674
ager@chromium.org7c537e22008-10-16 08:43:32 +00001675uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676 ASSERT(index >= 0 && index < length());
1677 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1678}
1679
1680
ager@chromium.org7c537e22008-10-16 08:43:32 +00001681void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001682 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1683 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1684 static_cast<byte>(value));
1685}
1686
1687
ager@chromium.org7c537e22008-10-16 08:43:32 +00001688Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001689 return FIELD_ADDR(this, kHeaderSize);
1690}
1691
1692
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001693char* SeqAsciiString::GetChars() {
1694 return reinterpret_cast<char*>(GetCharsAddress());
1695}
1696
1697
ager@chromium.org7c537e22008-10-16 08:43:32 +00001698Address SeqTwoByteString::GetCharsAddress() {
1699 return FIELD_ADDR(this, kHeaderSize);
1700}
1701
1702
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001703uc16* SeqTwoByteString::GetChars() {
1704 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1705}
1706
1707
ager@chromium.org7c537e22008-10-16 08:43:32 +00001708uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001709 ASSERT(index >= 0 && index < length());
1710 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1711}
1712
1713
ager@chromium.org7c537e22008-10-16 08:43:32 +00001714void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001715 ASSERT(index >= 0 && index < length());
1716 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1717}
1718
1719
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001720int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001721 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1722
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001723 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1724 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1725 ASSERT(kLongStringTag == 0);
1726
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001727 // Use the map (and not 'this') to compute the size tag, since
1728 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001729 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001730
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001731 return SizeFor(length);
1732}
1733
1734
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001735int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001736 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1737
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001738 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1739 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1740 ASSERT(kLongStringTag == 0);
1741
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001742 // Use the map (and not 'this') to compute the size tag, since
1743 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001744 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745
1746 return SizeFor(length);
1747}
1748
1749
ager@chromium.org870a0b62008-11-04 11:43:05 +00001750String* ConsString::first() {
1751 return String::cast(READ_FIELD(this, kFirstOffset));
1752}
1753
1754
1755Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756 return READ_FIELD(this, kFirstOffset);
1757}
1758
1759
ager@chromium.org870a0b62008-11-04 11:43:05 +00001760void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001762 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001763}
1764
1765
ager@chromium.org870a0b62008-11-04 11:43:05 +00001766String* ConsString::second() {
1767 return String::cast(READ_FIELD(this, kSecondOffset));
1768}
1769
1770
1771Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001772 return READ_FIELD(this, kSecondOffset);
1773}
1774
1775
ager@chromium.org870a0b62008-11-04 11:43:05 +00001776void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001777 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001778 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001779}
1780
1781
ager@chromium.org870a0b62008-11-04 11:43:05 +00001782String* SlicedString::buffer() {
1783 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001784}
1785
1786
ager@chromium.org870a0b62008-11-04 11:43:05 +00001787void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001788 WRITE_FIELD(this, kBufferOffset, buffer);
1789 WRITE_BARRIER(this, kBufferOffset);
1790}
1791
1792
1793int SlicedString::start() {
1794 return READ_INT_FIELD(this, kStartOffset);
1795}
1796
1797
1798void SlicedString::set_start(int start) {
1799 WRITE_INT_FIELD(this, kStartOffset, start);
1800}
1801
1802
1803ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1804 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1805}
1806
1807
1808void ExternalAsciiString::set_resource(
1809 ExternalAsciiString::Resource* resource) {
1810 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1811}
1812
1813
ager@chromium.org6f10e412009-02-13 10:11:16 +00001814Map* ExternalAsciiString::StringMap(int length) {
1815 Map* map;
1816 // Number of characters: determines the map.
1817 if (length <= String::kMaxShortStringSize) {
1818 map = Heap::short_external_ascii_string_map();
1819 } else if (length <= String::kMaxMediumStringSize) {
1820 map = Heap::medium_external_ascii_string_map();
1821 } else {
1822 map = Heap::long_external_ascii_string_map();
1823 }
1824 return map;
1825}
1826
1827
1828Map* ExternalAsciiString::SymbolMap(int length) {
1829 Map* map;
1830 // Number of characters: determines the map.
1831 if (length <= String::kMaxShortStringSize) {
1832 map = Heap::short_external_ascii_symbol_map();
1833 } else if (length <= String::kMaxMediumStringSize) {
1834 map = Heap::medium_external_ascii_symbol_map();
1835 } else {
1836 map = Heap::long_external_ascii_symbol_map();
1837 }
1838 return map;
1839}
1840
1841
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001842ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1843 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1844}
1845
1846
1847void ExternalTwoByteString::set_resource(
1848 ExternalTwoByteString::Resource* resource) {
1849 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1850}
1851
1852
ager@chromium.org6f10e412009-02-13 10:11:16 +00001853Map* ExternalTwoByteString::StringMap(int length) {
1854 Map* map;
1855 // Number of characters: determines the map.
1856 if (length <= String::kMaxShortStringSize) {
1857 map = Heap::short_external_string_map();
1858 } else if (length <= String::kMaxMediumStringSize) {
1859 map = Heap::medium_external_string_map();
1860 } else {
1861 map = Heap::long_external_string_map();
1862 }
1863 return map;
1864}
1865
1866
1867Map* ExternalTwoByteString::SymbolMap(int length) {
1868 Map* map;
1869 // Number of characters: determines the map.
1870 if (length <= String::kMaxShortStringSize) {
1871 map = Heap::short_external_symbol_map();
1872 } else if (length <= String::kMaxMediumStringSize) {
1873 map = Heap::medium_external_symbol_map();
1874 } else {
1875 map = Heap::long_external_symbol_map();
1876 }
1877 return map;
1878}
1879
1880
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001881byte ByteArray::get(int index) {
1882 ASSERT(index >= 0 && index < this->length());
1883 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1884}
1885
1886
1887void ByteArray::set(int index, byte value) {
1888 ASSERT(index >= 0 && index < this->length());
1889 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1890}
1891
1892
1893int ByteArray::get_int(int index) {
1894 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1895 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1896}
1897
1898
1899ByteArray* ByteArray::FromDataStartAddress(Address address) {
1900 ASSERT_TAG_ALIGNED(address);
1901 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1902}
1903
1904
1905Address ByteArray::GetDataStartAddress() {
1906 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1907}
1908
1909
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001910uint8_t* PixelArray::external_pointer() {
1911 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1912 return reinterpret_cast<uint8_t*>(ptr);
1913}
1914
1915
1916void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1917 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1918 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1919}
1920
1921
1922uint8_t PixelArray::get(int index) {
1923 ASSERT((index >= 0) && (index < this->length()));
1924 uint8_t* ptr = external_pointer();
1925 return ptr[index];
1926}
1927
1928
1929void PixelArray::set(int index, uint8_t value) {
1930 ASSERT((index >= 0) && (index < this->length()));
1931 uint8_t* ptr = external_pointer();
1932 ptr[index] = value;
1933}
1934
1935
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001936int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001937 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1938}
1939
1940
1941int Map::inobject_properties() {
1942 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001943}
1944
1945
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001946int Map::pre_allocated_property_fields() {
1947 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1948}
1949
1950
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001951int HeapObject::SizeFromMap(Map* map) {
1952 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001953 // Only inline the most frequent cases.
1954 if (instance_type == JS_OBJECT_TYPE ||
1955 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1956 (kStringTag | kConsStringTag) ||
1957 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001958 if (instance_type == FIXED_ARRAY_TYPE) {
1959 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1960 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001961 if (instance_type == BYTE_ARRAY_TYPE) {
1962 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1963 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001964 // Otherwise do the general size computation.
1965 return SlowSizeFromMap(map);
1966}
1967
1968
1969void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001970 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001971 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001972 ASSERT(0 <= value && value < 256);
1973 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1974}
1975
1976
ager@chromium.org7c537e22008-10-16 08:43:32 +00001977void Map::set_inobject_properties(int value) {
1978 ASSERT(0 <= value && value < 256);
1979 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1980}
1981
1982
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001983void Map::set_pre_allocated_property_fields(int value) {
1984 ASSERT(0 <= value && value < 256);
1985 WRITE_BYTE_FIELD(this,
1986 kPreAllocatedPropertyFieldsOffset,
1987 static_cast<byte>(value));
1988}
1989
1990
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001991InstanceType Map::instance_type() {
1992 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1993}
1994
1995
1996void Map::set_instance_type(InstanceType value) {
1997 ASSERT(0 <= value && value < 256);
1998 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1999}
2000
2001
2002int Map::unused_property_fields() {
2003 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2004}
2005
2006
2007void Map::set_unused_property_fields(int value) {
2008 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2009}
2010
2011
2012byte Map::bit_field() {
2013 return READ_BYTE_FIELD(this, kBitFieldOffset);
2014}
2015
2016
2017void Map::set_bit_field(byte value) {
2018 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2019}
2020
2021
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002022byte Map::bit_field2() {
2023 return READ_BYTE_FIELD(this, kBitField2Offset);
2024}
2025
2026
2027void Map::set_bit_field2(byte value) {
2028 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2029}
2030
2031
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002032void Map::set_non_instance_prototype(bool value) {
2033 if (value) {
2034 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2035 } else {
2036 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2037 }
2038}
2039
2040
2041bool Map::has_non_instance_prototype() {
2042 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2043}
2044
2045
ager@chromium.org870a0b62008-11-04 11:43:05 +00002046void Map::set_is_access_check_needed(bool access_check_needed) {
2047 if (access_check_needed) {
2048 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2049 } else {
2050 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2051 }
2052}
2053
2054
2055bool Map::is_access_check_needed() {
2056 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2057}
2058
2059
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002060Code::Flags Code::flags() {
2061 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2062}
2063
2064
2065void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002066 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002067 // Make sure that all call stubs have an arguments count.
2068 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2069 ExtractArgumentsCountFromFlags(flags) >= 0);
2070 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2071}
2072
2073
2074Code::Kind Code::kind() {
2075 return ExtractKindFromFlags(flags());
2076}
2077
2078
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002079InLoopFlag Code::ic_in_loop() {
2080 return ExtractICInLoopFromFlags(flags());
2081}
2082
2083
kasper.lund7276f142008-07-30 08:49:36 +00002084InlineCacheState Code::ic_state() {
2085 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002086 // Only allow uninitialized or debugger states for non-IC code
2087 // objects. This is used in the debugger to determine whether or not
2088 // a call to code object has been replaced with a debug break call.
2089 ASSERT(is_inline_cache_stub() ||
2090 result == UNINITIALIZED ||
2091 result == DEBUG_BREAK ||
2092 result == DEBUG_PREPARE_STEP_IN);
2093 return result;
2094}
2095
2096
2097PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002098 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002099 return ExtractTypeFromFlags(flags());
2100}
2101
2102
2103int Code::arguments_count() {
2104 ASSERT(is_call_stub() || kind() == STUB);
2105 return ExtractArgumentsCountFromFlags(flags());
2106}
2107
2108
2109CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002110 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002111 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2112 kStubMajorKeyOffset));
2113}
2114
2115
2116void Code::set_major_key(CodeStub::Major major) {
2117 ASSERT(kind() == STUB);
2118 ASSERT(0 <= major && major < 256);
2119 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002120}
2121
2122
2123bool Code::is_inline_cache_stub() {
2124 Kind kind = this->kind();
2125 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2126}
2127
2128
2129Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002130 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002131 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002132 PropertyType type,
2133 int argc) {
2134 // Compute the bit mask.
2135 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002136 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002137 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002138 bits |= type << kFlagsTypeShift;
2139 bits |= argc << kFlagsArgumentsCountShift;
2140 // Cast to flags and validate result before returning it.
2141 Flags result = static_cast<Flags>(bits);
2142 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002143 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002144 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002145 ASSERT(ExtractTypeFromFlags(result) == type);
2146 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2147 return result;
2148}
2149
2150
2151Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2152 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002153 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002154 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002155 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002156}
2157
2158
2159Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2160 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2161 return static_cast<Kind>(bits);
2162}
2163
2164
kasper.lund7276f142008-07-30 08:49:36 +00002165InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2166 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002167 return static_cast<InlineCacheState>(bits);
2168}
2169
2170
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002171InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2172 int bits = (flags & kFlagsICInLoopMask);
2173 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2174}
2175
2176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002177PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2178 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2179 return static_cast<PropertyType>(bits);
2180}
2181
2182
2183int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2184 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2185}
2186
2187
2188Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2189 int bits = flags & ~kFlagsTypeMask;
2190 return static_cast<Flags>(bits);
2191}
2192
2193
ager@chromium.org8bb60582008-12-11 12:02:20 +00002194Code* Code::GetCodeFromTargetAddress(Address address) {
2195 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2196 // GetCodeFromTargetAddress might be called when marking objects during mark
2197 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2198 // Code::cast. Code::cast does not work when the object's map is
2199 // marked.
2200 Code* result = reinterpret_cast<Code*>(code);
2201 return result;
2202}
2203
2204
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002205Object* Map::prototype() {
2206 return READ_FIELD(this, kPrototypeOffset);
2207}
2208
2209
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002210void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002211 ASSERT(value->IsNull() || value->IsJSObject());
2212 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002213 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002214}
2215
2216
2217ACCESSORS(Map, instance_descriptors, DescriptorArray,
2218 kInstanceDescriptorsOffset)
2219ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2220ACCESSORS(Map, constructor, Object, kConstructorOffset)
2221
2222ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2223ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2224
2225ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2226ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002227ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002228
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002229ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002230
2231ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2232ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2233ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2234ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2235ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2236
2237ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2238ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2239ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2240
2241ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2242ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2243ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2244ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2245ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2246ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2247
2248ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2249ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2250
2251ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2252ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2253
2254ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2255ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002256ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2257 kPropertyAccessorsOffset)
2258ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2259 kPrototypeTemplateOffset)
2260ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2261ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2262 kNamedPropertyHandlerOffset)
2263ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2264 kIndexedPropertyHandlerOffset)
2265ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2266 kInstanceTemplateOffset)
2267ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2268ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002269ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2270 kInstanceCallHandlerOffset)
2271ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2272 kAccessCheckInfoOffset)
2273ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2274
2275ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002276ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2277 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002278
2279ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2280ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2281
2282ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2283
2284ACCESSORS(Script, source, Object, kSourceOffset)
2285ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002286ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002287ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2288ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002289ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002290ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002291ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2292ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002293ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002294ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002295ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2296ACCESSORS(Script, eval_from_instructions_offset, Smi,
2297 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002298
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002299#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002300ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2301ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2302ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2303ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2304
2305ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2306ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2307ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2308ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002309#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002310
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002311ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002312ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2313ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2314 kInstanceClassNameOffset)
2315ACCESSORS(SharedFunctionInfo, function_data, Object,
2316 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002317ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2318ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002319ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002320ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2321 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002322
2323BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2324 kHiddenPrototypeBit)
2325BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2326BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2327 kNeedsAccessCheckBit)
2328BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2329 kIsExpressionBit)
2330BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2331 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002332BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2333 has_only_this_property_assignments,
2334 kHasOnlyThisPropertyAssignments)
2335BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2336 has_only_simple_this_property_assignments,
2337 kHasOnlySimpleThisPropertyAssignments)
2338
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002339
2340INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2341INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2342 kFormalParameterCountOffset)
2343INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2344 kExpectedNofPropertiesOffset)
2345INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2346 kStartPositionAndTypeOffset)
2347INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2348INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2349 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002350INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2351 kCompilerHintsOffset)
2352INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2353 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002354
2355
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002356void SharedFunctionInfo::DontAdaptArguments() {
2357 ASSERT(code()->kind() == Code::BUILTIN);
2358 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2359}
2360
2361
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002362int SharedFunctionInfo::start_position() {
2363 return start_position_and_type() >> kStartPositionShift;
2364}
2365
2366
2367void SharedFunctionInfo::set_start_position(int start_position) {
2368 set_start_position_and_type((start_position << kStartPositionShift)
2369 | (start_position_and_type() & ~kStartPositionMask));
2370}
2371
2372
2373Code* SharedFunctionInfo::code() {
2374 return Code::cast(READ_FIELD(this, kCodeOffset));
2375}
2376
2377
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002378void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002379 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002380 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002381}
2382
2383
2384bool SharedFunctionInfo::is_compiled() {
2385 // TODO(1242782): Create a code kind for uncompiled code.
2386 return code()->kind() != Code::STUB;
2387}
2388
2389
2390bool JSFunction::IsBoilerplate() {
2391 return map() == Heap::boilerplate_function_map();
2392}
2393
2394
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002395bool JSFunction::IsBuiltin() {
2396 return context()->global()->IsJSBuiltinsObject();
2397}
2398
2399
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002400bool JSObject::IsLoaded() {
2401 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002402}
2403
2404
2405Code* JSFunction::code() {
2406 return shared()->code();
2407}
2408
2409
2410void JSFunction::set_code(Code* value) {
2411 shared()->set_code(value);
2412}
2413
2414
2415Context* JSFunction::context() {
2416 return Context::cast(READ_FIELD(this, kContextOffset));
2417}
2418
2419
2420Object* JSFunction::unchecked_context() {
2421 return READ_FIELD(this, kContextOffset);
2422}
2423
2424
2425void JSFunction::set_context(Object* value) {
2426 ASSERT(value == Heap::undefined_value() || value->IsContext());
2427 WRITE_FIELD(this, kContextOffset, value);
2428 WRITE_BARRIER(this, kContextOffset);
2429}
2430
2431ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2432 kPrototypeOrInitialMapOffset)
2433
2434
2435Map* JSFunction::initial_map() {
2436 return Map::cast(prototype_or_initial_map());
2437}
2438
2439
2440void JSFunction::set_initial_map(Map* value) {
2441 set_prototype_or_initial_map(value);
2442}
2443
2444
2445bool JSFunction::has_initial_map() {
2446 return prototype_or_initial_map()->IsMap();
2447}
2448
2449
2450bool JSFunction::has_instance_prototype() {
2451 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2452}
2453
2454
2455bool JSFunction::has_prototype() {
2456 return map()->has_non_instance_prototype() || has_instance_prototype();
2457}
2458
2459
2460Object* JSFunction::instance_prototype() {
2461 ASSERT(has_instance_prototype());
2462 if (has_initial_map()) return initial_map()->prototype();
2463 // When there is no initial map and the prototype is a JSObject, the
2464 // initial map field is used for the prototype field.
2465 return prototype_or_initial_map();
2466}
2467
2468
2469Object* JSFunction::prototype() {
2470 ASSERT(has_prototype());
2471 // If the function's prototype property has been set to a non-JSObject
2472 // value, that value is stored in the constructor field of the map.
2473 if (map()->has_non_instance_prototype()) return map()->constructor();
2474 return instance_prototype();
2475}
2476
2477
2478bool JSFunction::is_compiled() {
2479 return shared()->is_compiled();
2480}
2481
2482
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002483int JSFunction::NumberOfLiterals() {
2484 return literals()->length();
2485}
2486
2487
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002488Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2489 ASSERT(0 <= id && id < kJSBuiltinsCount);
2490 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2491}
2492
2493
2494void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2495 Object* value) {
2496 ASSERT(0 <= id && id < kJSBuiltinsCount);
2497 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2498 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2499}
2500
2501
2502Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002503 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002504}
2505
2506
2507void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002508 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002509}
2510
2511
2512void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2513 visitor->VisitExternalReference(
2514 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2515}
2516
2517
2518ACCESSORS(JSValue, value, Object, kValueOffset)
2519
2520
2521JSValue* JSValue::cast(Object* obj) {
2522 ASSERT(obj->IsJSValue());
2523 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2524 return reinterpret_cast<JSValue*>(obj);
2525}
2526
2527
2528INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2529INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2530INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2531
2532
2533Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002534 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002535}
2536
2537
2538void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002539 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002540}
2541
2542
2543byte* Code::instruction_start() {
2544 return FIELD_ADDR(this, kHeaderSize);
2545}
2546
2547
2548int Code::body_size() {
2549 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2550}
2551
2552
2553byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002554 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002555}
2556
2557
2558byte* Code::entry() {
2559 return instruction_start();
2560}
2561
2562
2563bool Code::contains(byte* pc) {
2564 return (instruction_start() <= pc) &&
2565 (pc < instruction_start() + instruction_size());
2566}
2567
2568
2569byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002570 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002571}
2572
2573
2574ACCESSORS(JSArray, length, Object, kLengthOffset)
2575
2576
ager@chromium.org236ad962008-09-25 09:45:57 +00002577ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002578
2579
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002580JSRegExp::Type JSRegExp::TypeTag() {
2581 Object* data = this->data();
2582 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2583 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2584 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002585}
2586
2587
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002588int JSRegExp::CaptureCount() {
2589 switch (TypeTag()) {
2590 case ATOM:
2591 return 0;
2592 case IRREGEXP:
2593 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2594 default:
2595 UNREACHABLE();
2596 return -1;
2597 }
2598}
2599
2600
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002601JSRegExp::Flags JSRegExp::GetFlags() {
2602 ASSERT(this->data()->IsFixedArray());
2603 Object* data = this->data();
2604 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2605 return Flags(smi->value());
2606}
2607
2608
2609String* JSRegExp::Pattern() {
2610 ASSERT(this->data()->IsFixedArray());
2611 Object* data = this->data();
2612 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2613 return pattern;
2614}
2615
2616
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002617Object* JSRegExp::DataAt(int index) {
2618 ASSERT(TypeTag() != NOT_COMPILED);
2619 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002620}
2621
2622
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002623void JSRegExp::SetDataAt(int index, Object* value) {
2624 ASSERT(TypeTag() != NOT_COMPILED);
2625 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2626 FixedArray::cast(data())->set(index, value);
2627}
2628
2629
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002630JSObject::ElementsKind JSObject::GetElementsKind() {
2631 Array* array = elements();
2632 if (array->IsFixedArray()) {
2633 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2634 if (array->map() == Heap::fixed_array_map()) {
2635 return FAST_ELEMENTS;
2636 }
2637 ASSERT(array->IsDictionary());
2638 return DICTIONARY_ELEMENTS;
2639 }
2640 ASSERT(array->IsPixelArray());
2641 return PIXEL_ELEMENTS;
2642}
2643
2644
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002645bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002646 return GetElementsKind() == FAST_ELEMENTS;
2647}
2648
2649
2650bool JSObject::HasDictionaryElements() {
2651 return GetElementsKind() == DICTIONARY_ELEMENTS;
2652}
2653
2654
2655bool JSObject::HasPixelElements() {
2656 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002657}
2658
2659
2660bool JSObject::HasNamedInterceptor() {
2661 return map()->has_named_interceptor();
2662}
2663
2664
2665bool JSObject::HasIndexedInterceptor() {
2666 return map()->has_indexed_interceptor();
2667}
2668
2669
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002670StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002671 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002672 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002673}
2674
2675
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002676NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002677 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002678 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002679}
2680
2681
2682bool String::HasHashCode() {
2683 return (length_field() & kHashComputedMask) != 0;
2684}
2685
2686
2687uint32_t String::Hash() {
2688 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002689 uint32_t field = length_field();
2690 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002691 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002692 return ComputeAndSetHash();
2693}
2694
2695
ager@chromium.org7c537e22008-10-16 08:43:32 +00002696StringHasher::StringHasher(int length)
2697 : length_(length),
2698 raw_running_hash_(0),
2699 array_index_(0),
2700 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2701 is_first_char_(true),
2702 is_valid_(true) { }
2703
2704
2705bool StringHasher::has_trivial_hash() {
2706 return length_ > String::kMaxMediumStringSize;
2707}
2708
2709
2710void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002711 // Use the Jenkins one-at-a-time hash function to update the hash
2712 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002713 raw_running_hash_ += c;
2714 raw_running_hash_ += (raw_running_hash_ << 10);
2715 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002716 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002717 if (is_array_index_) {
2718 if (c < '0' || c > '9') {
2719 is_array_index_ = false;
2720 } else {
2721 int d = c - '0';
2722 if (is_first_char_) {
2723 is_first_char_ = false;
2724 if (c == '0' && length_ > 1) {
2725 is_array_index_ = false;
2726 return;
2727 }
2728 }
2729 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2730 is_array_index_ = false;
2731 } else {
2732 array_index_ = array_index_ * 10 + d;
2733 }
2734 }
2735 }
2736}
2737
2738
2739void StringHasher::AddCharacterNoIndex(uc32 c) {
2740 ASSERT(!is_array_index());
2741 raw_running_hash_ += c;
2742 raw_running_hash_ += (raw_running_hash_ << 10);
2743 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2744}
2745
2746
2747uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002748 // Get the calculated raw hash value and do some more bit ops to distribute
2749 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002750 uint32_t result = raw_running_hash_;
2751 result += (result << 3);
2752 result ^= (result >> 11);
2753 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002754 if (result == 0) {
2755 result = 27;
2756 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002757 return result;
2758}
2759
2760
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002761bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002762 uint32_t field = length_field();
2763 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002764 return SlowAsArrayIndex(index);
2765}
2766
2767
2768Object* JSObject::GetPrototype() {
2769 return JSObject::cast(this)->map()->prototype();
2770}
2771
2772
2773PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2774 return GetPropertyAttributeWithReceiver(this, key);
2775}
2776
2777
2778bool JSObject::HasElement(uint32_t index) {
2779 return HasElementWithReceiver(this, index);
2780}
2781
2782
2783bool AccessorInfo::all_can_read() {
2784 return BooleanBit::get(flag(), kAllCanReadBit);
2785}
2786
2787
2788void AccessorInfo::set_all_can_read(bool value) {
2789 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2790}
2791
2792
2793bool AccessorInfo::all_can_write() {
2794 return BooleanBit::get(flag(), kAllCanWriteBit);
2795}
2796
2797
2798void AccessorInfo::set_all_can_write(bool value) {
2799 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2800}
2801
2802
ager@chromium.org870a0b62008-11-04 11:43:05 +00002803bool AccessorInfo::prohibits_overwriting() {
2804 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2805}
2806
2807
2808void AccessorInfo::set_prohibits_overwriting(bool value) {
2809 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2810}
2811
2812
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002813PropertyAttributes AccessorInfo::property_attributes() {
2814 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2815}
2816
2817
2818void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2819 ASSERT(AttributesField::is_valid(attributes));
2820 int rest_value = flag()->value() & ~AttributesField::mask();
2821 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2822}
2823
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002824template<typename Shape, typename Key>
2825void Dictionary<Shape, Key>::SetEntry(int entry,
2826 Object* key,
2827 Object* value,
2828 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002829 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002830 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2831 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2832 FixedArray::set(index, key, mode);
2833 FixedArray::set(index+1, value, mode);
2834 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002835}
2836
2837
2838void Map::ClearCodeCache() {
2839 // No write barrier is needed since empty_fixed_array is not in new space.
2840 // Please note this function is used during marking:
2841 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002842 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2843 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002844}
2845
2846
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002847void JSArray::EnsureSize(int required_size) {
2848 ASSERT(HasFastElements());
2849 if (elements()->length() >= required_size) return;
2850 Expand(required_size);
2851}
2852
2853
ager@chromium.org7c537e22008-10-16 08:43:32 +00002854void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002855 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002856 set_elements(storage);
2857}
2858
2859
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002860Object* FixedArray::Copy() {
2861 if (length() == 0) return this;
2862 return Heap::CopyFixedArray(this);
2863}
2864
2865
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002866#undef CAST_ACCESSOR
2867#undef INT_ACCESSORS
2868#undef SMI_ACCESSORS
2869#undef ACCESSORS
2870#undef FIELD_ADDR
2871#undef READ_FIELD
2872#undef WRITE_FIELD
2873#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002874#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002875#undef READ_MEMADDR_FIELD
2876#undef WRITE_MEMADDR_FIELD
2877#undef READ_DOUBLE_FIELD
2878#undef WRITE_DOUBLE_FIELD
2879#undef READ_INT_FIELD
2880#undef WRITE_INT_FIELD
2881#undef READ_SHORT_FIELD
2882#undef WRITE_SHORT_FIELD
2883#undef READ_BYTE_FIELD
2884#undef WRITE_BYTE_FIELD
2885
2886
2887} } // namespace v8::internal
2888
2889#endif // V8_OBJECTS_INL_H_