blob: cb7b7c881d0c5853138e2e48ad5abe0886816de2 [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() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000134 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135}
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
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000303STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
304 Internals::kFullStringRepresentationMask);
305
306
ager@chromium.org870a0b62008-11-04 11:43:05 +0000307uint32_t StringShape::size_tag() {
308 return (type_ & kStringSizeMask);
309}
310
311
312bool StringShape::IsSequentialAscii() {
313 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
314}
315
316
317bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000318 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000319}
320
321
322bool StringShape::IsExternalAscii() {
323 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
324}
325
326
327bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000328 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000329}
330
331
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000332STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
333 Internals::kExternalTwoByteRepresentationTag);
334
335
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000336uc32 FlatStringReader::Get(int index) {
337 ASSERT(0 <= index && index <= length_);
338 if (is_ascii_) {
339 return static_cast<const byte*>(start_)[index];
340 } else {
341 return static_cast<const uc16*>(start_)[index];
342 }
343}
344
345
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000346bool Object::IsNumber() {
347 return IsSmi() || IsHeapNumber();
348}
349
350
351bool Object::IsByteArray() {
352 return Object::IsHeapObject()
353 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
354}
355
356
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000357bool Object::IsPixelArray() {
358 return Object::IsHeapObject() &&
359 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
360}
361
362
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000363bool Object::IsFailure() {
364 return HAS_FAILURE_TAG(this);
365}
366
367
368bool Object::IsRetryAfterGC() {
369 return HAS_FAILURE_TAG(this)
370 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
371}
372
373
ager@chromium.org7c537e22008-10-16 08:43:32 +0000374bool Object::IsOutOfMemoryFailure() {
375 return HAS_FAILURE_TAG(this)
376 && Failure::cast(this)->IsOutOfMemoryException();
377}
378
379
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380bool Object::IsException() {
381 return this == Failure::Exception();
382}
383
384
385bool Object::IsJSObject() {
386 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000387 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388}
389
390
ager@chromium.org32912102009-01-16 10:38:43 +0000391bool Object::IsJSContextExtensionObject() {
392 return IsHeapObject()
393 && (HeapObject::cast(this)->map()->instance_type() ==
394 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
395}
396
397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398bool Object::IsMap() {
399 return Object::IsHeapObject()
400 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
401}
402
403
404bool Object::IsFixedArray() {
405 return Object::IsHeapObject()
406 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
407}
408
409
410bool Object::IsDescriptorArray() {
411 return IsFixedArray();
412}
413
414
415bool Object::IsContext() {
416 return Object::IsHeapObject()
417 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000418 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000419 HeapObject::cast(this)->map() == Heap::global_context_map());
420}
421
422
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000423bool Object::IsCatchContext() {
424 return Object::IsHeapObject()
425 && HeapObject::cast(this)->map() == Heap::catch_context_map();
426}
427
428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429bool Object::IsGlobalContext() {
430 return Object::IsHeapObject()
431 && HeapObject::cast(this)->map() == Heap::global_context_map();
432}
433
434
435bool Object::IsJSFunction() {
436 return Object::IsHeapObject()
437 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
438}
439
440
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000441template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000442 return obj->IsJSFunction();
443}
444
445
446bool Object::IsCode() {
447 return Object::IsHeapObject()
448 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
449}
450
451
452bool Object::IsOddball() {
453 return Object::IsHeapObject()
454 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
455}
456
457
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000458bool Object::IsJSGlobalPropertyCell() {
459 return Object::IsHeapObject()
460 && HeapObject::cast(this)->map()->instance_type()
461 == JS_GLOBAL_PROPERTY_CELL_TYPE;
462}
463
464
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000465bool Object::IsSharedFunctionInfo() {
466 return Object::IsHeapObject() &&
467 (HeapObject::cast(this)->map()->instance_type() ==
468 SHARED_FUNCTION_INFO_TYPE);
469}
470
471
472bool Object::IsJSValue() {
473 return Object::IsHeapObject()
474 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
475}
476
477
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000478bool Object::IsStringWrapper() {
479 return IsJSValue() && JSValue::cast(this)->value()->IsString();
480}
481
482
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000483bool Object::IsProxy() {
484 return Object::IsHeapObject()
485 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
486}
487
488
489bool Object::IsBoolean() {
490 return IsTrue() || IsFalse();
491}
492
493
494bool Object::IsJSArray() {
495 return Object::IsHeapObject()
496 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
497}
498
499
ager@chromium.org236ad962008-09-25 09:45:57 +0000500bool Object::IsJSRegExp() {
501 return Object::IsHeapObject()
502 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
503}
504
505
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000506template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507 return obj->IsJSArray();
508}
509
510
511bool Object::IsHashTable() {
512 return Object::IsHeapObject()
513 && HeapObject::cast(this)->map() == Heap::hash_table_map();
514}
515
516
517bool Object::IsDictionary() {
518 return IsHashTable() && this != Heap::symbol_table();
519}
520
521
522bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000523 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524}
525
526
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000527bool Object::IsCompilationCacheTable() {
528 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000529}
530
531
ager@chromium.org236ad962008-09-25 09:45:57 +0000532bool Object::IsMapCache() {
533 return IsHashTable();
534}
535
536
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537bool Object::IsPrimitive() {
538 return IsOddball() || IsNumber() || IsString();
539}
540
541
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000542bool Object::IsJSGlobalProxy() {
543 bool result = IsHeapObject() &&
544 (HeapObject::cast(this)->map()->instance_type() ==
545 JS_GLOBAL_PROXY_TYPE);
546 ASSERT(!result || IsAccessCheckNeeded());
547 return result;
548}
549
550
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000552 if (!IsHeapObject()) return false;
553
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000554 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000555 return type == JS_GLOBAL_OBJECT_TYPE ||
556 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557}
558
559
560bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561 return IsHeapObject() &&
562 (HeapObject::cast(this)->map()->instance_type() ==
563 JS_GLOBAL_OBJECT_TYPE);
564}
565
566
567bool Object::IsJSBuiltinsObject() {
568 return IsHeapObject() &&
569 (HeapObject::cast(this)->map()->instance_type() ==
570 JS_BUILTINS_OBJECT_TYPE);
571}
572
573
574bool Object::IsUndetectableObject() {
575 return IsHeapObject()
576 && HeapObject::cast(this)->map()->is_undetectable();
577}
578
579
580bool Object::IsAccessCheckNeeded() {
581 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000582 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583}
584
585
586bool Object::IsStruct() {
587 if (!IsHeapObject()) return false;
588 switch (HeapObject::cast(this)->map()->instance_type()) {
589#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
590 STRUCT_LIST(MAKE_STRUCT_CASE)
591#undef MAKE_STRUCT_CASE
592 default: return false;
593 }
594}
595
596
597#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
598 bool Object::Is##Name() { \
599 return Object::IsHeapObject() \
600 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
601 }
602 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
603#undef MAKE_STRUCT_PREDICATE
604
605
606bool Object::IsUndefined() {
607 return this == Heap::undefined_value();
608}
609
610
611bool Object::IsTheHole() {
612 return this == Heap::the_hole_value();
613}
614
615
616bool Object::IsNull() {
617 return this == Heap::null_value();
618}
619
620
621bool Object::IsTrue() {
622 return this == Heap::true_value();
623}
624
625
626bool Object::IsFalse() {
627 return this == Heap::false_value();
628}
629
630
631double Object::Number() {
632 ASSERT(IsNumber());
633 return IsSmi()
634 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
635 : reinterpret_cast<HeapNumber*>(this)->value();
636}
637
638
639
640Object* Object::ToSmi() {
641 if (IsSmi()) return this;
642 if (IsHeapNumber()) {
643 double value = HeapNumber::cast(this)->value();
644 int int_value = FastD2I(value);
645 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
646 return Smi::FromInt(int_value);
647 }
648 }
649 return Failure::Exception();
650}
651
652
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000653bool Object::HasSpecificClassOf(String* name) {
654 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
655}
656
657
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000658Object* Object::GetElement(uint32_t index) {
659 return GetElementWithReceiver(this, index);
660}
661
662
663Object* Object::GetProperty(String* key) {
664 PropertyAttributes attributes;
665 return GetPropertyWithReceiver(this, key, &attributes);
666}
667
668
669Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
670 return GetPropertyWithReceiver(this, key, attributes);
671}
672
673
674#define FIELD_ADDR(p, offset) \
675 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
676
677#define READ_FIELD(p, offset) \
678 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
679
680#define WRITE_FIELD(p, offset, value) \
681 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
682
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000683
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684#define WRITE_BARRIER(object, offset) \
685 Heap::RecordWrite(object->address(), offset);
686
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000687// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000688// write due to the assert validating the written value.
689#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
690 if (mode == UPDATE_WRITE_BARRIER) { \
691 Heap::RecordWrite(object->address(), offset); \
692 } else { \
693 ASSERT(mode == SKIP_WRITE_BARRIER); \
694 ASSERT(Heap::InNewSpace(object) || \
695 !Heap::InNewSpace(READ_FIELD(object, offset))); \
696 }
697
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000698#define READ_DOUBLE_FIELD(p, offset) \
699 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
700
701#define WRITE_DOUBLE_FIELD(p, offset, value) \
702 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
703
704#define READ_INT_FIELD(p, offset) \
705 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
706
707#define WRITE_INT_FIELD(p, offset, value) \
708 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
709
ager@chromium.org3e875802009-06-29 08:26:34 +0000710#define READ_INTPTR_FIELD(p, offset) \
711 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
712
713#define WRITE_INTPTR_FIELD(p, offset, value) \
714 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
715
ager@chromium.org7c537e22008-10-16 08:43:32 +0000716#define READ_UINT32_FIELD(p, offset) \
717 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
718
719#define WRITE_UINT32_FIELD(p, offset, value) \
720 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
721
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722#define READ_SHORT_FIELD(p, offset) \
723 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
724
725#define WRITE_SHORT_FIELD(p, offset, value) \
726 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
727
728#define READ_BYTE_FIELD(p, offset) \
729 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
730
731#define WRITE_BYTE_FIELD(p, offset, value) \
732 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
733
734
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000735Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
736 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737}
738
739
740int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000741 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000742}
743
744
745Smi* Smi::FromInt(int value) {
746 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000747 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000748 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000749 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000750 return reinterpret_cast<Smi*>(tagged_value);
751}
752
753
754Smi* Smi::FromIntptr(intptr_t value) {
755 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000756 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
757 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000758}
759
760
761Failure::Type Failure::type() const {
762 return static_cast<Type>(value() & kFailureTypeTagMask);
763}
764
765
766bool Failure::IsInternalError() const {
767 return type() == INTERNAL_ERROR;
768}
769
770
771bool Failure::IsOutOfMemoryException() const {
772 return type() == OUT_OF_MEMORY_EXCEPTION;
773}
774
775
776int Failure::requested() const {
777 const int kShiftBits =
778 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
779 STATIC_ASSERT(kShiftBits >= 0);
780 ASSERT(type() == RETRY_AFTER_GC);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000781 return static_cast<int>(value() >> kShiftBits);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000782}
783
784
785AllocationSpace Failure::allocation_space() const {
786 ASSERT_EQ(RETRY_AFTER_GC, type());
787 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
788 & kSpaceTagMask);
789}
790
791
792Failure* Failure::InternalError() {
793 return Construct(INTERNAL_ERROR);
794}
795
796
797Failure* Failure::Exception() {
798 return Construct(EXCEPTION);
799}
800
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000801
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000802Failure* Failure::OutOfMemoryException() {
803 return Construct(OUT_OF_MEMORY_EXCEPTION);
804}
805
806
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000807intptr_t Failure::value() const {
808 return reinterpret_cast<intptr_t>(this) >> kFailureTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000809}
810
811
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000812Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000813 // Assert that the space encoding fits in the three bytes allotted for it.
814 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000815 intptr_t requested = requested_bytes >> kObjectAlignmentBits;
816 int tag_bits = kSpaceTagSize + kFailureTypeTagSize;
817 if (((requested << tag_bits) >> tag_bits) != requested) {
818 // No room for entire requested size in the bits. Round down to
819 // maximally representable size.
820 requested = static_cast<intptr_t>(
821 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
822 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000823 int value = (requested << kSpaceTagSize) | NEW_SPACE;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000824 return Construct(RETRY_AFTER_GC, value);
825}
826
827
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000828Failure* Failure::Construct(Type type, intptr_t value) {
829 intptr_t info = (static_cast<intptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000830 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000831 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832}
833
834
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000835bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000836#ifdef DEBUG
837 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
838#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000839
840#ifdef V8_TARGET_ARCH_X64
841 // To be representable as a long smi, the value must be a 32-bit integer.
842 bool result = (value == static_cast<int32_t>(value));
843#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 // To be representable as an tagged small integer, the two
845 // most-significant bits of 'value' must be either 00 or 11 due to
846 // sign-extension. To check this we add 01 to the two
847 // most-significant bits, and check if the most-significant bit is 0
848 //
849 // CAUTION: The original code below:
850 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
851 // may lead to incorrect results according to the C language spec, and
852 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
853 // compiler may produce undefined results in case of signed integer
854 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000855 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +0000856#endif
ager@chromium.org9085a012009-05-11 19:22:57 +0000857 ASSERT(result == in_range);
858 return result;
859}
860
861
kasper.lund7276f142008-07-30 08:49:36 +0000862MapWord MapWord::FromMap(Map* map) {
863 return MapWord(reinterpret_cast<uintptr_t>(map));
864}
865
866
867Map* MapWord::ToMap() {
868 return reinterpret_cast<Map*>(value_);
869}
870
871
872bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000873 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000874}
875
876
877MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000878 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
879 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000880}
881
882
883HeapObject* MapWord::ToForwardingAddress() {
884 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000885 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000886}
887
888
889bool MapWord::IsMarked() {
890 return (value_ & kMarkingMask) == 0;
891}
892
893
894void MapWord::SetMark() {
895 value_ &= ~kMarkingMask;
896}
897
898
899void MapWord::ClearMark() {
900 value_ |= kMarkingMask;
901}
902
903
904bool MapWord::IsOverflowed() {
905 return (value_ & kOverflowMask) != 0;
906}
907
908
909void MapWord::SetOverflow() {
910 value_ |= kOverflowMask;
911}
912
913
914void MapWord::ClearOverflow() {
915 value_ &= ~kOverflowMask;
916}
917
918
919MapWord MapWord::EncodeAddress(Address map_address, int offset) {
920 // Offset is the distance in live bytes from the first live object in the
921 // same page. The offset between two objects in the same page should not
922 // exceed the object area size of a page.
923 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
924
925 int compact_offset = offset >> kObjectAlignmentBits;
926 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
927
928 Page* map_page = Page::FromAddress(map_address);
929 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
930
931 int map_page_offset =
932 map_page->Offset(map_address) >> kObjectAlignmentBits;
933
934 uintptr_t encoding =
935 (compact_offset << kForwardingOffsetShift) |
936 (map_page_offset << kMapPageOffsetShift) |
937 (map_page->mc_page_index << kMapPageIndexShift);
938 return MapWord(encoding);
939}
940
941
942Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000943 int map_page_index =
944 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +0000945 ASSERT_MAP_PAGE_INDEX(map_page_index);
946
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000947 int map_page_offset = static_cast<int>(
kasper.lund7276f142008-07-30 08:49:36 +0000948 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000949 << kObjectAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +0000950
951 return (map_space->PageAddress(map_page_index) + map_page_offset);
952}
953
954
955int MapWord::DecodeOffset() {
956 // The offset field is represented in the kForwardingOffsetBits
957 // most-significant bits.
958 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
959 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
960 return offset;
961}
962
963
964MapWord MapWord::FromEncodedAddress(Address address) {
965 return MapWord(reinterpret_cast<uintptr_t>(address));
966}
967
968
969Address MapWord::ToEncodedAddress() {
970 return reinterpret_cast<Address>(value_);
971}
972
973
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000974#ifdef DEBUG
975void HeapObject::VerifyObjectField(int offset) {
976 VerifyPointer(READ_FIELD(this, offset));
977}
978#endif
979
980
981Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000982 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000983}
984
985
986void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000987 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000988}
989
990
kasper.lund7276f142008-07-30 08:49:36 +0000991MapWord HeapObject::map_word() {
992 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
993}
994
995
996void HeapObject::set_map_word(MapWord map_word) {
997 // WRITE_FIELD does not update the remembered set, but there is no need
998 // here.
999 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1000}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001001
1002
1003HeapObject* HeapObject::FromAddress(Address address) {
1004 ASSERT_TAG_ALIGNED(address);
1005 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1006}
1007
1008
1009Address HeapObject::address() {
1010 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1011}
1012
1013
1014int HeapObject::Size() {
1015 return SizeFromMap(map());
1016}
1017
1018
1019void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1020 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1021 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1022}
1023
1024
1025void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1026 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1027}
1028
1029
kasper.lund7276f142008-07-30 08:49:36 +00001030bool HeapObject::IsMarked() {
1031 return map_word().IsMarked();
1032}
1033
1034
1035void HeapObject::SetMark() {
1036 ASSERT(!IsMarked());
1037 MapWord first_word = map_word();
1038 first_word.SetMark();
1039 set_map_word(first_word);
1040}
1041
1042
1043void HeapObject::ClearMark() {
1044 ASSERT(IsMarked());
1045 MapWord first_word = map_word();
1046 first_word.ClearMark();
1047 set_map_word(first_word);
1048}
1049
1050
1051bool HeapObject::IsOverflowed() {
1052 return map_word().IsOverflowed();
1053}
1054
1055
1056void HeapObject::SetOverflow() {
1057 MapWord first_word = map_word();
1058 first_word.SetOverflow();
1059 set_map_word(first_word);
1060}
1061
1062
1063void HeapObject::ClearOverflow() {
1064 ASSERT(IsOverflowed());
1065 MapWord first_word = map_word();
1066 first_word.ClearOverflow();
1067 set_map_word(first_word);
1068}
1069
1070
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071double HeapNumber::value() {
1072 return READ_DOUBLE_FIELD(this, kValueOffset);
1073}
1074
1075
1076void HeapNumber::set_value(double value) {
1077 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1078}
1079
1080
1081ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001082
1083
1084Array* JSObject::elements() {
1085 Object* array = READ_FIELD(this, kElementsOffset);
1086 // In the assert below Dictionary is covered under FixedArray.
1087 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1088 return reinterpret_cast<Array*>(array);
1089}
1090
1091
1092void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1093 // In the assert below Dictionary is covered under FixedArray.
1094 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1095 WRITE_FIELD(this, kElementsOffset, value);
1096 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1097}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001098
1099
1100void JSObject::initialize_properties() {
1101 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1102 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1103}
1104
1105
1106void JSObject::initialize_elements() {
1107 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1108 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1109}
1110
1111
1112ACCESSORS(Oddball, to_string, String, kToStringOffset)
1113ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1114
1115
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001116Object* JSGlobalPropertyCell::value() {
1117 return READ_FIELD(this, kValueOffset);
1118}
1119
1120
1121void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1122 // The write barrier is not used for global property cells.
1123 ASSERT(!val->IsJSGlobalPropertyCell());
1124 WRITE_FIELD(this, kValueOffset, val);
1125}
1126
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001128int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001129 InstanceType type = map()->instance_type();
1130 // Check for the most common kind of JavaScript object before
1131 // falling into the generic switch. This speeds up the internal
1132 // field operations considerably on average.
1133 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1134 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001135 case JS_GLOBAL_PROXY_TYPE:
1136 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001137 case JS_GLOBAL_OBJECT_TYPE:
1138 return JSGlobalObject::kSize;
1139 case JS_BUILTINS_OBJECT_TYPE:
1140 return JSBuiltinsObject::kSize;
1141 case JS_FUNCTION_TYPE:
1142 return JSFunction::kSize;
1143 case JS_VALUE_TYPE:
1144 return JSValue::kSize;
1145 case JS_ARRAY_TYPE:
1146 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001147 case JS_REGEXP_TYPE:
1148 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001149 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001150 return JSObject::kHeaderSize;
1151 default:
1152 UNREACHABLE();
1153 return 0;
1154 }
1155}
1156
1157
1158int JSObject::GetInternalFieldCount() {
1159 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001160 // Make sure to adjust for the number of in-object properties. These
1161 // properties do contribute to the size, but are not internal fields.
1162 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1163 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001164}
1165
1166
1167Object* JSObject::GetInternalField(int index) {
1168 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001169 // Internal objects do follow immediately after the header, whereas in-object
1170 // properties are at the end of the object. Therefore there is no need
1171 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1173}
1174
1175
1176void JSObject::SetInternalField(int index, Object* value) {
1177 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001178 // Internal objects do follow immediately after the header, whereas in-object
1179 // properties are at the end of the object. Therefore there is no need
1180 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001181 int offset = GetHeaderSize() + (kPointerSize * index);
1182 WRITE_FIELD(this, offset, value);
1183 WRITE_BARRIER(this, offset);
1184}
1185
1186
ager@chromium.org7c537e22008-10-16 08:43:32 +00001187// Access fast-case object properties at index. The use of these routines
1188// is needed to correctly distinguish between properties stored in-object and
1189// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001190Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001191 // Adjust for the number of properties stored in the object.
1192 index -= map()->inobject_properties();
1193 if (index < 0) {
1194 int offset = map()->instance_size() + (index * kPointerSize);
1195 return READ_FIELD(this, offset);
1196 } else {
1197 ASSERT(index < properties()->length());
1198 return properties()->get(index);
1199 }
1200}
1201
1202
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001203Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001204 // Adjust for the number of properties stored in the object.
1205 index -= map()->inobject_properties();
1206 if (index < 0) {
1207 int offset = map()->instance_size() + (index * kPointerSize);
1208 WRITE_FIELD(this, offset, value);
1209 WRITE_BARRIER(this, offset);
1210 } else {
1211 ASSERT(index < properties()->length());
1212 properties()->set(index, value);
1213 }
1214 return value;
1215}
1216
1217
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001218Object* JSObject::InObjectPropertyAt(int index) {
1219 // Adjust for the number of properties stored in the object.
1220 index -= map()->inobject_properties();
1221 ASSERT(index < 0);
1222 int offset = map()->instance_size() + (index * kPointerSize);
1223 return READ_FIELD(this, offset);
1224}
1225
1226
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001227Object* JSObject::InObjectPropertyAtPut(int index,
1228 Object* value,
1229 WriteBarrierMode mode) {
1230 // Adjust for the number of properties stored in the object.
1231 index -= map()->inobject_properties();
1232 ASSERT(index < 0);
1233 int offset = map()->instance_size() + (index * kPointerSize);
1234 WRITE_FIELD(this, offset, value);
1235 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1236 return value;
1237}
1238
1239
1240
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001241void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001242 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001243 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001244 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245 }
1246}
1247
1248
1249void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001250 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001251 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001252 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001253 }
1254}
1255
1256
1257bool JSObject::HasFastProperties() {
1258 return !properties()->IsDictionary();
1259}
1260
1261
1262bool Array::IndexFromObject(Object* object, uint32_t* index) {
1263 if (object->IsSmi()) {
1264 int value = Smi::cast(object)->value();
1265 if (value < 0) return false;
1266 *index = value;
1267 return true;
1268 }
1269 if (object->IsHeapNumber()) {
1270 double value = HeapNumber::cast(object)->value();
1271 uint32_t uint_value = static_cast<uint32_t>(value);
1272 if (value == static_cast<double>(uint_value)) {
1273 *index = uint_value;
1274 return true;
1275 }
1276 }
1277 return false;
1278}
1279
1280
1281bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1282 if (!this->IsJSValue()) return false;
1283
1284 JSValue* js_value = JSValue::cast(this);
1285 if (!js_value->value()->IsString()) return false;
1286
1287 String* str = String::cast(js_value->value());
1288 if (index >= (uint32_t)str->length()) return false;
1289
1290 return true;
1291}
1292
1293
1294Object* FixedArray::get(int index) {
1295 ASSERT(index >= 0 && index < this->length());
1296 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1297}
1298
1299
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001300void FixedArray::set(int index, Smi* value) {
1301 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1302 int offset = kHeaderSize + index * kPointerSize;
1303 WRITE_FIELD(this, offset, value);
1304}
1305
1306
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001307void FixedArray::set(int index, Object* value) {
1308 ASSERT(index >= 0 && index < this->length());
1309 int offset = kHeaderSize + index * kPointerSize;
1310 WRITE_FIELD(this, offset, value);
1311 WRITE_BARRIER(this, offset);
1312}
1313
1314
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001315WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001316 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1317 return UPDATE_WRITE_BARRIER;
1318}
1319
1320
1321void FixedArray::set(int index,
1322 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001323 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324 ASSERT(index >= 0 && index < this->length());
1325 int offset = kHeaderSize + index * kPointerSize;
1326 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001327 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001328}
1329
1330
1331void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1332 ASSERT(index >= 0 && index < array->length());
1333 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1334}
1335
1336
1337void FixedArray::set_undefined(int index) {
1338 ASSERT(index >= 0 && index < this->length());
1339 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1340 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1341 Heap::undefined_value());
1342}
1343
1344
ager@chromium.org236ad962008-09-25 09:45:57 +00001345void FixedArray::set_null(int index) {
1346 ASSERT(index >= 0 && index < this->length());
1347 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1348 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1349}
1350
1351
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001352void FixedArray::set_the_hole(int index) {
1353 ASSERT(index >= 0 && index < this->length());
1354 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1355 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1356}
1357
1358
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001359bool DescriptorArray::IsEmpty() {
1360 ASSERT(this == Heap::empty_descriptor_array() ||
1361 this->length() > 2);
1362 return this == Heap::empty_descriptor_array();
1363}
1364
1365
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001366void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1367 Object* tmp = array->get(first);
1368 fast_set(array, first, array->get(second));
1369 fast_set(array, second, tmp);
1370}
1371
1372
1373int DescriptorArray::Search(String* name) {
1374 SLOW_ASSERT(IsSortedNoDuplicates());
1375
1376 // Check for empty descriptor array.
1377 int nof = number_of_descriptors();
1378 if (nof == 0) return kNotFound;
1379
1380 // Fast case: do linear search for small arrays.
1381 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001382 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001383 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001384 }
1385
1386 // Slow case: perform binary search.
1387 return BinarySearch(name, 0, nof - 1);
1388}
1389
1390
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001391String* DescriptorArray::GetKey(int descriptor_number) {
1392 ASSERT(descriptor_number < number_of_descriptors());
1393 return String::cast(get(ToKeyIndex(descriptor_number)));
1394}
1395
1396
1397Object* DescriptorArray::GetValue(int descriptor_number) {
1398 ASSERT(descriptor_number < number_of_descriptors());
1399 return GetContentArray()->get(ToValueIndex(descriptor_number));
1400}
1401
1402
1403Smi* DescriptorArray::GetDetails(int descriptor_number) {
1404 ASSERT(descriptor_number < number_of_descriptors());
1405 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1406}
1407
1408
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001409PropertyType DescriptorArray::GetType(int descriptor_number) {
1410 ASSERT(descriptor_number < number_of_descriptors());
1411 return PropertyDetails(GetDetails(descriptor_number)).type();
1412}
1413
1414
1415int DescriptorArray::GetFieldIndex(int descriptor_number) {
1416 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1417}
1418
1419
1420JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1421 return JSFunction::cast(GetValue(descriptor_number));
1422}
1423
1424
1425Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1426 ASSERT(GetType(descriptor_number) == CALLBACKS);
1427 return GetValue(descriptor_number);
1428}
1429
1430
1431AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1432 ASSERT(GetType(descriptor_number) == CALLBACKS);
1433 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1434 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1435}
1436
1437
1438bool DescriptorArray::IsProperty(int descriptor_number) {
1439 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1440}
1441
1442
1443bool DescriptorArray::IsTransition(int descriptor_number) {
1444 PropertyType t = GetType(descriptor_number);
1445 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1446}
1447
1448
1449bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1450 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1451}
1452
1453
1454bool DescriptorArray::IsDontEnum(int descriptor_number) {
1455 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1456}
1457
1458
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001459void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1460 desc->Init(GetKey(descriptor_number),
1461 GetValue(descriptor_number),
1462 GetDetails(descriptor_number));
1463}
1464
1465
1466void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1467 // Range check.
1468 ASSERT(descriptor_number < number_of_descriptors());
1469
1470 // Make sure non of the elements in desc are in new space.
1471 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1472 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1473
1474 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1475 FixedArray* content_array = GetContentArray();
1476 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1477 fast_set(content_array, ToDetailsIndex(descriptor_number),
1478 desc->GetDetails().AsSmi());
1479}
1480
1481
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001482void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1483 Descriptor desc;
1484 src->Get(src_index, &desc);
1485 Set(index, &desc);
1486}
1487
1488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001489void DescriptorArray::Swap(int first, int second) {
1490 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1491 FixedArray* content_array = GetContentArray();
1492 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1493 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1494}
1495
1496
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001497bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001498 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001499 if (!max_index_object->IsSmi()) return false;
1500 return 0 !=
1501 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1502}
1503
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001504uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001505 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001506 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001507 if (!max_index_object->IsSmi()) return 0;
1508 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1509 return value >> kRequiresSlowElementsTagSize;
1510}
1511
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001512void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001513 set(kMaxNumberKeyIndex,
1514 Smi::FromInt(kRequiresSlowElementsMask),
1515 SKIP_WRITE_BARRIER);
1516}
1517
1518
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001519// ------------------------------------
1520// Cast operations
1521
1522
1523CAST_ACCESSOR(FixedArray)
1524CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001525CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001526CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001527CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001528CAST_ACCESSOR(String)
1529CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001530CAST_ACCESSOR(SeqAsciiString)
1531CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001532CAST_ACCESSOR(ConsString)
1533CAST_ACCESSOR(SlicedString)
1534CAST_ACCESSOR(ExternalString)
1535CAST_ACCESSOR(ExternalAsciiString)
1536CAST_ACCESSOR(ExternalTwoByteString)
1537CAST_ACCESSOR(JSObject)
1538CAST_ACCESSOR(Smi)
1539CAST_ACCESSOR(Failure)
1540CAST_ACCESSOR(HeapObject)
1541CAST_ACCESSOR(HeapNumber)
1542CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001543CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001544CAST_ACCESSOR(SharedFunctionInfo)
1545CAST_ACCESSOR(Map)
1546CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001547CAST_ACCESSOR(GlobalObject)
1548CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001549CAST_ACCESSOR(JSGlobalObject)
1550CAST_ACCESSOR(JSBuiltinsObject)
1551CAST_ACCESSOR(Code)
1552CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001553CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001554CAST_ACCESSOR(Proxy)
1555CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001556CAST_ACCESSOR(PixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557CAST_ACCESSOR(Struct)
1558
1559
1560#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1561 STRUCT_LIST(MAKE_STRUCT_CAST)
1562#undef MAKE_STRUCT_CAST
1563
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001564
1565template <typename Shape, typename Key>
1566HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001567 ASSERT(obj->IsHashTable());
1568 return reinterpret_cast<HashTable*>(obj);
1569}
1570
1571
1572INT_ACCESSORS(Array, length, kLengthOffset)
1573
1574
1575bool String::Equals(String* other) {
1576 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001577 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1578 return false;
1579 }
1580 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001581}
1582
1583
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001584int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1586
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001587 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1588 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1589 ASSERT(kLongStringTag == 0);
1590
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001591 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001592}
1593
1594
1595void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001596 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1597 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1598 ASSERT(kLongStringTag == 0);
1599
1600 WRITE_INT_FIELD(this,
1601 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001602 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001603}
1604
1605
ager@chromium.org7c537e22008-10-16 08:43:32 +00001606uint32_t String::length_field() {
1607 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001608}
1609
1610
ager@chromium.org7c537e22008-10-16 08:43:32 +00001611void String::set_length_field(uint32_t value) {
1612 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001613}
1614
1615
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001616Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001617 // We don't need to flatten strings that are already flat. Since this code
1618 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001619 if (!IsFlat()) {
1620 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001621 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001622 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623}
1624
1625
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001626uint16_t String::Get(int index) {
1627 ASSERT(index >= 0 && index < length());
1628 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001629 case kSeqStringTag | kAsciiStringTag:
1630 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1631 case kSeqStringTag | kTwoByteStringTag:
1632 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1633 case kConsStringTag | kAsciiStringTag:
1634 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001635 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001636 case kSlicedStringTag | kAsciiStringTag:
1637 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001639 case kExternalStringTag | kAsciiStringTag:
1640 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1641 case kExternalStringTag | kTwoByteStringTag:
1642 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643 default:
1644 break;
1645 }
1646
1647 UNREACHABLE();
1648 return 0;
1649}
1650
1651
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001652void String::Set(int index, uint16_t value) {
1653 ASSERT(index >= 0 && index < length());
1654 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001655
ager@chromium.org5ec48922009-05-05 07:25:34 +00001656 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001657 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1658 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001659}
1660
1661
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001662bool String::IsFlat() {
1663 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001664 case kConsStringTag: {
1665 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001666 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001667 return second->length() == 0;
1668 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001669 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001670 StringRepresentationTag tag =
1671 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001672 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001673 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001674 default:
1675 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676 }
1677}
1678
1679
ager@chromium.org7c537e22008-10-16 08:43:32 +00001680uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001681 ASSERT(index >= 0 && index < length());
1682 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1683}
1684
1685
ager@chromium.org7c537e22008-10-16 08:43:32 +00001686void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001687 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1688 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1689 static_cast<byte>(value));
1690}
1691
1692
ager@chromium.org7c537e22008-10-16 08:43:32 +00001693Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001694 return FIELD_ADDR(this, kHeaderSize);
1695}
1696
1697
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001698char* SeqAsciiString::GetChars() {
1699 return reinterpret_cast<char*>(GetCharsAddress());
1700}
1701
1702
ager@chromium.org7c537e22008-10-16 08:43:32 +00001703Address SeqTwoByteString::GetCharsAddress() {
1704 return FIELD_ADDR(this, kHeaderSize);
1705}
1706
1707
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001708uc16* SeqTwoByteString::GetChars() {
1709 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1710}
1711
1712
ager@chromium.org7c537e22008-10-16 08:43:32 +00001713uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001714 ASSERT(index >= 0 && index < length());
1715 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1716}
1717
1718
ager@chromium.org7c537e22008-10-16 08:43:32 +00001719void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001720 ASSERT(index >= 0 && index < length());
1721 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1722}
1723
1724
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001725int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001726 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1727
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001728 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1729 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1730 ASSERT(kLongStringTag == 0);
1731
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001732 // Use the map (and not 'this') to compute the size tag, since
1733 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001734 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001735
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001736 return SizeFor(length);
1737}
1738
1739
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001740int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001741 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1742
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001743 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1744 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1745 ASSERT(kLongStringTag == 0);
1746
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001747 // Use the map (and not 'this') to compute the size tag, since
1748 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001749 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001750
1751 return SizeFor(length);
1752}
1753
1754
ager@chromium.org870a0b62008-11-04 11:43:05 +00001755String* ConsString::first() {
1756 return String::cast(READ_FIELD(this, kFirstOffset));
1757}
1758
1759
1760Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761 return READ_FIELD(this, kFirstOffset);
1762}
1763
1764
ager@chromium.org870a0b62008-11-04 11:43:05 +00001765void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001766 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001767 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001768}
1769
1770
ager@chromium.org870a0b62008-11-04 11:43:05 +00001771String* ConsString::second() {
1772 return String::cast(READ_FIELD(this, kSecondOffset));
1773}
1774
1775
1776Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001777 return READ_FIELD(this, kSecondOffset);
1778}
1779
1780
ager@chromium.org870a0b62008-11-04 11:43:05 +00001781void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001782 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001783 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001784}
1785
1786
ager@chromium.org870a0b62008-11-04 11:43:05 +00001787String* SlicedString::buffer() {
1788 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001789}
1790
1791
ager@chromium.org870a0b62008-11-04 11:43:05 +00001792void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001793 WRITE_FIELD(this, kBufferOffset, buffer);
1794 WRITE_BARRIER(this, kBufferOffset);
1795}
1796
1797
1798int SlicedString::start() {
1799 return READ_INT_FIELD(this, kStartOffset);
1800}
1801
1802
1803void SlicedString::set_start(int start) {
1804 WRITE_INT_FIELD(this, kStartOffset, start);
1805}
1806
1807
1808ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1809 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1810}
1811
1812
1813void ExternalAsciiString::set_resource(
1814 ExternalAsciiString::Resource* resource) {
1815 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1816}
1817
1818
ager@chromium.org6f10e412009-02-13 10:11:16 +00001819Map* ExternalAsciiString::StringMap(int length) {
1820 Map* map;
1821 // Number of characters: determines the map.
1822 if (length <= String::kMaxShortStringSize) {
1823 map = Heap::short_external_ascii_string_map();
1824 } else if (length <= String::kMaxMediumStringSize) {
1825 map = Heap::medium_external_ascii_string_map();
1826 } else {
1827 map = Heap::long_external_ascii_string_map();
1828 }
1829 return map;
1830}
1831
1832
1833Map* ExternalAsciiString::SymbolMap(int length) {
1834 Map* map;
1835 // Number of characters: determines the map.
1836 if (length <= String::kMaxShortStringSize) {
1837 map = Heap::short_external_ascii_symbol_map();
1838 } else if (length <= String::kMaxMediumStringSize) {
1839 map = Heap::medium_external_ascii_symbol_map();
1840 } else {
1841 map = Heap::long_external_ascii_symbol_map();
1842 }
1843 return map;
1844}
1845
1846
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001847ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1848 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1849}
1850
1851
1852void ExternalTwoByteString::set_resource(
1853 ExternalTwoByteString::Resource* resource) {
1854 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1855}
1856
1857
ager@chromium.org6f10e412009-02-13 10:11:16 +00001858Map* ExternalTwoByteString::StringMap(int length) {
1859 Map* map;
1860 // Number of characters: determines the map.
1861 if (length <= String::kMaxShortStringSize) {
1862 map = Heap::short_external_string_map();
1863 } else if (length <= String::kMaxMediumStringSize) {
1864 map = Heap::medium_external_string_map();
1865 } else {
1866 map = Heap::long_external_string_map();
1867 }
1868 return map;
1869}
1870
1871
1872Map* ExternalTwoByteString::SymbolMap(int length) {
1873 Map* map;
1874 // Number of characters: determines the map.
1875 if (length <= String::kMaxShortStringSize) {
1876 map = Heap::short_external_symbol_map();
1877 } else if (length <= String::kMaxMediumStringSize) {
1878 map = Heap::medium_external_symbol_map();
1879 } else {
1880 map = Heap::long_external_symbol_map();
1881 }
1882 return map;
1883}
1884
1885
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001886byte ByteArray::get(int index) {
1887 ASSERT(index >= 0 && index < this->length());
1888 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1889}
1890
1891
1892void ByteArray::set(int index, byte value) {
1893 ASSERT(index >= 0 && index < this->length());
1894 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1895}
1896
1897
1898int ByteArray::get_int(int index) {
1899 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1900 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1901}
1902
1903
1904ByteArray* ByteArray::FromDataStartAddress(Address address) {
1905 ASSERT_TAG_ALIGNED(address);
1906 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1907}
1908
1909
1910Address ByteArray::GetDataStartAddress() {
1911 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1912}
1913
1914
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001915uint8_t* PixelArray::external_pointer() {
1916 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1917 return reinterpret_cast<uint8_t*>(ptr);
1918}
1919
1920
1921void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1922 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1923 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1924}
1925
1926
1927uint8_t PixelArray::get(int index) {
1928 ASSERT((index >= 0) && (index < this->length()));
1929 uint8_t* ptr = external_pointer();
1930 return ptr[index];
1931}
1932
1933
1934void PixelArray::set(int index, uint8_t value) {
1935 ASSERT((index >= 0) && (index < this->length()));
1936 uint8_t* ptr = external_pointer();
1937 ptr[index] = value;
1938}
1939
1940
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001941int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001942 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1943}
1944
1945
1946int Map::inobject_properties() {
1947 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001948}
1949
1950
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001951int Map::pre_allocated_property_fields() {
1952 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1953}
1954
1955
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001956int HeapObject::SizeFromMap(Map* map) {
1957 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001958 // Only inline the most frequent cases.
1959 if (instance_type == JS_OBJECT_TYPE ||
1960 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1961 (kStringTag | kConsStringTag) ||
1962 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001963 if (instance_type == FIXED_ARRAY_TYPE) {
1964 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1965 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001966 if (instance_type == BYTE_ARRAY_TYPE) {
1967 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1968 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001969 // Otherwise do the general size computation.
1970 return SlowSizeFromMap(map);
1971}
1972
1973
1974void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001975 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001976 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001977 ASSERT(0 <= value && value < 256);
1978 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1979}
1980
1981
ager@chromium.org7c537e22008-10-16 08:43:32 +00001982void Map::set_inobject_properties(int value) {
1983 ASSERT(0 <= value && value < 256);
1984 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1985}
1986
1987
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001988void Map::set_pre_allocated_property_fields(int value) {
1989 ASSERT(0 <= value && value < 256);
1990 WRITE_BYTE_FIELD(this,
1991 kPreAllocatedPropertyFieldsOffset,
1992 static_cast<byte>(value));
1993}
1994
1995
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001996InstanceType Map::instance_type() {
1997 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1998}
1999
2000
2001void Map::set_instance_type(InstanceType value) {
2002 ASSERT(0 <= value && value < 256);
2003 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2004}
2005
2006
2007int Map::unused_property_fields() {
2008 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2009}
2010
2011
2012void Map::set_unused_property_fields(int value) {
2013 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2014}
2015
2016
2017byte Map::bit_field() {
2018 return READ_BYTE_FIELD(this, kBitFieldOffset);
2019}
2020
2021
2022void Map::set_bit_field(byte value) {
2023 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2024}
2025
2026
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002027byte Map::bit_field2() {
2028 return READ_BYTE_FIELD(this, kBitField2Offset);
2029}
2030
2031
2032void Map::set_bit_field2(byte value) {
2033 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2034}
2035
2036
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002037void Map::set_non_instance_prototype(bool value) {
2038 if (value) {
2039 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2040 } else {
2041 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2042 }
2043}
2044
2045
2046bool Map::has_non_instance_prototype() {
2047 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2048}
2049
2050
ager@chromium.org870a0b62008-11-04 11:43:05 +00002051void Map::set_is_access_check_needed(bool access_check_needed) {
2052 if (access_check_needed) {
2053 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2054 } else {
2055 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2056 }
2057}
2058
2059
2060bool Map::is_access_check_needed() {
2061 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2062}
2063
2064
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002065Code::Flags Code::flags() {
2066 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2067}
2068
2069
2070void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002071 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002072 // Make sure that all call stubs have an arguments count.
2073 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2074 ExtractArgumentsCountFromFlags(flags) >= 0);
2075 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2076}
2077
2078
2079Code::Kind Code::kind() {
2080 return ExtractKindFromFlags(flags());
2081}
2082
2083
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002084InLoopFlag Code::ic_in_loop() {
2085 return ExtractICInLoopFromFlags(flags());
2086}
2087
2088
kasper.lund7276f142008-07-30 08:49:36 +00002089InlineCacheState Code::ic_state() {
2090 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091 // Only allow uninitialized or debugger states for non-IC code
2092 // objects. This is used in the debugger to determine whether or not
2093 // a call to code object has been replaced with a debug break call.
2094 ASSERT(is_inline_cache_stub() ||
2095 result == UNINITIALIZED ||
2096 result == DEBUG_BREAK ||
2097 result == DEBUG_PREPARE_STEP_IN);
2098 return result;
2099}
2100
2101
2102PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002103 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002104 return ExtractTypeFromFlags(flags());
2105}
2106
2107
2108int Code::arguments_count() {
2109 ASSERT(is_call_stub() || kind() == STUB);
2110 return ExtractArgumentsCountFromFlags(flags());
2111}
2112
2113
2114CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002115 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002116 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2117 kStubMajorKeyOffset));
2118}
2119
2120
2121void Code::set_major_key(CodeStub::Major major) {
2122 ASSERT(kind() == STUB);
2123 ASSERT(0 <= major && major < 256);
2124 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002125}
2126
2127
2128bool Code::is_inline_cache_stub() {
2129 Kind kind = this->kind();
2130 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2131}
2132
2133
2134Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002135 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002136 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002137 PropertyType type,
2138 int argc) {
2139 // Compute the bit mask.
2140 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002141 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002142 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002143 bits |= type << kFlagsTypeShift;
2144 bits |= argc << kFlagsArgumentsCountShift;
2145 // Cast to flags and validate result before returning it.
2146 Flags result = static_cast<Flags>(bits);
2147 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002148 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002149 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002150 ASSERT(ExtractTypeFromFlags(result) == type);
2151 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2152 return result;
2153}
2154
2155
2156Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2157 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002158 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002159 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002160 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002161}
2162
2163
2164Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2165 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2166 return static_cast<Kind>(bits);
2167}
2168
2169
kasper.lund7276f142008-07-30 08:49:36 +00002170InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2171 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002172 return static_cast<InlineCacheState>(bits);
2173}
2174
2175
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002176InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2177 int bits = (flags & kFlagsICInLoopMask);
2178 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2179}
2180
2181
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002182PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2183 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2184 return static_cast<PropertyType>(bits);
2185}
2186
2187
2188int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2189 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2190}
2191
2192
2193Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2194 int bits = flags & ~kFlagsTypeMask;
2195 return static_cast<Flags>(bits);
2196}
2197
2198
ager@chromium.org8bb60582008-12-11 12:02:20 +00002199Code* Code::GetCodeFromTargetAddress(Address address) {
2200 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2201 // GetCodeFromTargetAddress might be called when marking objects during mark
2202 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2203 // Code::cast. Code::cast does not work when the object's map is
2204 // marked.
2205 Code* result = reinterpret_cast<Code*>(code);
2206 return result;
2207}
2208
2209
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002210Object* Map::prototype() {
2211 return READ_FIELD(this, kPrototypeOffset);
2212}
2213
2214
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002215void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002216 ASSERT(value->IsNull() || value->IsJSObject());
2217 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002218 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002219}
2220
2221
2222ACCESSORS(Map, instance_descriptors, DescriptorArray,
2223 kInstanceDescriptorsOffset)
2224ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2225ACCESSORS(Map, constructor, Object, kConstructorOffset)
2226
2227ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2228ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2229
2230ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2231ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002232ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002233
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002234ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002235
2236ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2237ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2238ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2239ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2240ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2241
2242ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2243ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2244ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2245
2246ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2247ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2248ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2249ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2250ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2251ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2252
2253ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2254ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2255
2256ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2257ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2258
2259ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2260ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002261ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2262 kPropertyAccessorsOffset)
2263ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2264 kPrototypeTemplateOffset)
2265ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2266ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2267 kNamedPropertyHandlerOffset)
2268ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2269 kIndexedPropertyHandlerOffset)
2270ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2271 kInstanceTemplateOffset)
2272ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2273ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002274ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2275 kInstanceCallHandlerOffset)
2276ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2277 kAccessCheckInfoOffset)
2278ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2279
2280ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002281ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2282 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002283
2284ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2285ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2286
2287ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2288
2289ACCESSORS(Script, source, Object, kSourceOffset)
2290ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002291ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002292ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2293ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002294ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002295ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002296ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2297ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002298ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002299ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002300ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2301ACCESSORS(Script, eval_from_instructions_offset, Smi,
2302 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002303
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002304#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002305ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2306ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2307ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2308ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2309
2310ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2311ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2312ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2313ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002314#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002315
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002316ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002317ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2318ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2319 kInstanceClassNameOffset)
2320ACCESSORS(SharedFunctionInfo, function_data, Object,
2321 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002322ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2323ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002324ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002325ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2326 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002327
2328BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2329 kHiddenPrototypeBit)
2330BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2331BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2332 kNeedsAccessCheckBit)
2333BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2334 kIsExpressionBit)
2335BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2336 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002337BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2338 has_only_this_property_assignments,
2339 kHasOnlyThisPropertyAssignments)
2340BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2341 has_only_simple_this_property_assignments,
2342 kHasOnlySimpleThisPropertyAssignments)
2343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002344
2345INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2346INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2347 kFormalParameterCountOffset)
2348INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2349 kExpectedNofPropertiesOffset)
2350INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2351 kStartPositionAndTypeOffset)
2352INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2353INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2354 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002355INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2356 kCompilerHintsOffset)
2357INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2358 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002359
2360
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00002361bool Script::HasValidSource() {
2362 Object* src = this->source();
2363 if (!src->IsString()) return true;
2364 String* src_str = String::cast(src);
2365 if (!StringShape(src_str).IsExternal()) return true;
2366 if (src_str->IsAsciiRepresentation()) {
2367 return ExternalAsciiString::cast(src)->resource() != NULL;
2368 } else if (src_str->IsTwoByteRepresentation()) {
2369 return ExternalTwoByteString::cast(src)->resource() != NULL;
2370 }
2371 return true;
2372}
2373
2374
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002375void SharedFunctionInfo::DontAdaptArguments() {
2376 ASSERT(code()->kind() == Code::BUILTIN);
2377 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2378}
2379
2380
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002381int SharedFunctionInfo::start_position() {
2382 return start_position_and_type() >> kStartPositionShift;
2383}
2384
2385
2386void SharedFunctionInfo::set_start_position(int start_position) {
2387 set_start_position_and_type((start_position << kStartPositionShift)
2388 | (start_position_and_type() & ~kStartPositionMask));
2389}
2390
2391
2392Code* SharedFunctionInfo::code() {
2393 return Code::cast(READ_FIELD(this, kCodeOffset));
2394}
2395
2396
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002397void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002398 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002399 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002400}
2401
2402
2403bool SharedFunctionInfo::is_compiled() {
2404 // TODO(1242782): Create a code kind for uncompiled code.
2405 return code()->kind() != Code::STUB;
2406}
2407
2408
2409bool JSFunction::IsBoilerplate() {
2410 return map() == Heap::boilerplate_function_map();
2411}
2412
2413
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002414bool JSFunction::IsBuiltin() {
2415 return context()->global()->IsJSBuiltinsObject();
2416}
2417
2418
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002419bool JSObject::IsLoaded() {
2420 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002421}
2422
2423
2424Code* JSFunction::code() {
2425 return shared()->code();
2426}
2427
2428
2429void JSFunction::set_code(Code* value) {
2430 shared()->set_code(value);
2431}
2432
2433
2434Context* JSFunction::context() {
2435 return Context::cast(READ_FIELD(this, kContextOffset));
2436}
2437
2438
2439Object* JSFunction::unchecked_context() {
2440 return READ_FIELD(this, kContextOffset);
2441}
2442
2443
2444void JSFunction::set_context(Object* value) {
2445 ASSERT(value == Heap::undefined_value() || value->IsContext());
2446 WRITE_FIELD(this, kContextOffset, value);
2447 WRITE_BARRIER(this, kContextOffset);
2448}
2449
2450ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2451 kPrototypeOrInitialMapOffset)
2452
2453
2454Map* JSFunction::initial_map() {
2455 return Map::cast(prototype_or_initial_map());
2456}
2457
2458
2459void JSFunction::set_initial_map(Map* value) {
2460 set_prototype_or_initial_map(value);
2461}
2462
2463
2464bool JSFunction::has_initial_map() {
2465 return prototype_or_initial_map()->IsMap();
2466}
2467
2468
2469bool JSFunction::has_instance_prototype() {
2470 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2471}
2472
2473
2474bool JSFunction::has_prototype() {
2475 return map()->has_non_instance_prototype() || has_instance_prototype();
2476}
2477
2478
2479Object* JSFunction::instance_prototype() {
2480 ASSERT(has_instance_prototype());
2481 if (has_initial_map()) return initial_map()->prototype();
2482 // When there is no initial map and the prototype is a JSObject, the
2483 // initial map field is used for the prototype field.
2484 return prototype_or_initial_map();
2485}
2486
2487
2488Object* JSFunction::prototype() {
2489 ASSERT(has_prototype());
2490 // If the function's prototype property has been set to a non-JSObject
2491 // value, that value is stored in the constructor field of the map.
2492 if (map()->has_non_instance_prototype()) return map()->constructor();
2493 return instance_prototype();
2494}
2495
2496
2497bool JSFunction::is_compiled() {
2498 return shared()->is_compiled();
2499}
2500
2501
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002502int JSFunction::NumberOfLiterals() {
2503 return literals()->length();
2504}
2505
2506
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002507Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2508 ASSERT(0 <= id && id < kJSBuiltinsCount);
2509 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2510}
2511
2512
2513void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2514 Object* value) {
2515 ASSERT(0 <= id && id < kJSBuiltinsCount);
2516 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2517 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2518}
2519
2520
2521Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002522 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002523}
2524
2525
2526void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002527 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002528}
2529
2530
2531void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2532 visitor->VisitExternalReference(
2533 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2534}
2535
2536
2537ACCESSORS(JSValue, value, Object, kValueOffset)
2538
2539
2540JSValue* JSValue::cast(Object* obj) {
2541 ASSERT(obj->IsJSValue());
2542 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2543 return reinterpret_cast<JSValue*>(obj);
2544}
2545
2546
2547INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2548INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2549INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2550
2551
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002552byte* Code::instruction_start() {
2553 return FIELD_ADDR(this, kHeaderSize);
2554}
2555
2556
2557int Code::body_size() {
2558 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2559}
2560
2561
2562byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002563 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002564}
2565
2566
2567byte* Code::entry() {
2568 return instruction_start();
2569}
2570
2571
2572bool Code::contains(byte* pc) {
2573 return (instruction_start() <= pc) &&
2574 (pc < instruction_start() + instruction_size());
2575}
2576
2577
2578byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002579 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002580}
2581
2582
2583ACCESSORS(JSArray, length, Object, kLengthOffset)
2584
2585
ager@chromium.org236ad962008-09-25 09:45:57 +00002586ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002587
2588
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002589JSRegExp::Type JSRegExp::TypeTag() {
2590 Object* data = this->data();
2591 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2592 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2593 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002594}
2595
2596
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002597int JSRegExp::CaptureCount() {
2598 switch (TypeTag()) {
2599 case ATOM:
2600 return 0;
2601 case IRREGEXP:
2602 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2603 default:
2604 UNREACHABLE();
2605 return -1;
2606 }
2607}
2608
2609
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002610JSRegExp::Flags JSRegExp::GetFlags() {
2611 ASSERT(this->data()->IsFixedArray());
2612 Object* data = this->data();
2613 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2614 return Flags(smi->value());
2615}
2616
2617
2618String* JSRegExp::Pattern() {
2619 ASSERT(this->data()->IsFixedArray());
2620 Object* data = this->data();
2621 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2622 return pattern;
2623}
2624
2625
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002626Object* JSRegExp::DataAt(int index) {
2627 ASSERT(TypeTag() != NOT_COMPILED);
2628 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002629}
2630
2631
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002632void JSRegExp::SetDataAt(int index, Object* value) {
2633 ASSERT(TypeTag() != NOT_COMPILED);
2634 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2635 FixedArray::cast(data())->set(index, value);
2636}
2637
2638
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002639JSObject::ElementsKind JSObject::GetElementsKind() {
2640 Array* array = elements();
2641 if (array->IsFixedArray()) {
2642 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2643 if (array->map() == Heap::fixed_array_map()) {
2644 return FAST_ELEMENTS;
2645 }
2646 ASSERT(array->IsDictionary());
2647 return DICTIONARY_ELEMENTS;
2648 }
2649 ASSERT(array->IsPixelArray());
2650 return PIXEL_ELEMENTS;
2651}
2652
2653
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002654bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002655 return GetElementsKind() == FAST_ELEMENTS;
2656}
2657
2658
2659bool JSObject::HasDictionaryElements() {
2660 return GetElementsKind() == DICTIONARY_ELEMENTS;
2661}
2662
2663
2664bool JSObject::HasPixelElements() {
2665 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002666}
2667
2668
2669bool JSObject::HasNamedInterceptor() {
2670 return map()->has_named_interceptor();
2671}
2672
2673
2674bool JSObject::HasIndexedInterceptor() {
2675 return map()->has_indexed_interceptor();
2676}
2677
2678
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002679StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002680 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002681 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002682}
2683
2684
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002685NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002686 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002687 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002688}
2689
2690
2691bool String::HasHashCode() {
2692 return (length_field() & kHashComputedMask) != 0;
2693}
2694
2695
2696uint32_t String::Hash() {
2697 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002698 uint32_t field = length_field();
2699 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002700 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002701 return ComputeAndSetHash();
2702}
2703
2704
ager@chromium.org7c537e22008-10-16 08:43:32 +00002705StringHasher::StringHasher(int length)
2706 : length_(length),
2707 raw_running_hash_(0),
2708 array_index_(0),
2709 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2710 is_first_char_(true),
2711 is_valid_(true) { }
2712
2713
2714bool StringHasher::has_trivial_hash() {
2715 return length_ > String::kMaxMediumStringSize;
2716}
2717
2718
2719void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002720 // Use the Jenkins one-at-a-time hash function to update the hash
2721 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002722 raw_running_hash_ += c;
2723 raw_running_hash_ += (raw_running_hash_ << 10);
2724 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002725 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002726 if (is_array_index_) {
2727 if (c < '0' || c > '9') {
2728 is_array_index_ = false;
2729 } else {
2730 int d = c - '0';
2731 if (is_first_char_) {
2732 is_first_char_ = false;
2733 if (c == '0' && length_ > 1) {
2734 is_array_index_ = false;
2735 return;
2736 }
2737 }
2738 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2739 is_array_index_ = false;
2740 } else {
2741 array_index_ = array_index_ * 10 + d;
2742 }
2743 }
2744 }
2745}
2746
2747
2748void StringHasher::AddCharacterNoIndex(uc32 c) {
2749 ASSERT(!is_array_index());
2750 raw_running_hash_ += c;
2751 raw_running_hash_ += (raw_running_hash_ << 10);
2752 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2753}
2754
2755
2756uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002757 // Get the calculated raw hash value and do some more bit ops to distribute
2758 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002759 uint32_t result = raw_running_hash_;
2760 result += (result << 3);
2761 result ^= (result >> 11);
2762 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002763 if (result == 0) {
2764 result = 27;
2765 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002766 return result;
2767}
2768
2769
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002770bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002771 uint32_t field = length_field();
2772 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002773 return SlowAsArrayIndex(index);
2774}
2775
2776
2777Object* JSObject::GetPrototype() {
2778 return JSObject::cast(this)->map()->prototype();
2779}
2780
2781
2782PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2783 return GetPropertyAttributeWithReceiver(this, key);
2784}
2785
2786
2787bool JSObject::HasElement(uint32_t index) {
2788 return HasElementWithReceiver(this, index);
2789}
2790
2791
2792bool AccessorInfo::all_can_read() {
2793 return BooleanBit::get(flag(), kAllCanReadBit);
2794}
2795
2796
2797void AccessorInfo::set_all_can_read(bool value) {
2798 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2799}
2800
2801
2802bool AccessorInfo::all_can_write() {
2803 return BooleanBit::get(flag(), kAllCanWriteBit);
2804}
2805
2806
2807void AccessorInfo::set_all_can_write(bool value) {
2808 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2809}
2810
2811
ager@chromium.org870a0b62008-11-04 11:43:05 +00002812bool AccessorInfo::prohibits_overwriting() {
2813 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2814}
2815
2816
2817void AccessorInfo::set_prohibits_overwriting(bool value) {
2818 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2819}
2820
2821
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002822PropertyAttributes AccessorInfo::property_attributes() {
2823 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2824}
2825
2826
2827void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2828 ASSERT(AttributesField::is_valid(attributes));
2829 int rest_value = flag()->value() & ~AttributesField::mask();
2830 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2831}
2832
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002833template<typename Shape, typename Key>
2834void Dictionary<Shape, Key>::SetEntry(int entry,
2835 Object* key,
2836 Object* value,
2837 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002838 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002839 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2840 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2841 FixedArray::set(index, key, mode);
2842 FixedArray::set(index+1, value, mode);
2843 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002844}
2845
2846
2847void Map::ClearCodeCache() {
2848 // No write barrier is needed since empty_fixed_array is not in new space.
2849 // Please note this function is used during marking:
2850 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002851 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2852 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002853}
2854
2855
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002856void JSArray::EnsureSize(int required_size) {
2857 ASSERT(HasFastElements());
2858 if (elements()->length() >= required_size) return;
2859 Expand(required_size);
2860}
2861
2862
ager@chromium.org7c537e22008-10-16 08:43:32 +00002863void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002864 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002865 set_elements(storage);
2866}
2867
2868
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002869Object* FixedArray::Copy() {
2870 if (length() == 0) return this;
2871 return Heap::CopyFixedArray(this);
2872}
2873
2874
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002875#undef CAST_ACCESSOR
2876#undef INT_ACCESSORS
2877#undef SMI_ACCESSORS
2878#undef ACCESSORS
2879#undef FIELD_ADDR
2880#undef READ_FIELD
2881#undef WRITE_FIELD
2882#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002883#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002884#undef READ_MEMADDR_FIELD
2885#undef WRITE_MEMADDR_FIELD
2886#undef READ_DOUBLE_FIELD
2887#undef WRITE_DOUBLE_FIELD
2888#undef READ_INT_FIELD
2889#undef WRITE_INT_FIELD
2890#undef READ_SHORT_FIELD
2891#undef WRITE_SHORT_FIELD
2892#undef READ_BYTE_FIELD
2893#undef WRITE_BYTE_FIELD
2894
2895
2896} } // namespace v8::internal
2897
2898#endif // V8_OBJECTS_INL_H_