blob: cabc8a218755f189ef8eb3298c75e38db97126e1 [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));
ager@chromium.org9085a012009-05-11 19:22:57 +0000747 intptr_t tagged_value =
748 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
749 return reinterpret_cast<Smi*>(tagged_value);
750}
751
752
753Smi* Smi::FromIntptr(intptr_t value) {
754 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
756}
757
758
759Failure::Type Failure::type() const {
760 return static_cast<Type>(value() & kFailureTypeTagMask);
761}
762
763
764bool Failure::IsInternalError() const {
765 return type() == INTERNAL_ERROR;
766}
767
768
769bool Failure::IsOutOfMemoryException() const {
770 return type() == OUT_OF_MEMORY_EXCEPTION;
771}
772
773
774int Failure::requested() const {
775 const int kShiftBits =
776 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
777 STATIC_ASSERT(kShiftBits >= 0);
778 ASSERT(type() == RETRY_AFTER_GC);
779 return value() >> kShiftBits;
780}
781
782
783AllocationSpace Failure::allocation_space() const {
784 ASSERT_EQ(RETRY_AFTER_GC, type());
785 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
786 & kSpaceTagMask);
787}
788
789
790Failure* Failure::InternalError() {
791 return Construct(INTERNAL_ERROR);
792}
793
794
795Failure* Failure::Exception() {
796 return Construct(EXCEPTION);
797}
798
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000799
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000800Failure* Failure::OutOfMemoryException() {
801 return Construct(OUT_OF_MEMORY_EXCEPTION);
802}
803
804
805int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000806 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000807}
808
809
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000810Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000811 // Assert that the space encoding fits in the three bytes allotted for it.
812 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000813 int requested = requested_bytes >> kObjectAlignmentBits;
814 int value = (requested << kSpaceTagSize) | NEW_SPACE;
815 ASSERT(value >> kSpaceTagSize == requested);
816 ASSERT(Smi::IsValid(value));
817 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
818 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
819 return Construct(RETRY_AFTER_GC, value);
820}
821
822
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000823Failure* Failure::Construct(Type type, int value) {
824 int info = (value << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000825 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
ager@chromium.org5ec48922009-05-05 07:25:34 +0000826 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000827 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000828}
829
830
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000831bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832#ifdef DEBUG
833 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
834#endif
835 // To be representable as an tagged small integer, the two
836 // most-significant bits of 'value' must be either 00 or 11 due to
837 // sign-extension. To check this we add 01 to the two
838 // most-significant bits, and check if the most-significant bit is 0
839 //
840 // CAUTION: The original code below:
841 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
842 // may lead to incorrect results according to the C language spec, and
843 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
844 // compiler may produce undefined results in case of signed integer
845 // overflow. The computation must be done w/ unsigned ints.
846 bool result =
847 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
848 ASSERT(result == in_range);
849 return result;
850}
851
852
ager@chromium.org9085a012009-05-11 19:22:57 +0000853bool Smi::IsIntptrValid(intptr_t value) {
854#ifdef DEBUG
855 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
856#endif
857 // See Smi::IsValid(int) for description.
858 bool result =
859 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
860 ASSERT(result == in_range);
861 return result;
862}
863
864
kasper.lund7276f142008-07-30 08:49:36 +0000865MapWord MapWord::FromMap(Map* map) {
866 return MapWord(reinterpret_cast<uintptr_t>(map));
867}
868
869
870Map* MapWord::ToMap() {
871 return reinterpret_cast<Map*>(value_);
872}
873
874
875bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000876 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000877}
878
879
880MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000881 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
882 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000883}
884
885
886HeapObject* MapWord::ToForwardingAddress() {
887 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000888 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000889}
890
891
892bool MapWord::IsMarked() {
893 return (value_ & kMarkingMask) == 0;
894}
895
896
897void MapWord::SetMark() {
898 value_ &= ~kMarkingMask;
899}
900
901
902void MapWord::ClearMark() {
903 value_ |= kMarkingMask;
904}
905
906
907bool MapWord::IsOverflowed() {
908 return (value_ & kOverflowMask) != 0;
909}
910
911
912void MapWord::SetOverflow() {
913 value_ |= kOverflowMask;
914}
915
916
917void MapWord::ClearOverflow() {
918 value_ &= ~kOverflowMask;
919}
920
921
922MapWord MapWord::EncodeAddress(Address map_address, int offset) {
923 // Offset is the distance in live bytes from the first live object in the
924 // same page. The offset between two objects in the same page should not
925 // exceed the object area size of a page.
926 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
927
928 int compact_offset = offset >> kObjectAlignmentBits;
929 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
930
931 Page* map_page = Page::FromAddress(map_address);
932 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
933
934 int map_page_offset =
935 map_page->Offset(map_address) >> kObjectAlignmentBits;
936
937 uintptr_t encoding =
938 (compact_offset << kForwardingOffsetShift) |
939 (map_page_offset << kMapPageOffsetShift) |
940 (map_page->mc_page_index << kMapPageIndexShift);
941 return MapWord(encoding);
942}
943
944
945Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000946 int map_page_index =
947 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +0000948 ASSERT_MAP_PAGE_INDEX(map_page_index);
949
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000950 int map_page_offset = static_cast<int>(
kasper.lund7276f142008-07-30 08:49:36 +0000951 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000952 << kObjectAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +0000953
954 return (map_space->PageAddress(map_page_index) + map_page_offset);
955}
956
957
958int MapWord::DecodeOffset() {
959 // The offset field is represented in the kForwardingOffsetBits
960 // most-significant bits.
961 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
962 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
963 return offset;
964}
965
966
967MapWord MapWord::FromEncodedAddress(Address address) {
968 return MapWord(reinterpret_cast<uintptr_t>(address));
969}
970
971
972Address MapWord::ToEncodedAddress() {
973 return reinterpret_cast<Address>(value_);
974}
975
976
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000977#ifdef DEBUG
978void HeapObject::VerifyObjectField(int offset) {
979 VerifyPointer(READ_FIELD(this, offset));
980}
981#endif
982
983
984Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000985 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000986}
987
988
989void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000990 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991}
992
993
kasper.lund7276f142008-07-30 08:49:36 +0000994MapWord HeapObject::map_word() {
995 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
996}
997
998
999void HeapObject::set_map_word(MapWord map_word) {
1000 // WRITE_FIELD does not update the remembered set, but there is no need
1001 // here.
1002 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1003}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001004
1005
1006HeapObject* HeapObject::FromAddress(Address address) {
1007 ASSERT_TAG_ALIGNED(address);
1008 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1009}
1010
1011
1012Address HeapObject::address() {
1013 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1014}
1015
1016
1017int HeapObject::Size() {
1018 return SizeFromMap(map());
1019}
1020
1021
1022void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1023 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1024 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1025}
1026
1027
1028void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1029 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1030}
1031
1032
kasper.lund7276f142008-07-30 08:49:36 +00001033bool HeapObject::IsMarked() {
1034 return map_word().IsMarked();
1035}
1036
1037
1038void HeapObject::SetMark() {
1039 ASSERT(!IsMarked());
1040 MapWord first_word = map_word();
1041 first_word.SetMark();
1042 set_map_word(first_word);
1043}
1044
1045
1046void HeapObject::ClearMark() {
1047 ASSERT(IsMarked());
1048 MapWord first_word = map_word();
1049 first_word.ClearMark();
1050 set_map_word(first_word);
1051}
1052
1053
1054bool HeapObject::IsOverflowed() {
1055 return map_word().IsOverflowed();
1056}
1057
1058
1059void HeapObject::SetOverflow() {
1060 MapWord first_word = map_word();
1061 first_word.SetOverflow();
1062 set_map_word(first_word);
1063}
1064
1065
1066void HeapObject::ClearOverflow() {
1067 ASSERT(IsOverflowed());
1068 MapWord first_word = map_word();
1069 first_word.ClearOverflow();
1070 set_map_word(first_word);
1071}
1072
1073
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001074double HeapNumber::value() {
1075 return READ_DOUBLE_FIELD(this, kValueOffset);
1076}
1077
1078
1079void HeapNumber::set_value(double value) {
1080 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1081}
1082
1083
1084ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001085
1086
1087Array* JSObject::elements() {
1088 Object* array = READ_FIELD(this, kElementsOffset);
1089 // In the assert below Dictionary is covered under FixedArray.
1090 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1091 return reinterpret_cast<Array*>(array);
1092}
1093
1094
1095void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1096 // In the assert below Dictionary is covered under FixedArray.
1097 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1098 WRITE_FIELD(this, kElementsOffset, value);
1099 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1100}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101
1102
1103void JSObject::initialize_properties() {
1104 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1105 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1106}
1107
1108
1109void JSObject::initialize_elements() {
1110 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1111 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1112}
1113
1114
1115ACCESSORS(Oddball, to_string, String, kToStringOffset)
1116ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1117
1118
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001119Object* JSGlobalPropertyCell::value() {
1120 return READ_FIELD(this, kValueOffset);
1121}
1122
1123
1124void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1125 // The write barrier is not used for global property cells.
1126 ASSERT(!val->IsJSGlobalPropertyCell());
1127 WRITE_FIELD(this, kValueOffset, val);
1128}
1129
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001130
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001131int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001132 InstanceType type = map()->instance_type();
1133 // Check for the most common kind of JavaScript object before
1134 // falling into the generic switch. This speeds up the internal
1135 // field operations considerably on average.
1136 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1137 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001138 case JS_GLOBAL_PROXY_TYPE:
1139 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140 case JS_GLOBAL_OBJECT_TYPE:
1141 return JSGlobalObject::kSize;
1142 case JS_BUILTINS_OBJECT_TYPE:
1143 return JSBuiltinsObject::kSize;
1144 case JS_FUNCTION_TYPE:
1145 return JSFunction::kSize;
1146 case JS_VALUE_TYPE:
1147 return JSValue::kSize;
1148 case JS_ARRAY_TYPE:
1149 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001150 case JS_REGEXP_TYPE:
1151 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001152 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001153 return JSObject::kHeaderSize;
1154 default:
1155 UNREACHABLE();
1156 return 0;
1157 }
1158}
1159
1160
1161int JSObject::GetInternalFieldCount() {
1162 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001163 // Make sure to adjust for the number of in-object properties. These
1164 // properties do contribute to the size, but are not internal fields.
1165 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1166 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001167}
1168
1169
1170Object* JSObject::GetInternalField(int index) {
1171 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001172 // Internal objects do follow immediately after the header, whereas in-object
1173 // properties are at the end of the object. Therefore there is no need
1174 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001175 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1176}
1177
1178
1179void JSObject::SetInternalField(int index, Object* value) {
1180 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001181 // Internal objects do follow immediately after the header, whereas in-object
1182 // properties are at the end of the object. Therefore there is no need
1183 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001184 int offset = GetHeaderSize() + (kPointerSize * index);
1185 WRITE_FIELD(this, offset, value);
1186 WRITE_BARRIER(this, offset);
1187}
1188
1189
ager@chromium.org7c537e22008-10-16 08:43:32 +00001190// Access fast-case object properties at index. The use of these routines
1191// is needed to correctly distinguish between properties stored in-object and
1192// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001193Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001194 // Adjust for the number of properties stored in the object.
1195 index -= map()->inobject_properties();
1196 if (index < 0) {
1197 int offset = map()->instance_size() + (index * kPointerSize);
1198 return READ_FIELD(this, offset);
1199 } else {
1200 ASSERT(index < properties()->length());
1201 return properties()->get(index);
1202 }
1203}
1204
1205
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001206Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001207 // Adjust for the number of properties stored in the object.
1208 index -= map()->inobject_properties();
1209 if (index < 0) {
1210 int offset = map()->instance_size() + (index * kPointerSize);
1211 WRITE_FIELD(this, offset, value);
1212 WRITE_BARRIER(this, offset);
1213 } else {
1214 ASSERT(index < properties()->length());
1215 properties()->set(index, value);
1216 }
1217 return value;
1218}
1219
1220
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001221Object* JSObject::InObjectPropertyAt(int index) {
1222 // Adjust for the number of properties stored in the object.
1223 index -= map()->inobject_properties();
1224 ASSERT(index < 0);
1225 int offset = map()->instance_size() + (index * kPointerSize);
1226 return READ_FIELD(this, offset);
1227}
1228
1229
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001230Object* JSObject::InObjectPropertyAtPut(int index,
1231 Object* value,
1232 WriteBarrierMode mode) {
1233 // Adjust for the number of properties stored in the object.
1234 index -= map()->inobject_properties();
1235 ASSERT(index < 0);
1236 int offset = map()->instance_size() + (index * kPointerSize);
1237 WRITE_FIELD(this, offset, value);
1238 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1239 return value;
1240}
1241
1242
1243
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001244void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001245 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001246 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001247 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001248 }
1249}
1250
1251
1252void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001253 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001254 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001255 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001256 }
1257}
1258
1259
1260bool JSObject::HasFastProperties() {
1261 return !properties()->IsDictionary();
1262}
1263
1264
1265bool Array::IndexFromObject(Object* object, uint32_t* index) {
1266 if (object->IsSmi()) {
1267 int value = Smi::cast(object)->value();
1268 if (value < 0) return false;
1269 *index = value;
1270 return true;
1271 }
1272 if (object->IsHeapNumber()) {
1273 double value = HeapNumber::cast(object)->value();
1274 uint32_t uint_value = static_cast<uint32_t>(value);
1275 if (value == static_cast<double>(uint_value)) {
1276 *index = uint_value;
1277 return true;
1278 }
1279 }
1280 return false;
1281}
1282
1283
1284bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1285 if (!this->IsJSValue()) return false;
1286
1287 JSValue* js_value = JSValue::cast(this);
1288 if (!js_value->value()->IsString()) return false;
1289
1290 String* str = String::cast(js_value->value());
1291 if (index >= (uint32_t)str->length()) return false;
1292
1293 return true;
1294}
1295
1296
1297Object* FixedArray::get(int index) {
1298 ASSERT(index >= 0 && index < this->length());
1299 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1300}
1301
1302
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001303void FixedArray::set(int index, Smi* value) {
1304 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1305 int offset = kHeaderSize + index * kPointerSize;
1306 WRITE_FIELD(this, offset, value);
1307}
1308
1309
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001310void FixedArray::set(int index, Object* value) {
1311 ASSERT(index >= 0 && index < this->length());
1312 int offset = kHeaderSize + index * kPointerSize;
1313 WRITE_FIELD(this, offset, value);
1314 WRITE_BARRIER(this, offset);
1315}
1316
1317
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001318WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001319 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1320 return UPDATE_WRITE_BARRIER;
1321}
1322
1323
1324void FixedArray::set(int index,
1325 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001326 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001327 ASSERT(index >= 0 && index < this->length());
1328 int offset = kHeaderSize + index * kPointerSize;
1329 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001330 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331}
1332
1333
1334void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1335 ASSERT(index >= 0 && index < array->length());
1336 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1337}
1338
1339
1340void FixedArray::set_undefined(int index) {
1341 ASSERT(index >= 0 && index < this->length());
1342 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1343 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1344 Heap::undefined_value());
1345}
1346
1347
ager@chromium.org236ad962008-09-25 09:45:57 +00001348void FixedArray::set_null(int index) {
1349 ASSERT(index >= 0 && index < this->length());
1350 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1351 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1352}
1353
1354
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001355void FixedArray::set_the_hole(int index) {
1356 ASSERT(index >= 0 && index < this->length());
1357 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1358 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1359}
1360
1361
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001362bool DescriptorArray::IsEmpty() {
1363 ASSERT(this == Heap::empty_descriptor_array() ||
1364 this->length() > 2);
1365 return this == Heap::empty_descriptor_array();
1366}
1367
1368
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001369void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1370 Object* tmp = array->get(first);
1371 fast_set(array, first, array->get(second));
1372 fast_set(array, second, tmp);
1373}
1374
1375
1376int DescriptorArray::Search(String* name) {
1377 SLOW_ASSERT(IsSortedNoDuplicates());
1378
1379 // Check for empty descriptor array.
1380 int nof = number_of_descriptors();
1381 if (nof == 0) return kNotFound;
1382
1383 // Fast case: do linear search for small arrays.
1384 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001385 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001386 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001387 }
1388
1389 // Slow case: perform binary search.
1390 return BinarySearch(name, 0, nof - 1);
1391}
1392
1393
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394String* DescriptorArray::GetKey(int descriptor_number) {
1395 ASSERT(descriptor_number < number_of_descriptors());
1396 return String::cast(get(ToKeyIndex(descriptor_number)));
1397}
1398
1399
1400Object* DescriptorArray::GetValue(int descriptor_number) {
1401 ASSERT(descriptor_number < number_of_descriptors());
1402 return GetContentArray()->get(ToValueIndex(descriptor_number));
1403}
1404
1405
1406Smi* DescriptorArray::GetDetails(int descriptor_number) {
1407 ASSERT(descriptor_number < number_of_descriptors());
1408 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1409}
1410
1411
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001412PropertyType DescriptorArray::GetType(int descriptor_number) {
1413 ASSERT(descriptor_number < number_of_descriptors());
1414 return PropertyDetails(GetDetails(descriptor_number)).type();
1415}
1416
1417
1418int DescriptorArray::GetFieldIndex(int descriptor_number) {
1419 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1420}
1421
1422
1423JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1424 return JSFunction::cast(GetValue(descriptor_number));
1425}
1426
1427
1428Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1429 ASSERT(GetType(descriptor_number) == CALLBACKS);
1430 return GetValue(descriptor_number);
1431}
1432
1433
1434AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1435 ASSERT(GetType(descriptor_number) == CALLBACKS);
1436 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1437 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1438}
1439
1440
1441bool DescriptorArray::IsProperty(int descriptor_number) {
1442 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1443}
1444
1445
1446bool DescriptorArray::IsTransition(int descriptor_number) {
1447 PropertyType t = GetType(descriptor_number);
1448 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1449}
1450
1451
1452bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1453 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1454}
1455
1456
1457bool DescriptorArray::IsDontEnum(int descriptor_number) {
1458 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1459}
1460
1461
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1463 desc->Init(GetKey(descriptor_number),
1464 GetValue(descriptor_number),
1465 GetDetails(descriptor_number));
1466}
1467
1468
1469void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1470 // Range check.
1471 ASSERT(descriptor_number < number_of_descriptors());
1472
1473 // Make sure non of the elements in desc are in new space.
1474 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1475 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1476
1477 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1478 FixedArray* content_array = GetContentArray();
1479 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1480 fast_set(content_array, ToDetailsIndex(descriptor_number),
1481 desc->GetDetails().AsSmi());
1482}
1483
1484
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001485void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1486 Descriptor desc;
1487 src->Get(src_index, &desc);
1488 Set(index, &desc);
1489}
1490
1491
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001492void DescriptorArray::Swap(int first, int second) {
1493 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1494 FixedArray* content_array = GetContentArray();
1495 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1496 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1497}
1498
1499
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001500bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001501 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502 if (!max_index_object->IsSmi()) return false;
1503 return 0 !=
1504 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1505}
1506
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001507uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001508 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001509 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 if (!max_index_object->IsSmi()) return 0;
1511 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1512 return value >> kRequiresSlowElementsTagSize;
1513}
1514
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001515void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001516 set(kMaxNumberKeyIndex,
1517 Smi::FromInt(kRequiresSlowElementsMask),
1518 SKIP_WRITE_BARRIER);
1519}
1520
1521
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001522// ------------------------------------
1523// Cast operations
1524
1525
1526CAST_ACCESSOR(FixedArray)
1527CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001528CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001529CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001530CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001531CAST_ACCESSOR(String)
1532CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001533CAST_ACCESSOR(SeqAsciiString)
1534CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001535CAST_ACCESSOR(ConsString)
1536CAST_ACCESSOR(SlicedString)
1537CAST_ACCESSOR(ExternalString)
1538CAST_ACCESSOR(ExternalAsciiString)
1539CAST_ACCESSOR(ExternalTwoByteString)
1540CAST_ACCESSOR(JSObject)
1541CAST_ACCESSOR(Smi)
1542CAST_ACCESSOR(Failure)
1543CAST_ACCESSOR(HeapObject)
1544CAST_ACCESSOR(HeapNumber)
1545CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001546CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001547CAST_ACCESSOR(SharedFunctionInfo)
1548CAST_ACCESSOR(Map)
1549CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001550CAST_ACCESSOR(GlobalObject)
1551CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552CAST_ACCESSOR(JSGlobalObject)
1553CAST_ACCESSOR(JSBuiltinsObject)
1554CAST_ACCESSOR(Code)
1555CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001556CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557CAST_ACCESSOR(Proxy)
1558CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001559CAST_ACCESSOR(PixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001560CAST_ACCESSOR(Struct)
1561
1562
1563#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1564 STRUCT_LIST(MAKE_STRUCT_CAST)
1565#undef MAKE_STRUCT_CAST
1566
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001567
1568template <typename Shape, typename Key>
1569HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570 ASSERT(obj->IsHashTable());
1571 return reinterpret_cast<HashTable*>(obj);
1572}
1573
1574
1575INT_ACCESSORS(Array, length, kLengthOffset)
1576
1577
1578bool String::Equals(String* other) {
1579 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001580 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1581 return false;
1582 }
1583 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001584}
1585
1586
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001587int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001588 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1589
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001590 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1591 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1592 ASSERT(kLongStringTag == 0);
1593
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001594 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001595}
1596
1597
1598void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001599 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1600 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1601 ASSERT(kLongStringTag == 0);
1602
1603 WRITE_INT_FIELD(this,
1604 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001605 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001606}
1607
1608
ager@chromium.org7c537e22008-10-16 08:43:32 +00001609uint32_t String::length_field() {
1610 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611}
1612
1613
ager@chromium.org7c537e22008-10-16 08:43:32 +00001614void String::set_length_field(uint32_t value) {
1615 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001616}
1617
1618
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001619Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001620 // We don't need to flatten strings that are already flat. Since this code
1621 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001622 if (!IsFlat()) {
1623 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001624 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001625 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001626}
1627
1628
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001629uint16_t String::Get(int index) {
1630 ASSERT(index >= 0 && index < length());
1631 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001632 case kSeqStringTag | kAsciiStringTag:
1633 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1634 case kSeqStringTag | kTwoByteStringTag:
1635 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1636 case kConsStringTag | kAsciiStringTag:
1637 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001639 case kSlicedStringTag | kAsciiStringTag:
1640 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001641 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001642 case kExternalStringTag | kAsciiStringTag:
1643 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1644 case kExternalStringTag | kTwoByteStringTag:
1645 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001646 default:
1647 break;
1648 }
1649
1650 UNREACHABLE();
1651 return 0;
1652}
1653
1654
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001655void String::Set(int index, uint16_t value) {
1656 ASSERT(index >= 0 && index < length());
1657 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001658
ager@chromium.org5ec48922009-05-05 07:25:34 +00001659 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001660 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1661 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001662}
1663
1664
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001665bool String::IsFlat() {
1666 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001667 case kConsStringTag: {
1668 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001669 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001670 return second->length() == 0;
1671 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001672 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001673 StringRepresentationTag tag =
1674 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001675 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001677 default:
1678 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001679 }
1680}
1681
1682
ager@chromium.org7c537e22008-10-16 08:43:32 +00001683uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001684 ASSERT(index >= 0 && index < length());
1685 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1686}
1687
1688
ager@chromium.org7c537e22008-10-16 08:43:32 +00001689void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001690 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1691 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1692 static_cast<byte>(value));
1693}
1694
1695
ager@chromium.org7c537e22008-10-16 08:43:32 +00001696Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001697 return FIELD_ADDR(this, kHeaderSize);
1698}
1699
1700
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001701char* SeqAsciiString::GetChars() {
1702 return reinterpret_cast<char*>(GetCharsAddress());
1703}
1704
1705
ager@chromium.org7c537e22008-10-16 08:43:32 +00001706Address SeqTwoByteString::GetCharsAddress() {
1707 return FIELD_ADDR(this, kHeaderSize);
1708}
1709
1710
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001711uc16* SeqTwoByteString::GetChars() {
1712 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1713}
1714
1715
ager@chromium.org7c537e22008-10-16 08:43:32 +00001716uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001717 ASSERT(index >= 0 && index < length());
1718 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1719}
1720
1721
ager@chromium.org7c537e22008-10-16 08:43:32 +00001722void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001723 ASSERT(index >= 0 && index < length());
1724 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1725}
1726
1727
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001728int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001729 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1730
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001731 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1732 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1733 ASSERT(kLongStringTag == 0);
1734
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001735 // Use the map (and not 'this') to compute the size tag, since
1736 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001737 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001738
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739 return SizeFor(length);
1740}
1741
1742
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001743int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001744 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1745
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001746 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1747 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1748 ASSERT(kLongStringTag == 0);
1749
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001750 // Use the map (and not 'this') to compute the size tag, since
1751 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001752 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001753
1754 return SizeFor(length);
1755}
1756
1757
ager@chromium.org870a0b62008-11-04 11:43:05 +00001758String* ConsString::first() {
1759 return String::cast(READ_FIELD(this, kFirstOffset));
1760}
1761
1762
1763Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001764 return READ_FIELD(this, kFirstOffset);
1765}
1766
1767
ager@chromium.org870a0b62008-11-04 11:43:05 +00001768void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001769 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001770 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001771}
1772
1773
ager@chromium.org870a0b62008-11-04 11:43:05 +00001774String* ConsString::second() {
1775 return String::cast(READ_FIELD(this, kSecondOffset));
1776}
1777
1778
1779Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001780 return READ_FIELD(this, kSecondOffset);
1781}
1782
1783
ager@chromium.org870a0b62008-11-04 11:43:05 +00001784void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001785 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001786 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001787}
1788
1789
ager@chromium.org870a0b62008-11-04 11:43:05 +00001790String* SlicedString::buffer() {
1791 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001792}
1793
1794
ager@chromium.org870a0b62008-11-04 11:43:05 +00001795void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001796 WRITE_FIELD(this, kBufferOffset, buffer);
1797 WRITE_BARRIER(this, kBufferOffset);
1798}
1799
1800
1801int SlicedString::start() {
1802 return READ_INT_FIELD(this, kStartOffset);
1803}
1804
1805
1806void SlicedString::set_start(int start) {
1807 WRITE_INT_FIELD(this, kStartOffset, start);
1808}
1809
1810
1811ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1812 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1813}
1814
1815
1816void ExternalAsciiString::set_resource(
1817 ExternalAsciiString::Resource* resource) {
1818 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1819}
1820
1821
ager@chromium.org6f10e412009-02-13 10:11:16 +00001822Map* ExternalAsciiString::StringMap(int length) {
1823 Map* map;
1824 // Number of characters: determines the map.
1825 if (length <= String::kMaxShortStringSize) {
1826 map = Heap::short_external_ascii_string_map();
1827 } else if (length <= String::kMaxMediumStringSize) {
1828 map = Heap::medium_external_ascii_string_map();
1829 } else {
1830 map = Heap::long_external_ascii_string_map();
1831 }
1832 return map;
1833}
1834
1835
1836Map* ExternalAsciiString::SymbolMap(int length) {
1837 Map* map;
1838 // Number of characters: determines the map.
1839 if (length <= String::kMaxShortStringSize) {
1840 map = Heap::short_external_ascii_symbol_map();
1841 } else if (length <= String::kMaxMediumStringSize) {
1842 map = Heap::medium_external_ascii_symbol_map();
1843 } else {
1844 map = Heap::long_external_ascii_symbol_map();
1845 }
1846 return map;
1847}
1848
1849
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001850ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1851 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1852}
1853
1854
1855void ExternalTwoByteString::set_resource(
1856 ExternalTwoByteString::Resource* resource) {
1857 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1858}
1859
1860
ager@chromium.org6f10e412009-02-13 10:11:16 +00001861Map* ExternalTwoByteString::StringMap(int length) {
1862 Map* map;
1863 // Number of characters: determines the map.
1864 if (length <= String::kMaxShortStringSize) {
1865 map = Heap::short_external_string_map();
1866 } else if (length <= String::kMaxMediumStringSize) {
1867 map = Heap::medium_external_string_map();
1868 } else {
1869 map = Heap::long_external_string_map();
1870 }
1871 return map;
1872}
1873
1874
1875Map* ExternalTwoByteString::SymbolMap(int length) {
1876 Map* map;
1877 // Number of characters: determines the map.
1878 if (length <= String::kMaxShortStringSize) {
1879 map = Heap::short_external_symbol_map();
1880 } else if (length <= String::kMaxMediumStringSize) {
1881 map = Heap::medium_external_symbol_map();
1882 } else {
1883 map = Heap::long_external_symbol_map();
1884 }
1885 return map;
1886}
1887
1888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889byte ByteArray::get(int index) {
1890 ASSERT(index >= 0 && index < this->length());
1891 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1892}
1893
1894
1895void ByteArray::set(int index, byte value) {
1896 ASSERT(index >= 0 && index < this->length());
1897 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1898}
1899
1900
1901int ByteArray::get_int(int index) {
1902 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1903 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1904}
1905
1906
1907ByteArray* ByteArray::FromDataStartAddress(Address address) {
1908 ASSERT_TAG_ALIGNED(address);
1909 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1910}
1911
1912
1913Address ByteArray::GetDataStartAddress() {
1914 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1915}
1916
1917
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001918uint8_t* PixelArray::external_pointer() {
1919 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1920 return reinterpret_cast<uint8_t*>(ptr);
1921}
1922
1923
1924void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1925 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1926 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1927}
1928
1929
1930uint8_t PixelArray::get(int index) {
1931 ASSERT((index >= 0) && (index < this->length()));
1932 uint8_t* ptr = external_pointer();
1933 return ptr[index];
1934}
1935
1936
1937void PixelArray::set(int index, uint8_t value) {
1938 ASSERT((index >= 0) && (index < this->length()));
1939 uint8_t* ptr = external_pointer();
1940 ptr[index] = value;
1941}
1942
1943
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001944int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001945 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1946}
1947
1948
1949int Map::inobject_properties() {
1950 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001951}
1952
1953
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001954int Map::pre_allocated_property_fields() {
1955 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1956}
1957
1958
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001959int HeapObject::SizeFromMap(Map* map) {
1960 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001961 // Only inline the most frequent cases.
1962 if (instance_type == JS_OBJECT_TYPE ||
1963 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1964 (kStringTag | kConsStringTag) ||
1965 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001966 if (instance_type == FIXED_ARRAY_TYPE) {
1967 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1968 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001969 if (instance_type == BYTE_ARRAY_TYPE) {
1970 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1971 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001972 // Otherwise do the general size computation.
1973 return SlowSizeFromMap(map);
1974}
1975
1976
1977void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001978 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001979 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001980 ASSERT(0 <= value && value < 256);
1981 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1982}
1983
1984
ager@chromium.org7c537e22008-10-16 08:43:32 +00001985void Map::set_inobject_properties(int value) {
1986 ASSERT(0 <= value && value < 256);
1987 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1988}
1989
1990
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001991void Map::set_pre_allocated_property_fields(int value) {
1992 ASSERT(0 <= value && value < 256);
1993 WRITE_BYTE_FIELD(this,
1994 kPreAllocatedPropertyFieldsOffset,
1995 static_cast<byte>(value));
1996}
1997
1998
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001999InstanceType Map::instance_type() {
2000 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2001}
2002
2003
2004void Map::set_instance_type(InstanceType value) {
2005 ASSERT(0 <= value && value < 256);
2006 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2007}
2008
2009
2010int Map::unused_property_fields() {
2011 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2012}
2013
2014
2015void Map::set_unused_property_fields(int value) {
2016 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2017}
2018
2019
2020byte Map::bit_field() {
2021 return READ_BYTE_FIELD(this, kBitFieldOffset);
2022}
2023
2024
2025void Map::set_bit_field(byte value) {
2026 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2027}
2028
2029
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002030byte Map::bit_field2() {
2031 return READ_BYTE_FIELD(this, kBitField2Offset);
2032}
2033
2034
2035void Map::set_bit_field2(byte value) {
2036 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2037}
2038
2039
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002040void Map::set_non_instance_prototype(bool value) {
2041 if (value) {
2042 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2043 } else {
2044 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2045 }
2046}
2047
2048
2049bool Map::has_non_instance_prototype() {
2050 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2051}
2052
2053
ager@chromium.org870a0b62008-11-04 11:43:05 +00002054void Map::set_is_access_check_needed(bool access_check_needed) {
2055 if (access_check_needed) {
2056 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2057 } else {
2058 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2059 }
2060}
2061
2062
2063bool Map::is_access_check_needed() {
2064 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2065}
2066
2067
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002068Code::Flags Code::flags() {
2069 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2070}
2071
2072
2073void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002074 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002075 // Make sure that all call stubs have an arguments count.
2076 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2077 ExtractArgumentsCountFromFlags(flags) >= 0);
2078 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2079}
2080
2081
2082Code::Kind Code::kind() {
2083 return ExtractKindFromFlags(flags());
2084}
2085
2086
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002087InLoopFlag Code::ic_in_loop() {
2088 return ExtractICInLoopFromFlags(flags());
2089}
2090
2091
kasper.lund7276f142008-07-30 08:49:36 +00002092InlineCacheState Code::ic_state() {
2093 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002094 // Only allow uninitialized or debugger states for non-IC code
2095 // objects. This is used in the debugger to determine whether or not
2096 // a call to code object has been replaced with a debug break call.
2097 ASSERT(is_inline_cache_stub() ||
2098 result == UNINITIALIZED ||
2099 result == DEBUG_BREAK ||
2100 result == DEBUG_PREPARE_STEP_IN);
2101 return result;
2102}
2103
2104
2105PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002106 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002107 return ExtractTypeFromFlags(flags());
2108}
2109
2110
2111int Code::arguments_count() {
2112 ASSERT(is_call_stub() || kind() == STUB);
2113 return ExtractArgumentsCountFromFlags(flags());
2114}
2115
2116
2117CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002118 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002119 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2120 kStubMajorKeyOffset));
2121}
2122
2123
2124void Code::set_major_key(CodeStub::Major major) {
2125 ASSERT(kind() == STUB);
2126 ASSERT(0 <= major && major < 256);
2127 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128}
2129
2130
2131bool Code::is_inline_cache_stub() {
2132 Kind kind = this->kind();
2133 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2134}
2135
2136
2137Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002138 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002139 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002140 PropertyType type,
2141 int argc) {
2142 // Compute the bit mask.
2143 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002144 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002145 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002146 bits |= type << kFlagsTypeShift;
2147 bits |= argc << kFlagsArgumentsCountShift;
2148 // Cast to flags and validate result before returning it.
2149 Flags result = static_cast<Flags>(bits);
2150 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002151 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002152 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002153 ASSERT(ExtractTypeFromFlags(result) == type);
2154 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2155 return result;
2156}
2157
2158
2159Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2160 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002161 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002162 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002163 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002164}
2165
2166
2167Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2168 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2169 return static_cast<Kind>(bits);
2170}
2171
2172
kasper.lund7276f142008-07-30 08:49:36 +00002173InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2174 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002175 return static_cast<InlineCacheState>(bits);
2176}
2177
2178
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002179InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2180 int bits = (flags & kFlagsICInLoopMask);
2181 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2182}
2183
2184
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002185PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2186 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2187 return static_cast<PropertyType>(bits);
2188}
2189
2190
2191int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2192 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2193}
2194
2195
2196Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2197 int bits = flags & ~kFlagsTypeMask;
2198 return static_cast<Flags>(bits);
2199}
2200
2201
ager@chromium.org8bb60582008-12-11 12:02:20 +00002202Code* Code::GetCodeFromTargetAddress(Address address) {
2203 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2204 // GetCodeFromTargetAddress might be called when marking objects during mark
2205 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2206 // Code::cast. Code::cast does not work when the object's map is
2207 // marked.
2208 Code* result = reinterpret_cast<Code*>(code);
2209 return result;
2210}
2211
2212
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002213Object* Map::prototype() {
2214 return READ_FIELD(this, kPrototypeOffset);
2215}
2216
2217
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002218void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002219 ASSERT(value->IsNull() || value->IsJSObject());
2220 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002221 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002222}
2223
2224
2225ACCESSORS(Map, instance_descriptors, DescriptorArray,
2226 kInstanceDescriptorsOffset)
2227ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2228ACCESSORS(Map, constructor, Object, kConstructorOffset)
2229
2230ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2231ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2232
2233ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2234ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002235ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002236
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002237ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002238
2239ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2240ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2241ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2242ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2243ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2244
2245ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2246ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2247ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2248
2249ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2250ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2251ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2252ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2253ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2254ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2255
2256ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2257ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2258
2259ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2260ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2261
2262ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2263ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002264ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2265 kPropertyAccessorsOffset)
2266ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2267 kPrototypeTemplateOffset)
2268ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2269ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2270 kNamedPropertyHandlerOffset)
2271ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2272 kIndexedPropertyHandlerOffset)
2273ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2274 kInstanceTemplateOffset)
2275ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2276ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002277ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2278 kInstanceCallHandlerOffset)
2279ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2280 kAccessCheckInfoOffset)
2281ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2282
2283ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002284ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2285 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002286
2287ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2288ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2289
2290ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2291
2292ACCESSORS(Script, source, Object, kSourceOffset)
2293ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002294ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002295ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2296ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002297ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002298ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002299ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2300ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002301ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002302ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002303ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2304ACCESSORS(Script, eval_from_instructions_offset, Smi,
2305 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002306
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002307#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002308ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2309ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2310ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2311ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2312
2313ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2314ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2315ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2316ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002317#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002318
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002319ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002320ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2321ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2322 kInstanceClassNameOffset)
2323ACCESSORS(SharedFunctionInfo, function_data, Object,
2324 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002325ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2326ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002327ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002328ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2329 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002330
2331BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2332 kHiddenPrototypeBit)
2333BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2334BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2335 kNeedsAccessCheckBit)
2336BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2337 kIsExpressionBit)
2338BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2339 kIsTopLevelBit)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002340BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2341 has_only_this_property_assignments,
2342 kHasOnlyThisPropertyAssignments)
2343BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2344 has_only_simple_this_property_assignments,
2345 kHasOnlySimpleThisPropertyAssignments)
2346
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002347
2348INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2349INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2350 kFormalParameterCountOffset)
2351INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2352 kExpectedNofPropertiesOffset)
2353INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2354 kStartPositionAndTypeOffset)
2355INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2356INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2357 kFunctionTokenPositionOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002358INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2359 kCompilerHintsOffset)
2360INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2361 kThisPropertyAssignmentsCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002362
2363
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002364void SharedFunctionInfo::DontAdaptArguments() {
2365 ASSERT(code()->kind() == Code::BUILTIN);
2366 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2367}
2368
2369
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002370int SharedFunctionInfo::start_position() {
2371 return start_position_and_type() >> kStartPositionShift;
2372}
2373
2374
2375void SharedFunctionInfo::set_start_position(int start_position) {
2376 set_start_position_and_type((start_position << kStartPositionShift)
2377 | (start_position_and_type() & ~kStartPositionMask));
2378}
2379
2380
2381Code* SharedFunctionInfo::code() {
2382 return Code::cast(READ_FIELD(this, kCodeOffset));
2383}
2384
2385
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002386void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002387 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002388 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002389}
2390
2391
2392bool SharedFunctionInfo::is_compiled() {
2393 // TODO(1242782): Create a code kind for uncompiled code.
2394 return code()->kind() != Code::STUB;
2395}
2396
2397
2398bool JSFunction::IsBoilerplate() {
2399 return map() == Heap::boilerplate_function_map();
2400}
2401
2402
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002403bool JSFunction::IsBuiltin() {
2404 return context()->global()->IsJSBuiltinsObject();
2405}
2406
2407
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002408bool JSObject::IsLoaded() {
2409 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002410}
2411
2412
2413Code* JSFunction::code() {
2414 return shared()->code();
2415}
2416
2417
2418void JSFunction::set_code(Code* value) {
2419 shared()->set_code(value);
2420}
2421
2422
2423Context* JSFunction::context() {
2424 return Context::cast(READ_FIELD(this, kContextOffset));
2425}
2426
2427
2428Object* JSFunction::unchecked_context() {
2429 return READ_FIELD(this, kContextOffset);
2430}
2431
2432
2433void JSFunction::set_context(Object* value) {
2434 ASSERT(value == Heap::undefined_value() || value->IsContext());
2435 WRITE_FIELD(this, kContextOffset, value);
2436 WRITE_BARRIER(this, kContextOffset);
2437}
2438
2439ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2440 kPrototypeOrInitialMapOffset)
2441
2442
2443Map* JSFunction::initial_map() {
2444 return Map::cast(prototype_or_initial_map());
2445}
2446
2447
2448void JSFunction::set_initial_map(Map* value) {
2449 set_prototype_or_initial_map(value);
2450}
2451
2452
2453bool JSFunction::has_initial_map() {
2454 return prototype_or_initial_map()->IsMap();
2455}
2456
2457
2458bool JSFunction::has_instance_prototype() {
2459 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2460}
2461
2462
2463bool JSFunction::has_prototype() {
2464 return map()->has_non_instance_prototype() || has_instance_prototype();
2465}
2466
2467
2468Object* JSFunction::instance_prototype() {
2469 ASSERT(has_instance_prototype());
2470 if (has_initial_map()) return initial_map()->prototype();
2471 // When there is no initial map and the prototype is a JSObject, the
2472 // initial map field is used for the prototype field.
2473 return prototype_or_initial_map();
2474}
2475
2476
2477Object* JSFunction::prototype() {
2478 ASSERT(has_prototype());
2479 // If the function's prototype property has been set to a non-JSObject
2480 // value, that value is stored in the constructor field of the map.
2481 if (map()->has_non_instance_prototype()) return map()->constructor();
2482 return instance_prototype();
2483}
2484
2485
2486bool JSFunction::is_compiled() {
2487 return shared()->is_compiled();
2488}
2489
2490
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002491int JSFunction::NumberOfLiterals() {
2492 return literals()->length();
2493}
2494
2495
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002496Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2497 ASSERT(0 <= id && id < kJSBuiltinsCount);
2498 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2499}
2500
2501
2502void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2503 Object* value) {
2504 ASSERT(0 <= id && id < kJSBuiltinsCount);
2505 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2506 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2507}
2508
2509
2510Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002511 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002512}
2513
2514
2515void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002516 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002517}
2518
2519
2520void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2521 visitor->VisitExternalReference(
2522 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2523}
2524
2525
2526ACCESSORS(JSValue, value, Object, kValueOffset)
2527
2528
2529JSValue* JSValue::cast(Object* obj) {
2530 ASSERT(obj->IsJSValue());
2531 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2532 return reinterpret_cast<JSValue*>(obj);
2533}
2534
2535
2536INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2537INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2538INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2539
2540
2541Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002542 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002543}
2544
2545
2546void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002547 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002548}
2549
2550
2551byte* Code::instruction_start() {
2552 return FIELD_ADDR(this, kHeaderSize);
2553}
2554
2555
2556int Code::body_size() {
2557 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2558}
2559
2560
2561byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002562 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002563}
2564
2565
2566byte* Code::entry() {
2567 return instruction_start();
2568}
2569
2570
2571bool Code::contains(byte* pc) {
2572 return (instruction_start() <= pc) &&
2573 (pc < instruction_start() + instruction_size());
2574}
2575
2576
2577byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002578 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002579}
2580
2581
2582ACCESSORS(JSArray, length, Object, kLengthOffset)
2583
2584
ager@chromium.org236ad962008-09-25 09:45:57 +00002585ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002586
2587
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002588JSRegExp::Type JSRegExp::TypeTag() {
2589 Object* data = this->data();
2590 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2591 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2592 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002593}
2594
2595
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002596int JSRegExp::CaptureCount() {
2597 switch (TypeTag()) {
2598 case ATOM:
2599 return 0;
2600 case IRREGEXP:
2601 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2602 default:
2603 UNREACHABLE();
2604 return -1;
2605 }
2606}
2607
2608
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002609JSRegExp::Flags JSRegExp::GetFlags() {
2610 ASSERT(this->data()->IsFixedArray());
2611 Object* data = this->data();
2612 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2613 return Flags(smi->value());
2614}
2615
2616
2617String* JSRegExp::Pattern() {
2618 ASSERT(this->data()->IsFixedArray());
2619 Object* data = this->data();
2620 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2621 return pattern;
2622}
2623
2624
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002625Object* JSRegExp::DataAt(int index) {
2626 ASSERT(TypeTag() != NOT_COMPILED);
2627 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002628}
2629
2630
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002631void JSRegExp::SetDataAt(int index, Object* value) {
2632 ASSERT(TypeTag() != NOT_COMPILED);
2633 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2634 FixedArray::cast(data())->set(index, value);
2635}
2636
2637
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002638JSObject::ElementsKind JSObject::GetElementsKind() {
2639 Array* array = elements();
2640 if (array->IsFixedArray()) {
2641 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2642 if (array->map() == Heap::fixed_array_map()) {
2643 return FAST_ELEMENTS;
2644 }
2645 ASSERT(array->IsDictionary());
2646 return DICTIONARY_ELEMENTS;
2647 }
2648 ASSERT(array->IsPixelArray());
2649 return PIXEL_ELEMENTS;
2650}
2651
2652
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002653bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002654 return GetElementsKind() == FAST_ELEMENTS;
2655}
2656
2657
2658bool JSObject::HasDictionaryElements() {
2659 return GetElementsKind() == DICTIONARY_ELEMENTS;
2660}
2661
2662
2663bool JSObject::HasPixelElements() {
2664 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002665}
2666
2667
2668bool JSObject::HasNamedInterceptor() {
2669 return map()->has_named_interceptor();
2670}
2671
2672
2673bool JSObject::HasIndexedInterceptor() {
2674 return map()->has_indexed_interceptor();
2675}
2676
2677
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002678StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002679 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002680 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002681}
2682
2683
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002684NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002685 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002686 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002687}
2688
2689
2690bool String::HasHashCode() {
2691 return (length_field() & kHashComputedMask) != 0;
2692}
2693
2694
2695uint32_t String::Hash() {
2696 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002697 uint32_t field = length_field();
2698 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002699 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002700 return ComputeAndSetHash();
2701}
2702
2703
ager@chromium.org7c537e22008-10-16 08:43:32 +00002704StringHasher::StringHasher(int length)
2705 : length_(length),
2706 raw_running_hash_(0),
2707 array_index_(0),
2708 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2709 is_first_char_(true),
2710 is_valid_(true) { }
2711
2712
2713bool StringHasher::has_trivial_hash() {
2714 return length_ > String::kMaxMediumStringSize;
2715}
2716
2717
2718void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002719 // Use the Jenkins one-at-a-time hash function to update the hash
2720 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002721 raw_running_hash_ += c;
2722 raw_running_hash_ += (raw_running_hash_ << 10);
2723 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002724 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002725 if (is_array_index_) {
2726 if (c < '0' || c > '9') {
2727 is_array_index_ = false;
2728 } else {
2729 int d = c - '0';
2730 if (is_first_char_) {
2731 is_first_char_ = false;
2732 if (c == '0' && length_ > 1) {
2733 is_array_index_ = false;
2734 return;
2735 }
2736 }
2737 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2738 is_array_index_ = false;
2739 } else {
2740 array_index_ = array_index_ * 10 + d;
2741 }
2742 }
2743 }
2744}
2745
2746
2747void StringHasher::AddCharacterNoIndex(uc32 c) {
2748 ASSERT(!is_array_index());
2749 raw_running_hash_ += c;
2750 raw_running_hash_ += (raw_running_hash_ << 10);
2751 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2752}
2753
2754
2755uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002756 // Get the calculated raw hash value and do some more bit ops to distribute
2757 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002758 uint32_t result = raw_running_hash_;
2759 result += (result << 3);
2760 result ^= (result >> 11);
2761 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002762 if (result == 0) {
2763 result = 27;
2764 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002765 return result;
2766}
2767
2768
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002769bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002770 uint32_t field = length_field();
2771 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002772 return SlowAsArrayIndex(index);
2773}
2774
2775
2776Object* JSObject::GetPrototype() {
2777 return JSObject::cast(this)->map()->prototype();
2778}
2779
2780
2781PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2782 return GetPropertyAttributeWithReceiver(this, key);
2783}
2784
2785
2786bool JSObject::HasElement(uint32_t index) {
2787 return HasElementWithReceiver(this, index);
2788}
2789
2790
2791bool AccessorInfo::all_can_read() {
2792 return BooleanBit::get(flag(), kAllCanReadBit);
2793}
2794
2795
2796void AccessorInfo::set_all_can_read(bool value) {
2797 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2798}
2799
2800
2801bool AccessorInfo::all_can_write() {
2802 return BooleanBit::get(flag(), kAllCanWriteBit);
2803}
2804
2805
2806void AccessorInfo::set_all_can_write(bool value) {
2807 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2808}
2809
2810
ager@chromium.org870a0b62008-11-04 11:43:05 +00002811bool AccessorInfo::prohibits_overwriting() {
2812 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2813}
2814
2815
2816void AccessorInfo::set_prohibits_overwriting(bool value) {
2817 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2818}
2819
2820
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002821PropertyAttributes AccessorInfo::property_attributes() {
2822 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2823}
2824
2825
2826void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2827 ASSERT(AttributesField::is_valid(attributes));
2828 int rest_value = flag()->value() & ~AttributesField::mask();
2829 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2830}
2831
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002832template<typename Shape, typename Key>
2833void Dictionary<Shape, Key>::SetEntry(int entry,
2834 Object* key,
2835 Object* value,
2836 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002837 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002838 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2839 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2840 FixedArray::set(index, key, mode);
2841 FixedArray::set(index+1, value, mode);
2842 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002843}
2844
2845
2846void Map::ClearCodeCache() {
2847 // No write barrier is needed since empty_fixed_array is not in new space.
2848 // Please note this function is used during marking:
2849 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002850 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2851 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002852}
2853
2854
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002855void JSArray::EnsureSize(int required_size) {
2856 ASSERT(HasFastElements());
2857 if (elements()->length() >= required_size) return;
2858 Expand(required_size);
2859}
2860
2861
ager@chromium.org7c537e22008-10-16 08:43:32 +00002862void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002863 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002864 set_elements(storage);
2865}
2866
2867
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002868Object* FixedArray::Copy() {
2869 if (length() == 0) return this;
2870 return Heap::CopyFixedArray(this);
2871}
2872
2873
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002874#undef CAST_ACCESSOR
2875#undef INT_ACCESSORS
2876#undef SMI_ACCESSORS
2877#undef ACCESSORS
2878#undef FIELD_ADDR
2879#undef READ_FIELD
2880#undef WRITE_FIELD
2881#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002882#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002883#undef READ_MEMADDR_FIELD
2884#undef WRITE_MEMADDR_FIELD
2885#undef READ_DOUBLE_FIELD
2886#undef WRITE_DOUBLE_FIELD
2887#undef READ_INT_FIELD
2888#undef WRITE_INT_FIELD
2889#undef READ_SHORT_FIELD
2890#undef WRITE_SHORT_FIELD
2891#undef READ_BYTE_FIELD
2892#undef WRITE_BYTE_FIELD
2893
2894
2895} } // namespace v8::internal
2896
2897#endif // V8_OBJECTS_INL_H_