blob: 91aae2f420c1f1dcfe93eedb6c93cc664c7d85b5 [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;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000817 // TODO(X64): Stop using Smi validation for non-smi checks, even if they
818 // happen to be identical at the moment.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000819 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000820 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000821 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000822}
823
824
825bool Smi::IsValid(int value) {
826#ifdef DEBUG
827 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
828#endif
829 // To be representable as an tagged small integer, the two
830 // most-significant bits of 'value' must be either 00 or 11 due to
831 // sign-extension. To check this we add 01 to the two
832 // most-significant bits, and check if the most-significant bit is 0
833 //
834 // CAUTION: The original code below:
835 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
836 // may lead to incorrect results according to the C language spec, and
837 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
838 // compiler may produce undefined results in case of signed integer
839 // overflow. The computation must be done w/ unsigned ints.
840 bool result =
841 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
842 ASSERT(result == in_range);
843 return result;
844}
845
846
ager@chromium.org9085a012009-05-11 19:22:57 +0000847bool Smi::IsIntptrValid(intptr_t value) {
848#ifdef DEBUG
849 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
850#endif
851 // See Smi::IsValid(int) for description.
852 bool result =
853 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
854 ASSERT(result == in_range);
855 return result;
856}
857
858
kasper.lund7276f142008-07-30 08:49:36 +0000859MapWord MapWord::FromMap(Map* map) {
860 return MapWord(reinterpret_cast<uintptr_t>(map));
861}
862
863
864Map* MapWord::ToMap() {
865 return reinterpret_cast<Map*>(value_);
866}
867
868
869bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000870 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000871}
872
873
874MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000875 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
876 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000877}
878
879
880HeapObject* MapWord::ToForwardingAddress() {
881 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000882 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000883}
884
885
886bool MapWord::IsMarked() {
887 return (value_ & kMarkingMask) == 0;
888}
889
890
891void MapWord::SetMark() {
892 value_ &= ~kMarkingMask;
893}
894
895
896void MapWord::ClearMark() {
897 value_ |= kMarkingMask;
898}
899
900
901bool MapWord::IsOverflowed() {
902 return (value_ & kOverflowMask) != 0;
903}
904
905
906void MapWord::SetOverflow() {
907 value_ |= kOverflowMask;
908}
909
910
911void MapWord::ClearOverflow() {
912 value_ &= ~kOverflowMask;
913}
914
915
916MapWord MapWord::EncodeAddress(Address map_address, int offset) {
917 // Offset is the distance in live bytes from the first live object in the
918 // same page. The offset between two objects in the same page should not
919 // exceed the object area size of a page.
920 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
921
922 int compact_offset = offset >> kObjectAlignmentBits;
923 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
924
925 Page* map_page = Page::FromAddress(map_address);
926 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
927
928 int map_page_offset =
929 map_page->Offset(map_address) >> kObjectAlignmentBits;
930
931 uintptr_t encoding =
932 (compact_offset << kForwardingOffsetShift) |
933 (map_page_offset << kMapPageOffsetShift) |
934 (map_page->mc_page_index << kMapPageIndexShift);
935 return MapWord(encoding);
936}
937
938
939Address MapWord::DecodeMapAddress(MapSpace* map_space) {
940 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
941 ASSERT_MAP_PAGE_INDEX(map_page_index);
942
943 int map_page_offset =
944 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
945 << kObjectAlignmentBits;
946
947 return (map_space->PageAddress(map_page_index) + map_page_offset);
948}
949
950
951int MapWord::DecodeOffset() {
952 // The offset field is represented in the kForwardingOffsetBits
953 // most-significant bits.
954 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
955 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
956 return offset;
957}
958
959
960MapWord MapWord::FromEncodedAddress(Address address) {
961 return MapWord(reinterpret_cast<uintptr_t>(address));
962}
963
964
965Address MapWord::ToEncodedAddress() {
966 return reinterpret_cast<Address>(value_);
967}
968
969
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000970#ifdef DEBUG
971void HeapObject::VerifyObjectField(int offset) {
972 VerifyPointer(READ_FIELD(this, offset));
973}
974#endif
975
976
977Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000978 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979}
980
981
982void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000983 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000984}
985
986
kasper.lund7276f142008-07-30 08:49:36 +0000987MapWord HeapObject::map_word() {
988 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
989}
990
991
992void HeapObject::set_map_word(MapWord map_word) {
993 // WRITE_FIELD does not update the remembered set, but there is no need
994 // here.
995 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
996}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000997
998
999HeapObject* HeapObject::FromAddress(Address address) {
1000 ASSERT_TAG_ALIGNED(address);
1001 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1002}
1003
1004
1005Address HeapObject::address() {
1006 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1007}
1008
1009
1010int HeapObject::Size() {
1011 return SizeFromMap(map());
1012}
1013
1014
1015void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1016 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1017 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1018}
1019
1020
1021void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1022 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1023}
1024
1025
kasper.lund7276f142008-07-30 08:49:36 +00001026bool HeapObject::IsMarked() {
1027 return map_word().IsMarked();
1028}
1029
1030
1031void HeapObject::SetMark() {
1032 ASSERT(!IsMarked());
1033 MapWord first_word = map_word();
1034 first_word.SetMark();
1035 set_map_word(first_word);
1036}
1037
1038
1039void HeapObject::ClearMark() {
1040 ASSERT(IsMarked());
1041 MapWord first_word = map_word();
1042 first_word.ClearMark();
1043 set_map_word(first_word);
1044}
1045
1046
1047bool HeapObject::IsOverflowed() {
1048 return map_word().IsOverflowed();
1049}
1050
1051
1052void HeapObject::SetOverflow() {
1053 MapWord first_word = map_word();
1054 first_word.SetOverflow();
1055 set_map_word(first_word);
1056}
1057
1058
1059void HeapObject::ClearOverflow() {
1060 ASSERT(IsOverflowed());
1061 MapWord first_word = map_word();
1062 first_word.ClearOverflow();
1063 set_map_word(first_word);
1064}
1065
1066
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001067double HeapNumber::value() {
1068 return READ_DOUBLE_FIELD(this, kValueOffset);
1069}
1070
1071
1072void HeapNumber::set_value(double value) {
1073 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1074}
1075
1076
1077ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001078
1079
1080Array* JSObject::elements() {
1081 Object* array = READ_FIELD(this, kElementsOffset);
1082 // In the assert below Dictionary is covered under FixedArray.
1083 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1084 return reinterpret_cast<Array*>(array);
1085}
1086
1087
1088void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1089 // In the assert below Dictionary is covered under FixedArray.
1090 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1091 WRITE_FIELD(this, kElementsOffset, value);
1092 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1093}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094
1095
1096void JSObject::initialize_properties() {
1097 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1098 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1099}
1100
1101
1102void JSObject::initialize_elements() {
1103 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1104 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1105}
1106
1107
1108ACCESSORS(Oddball, to_string, String, kToStringOffset)
1109ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1110
1111
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001112Object* JSGlobalPropertyCell::value() {
1113 return READ_FIELD(this, kValueOffset);
1114}
1115
1116
1117void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1118 // The write barrier is not used for global property cells.
1119 ASSERT(!val->IsJSGlobalPropertyCell());
1120 WRITE_FIELD(this, kValueOffset, val);
1121}
1122
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001123
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001124int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001125 InstanceType type = map()->instance_type();
1126 // Check for the most common kind of JavaScript object before
1127 // falling into the generic switch. This speeds up the internal
1128 // field operations considerably on average.
1129 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1130 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001131 case JS_GLOBAL_PROXY_TYPE:
1132 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001133 case JS_GLOBAL_OBJECT_TYPE:
1134 return JSGlobalObject::kSize;
1135 case JS_BUILTINS_OBJECT_TYPE:
1136 return JSBuiltinsObject::kSize;
1137 case JS_FUNCTION_TYPE:
1138 return JSFunction::kSize;
1139 case JS_VALUE_TYPE:
1140 return JSValue::kSize;
1141 case JS_ARRAY_TYPE:
1142 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001143 case JS_REGEXP_TYPE:
1144 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001145 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146 return JSObject::kHeaderSize;
1147 default:
1148 UNREACHABLE();
1149 return 0;
1150 }
1151}
1152
1153
1154int JSObject::GetInternalFieldCount() {
1155 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001156 // Make sure to adjust for the number of in-object properties. These
1157 // properties do contribute to the size, but are not internal fields.
1158 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1159 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001160}
1161
1162
1163Object* JSObject::GetInternalField(int index) {
1164 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001165 // Internal objects do follow immediately after the header, whereas in-object
1166 // properties are at the end of the object. Therefore there is no need
1167 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001168 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1169}
1170
1171
1172void JSObject::SetInternalField(int index, Object* value) {
1173 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001174 // Internal objects do follow immediately after the header, whereas in-object
1175 // properties are at the end of the object. Therefore there is no need
1176 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177 int offset = GetHeaderSize() + (kPointerSize * index);
1178 WRITE_FIELD(this, offset, value);
1179 WRITE_BARRIER(this, offset);
1180}
1181
1182
ager@chromium.org7c537e22008-10-16 08:43:32 +00001183// Access fast-case object properties at index. The use of these routines
1184// is needed to correctly distinguish between properties stored in-object and
1185// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001186Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001187 // Adjust for the number of properties stored in the object.
1188 index -= map()->inobject_properties();
1189 if (index < 0) {
1190 int offset = map()->instance_size() + (index * kPointerSize);
1191 return READ_FIELD(this, offset);
1192 } else {
1193 ASSERT(index < properties()->length());
1194 return properties()->get(index);
1195 }
1196}
1197
1198
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001199Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001200 // Adjust for the number of properties stored in the object.
1201 index -= map()->inobject_properties();
1202 if (index < 0) {
1203 int offset = map()->instance_size() + (index * kPointerSize);
1204 WRITE_FIELD(this, offset, value);
1205 WRITE_BARRIER(this, offset);
1206 } else {
1207 ASSERT(index < properties()->length());
1208 properties()->set(index, value);
1209 }
1210 return value;
1211}
1212
1213
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001214Object* JSObject::InObjectPropertyAt(int index) {
1215 // Adjust for the number of properties stored in the object.
1216 index -= map()->inobject_properties();
1217 ASSERT(index < 0);
1218 int offset = map()->instance_size() + (index * kPointerSize);
1219 return READ_FIELD(this, offset);
1220}
1221
1222
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001223Object* JSObject::InObjectPropertyAtPut(int index,
1224 Object* value,
1225 WriteBarrierMode mode) {
1226 // Adjust for the number of properties stored in the object.
1227 index -= map()->inobject_properties();
1228 ASSERT(index < 0);
1229 int offset = map()->instance_size() + (index * kPointerSize);
1230 WRITE_FIELD(this, offset, value);
1231 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1232 return value;
1233}
1234
1235
1236
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001237void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001238 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001239 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001240 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001241 }
1242}
1243
1244
1245void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001246 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001247 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001248 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249 }
1250}
1251
1252
1253bool JSObject::HasFastProperties() {
1254 return !properties()->IsDictionary();
1255}
1256
1257
1258bool Array::IndexFromObject(Object* object, uint32_t* index) {
1259 if (object->IsSmi()) {
1260 int value = Smi::cast(object)->value();
1261 if (value < 0) return false;
1262 *index = value;
1263 return true;
1264 }
1265 if (object->IsHeapNumber()) {
1266 double value = HeapNumber::cast(object)->value();
1267 uint32_t uint_value = static_cast<uint32_t>(value);
1268 if (value == static_cast<double>(uint_value)) {
1269 *index = uint_value;
1270 return true;
1271 }
1272 }
1273 return false;
1274}
1275
1276
1277bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1278 if (!this->IsJSValue()) return false;
1279
1280 JSValue* js_value = JSValue::cast(this);
1281 if (!js_value->value()->IsString()) return false;
1282
1283 String* str = String::cast(js_value->value());
1284 if (index >= (uint32_t)str->length()) return false;
1285
1286 return true;
1287}
1288
1289
1290Object* FixedArray::get(int index) {
1291 ASSERT(index >= 0 && index < this->length());
1292 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1293}
1294
1295
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001296void FixedArray::set(int index, Smi* value) {
1297 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1298 int offset = kHeaderSize + index * kPointerSize;
1299 WRITE_FIELD(this, offset, value);
1300}
1301
1302
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001303void FixedArray::set(int index, Object* value) {
1304 ASSERT(index >= 0 && index < this->length());
1305 int offset = kHeaderSize + index * kPointerSize;
1306 WRITE_FIELD(this, offset, value);
1307 WRITE_BARRIER(this, offset);
1308}
1309
1310
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001311WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001312 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1313 return UPDATE_WRITE_BARRIER;
1314}
1315
1316
1317void FixedArray::set(int index,
1318 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001319 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320 ASSERT(index >= 0 && index < this->length());
1321 int offset = kHeaderSize + index * kPointerSize;
1322 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001323 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324}
1325
1326
1327void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1328 ASSERT(index >= 0 && index < array->length());
1329 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1330}
1331
1332
1333void FixedArray::set_undefined(int index) {
1334 ASSERT(index >= 0 && index < this->length());
1335 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1336 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1337 Heap::undefined_value());
1338}
1339
1340
ager@chromium.org236ad962008-09-25 09:45:57 +00001341void FixedArray::set_null(int index) {
1342 ASSERT(index >= 0 && index < this->length());
1343 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1344 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1345}
1346
1347
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001348void FixedArray::set_the_hole(int index) {
1349 ASSERT(index >= 0 && index < this->length());
1350 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1351 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1352}
1353
1354
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001355bool DescriptorArray::IsEmpty() {
1356 ASSERT(this == Heap::empty_descriptor_array() ||
1357 this->length() > 2);
1358 return this == Heap::empty_descriptor_array();
1359}
1360
1361
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001362void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1363 Object* tmp = array->get(first);
1364 fast_set(array, first, array->get(second));
1365 fast_set(array, second, tmp);
1366}
1367
1368
1369int DescriptorArray::Search(String* name) {
1370 SLOW_ASSERT(IsSortedNoDuplicates());
1371
1372 // Check for empty descriptor array.
1373 int nof = number_of_descriptors();
1374 if (nof == 0) return kNotFound;
1375
1376 // Fast case: do linear search for small arrays.
1377 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001378 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001379 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380 }
1381
1382 // Slow case: perform binary search.
1383 return BinarySearch(name, 0, nof - 1);
1384}
1385
1386
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001387String* DescriptorArray::GetKey(int descriptor_number) {
1388 ASSERT(descriptor_number < number_of_descriptors());
1389 return String::cast(get(ToKeyIndex(descriptor_number)));
1390}
1391
1392
1393Object* DescriptorArray::GetValue(int descriptor_number) {
1394 ASSERT(descriptor_number < number_of_descriptors());
1395 return GetContentArray()->get(ToValueIndex(descriptor_number));
1396}
1397
1398
1399Smi* DescriptorArray::GetDetails(int descriptor_number) {
1400 ASSERT(descriptor_number < number_of_descriptors());
1401 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1402}
1403
1404
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001405PropertyType DescriptorArray::GetType(int descriptor_number) {
1406 ASSERT(descriptor_number < number_of_descriptors());
1407 return PropertyDetails(GetDetails(descriptor_number)).type();
1408}
1409
1410
1411int DescriptorArray::GetFieldIndex(int descriptor_number) {
1412 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1413}
1414
1415
1416JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1417 return JSFunction::cast(GetValue(descriptor_number));
1418}
1419
1420
1421Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1422 ASSERT(GetType(descriptor_number) == CALLBACKS);
1423 return GetValue(descriptor_number);
1424}
1425
1426
1427AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1428 ASSERT(GetType(descriptor_number) == CALLBACKS);
1429 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1430 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1431}
1432
1433
1434bool DescriptorArray::IsProperty(int descriptor_number) {
1435 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1436}
1437
1438
1439bool DescriptorArray::IsTransition(int descriptor_number) {
1440 PropertyType t = GetType(descriptor_number);
1441 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1442}
1443
1444
1445bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1446 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1447}
1448
1449
1450bool DescriptorArray::IsDontEnum(int descriptor_number) {
1451 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1452}
1453
1454
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001455void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1456 desc->Init(GetKey(descriptor_number),
1457 GetValue(descriptor_number),
1458 GetDetails(descriptor_number));
1459}
1460
1461
1462void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1463 // Range check.
1464 ASSERT(descriptor_number < number_of_descriptors());
1465
1466 // Make sure non of the elements in desc are in new space.
1467 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1468 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1469
1470 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1471 FixedArray* content_array = GetContentArray();
1472 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1473 fast_set(content_array, ToDetailsIndex(descriptor_number),
1474 desc->GetDetails().AsSmi());
1475}
1476
1477
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001478void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1479 Descriptor desc;
1480 src->Get(src_index, &desc);
1481 Set(index, &desc);
1482}
1483
1484
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001485void DescriptorArray::Swap(int first, int second) {
1486 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1487 FixedArray* content_array = GetContentArray();
1488 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1489 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1490}
1491
1492
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001493bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001494 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001495 if (!max_index_object->IsSmi()) return false;
1496 return 0 !=
1497 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1498}
1499
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001500uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001501 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001502 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001503 if (!max_index_object->IsSmi()) return 0;
1504 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1505 return value >> kRequiresSlowElementsTagSize;
1506}
1507
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001508void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001509 set(kMaxNumberKeyIndex,
1510 Smi::FromInt(kRequiresSlowElementsMask),
1511 SKIP_WRITE_BARRIER);
1512}
1513
1514
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001515// ------------------------------------
1516// Cast operations
1517
1518
1519CAST_ACCESSOR(FixedArray)
1520CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001521CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001522CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001523CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001524CAST_ACCESSOR(String)
1525CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001526CAST_ACCESSOR(SeqAsciiString)
1527CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001528CAST_ACCESSOR(ConsString)
1529CAST_ACCESSOR(SlicedString)
1530CAST_ACCESSOR(ExternalString)
1531CAST_ACCESSOR(ExternalAsciiString)
1532CAST_ACCESSOR(ExternalTwoByteString)
1533CAST_ACCESSOR(JSObject)
1534CAST_ACCESSOR(Smi)
1535CAST_ACCESSOR(Failure)
1536CAST_ACCESSOR(HeapObject)
1537CAST_ACCESSOR(HeapNumber)
1538CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001539CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540CAST_ACCESSOR(SharedFunctionInfo)
1541CAST_ACCESSOR(Map)
1542CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001543CAST_ACCESSOR(GlobalObject)
1544CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545CAST_ACCESSOR(JSGlobalObject)
1546CAST_ACCESSOR(JSBuiltinsObject)
1547CAST_ACCESSOR(Code)
1548CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001549CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001550CAST_ACCESSOR(Proxy)
1551CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001552CAST_ACCESSOR(PixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001553CAST_ACCESSOR(Struct)
1554
1555
1556#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1557 STRUCT_LIST(MAKE_STRUCT_CAST)
1558#undef MAKE_STRUCT_CAST
1559
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001560
1561template <typename Shape, typename Key>
1562HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001563 ASSERT(obj->IsHashTable());
1564 return reinterpret_cast<HashTable*>(obj);
1565}
1566
1567
1568INT_ACCESSORS(Array, length, kLengthOffset)
1569
1570
1571bool String::Equals(String* other) {
1572 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001573 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1574 return false;
1575 }
1576 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001577}
1578
1579
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001580int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001581 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1582
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001583 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1584 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1585 ASSERT(kLongStringTag == 0);
1586
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001587 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001588}
1589
1590
1591void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001592 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1593 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1594 ASSERT(kLongStringTag == 0);
1595
1596 WRITE_INT_FIELD(this,
1597 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001598 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599}
1600
1601
ager@chromium.org7c537e22008-10-16 08:43:32 +00001602uint32_t String::length_field() {
1603 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001604}
1605
1606
ager@chromium.org7c537e22008-10-16 08:43:32 +00001607void String::set_length_field(uint32_t value) {
1608 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001609}
1610
1611
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001612Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001613 // We don't need to flatten strings that are already flat. Since this code
1614 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001615 if (!IsFlat()) {
1616 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001617 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001618 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001619}
1620
1621
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001622uint16_t String::Get(int index) {
1623 ASSERT(index >= 0 && index < length());
1624 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001625 case kSeqStringTag | kAsciiStringTag:
1626 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1627 case kSeqStringTag | kTwoByteStringTag:
1628 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1629 case kConsStringTag | kAsciiStringTag:
1630 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001631 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001632 case kSlicedStringTag | kAsciiStringTag:
1633 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001634 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001635 case kExternalStringTag | kAsciiStringTag:
1636 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1637 case kExternalStringTag | kTwoByteStringTag:
1638 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001639 default:
1640 break;
1641 }
1642
1643 UNREACHABLE();
1644 return 0;
1645}
1646
1647
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001648void String::Set(int index, uint16_t value) {
1649 ASSERT(index >= 0 && index < length());
1650 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001651
ager@chromium.org5ec48922009-05-05 07:25:34 +00001652 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001653 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1654 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001655}
1656
1657
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001658bool String::IsFlat() {
1659 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001660 case kConsStringTag: {
1661 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001662 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001663 return second->length() == 0;
1664 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001665 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001666 StringRepresentationTag tag =
1667 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001668 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001669 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001670 default:
1671 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001672 }
1673}
1674
1675
ager@chromium.org7c537e22008-10-16 08:43:32 +00001676uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001677 ASSERT(index >= 0 && index < length());
1678 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1679}
1680
1681
ager@chromium.org7c537e22008-10-16 08:43:32 +00001682void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001683 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1684 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1685 static_cast<byte>(value));
1686}
1687
1688
ager@chromium.org7c537e22008-10-16 08:43:32 +00001689Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001690 return FIELD_ADDR(this, kHeaderSize);
1691}
1692
1693
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001694char* SeqAsciiString::GetChars() {
1695 return reinterpret_cast<char*>(GetCharsAddress());
1696}
1697
1698
ager@chromium.org7c537e22008-10-16 08:43:32 +00001699Address SeqTwoByteString::GetCharsAddress() {
1700 return FIELD_ADDR(this, kHeaderSize);
1701}
1702
1703
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001704uc16* SeqTwoByteString::GetChars() {
1705 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1706}
1707
1708
ager@chromium.org7c537e22008-10-16 08:43:32 +00001709uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001710 ASSERT(index >= 0 && index < length());
1711 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1712}
1713
1714
ager@chromium.org7c537e22008-10-16 08:43:32 +00001715void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001716 ASSERT(index >= 0 && index < length());
1717 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1718}
1719
1720
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001721int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001722 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1723
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001724 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1725 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1726 ASSERT(kLongStringTag == 0);
1727
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001728 // Use the map (and not 'this') to compute the size tag, since
1729 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001730 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001731
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001732 return SizeFor(length);
1733}
1734
1735
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001736int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001737 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1738
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001739 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1740 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1741 ASSERT(kLongStringTag == 0);
1742
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001743 // Use the map (and not 'this') to compute the size tag, since
1744 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001745 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001746
1747 return SizeFor(length);
1748}
1749
1750
ager@chromium.org870a0b62008-11-04 11:43:05 +00001751String* ConsString::first() {
1752 return String::cast(READ_FIELD(this, kFirstOffset));
1753}
1754
1755
1756Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001757 return READ_FIELD(this, kFirstOffset);
1758}
1759
1760
ager@chromium.org870a0b62008-11-04 11:43:05 +00001761void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001762 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001763 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001764}
1765
1766
ager@chromium.org870a0b62008-11-04 11:43:05 +00001767String* ConsString::second() {
1768 return String::cast(READ_FIELD(this, kSecondOffset));
1769}
1770
1771
1772Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001773 return READ_FIELD(this, kSecondOffset);
1774}
1775
1776
ager@chromium.org870a0b62008-11-04 11:43:05 +00001777void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001778 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001779 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001780}
1781
1782
ager@chromium.org870a0b62008-11-04 11:43:05 +00001783String* SlicedString::buffer() {
1784 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001785}
1786
1787
ager@chromium.org870a0b62008-11-04 11:43:05 +00001788void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001789 WRITE_FIELD(this, kBufferOffset, buffer);
1790 WRITE_BARRIER(this, kBufferOffset);
1791}
1792
1793
1794int SlicedString::start() {
1795 return READ_INT_FIELD(this, kStartOffset);
1796}
1797
1798
1799void SlicedString::set_start(int start) {
1800 WRITE_INT_FIELD(this, kStartOffset, start);
1801}
1802
1803
1804ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1805 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1806}
1807
1808
1809void ExternalAsciiString::set_resource(
1810 ExternalAsciiString::Resource* resource) {
1811 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1812}
1813
1814
ager@chromium.org6f10e412009-02-13 10:11:16 +00001815Map* ExternalAsciiString::StringMap(int length) {
1816 Map* map;
1817 // Number of characters: determines the map.
1818 if (length <= String::kMaxShortStringSize) {
1819 map = Heap::short_external_ascii_string_map();
1820 } else if (length <= String::kMaxMediumStringSize) {
1821 map = Heap::medium_external_ascii_string_map();
1822 } else {
1823 map = Heap::long_external_ascii_string_map();
1824 }
1825 return map;
1826}
1827
1828
1829Map* ExternalAsciiString::SymbolMap(int length) {
1830 Map* map;
1831 // Number of characters: determines the map.
1832 if (length <= String::kMaxShortStringSize) {
1833 map = Heap::short_external_ascii_symbol_map();
1834 } else if (length <= String::kMaxMediumStringSize) {
1835 map = Heap::medium_external_ascii_symbol_map();
1836 } else {
1837 map = Heap::long_external_ascii_symbol_map();
1838 }
1839 return map;
1840}
1841
1842
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001843ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1844 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1845}
1846
1847
1848void ExternalTwoByteString::set_resource(
1849 ExternalTwoByteString::Resource* resource) {
1850 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1851}
1852
1853
ager@chromium.org6f10e412009-02-13 10:11:16 +00001854Map* ExternalTwoByteString::StringMap(int length) {
1855 Map* map;
1856 // Number of characters: determines the map.
1857 if (length <= String::kMaxShortStringSize) {
1858 map = Heap::short_external_string_map();
1859 } else if (length <= String::kMaxMediumStringSize) {
1860 map = Heap::medium_external_string_map();
1861 } else {
1862 map = Heap::long_external_string_map();
1863 }
1864 return map;
1865}
1866
1867
1868Map* ExternalTwoByteString::SymbolMap(int length) {
1869 Map* map;
1870 // Number of characters: determines the map.
1871 if (length <= String::kMaxShortStringSize) {
1872 map = Heap::short_external_symbol_map();
1873 } else if (length <= String::kMaxMediumStringSize) {
1874 map = Heap::medium_external_symbol_map();
1875 } else {
1876 map = Heap::long_external_symbol_map();
1877 }
1878 return map;
1879}
1880
1881
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001882byte ByteArray::get(int index) {
1883 ASSERT(index >= 0 && index < this->length());
1884 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1885}
1886
1887
1888void ByteArray::set(int index, byte value) {
1889 ASSERT(index >= 0 && index < this->length());
1890 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1891}
1892
1893
1894int ByteArray::get_int(int index) {
1895 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1896 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1897}
1898
1899
1900ByteArray* ByteArray::FromDataStartAddress(Address address) {
1901 ASSERT_TAG_ALIGNED(address);
1902 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1903}
1904
1905
1906Address ByteArray::GetDataStartAddress() {
1907 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1908}
1909
1910
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001911uint8_t* PixelArray::external_pointer() {
1912 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1913 return reinterpret_cast<uint8_t*>(ptr);
1914}
1915
1916
1917void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1918 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1919 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1920}
1921
1922
1923uint8_t PixelArray::get(int index) {
1924 ASSERT((index >= 0) && (index < this->length()));
1925 uint8_t* ptr = external_pointer();
1926 return ptr[index];
1927}
1928
1929
1930void PixelArray::set(int index, uint8_t value) {
1931 ASSERT((index >= 0) && (index < this->length()));
1932 uint8_t* ptr = external_pointer();
1933 ptr[index] = value;
1934}
1935
1936
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001937int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001938 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1939}
1940
1941
1942int Map::inobject_properties() {
1943 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001944}
1945
1946
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001947int Map::pre_allocated_property_fields() {
1948 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1949}
1950
1951
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001952int HeapObject::SizeFromMap(Map* map) {
1953 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001954 // Only inline the most frequent cases.
1955 if (instance_type == JS_OBJECT_TYPE ||
1956 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1957 (kStringTag | kConsStringTag) ||
1958 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001959 if (instance_type == FIXED_ARRAY_TYPE) {
1960 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1961 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001962 if (instance_type == BYTE_ARRAY_TYPE) {
1963 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1964 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001965 // Otherwise do the general size computation.
1966 return SlowSizeFromMap(map);
1967}
1968
1969
1970void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001971 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001972 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001973 ASSERT(0 <= value && value < 256);
1974 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1975}
1976
1977
ager@chromium.org7c537e22008-10-16 08:43:32 +00001978void Map::set_inobject_properties(int value) {
1979 ASSERT(0 <= value && value < 256);
1980 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1981}
1982
1983
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001984void Map::set_pre_allocated_property_fields(int value) {
1985 ASSERT(0 <= value && value < 256);
1986 WRITE_BYTE_FIELD(this,
1987 kPreAllocatedPropertyFieldsOffset,
1988 static_cast<byte>(value));
1989}
1990
1991
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001992InstanceType Map::instance_type() {
1993 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1994}
1995
1996
1997void Map::set_instance_type(InstanceType value) {
1998 ASSERT(0 <= value && value < 256);
1999 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2000}
2001
2002
2003int Map::unused_property_fields() {
2004 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2005}
2006
2007
2008void Map::set_unused_property_fields(int value) {
2009 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2010}
2011
2012
2013byte Map::bit_field() {
2014 return READ_BYTE_FIELD(this, kBitFieldOffset);
2015}
2016
2017
2018void Map::set_bit_field(byte value) {
2019 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2020}
2021
2022
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002023byte Map::bit_field2() {
2024 return READ_BYTE_FIELD(this, kBitField2Offset);
2025}
2026
2027
2028void Map::set_bit_field2(byte value) {
2029 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2030}
2031
2032
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002033void Map::set_non_instance_prototype(bool value) {
2034 if (value) {
2035 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2036 } else {
2037 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2038 }
2039}
2040
2041
2042bool Map::has_non_instance_prototype() {
2043 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2044}
2045
2046
ager@chromium.org870a0b62008-11-04 11:43:05 +00002047void Map::set_is_access_check_needed(bool access_check_needed) {
2048 if (access_check_needed) {
2049 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2050 } else {
2051 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2052 }
2053}
2054
2055
2056bool Map::is_access_check_needed() {
2057 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2058}
2059
2060
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002061Code::Flags Code::flags() {
2062 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2063}
2064
2065
2066void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002067 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002068 // Make sure that all call stubs have an arguments count.
2069 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2070 ExtractArgumentsCountFromFlags(flags) >= 0);
2071 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2072}
2073
2074
2075Code::Kind Code::kind() {
2076 return ExtractKindFromFlags(flags());
2077}
2078
2079
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002080InLoopFlag Code::ic_in_loop() {
2081 return ExtractICInLoopFromFlags(flags());
2082}
2083
2084
kasper.lund7276f142008-07-30 08:49:36 +00002085InlineCacheState Code::ic_state() {
2086 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002087 // Only allow uninitialized or debugger states for non-IC code
2088 // objects. This is used in the debugger to determine whether or not
2089 // a call to code object has been replaced with a debug break call.
2090 ASSERT(is_inline_cache_stub() ||
2091 result == UNINITIALIZED ||
2092 result == DEBUG_BREAK ||
2093 result == DEBUG_PREPARE_STEP_IN);
2094 return result;
2095}
2096
2097
2098PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002099 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002100 return ExtractTypeFromFlags(flags());
2101}
2102
2103
2104int Code::arguments_count() {
2105 ASSERT(is_call_stub() || kind() == STUB);
2106 return ExtractArgumentsCountFromFlags(flags());
2107}
2108
2109
2110CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002111 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002112 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2113 kStubMajorKeyOffset));
2114}
2115
2116
2117void Code::set_major_key(CodeStub::Major major) {
2118 ASSERT(kind() == STUB);
2119 ASSERT(0 <= major && major < 256);
2120 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002121}
2122
2123
2124bool Code::is_inline_cache_stub() {
2125 Kind kind = this->kind();
2126 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2127}
2128
2129
2130Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002131 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002132 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002133 PropertyType type,
2134 int argc) {
2135 // Compute the bit mask.
2136 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002137 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002138 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002139 bits |= type << kFlagsTypeShift;
2140 bits |= argc << kFlagsArgumentsCountShift;
2141 // Cast to flags and validate result before returning it.
2142 Flags result = static_cast<Flags>(bits);
2143 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002144 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002145 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002146 ASSERT(ExtractTypeFromFlags(result) == type);
2147 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2148 return result;
2149}
2150
2151
2152Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2153 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002154 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002155 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002156 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002157}
2158
2159
2160Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2161 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2162 return static_cast<Kind>(bits);
2163}
2164
2165
kasper.lund7276f142008-07-30 08:49:36 +00002166InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2167 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002168 return static_cast<InlineCacheState>(bits);
2169}
2170
2171
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002172InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2173 int bits = (flags & kFlagsICInLoopMask);
2174 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2175}
2176
2177
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002178PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2179 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2180 return static_cast<PropertyType>(bits);
2181}
2182
2183
2184int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2185 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2186}
2187
2188
2189Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2190 int bits = flags & ~kFlagsTypeMask;
2191 return static_cast<Flags>(bits);
2192}
2193
2194
ager@chromium.org8bb60582008-12-11 12:02:20 +00002195Code* Code::GetCodeFromTargetAddress(Address address) {
2196 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2197 // GetCodeFromTargetAddress might be called when marking objects during mark
2198 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2199 // Code::cast. Code::cast does not work when the object's map is
2200 // marked.
2201 Code* result = reinterpret_cast<Code*>(code);
2202 return result;
2203}
2204
2205
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002206Object* Map::prototype() {
2207 return READ_FIELD(this, kPrototypeOffset);
2208}
2209
2210
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002211void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002212 ASSERT(value->IsNull() || value->IsJSObject());
2213 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002214 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002215}
2216
2217
2218ACCESSORS(Map, instance_descriptors, DescriptorArray,
2219 kInstanceDescriptorsOffset)
2220ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2221ACCESSORS(Map, constructor, Object, kConstructorOffset)
2222
2223ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2224ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2225
2226ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2227ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002228ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002229
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002230ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002231
2232ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2233ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2234ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2235ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2236ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2237
2238ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2239ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2240ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2241
2242ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2243ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2244ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2245ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2246ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2247ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2248
2249ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2250ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2251
2252ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2253ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2254
2255ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2256ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002257ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2258 kPropertyAccessorsOffset)
2259ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2260 kPrototypeTemplateOffset)
2261ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2262ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2263 kNamedPropertyHandlerOffset)
2264ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2265 kIndexedPropertyHandlerOffset)
2266ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2267 kInstanceTemplateOffset)
2268ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2269ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002270ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2271 kInstanceCallHandlerOffset)
2272ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2273 kAccessCheckInfoOffset)
2274ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2275
2276ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002277ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2278 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002279
2280ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2281ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2282
2283ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2284
2285ACCESSORS(Script, source, Object, kSourceOffset)
2286ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002287ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002288ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2289ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002290ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002291ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002292ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2293ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002294ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002295ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002296ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2297ACCESSORS(Script, eval_from_instructions_offset, Smi,
2298 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002299
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002300#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002301ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2302ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2303ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2304ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2305
2306ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2307ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2308ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2309ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002310#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002312ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002313ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2314ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2315 kInstanceClassNameOffset)
2316ACCESSORS(SharedFunctionInfo, function_data, Object,
2317 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002318ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2319ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002320ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002321ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2322 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002323
2324BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2325 kHiddenPrototypeBit)
2326BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2327BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2328 kNeedsAccessCheckBit)
2329BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2330 kIsExpressionBit)
2331BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2332 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002333BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2334 has_only_this_property_assignments,
2335 kHasOnlyThisPropertyAssignments)
2336BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2337 has_only_simple_this_property_assignments,
2338 kHasOnlySimpleThisPropertyAssignments)
2339
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002340
2341INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2342INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2343 kFormalParameterCountOffset)
2344INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2345 kExpectedNofPropertiesOffset)
2346INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2347 kStartPositionAndTypeOffset)
2348INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2349INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2350 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002351INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2352 kCompilerHintsOffset)
2353INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2354 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002355
2356
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002357void SharedFunctionInfo::DontAdaptArguments() {
2358 ASSERT(code()->kind() == Code::BUILTIN);
2359 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2360}
2361
2362
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002363int SharedFunctionInfo::start_position() {
2364 return start_position_and_type() >> kStartPositionShift;
2365}
2366
2367
2368void SharedFunctionInfo::set_start_position(int start_position) {
2369 set_start_position_and_type((start_position << kStartPositionShift)
2370 | (start_position_and_type() & ~kStartPositionMask));
2371}
2372
2373
2374Code* SharedFunctionInfo::code() {
2375 return Code::cast(READ_FIELD(this, kCodeOffset));
2376}
2377
2378
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002379void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002380 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002381 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002382}
2383
2384
2385bool SharedFunctionInfo::is_compiled() {
2386 // TODO(1242782): Create a code kind for uncompiled code.
2387 return code()->kind() != Code::STUB;
2388}
2389
2390
2391bool JSFunction::IsBoilerplate() {
2392 return map() == Heap::boilerplate_function_map();
2393}
2394
2395
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002396bool JSFunction::IsBuiltin() {
2397 return context()->global()->IsJSBuiltinsObject();
2398}
2399
2400
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002401bool JSObject::IsLoaded() {
2402 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002403}
2404
2405
2406Code* JSFunction::code() {
2407 return shared()->code();
2408}
2409
2410
2411void JSFunction::set_code(Code* value) {
2412 shared()->set_code(value);
2413}
2414
2415
2416Context* JSFunction::context() {
2417 return Context::cast(READ_FIELD(this, kContextOffset));
2418}
2419
2420
2421Object* JSFunction::unchecked_context() {
2422 return READ_FIELD(this, kContextOffset);
2423}
2424
2425
2426void JSFunction::set_context(Object* value) {
2427 ASSERT(value == Heap::undefined_value() || value->IsContext());
2428 WRITE_FIELD(this, kContextOffset, value);
2429 WRITE_BARRIER(this, kContextOffset);
2430}
2431
2432ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2433 kPrototypeOrInitialMapOffset)
2434
2435
2436Map* JSFunction::initial_map() {
2437 return Map::cast(prototype_or_initial_map());
2438}
2439
2440
2441void JSFunction::set_initial_map(Map* value) {
2442 set_prototype_or_initial_map(value);
2443}
2444
2445
2446bool JSFunction::has_initial_map() {
2447 return prototype_or_initial_map()->IsMap();
2448}
2449
2450
2451bool JSFunction::has_instance_prototype() {
2452 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2453}
2454
2455
2456bool JSFunction::has_prototype() {
2457 return map()->has_non_instance_prototype() || has_instance_prototype();
2458}
2459
2460
2461Object* JSFunction::instance_prototype() {
2462 ASSERT(has_instance_prototype());
2463 if (has_initial_map()) return initial_map()->prototype();
2464 // When there is no initial map and the prototype is a JSObject, the
2465 // initial map field is used for the prototype field.
2466 return prototype_or_initial_map();
2467}
2468
2469
2470Object* JSFunction::prototype() {
2471 ASSERT(has_prototype());
2472 // If the function's prototype property has been set to a non-JSObject
2473 // value, that value is stored in the constructor field of the map.
2474 if (map()->has_non_instance_prototype()) return map()->constructor();
2475 return instance_prototype();
2476}
2477
2478
2479bool JSFunction::is_compiled() {
2480 return shared()->is_compiled();
2481}
2482
2483
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002484int JSFunction::NumberOfLiterals() {
2485 return literals()->length();
2486}
2487
2488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002489Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2490 ASSERT(0 <= id && id < kJSBuiltinsCount);
2491 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2492}
2493
2494
2495void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2496 Object* value) {
2497 ASSERT(0 <= id && id < kJSBuiltinsCount);
2498 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2499 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2500}
2501
2502
2503Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002504 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002505}
2506
2507
2508void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002509 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002510}
2511
2512
2513void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2514 visitor->VisitExternalReference(
2515 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2516}
2517
2518
2519ACCESSORS(JSValue, value, Object, kValueOffset)
2520
2521
2522JSValue* JSValue::cast(Object* obj) {
2523 ASSERT(obj->IsJSValue());
2524 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2525 return reinterpret_cast<JSValue*>(obj);
2526}
2527
2528
2529INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2530INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2531INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2532
2533
2534Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002535 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002536}
2537
2538
2539void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002540 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002541}
2542
2543
2544byte* Code::instruction_start() {
2545 return FIELD_ADDR(this, kHeaderSize);
2546}
2547
2548
2549int Code::body_size() {
2550 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2551}
2552
2553
2554byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002555 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002556}
2557
2558
2559byte* Code::entry() {
2560 return instruction_start();
2561}
2562
2563
2564bool Code::contains(byte* pc) {
2565 return (instruction_start() <= pc) &&
2566 (pc < instruction_start() + instruction_size());
2567}
2568
2569
2570byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002571 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002572}
2573
2574
2575ACCESSORS(JSArray, length, Object, kLengthOffset)
2576
2577
ager@chromium.org236ad962008-09-25 09:45:57 +00002578ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002579
2580
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002581JSRegExp::Type JSRegExp::TypeTag() {
2582 Object* data = this->data();
2583 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2584 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2585 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002586}
2587
2588
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002589int JSRegExp::CaptureCount() {
2590 switch (TypeTag()) {
2591 case ATOM:
2592 return 0;
2593 case IRREGEXP:
2594 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2595 default:
2596 UNREACHABLE();
2597 return -1;
2598 }
2599}
2600
2601
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002602JSRegExp::Flags JSRegExp::GetFlags() {
2603 ASSERT(this->data()->IsFixedArray());
2604 Object* data = this->data();
2605 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2606 return Flags(smi->value());
2607}
2608
2609
2610String* JSRegExp::Pattern() {
2611 ASSERT(this->data()->IsFixedArray());
2612 Object* data = this->data();
2613 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2614 return pattern;
2615}
2616
2617
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002618Object* JSRegExp::DataAt(int index) {
2619 ASSERT(TypeTag() != NOT_COMPILED);
2620 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002621}
2622
2623
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002624void JSRegExp::SetDataAt(int index, Object* value) {
2625 ASSERT(TypeTag() != NOT_COMPILED);
2626 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2627 FixedArray::cast(data())->set(index, value);
2628}
2629
2630
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002631JSObject::ElementsKind JSObject::GetElementsKind() {
2632 Array* array = elements();
2633 if (array->IsFixedArray()) {
2634 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2635 if (array->map() == Heap::fixed_array_map()) {
2636 return FAST_ELEMENTS;
2637 }
2638 ASSERT(array->IsDictionary());
2639 return DICTIONARY_ELEMENTS;
2640 }
2641 ASSERT(array->IsPixelArray());
2642 return PIXEL_ELEMENTS;
2643}
2644
2645
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002646bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002647 return GetElementsKind() == FAST_ELEMENTS;
2648}
2649
2650
2651bool JSObject::HasDictionaryElements() {
2652 return GetElementsKind() == DICTIONARY_ELEMENTS;
2653}
2654
2655
2656bool JSObject::HasPixelElements() {
2657 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002658}
2659
2660
2661bool JSObject::HasNamedInterceptor() {
2662 return map()->has_named_interceptor();
2663}
2664
2665
2666bool JSObject::HasIndexedInterceptor() {
2667 return map()->has_indexed_interceptor();
2668}
2669
2670
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002671StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002672 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002673 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002674}
2675
2676
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002677NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002678 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002679 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002680}
2681
2682
2683bool String::HasHashCode() {
2684 return (length_field() & kHashComputedMask) != 0;
2685}
2686
2687
2688uint32_t String::Hash() {
2689 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002690 uint32_t field = length_field();
2691 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002692 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002693 return ComputeAndSetHash();
2694}
2695
2696
ager@chromium.org7c537e22008-10-16 08:43:32 +00002697StringHasher::StringHasher(int length)
2698 : length_(length),
2699 raw_running_hash_(0),
2700 array_index_(0),
2701 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2702 is_first_char_(true),
2703 is_valid_(true) { }
2704
2705
2706bool StringHasher::has_trivial_hash() {
2707 return length_ > String::kMaxMediumStringSize;
2708}
2709
2710
2711void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002712 // Use the Jenkins one-at-a-time hash function to update the hash
2713 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002714 raw_running_hash_ += c;
2715 raw_running_hash_ += (raw_running_hash_ << 10);
2716 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002717 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002718 if (is_array_index_) {
2719 if (c < '0' || c > '9') {
2720 is_array_index_ = false;
2721 } else {
2722 int d = c - '0';
2723 if (is_first_char_) {
2724 is_first_char_ = false;
2725 if (c == '0' && length_ > 1) {
2726 is_array_index_ = false;
2727 return;
2728 }
2729 }
2730 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2731 is_array_index_ = false;
2732 } else {
2733 array_index_ = array_index_ * 10 + d;
2734 }
2735 }
2736 }
2737}
2738
2739
2740void StringHasher::AddCharacterNoIndex(uc32 c) {
2741 ASSERT(!is_array_index());
2742 raw_running_hash_ += c;
2743 raw_running_hash_ += (raw_running_hash_ << 10);
2744 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2745}
2746
2747
2748uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002749 // Get the calculated raw hash value and do some more bit ops to distribute
2750 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002751 uint32_t result = raw_running_hash_;
2752 result += (result << 3);
2753 result ^= (result >> 11);
2754 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002755 if (result == 0) {
2756 result = 27;
2757 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002758 return result;
2759}
2760
2761
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002762bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002763 uint32_t field = length_field();
2764 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002765 return SlowAsArrayIndex(index);
2766}
2767
2768
2769Object* JSObject::GetPrototype() {
2770 return JSObject::cast(this)->map()->prototype();
2771}
2772
2773
2774PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2775 return GetPropertyAttributeWithReceiver(this, key);
2776}
2777
2778
2779bool JSObject::HasElement(uint32_t index) {
2780 return HasElementWithReceiver(this, index);
2781}
2782
2783
2784bool AccessorInfo::all_can_read() {
2785 return BooleanBit::get(flag(), kAllCanReadBit);
2786}
2787
2788
2789void AccessorInfo::set_all_can_read(bool value) {
2790 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2791}
2792
2793
2794bool AccessorInfo::all_can_write() {
2795 return BooleanBit::get(flag(), kAllCanWriteBit);
2796}
2797
2798
2799void AccessorInfo::set_all_can_write(bool value) {
2800 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2801}
2802
2803
ager@chromium.org870a0b62008-11-04 11:43:05 +00002804bool AccessorInfo::prohibits_overwriting() {
2805 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2806}
2807
2808
2809void AccessorInfo::set_prohibits_overwriting(bool value) {
2810 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2811}
2812
2813
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002814PropertyAttributes AccessorInfo::property_attributes() {
2815 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2816}
2817
2818
2819void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2820 ASSERT(AttributesField::is_valid(attributes));
2821 int rest_value = flag()->value() & ~AttributesField::mask();
2822 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2823}
2824
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002825template<typename Shape, typename Key>
2826void Dictionary<Shape, Key>::SetEntry(int entry,
2827 Object* key,
2828 Object* value,
2829 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002830 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002831 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2832 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2833 FixedArray::set(index, key, mode);
2834 FixedArray::set(index+1, value, mode);
2835 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002836}
2837
2838
2839void Map::ClearCodeCache() {
2840 // No write barrier is needed since empty_fixed_array is not in new space.
2841 // Please note this function is used during marking:
2842 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002843 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2844 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002845}
2846
2847
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002848void JSArray::EnsureSize(int required_size) {
2849 ASSERT(HasFastElements());
2850 if (elements()->length() >= required_size) return;
2851 Expand(required_size);
2852}
2853
2854
ager@chromium.org7c537e22008-10-16 08:43:32 +00002855void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002856 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002857 set_elements(storage);
2858}
2859
2860
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002861Object* FixedArray::Copy() {
2862 if (length() == 0) return this;
2863 return Heap::CopyFixedArray(this);
2864}
2865
2866
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002867#undef CAST_ACCESSOR
2868#undef INT_ACCESSORS
2869#undef SMI_ACCESSORS
2870#undef ACCESSORS
2871#undef FIELD_ADDR
2872#undef READ_FIELD
2873#undef WRITE_FIELD
2874#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002875#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002876#undef READ_MEMADDR_FIELD
2877#undef WRITE_MEMADDR_FIELD
2878#undef READ_DOUBLE_FIELD
2879#undef WRITE_DOUBLE_FIELD
2880#undef READ_INT_FIELD
2881#undef WRITE_INT_FIELD
2882#undef READ_SHORT_FIELD
2883#undef WRITE_SHORT_FIELD
2884#undef READ_BYTE_FIELD
2885#undef WRITE_BYTE_FIELD
2886
2887
2888} } // namespace v8::internal
2889
2890#endif // V8_OBJECTS_INL_H_