blob: c7f791cab4e685d1e7afd8edb5a0b5500c9ee393 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27//
28// Review notes:
29//
ager@chromium.org32912102009-01-16 10:38:43 +000030// - The use of macros in these inline functions may seem superfluous
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000031// but it is absolutely needed to make sure gcc generates optimal
32// code. gcc is not happy when attempting to inline too deep.
33//
34
35#ifndef V8_OBJECTS_INL_H_
36#define V8_OBJECTS_INL_H_
37
38#include "objects.h"
39#include "contexts.h"
40#include "conversions-inl.h"
41#include "property.h"
42
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48}
49
50
51Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53}
54
55
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000056PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60}
61
62
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063#define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70#define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75#define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000077 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078 WRITE_FIELD(this, offset, value); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000079 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 }
81
82
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000083
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084#define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
94#define BOOL_ACCESSORS(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98 void holder::set_##name(bool value) { \
99 set_##field(BooleanBit::set(field(), offset, value)); \
100 }
101
102
103bool Object::IsSmi() {
104 return HAS_SMI_TAG(this);
105}
106
107
108bool Object::IsHeapObject() {
109 return HAS_HEAP_OBJECT_TAG(this);
110}
111
112
113bool Object::IsHeapNumber() {
114 return Object::IsHeapObject()
115 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
116}
117
118
119bool Object::IsString() {
120 return Object::IsHeapObject()
121 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
122}
123
124
ager@chromium.org870a0b62008-11-04 11:43:05 +0000125bool Object::IsSymbol() {
126 if (!this->IsHeapObject()) return false;
127 uint32_t type = HeapObject::cast(this)->map()->instance_type();
128 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
129 (kStringTag | kSymbolTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130}
131
132
133bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000134 if (!this->IsHeapObject()) return false;
135 uint32_t type = HeapObject::cast(this)->map()->instance_type();
136 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
137 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138}
139
140
ager@chromium.org870a0b62008-11-04 11:43:05 +0000141#ifdef DEBUG
142// These are for cast checks. If you need one of these in release
143// mode you should consider using a StringShape before moving it out
144// of the ifdef
145
146bool Object::IsSeqString() {
147 if (!IsString()) return false;
148 return StringShape(String::cast(this)).IsSequential();
149}
150
151
152bool Object::IsSeqAsciiString() {
153 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000154 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000155 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000156}
157
158
159bool Object::IsSeqTwoByteString() {
160 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000161 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000162 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000163}
164
165
166bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000167 if (!IsString()) return false;
168 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169}
170
171
172bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000173 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000174 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000175 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176}
177
178
179bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000180 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000181 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000182 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183}
184
185
ager@chromium.org870a0b62008-11-04 11:43:05 +0000186bool Object::IsSlicedString() {
187 if (!IsString()) return false;
188 return StringShape(String::cast(this)).IsSliced();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189}
190
191
ager@chromium.org870a0b62008-11-04 11:43:05 +0000192#endif // DEBUG
193
194
195StringShape::StringShape(String* str)
196 : type_(str->map()->instance_type()) {
197 set_valid();
198 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199}
200
201
ager@chromium.org870a0b62008-11-04 11:43:05 +0000202StringShape::StringShape(Map* map)
203 : type_(map->instance_type()) {
204 set_valid();
205 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000206}
207
208
ager@chromium.org870a0b62008-11-04 11:43:05 +0000209StringShape::StringShape(InstanceType t)
210 : type_(static_cast<uint32_t>(t)) {
211 set_valid();
212 ASSERT((type_ & kIsNotStringMask) == kStringTag);
213}
214
215
216bool StringShape::IsSymbol() {
217 ASSERT(valid());
218 return (type_ & kIsSymbolMask) == kSymbolTag;
219}
220
221
ager@chromium.org5ec48922009-05-05 07:25:34 +0000222bool String::IsAsciiRepresentation() {
223 uint32_t type = map()->instance_type();
224 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
225 return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
226 }
227 if ((type & kStringRepresentationMask) == kConsStringTag &&
228 ConsString::cast(this)->second()->length() == 0) {
229 return ConsString::cast(this)->first()->IsAsciiRepresentation();
230 }
231 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000232}
233
234
ager@chromium.org5ec48922009-05-05 07:25:34 +0000235bool String::IsTwoByteRepresentation() {
236 uint32_t type = map()->instance_type();
237 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
238 return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
239 } else if ((type & kStringRepresentationMask) == kConsStringTag &&
240 ConsString::cast(this)->second()->length() == 0) {
241 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
242 }
243 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000244}
245
246
247bool StringShape::IsCons() {
248 return (type_ & kStringRepresentationMask) == kConsStringTag;
249}
250
251
252bool StringShape::IsSliced() {
253 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
254}
255
256
257bool StringShape::IsExternal() {
258 return (type_ & kStringRepresentationMask) == kExternalStringTag;
259}
260
261
262bool StringShape::IsSequential() {
263 return (type_ & kStringRepresentationMask) == kSeqStringTag;
264}
265
266
267StringRepresentationTag StringShape::representation_tag() {
268 uint32_t tag = (type_ & kStringRepresentationMask);
269 return static_cast<StringRepresentationTag>(tag);
270}
271
272
273uint32_t StringShape::full_representation_tag() {
274 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
275}
276
277
278uint32_t StringShape::size_tag() {
279 return (type_ & kStringSizeMask);
280}
281
282
283bool StringShape::IsSequentialAscii() {
284 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
285}
286
287
288bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000289 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000290}
291
292
293bool StringShape::IsExternalAscii() {
294 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
295}
296
297
298bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000299 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000300}
301
302
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000303uc32 FlatStringReader::Get(int index) {
304 ASSERT(0 <= index && index <= length_);
305 if (is_ascii_) {
306 return static_cast<const byte*>(start_)[index];
307 } else {
308 return static_cast<const uc16*>(start_)[index];
309 }
310}
311
312
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313bool Object::IsNumber() {
314 return IsSmi() || IsHeapNumber();
315}
316
317
318bool Object::IsByteArray() {
319 return Object::IsHeapObject()
320 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
321}
322
323
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000324bool Object::IsPixelArray() {
325 return Object::IsHeapObject() &&
326 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
327}
328
329
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330bool Object::IsFailure() {
331 return HAS_FAILURE_TAG(this);
332}
333
334
335bool Object::IsRetryAfterGC() {
336 return HAS_FAILURE_TAG(this)
337 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
338}
339
340
ager@chromium.org7c537e22008-10-16 08:43:32 +0000341bool Object::IsOutOfMemoryFailure() {
342 return HAS_FAILURE_TAG(this)
343 && Failure::cast(this)->IsOutOfMemoryException();
344}
345
346
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347bool Object::IsException() {
348 return this == Failure::Exception();
349}
350
351
352bool Object::IsJSObject() {
353 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000354 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355}
356
357
ager@chromium.org32912102009-01-16 10:38:43 +0000358bool Object::IsJSContextExtensionObject() {
359 return IsHeapObject()
360 && (HeapObject::cast(this)->map()->instance_type() ==
361 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
362}
363
364
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000365bool Object::IsMap() {
366 return Object::IsHeapObject()
367 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
368}
369
370
371bool Object::IsFixedArray() {
372 return Object::IsHeapObject()
373 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
374}
375
376
377bool Object::IsDescriptorArray() {
378 return IsFixedArray();
379}
380
381
382bool Object::IsContext() {
383 return Object::IsHeapObject()
384 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000385 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000386 HeapObject::cast(this)->map() == Heap::global_context_map());
387}
388
389
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000390bool Object::IsCatchContext() {
391 return Object::IsHeapObject()
392 && HeapObject::cast(this)->map() == Heap::catch_context_map();
393}
394
395
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396bool Object::IsGlobalContext() {
397 return Object::IsHeapObject()
398 && HeapObject::cast(this)->map() == Heap::global_context_map();
399}
400
401
402bool Object::IsJSFunction() {
403 return Object::IsHeapObject()
404 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
405}
406
407
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000408template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409 return obj->IsJSFunction();
410}
411
412
413bool Object::IsCode() {
414 return Object::IsHeapObject()
415 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
416}
417
418
419bool Object::IsOddball() {
420 return Object::IsHeapObject()
421 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
422}
423
424
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000425bool Object::IsJSGlobalPropertyCell() {
426 return Object::IsHeapObject()
427 && HeapObject::cast(this)->map()->instance_type()
428 == JS_GLOBAL_PROPERTY_CELL_TYPE;
429}
430
431
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432bool Object::IsSharedFunctionInfo() {
433 return Object::IsHeapObject() &&
434 (HeapObject::cast(this)->map()->instance_type() ==
435 SHARED_FUNCTION_INFO_TYPE);
436}
437
438
439bool Object::IsJSValue() {
440 return Object::IsHeapObject()
441 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
442}
443
444
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000445bool Object::IsStringWrapper() {
446 return IsJSValue() && JSValue::cast(this)->value()->IsString();
447}
448
449
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000450bool Object::IsProxy() {
451 return Object::IsHeapObject()
452 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
453}
454
455
456bool Object::IsBoolean() {
457 return IsTrue() || IsFalse();
458}
459
460
461bool Object::IsJSArray() {
462 return Object::IsHeapObject()
463 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
464}
465
466
ager@chromium.org236ad962008-09-25 09:45:57 +0000467bool Object::IsJSRegExp() {
468 return Object::IsHeapObject()
469 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
470}
471
472
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000473template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000474 return obj->IsJSArray();
475}
476
477
478bool Object::IsHashTable() {
479 return Object::IsHeapObject()
480 && HeapObject::cast(this)->map() == Heap::hash_table_map();
481}
482
483
484bool Object::IsDictionary() {
485 return IsHashTable() && this != Heap::symbol_table();
486}
487
488
489bool Object::IsSymbolTable() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000490 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491}
492
493
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000494bool Object::IsCompilationCacheTable() {
495 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000496}
497
498
ager@chromium.org236ad962008-09-25 09:45:57 +0000499bool Object::IsMapCache() {
500 return IsHashTable();
501}
502
503
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504bool Object::IsPrimitive() {
505 return IsOddball() || IsNumber() || IsString();
506}
507
508
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000509bool Object::IsJSGlobalProxy() {
510 bool result = IsHeapObject() &&
511 (HeapObject::cast(this)->map()->instance_type() ==
512 JS_GLOBAL_PROXY_TYPE);
513 ASSERT(!result || IsAccessCheckNeeded());
514 return result;
515}
516
517
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000519 if (!IsHeapObject()) return false;
520
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000521 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000522 return type == JS_GLOBAL_OBJECT_TYPE ||
523 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524}
525
526
527bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 return IsHeapObject() &&
529 (HeapObject::cast(this)->map()->instance_type() ==
530 JS_GLOBAL_OBJECT_TYPE);
531}
532
533
534bool Object::IsJSBuiltinsObject() {
535 return IsHeapObject() &&
536 (HeapObject::cast(this)->map()->instance_type() ==
537 JS_BUILTINS_OBJECT_TYPE);
538}
539
540
541bool Object::IsUndetectableObject() {
542 return IsHeapObject()
543 && HeapObject::cast(this)->map()->is_undetectable();
544}
545
546
547bool Object::IsAccessCheckNeeded() {
548 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000549 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550}
551
552
553bool Object::IsStruct() {
554 if (!IsHeapObject()) return false;
555 switch (HeapObject::cast(this)->map()->instance_type()) {
556#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
557 STRUCT_LIST(MAKE_STRUCT_CASE)
558#undef MAKE_STRUCT_CASE
559 default: return false;
560 }
561}
562
563
564#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
565 bool Object::Is##Name() { \
566 return Object::IsHeapObject() \
567 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
568 }
569 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
570#undef MAKE_STRUCT_PREDICATE
571
572
573bool Object::IsUndefined() {
574 return this == Heap::undefined_value();
575}
576
577
578bool Object::IsTheHole() {
579 return this == Heap::the_hole_value();
580}
581
582
583bool Object::IsNull() {
584 return this == Heap::null_value();
585}
586
587
588bool Object::IsTrue() {
589 return this == Heap::true_value();
590}
591
592
593bool Object::IsFalse() {
594 return this == Heap::false_value();
595}
596
597
598double Object::Number() {
599 ASSERT(IsNumber());
600 return IsSmi()
601 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
602 : reinterpret_cast<HeapNumber*>(this)->value();
603}
604
605
606
607Object* Object::ToSmi() {
608 if (IsSmi()) return this;
609 if (IsHeapNumber()) {
610 double value = HeapNumber::cast(this)->value();
611 int int_value = FastD2I(value);
612 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
613 return Smi::FromInt(int_value);
614 }
615 }
616 return Failure::Exception();
617}
618
619
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000620bool Object::HasSpecificClassOf(String* name) {
621 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
622}
623
624
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000625Object* Object::GetElement(uint32_t index) {
626 return GetElementWithReceiver(this, index);
627}
628
629
630Object* Object::GetProperty(String* key) {
631 PropertyAttributes attributes;
632 return GetPropertyWithReceiver(this, key, &attributes);
633}
634
635
636Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
637 return GetPropertyWithReceiver(this, key, attributes);
638}
639
640
641#define FIELD_ADDR(p, offset) \
642 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
643
644#define READ_FIELD(p, offset) \
645 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
646
647#define WRITE_FIELD(p, offset, value) \
648 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
649
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000650
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000651#define WRITE_BARRIER(object, offset) \
652 Heap::RecordWrite(object->address(), offset);
653
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000654// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000655// write due to the assert validating the written value.
656#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
657 if (mode == UPDATE_WRITE_BARRIER) { \
658 Heap::RecordWrite(object->address(), offset); \
659 } else { \
660 ASSERT(mode == SKIP_WRITE_BARRIER); \
661 ASSERT(Heap::InNewSpace(object) || \
662 !Heap::InNewSpace(READ_FIELD(object, offset))); \
663 }
664
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000665#define READ_DOUBLE_FIELD(p, offset) \
666 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
667
668#define WRITE_DOUBLE_FIELD(p, offset, value) \
669 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
670
671#define READ_INT_FIELD(p, offset) \
672 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
673
674#define WRITE_INT_FIELD(p, offset, value) \
675 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
676
ager@chromium.org3e875802009-06-29 08:26:34 +0000677#define READ_INTPTR_FIELD(p, offset) \
678 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
679
680#define WRITE_INTPTR_FIELD(p, offset, value) \
681 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
682
ager@chromium.org7c537e22008-10-16 08:43:32 +0000683#define READ_UINT32_FIELD(p, offset) \
684 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
685
686#define WRITE_UINT32_FIELD(p, offset, value) \
687 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
688
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689#define READ_SHORT_FIELD(p, offset) \
690 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
691
692#define WRITE_SHORT_FIELD(p, offset, value) \
693 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
694
695#define READ_BYTE_FIELD(p, offset) \
696 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
697
698#define WRITE_BYTE_FIELD(p, offset, value) \
699 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
700
701
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000702Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
703 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000704}
705
706
707int Smi::value() {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000708 return static_cast<int>(reinterpret_cast<intptr_t>(this)) >> kSmiTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709}
710
711
712Smi* Smi::FromInt(int value) {
713 ASSERT(Smi::IsValid(value));
ager@chromium.org9085a012009-05-11 19:22:57 +0000714 intptr_t tagged_value =
715 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
716 return reinterpret_cast<Smi*>(tagged_value);
717}
718
719
720Smi* Smi::FromIntptr(intptr_t value) {
721 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
723}
724
725
726Failure::Type Failure::type() const {
727 return static_cast<Type>(value() & kFailureTypeTagMask);
728}
729
730
731bool Failure::IsInternalError() const {
732 return type() == INTERNAL_ERROR;
733}
734
735
736bool Failure::IsOutOfMemoryException() const {
737 return type() == OUT_OF_MEMORY_EXCEPTION;
738}
739
740
741int Failure::requested() const {
742 const int kShiftBits =
743 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
744 STATIC_ASSERT(kShiftBits >= 0);
745 ASSERT(type() == RETRY_AFTER_GC);
746 return value() >> kShiftBits;
747}
748
749
750AllocationSpace Failure::allocation_space() const {
751 ASSERT_EQ(RETRY_AFTER_GC, type());
752 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
753 & kSpaceTagMask);
754}
755
756
757Failure* Failure::InternalError() {
758 return Construct(INTERNAL_ERROR);
759}
760
761
762Failure* Failure::Exception() {
763 return Construct(EXCEPTION);
764}
765
766Failure* Failure::OutOfMemoryException() {
767 return Construct(OUT_OF_MEMORY_EXCEPTION);
768}
769
770
771int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000772 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000773}
774
775
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000776Failure* Failure::RetryAfterGC(int requested_bytes) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000777 // Assert that the space encoding fits in the three bytes allotted for it.
778 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000779 int requested = requested_bytes >> kObjectAlignmentBits;
780 int value = (requested << kSpaceTagSize) | NEW_SPACE;
781 ASSERT(value >> kSpaceTagSize == requested);
782 ASSERT(Smi::IsValid(value));
783 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
784 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
785 return Construct(RETRY_AFTER_GC, value);
786}
787
788
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000789Failure* Failure::Construct(Type type, int value) {
790 int info = (value << kFailureTypeTagSize) | type;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000791 // TODO(X64): Stop using Smi validation for non-smi checks, even if they
792 // happen to be identical at the moment.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000794 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000795 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000796}
797
798
799bool Smi::IsValid(int value) {
800#ifdef DEBUG
801 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
802#endif
803 // To be representable as an tagged small integer, the two
804 // most-significant bits of 'value' must be either 00 or 11 due to
805 // sign-extension. To check this we add 01 to the two
806 // most-significant bits, and check if the most-significant bit is 0
807 //
808 // CAUTION: The original code below:
809 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
810 // may lead to incorrect results according to the C language spec, and
811 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
812 // compiler may produce undefined results in case of signed integer
813 // overflow. The computation must be done w/ unsigned ints.
814 bool result =
815 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
816 ASSERT(result == in_range);
817 return result;
818}
819
820
ager@chromium.org9085a012009-05-11 19:22:57 +0000821bool Smi::IsIntptrValid(intptr_t value) {
822#ifdef DEBUG
823 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
824#endif
825 // See Smi::IsValid(int) for description.
826 bool result =
827 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
828 ASSERT(result == in_range);
829 return result;
830}
831
832
kasper.lund7276f142008-07-30 08:49:36 +0000833MapWord MapWord::FromMap(Map* map) {
834 return MapWord(reinterpret_cast<uintptr_t>(map));
835}
836
837
838Map* MapWord::ToMap() {
839 return reinterpret_cast<Map*>(value_);
840}
841
842
843bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000844 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000845}
846
847
848MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000849 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
850 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000851}
852
853
854HeapObject* MapWord::ToForwardingAddress() {
855 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000856 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000857}
858
859
860bool MapWord::IsMarked() {
861 return (value_ & kMarkingMask) == 0;
862}
863
864
865void MapWord::SetMark() {
866 value_ &= ~kMarkingMask;
867}
868
869
870void MapWord::ClearMark() {
871 value_ |= kMarkingMask;
872}
873
874
875bool MapWord::IsOverflowed() {
876 return (value_ & kOverflowMask) != 0;
877}
878
879
880void MapWord::SetOverflow() {
881 value_ |= kOverflowMask;
882}
883
884
885void MapWord::ClearOverflow() {
886 value_ &= ~kOverflowMask;
887}
888
889
890MapWord MapWord::EncodeAddress(Address map_address, int offset) {
891 // Offset is the distance in live bytes from the first live object in the
892 // same page. The offset between two objects in the same page should not
893 // exceed the object area size of a page.
894 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
895
896 int compact_offset = offset >> kObjectAlignmentBits;
897 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
898
899 Page* map_page = Page::FromAddress(map_address);
900 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
901
902 int map_page_offset =
903 map_page->Offset(map_address) >> kObjectAlignmentBits;
904
905 uintptr_t encoding =
906 (compact_offset << kForwardingOffsetShift) |
907 (map_page_offset << kMapPageOffsetShift) |
908 (map_page->mc_page_index << kMapPageIndexShift);
909 return MapWord(encoding);
910}
911
912
913Address MapWord::DecodeMapAddress(MapSpace* map_space) {
914 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
915 ASSERT_MAP_PAGE_INDEX(map_page_index);
916
917 int map_page_offset =
918 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
919 << kObjectAlignmentBits;
920
921 return (map_space->PageAddress(map_page_index) + map_page_offset);
922}
923
924
925int MapWord::DecodeOffset() {
926 // The offset field is represented in the kForwardingOffsetBits
927 // most-significant bits.
928 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
929 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
930 return offset;
931}
932
933
934MapWord MapWord::FromEncodedAddress(Address address) {
935 return MapWord(reinterpret_cast<uintptr_t>(address));
936}
937
938
939Address MapWord::ToEncodedAddress() {
940 return reinterpret_cast<Address>(value_);
941}
942
943
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000944#ifdef DEBUG
945void HeapObject::VerifyObjectField(int offset) {
946 VerifyPointer(READ_FIELD(this, offset));
947}
948#endif
949
950
951Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000952 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000953}
954
955
956void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000957 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000958}
959
960
kasper.lund7276f142008-07-30 08:49:36 +0000961MapWord HeapObject::map_word() {
962 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
963}
964
965
966void HeapObject::set_map_word(MapWord map_word) {
967 // WRITE_FIELD does not update the remembered set, but there is no need
968 // here.
969 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
970}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000971
972
973HeapObject* HeapObject::FromAddress(Address address) {
974 ASSERT_TAG_ALIGNED(address);
975 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
976}
977
978
979Address HeapObject::address() {
980 return reinterpret_cast<Address>(this) - kHeapObjectTag;
981}
982
983
984int HeapObject::Size() {
985 return SizeFromMap(map());
986}
987
988
989void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
990 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
991 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
992}
993
994
995void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
996 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
997}
998
999
kasper.lund7276f142008-07-30 08:49:36 +00001000bool HeapObject::IsMarked() {
1001 return map_word().IsMarked();
1002}
1003
1004
1005void HeapObject::SetMark() {
1006 ASSERT(!IsMarked());
1007 MapWord first_word = map_word();
1008 first_word.SetMark();
1009 set_map_word(first_word);
1010}
1011
1012
1013void HeapObject::ClearMark() {
1014 ASSERT(IsMarked());
1015 MapWord first_word = map_word();
1016 first_word.ClearMark();
1017 set_map_word(first_word);
1018}
1019
1020
1021bool HeapObject::IsOverflowed() {
1022 return map_word().IsOverflowed();
1023}
1024
1025
1026void HeapObject::SetOverflow() {
1027 MapWord first_word = map_word();
1028 first_word.SetOverflow();
1029 set_map_word(first_word);
1030}
1031
1032
1033void HeapObject::ClearOverflow() {
1034 ASSERT(IsOverflowed());
1035 MapWord first_word = map_word();
1036 first_word.ClearOverflow();
1037 set_map_word(first_word);
1038}
1039
1040
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041double HeapNumber::value() {
1042 return READ_DOUBLE_FIELD(this, kValueOffset);
1043}
1044
1045
1046void HeapNumber::set_value(double value) {
1047 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1048}
1049
1050
1051ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001052
1053
1054Array* JSObject::elements() {
1055 Object* array = READ_FIELD(this, kElementsOffset);
1056 // In the assert below Dictionary is covered under FixedArray.
1057 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1058 return reinterpret_cast<Array*>(array);
1059}
1060
1061
1062void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1063 // In the assert below Dictionary is covered under FixedArray.
1064 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1065 WRITE_FIELD(this, kElementsOffset, value);
1066 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1067}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001068
1069
1070void JSObject::initialize_properties() {
1071 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1072 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1073}
1074
1075
1076void JSObject::initialize_elements() {
1077 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1078 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1079}
1080
1081
1082ACCESSORS(Oddball, to_string, String, kToStringOffset)
1083ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1084
1085
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001086Object* JSGlobalPropertyCell::value() {
1087 return READ_FIELD(this, kValueOffset);
1088}
1089
1090
1091void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1092 // The write barrier is not used for global property cells.
1093 ASSERT(!val->IsJSGlobalPropertyCell());
1094 WRITE_FIELD(this, kValueOffset, val);
1095}
1096
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001097
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001098int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001099 InstanceType type = map()->instance_type();
1100 // Check for the most common kind of JavaScript object before
1101 // falling into the generic switch. This speeds up the internal
1102 // field operations considerably on average.
1103 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1104 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001105 case JS_GLOBAL_PROXY_TYPE:
1106 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001107 case JS_GLOBAL_OBJECT_TYPE:
1108 return JSGlobalObject::kSize;
1109 case JS_BUILTINS_OBJECT_TYPE:
1110 return JSBuiltinsObject::kSize;
1111 case JS_FUNCTION_TYPE:
1112 return JSFunction::kSize;
1113 case JS_VALUE_TYPE:
1114 return JSValue::kSize;
1115 case JS_ARRAY_TYPE:
1116 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001117 case JS_REGEXP_TYPE:
1118 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001119 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001120 return JSObject::kHeaderSize;
1121 default:
1122 UNREACHABLE();
1123 return 0;
1124 }
1125}
1126
1127
1128int JSObject::GetInternalFieldCount() {
1129 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001130 // Make sure to adjust for the number of in-object properties. These
1131 // properties do contribute to the size, but are not internal fields.
1132 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1133 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001134}
1135
1136
1137Object* JSObject::GetInternalField(int index) {
1138 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001139 // Internal objects do follow immediately after the header, whereas in-object
1140 // properties are at the end of the object. Therefore there is no need
1141 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001142 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1143}
1144
1145
1146void JSObject::SetInternalField(int index, Object* value) {
1147 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001148 // Internal objects do follow immediately after the header, whereas in-object
1149 // properties are at the end of the object. Therefore there is no need
1150 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001151 int offset = GetHeaderSize() + (kPointerSize * index);
1152 WRITE_FIELD(this, offset, value);
1153 WRITE_BARRIER(this, offset);
1154}
1155
1156
ager@chromium.org7c537e22008-10-16 08:43:32 +00001157// Access fast-case object properties at index. The use of these routines
1158// is needed to correctly distinguish between properties stored in-object and
1159// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001160Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001161 // Adjust for the number of properties stored in the object.
1162 index -= map()->inobject_properties();
1163 if (index < 0) {
1164 int offset = map()->instance_size() + (index * kPointerSize);
1165 return READ_FIELD(this, offset);
1166 } else {
1167 ASSERT(index < properties()->length());
1168 return properties()->get(index);
1169 }
1170}
1171
1172
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001173Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001174 // Adjust for the number of properties stored in the object.
1175 index -= map()->inobject_properties();
1176 if (index < 0) {
1177 int offset = map()->instance_size() + (index * kPointerSize);
1178 WRITE_FIELD(this, offset, value);
1179 WRITE_BARRIER(this, offset);
1180 } else {
1181 ASSERT(index < properties()->length());
1182 properties()->set(index, value);
1183 }
1184 return value;
1185}
1186
1187
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001188Object* JSObject::InObjectPropertyAt(int index) {
1189 // Adjust for the number of properties stored in the object.
1190 index -= map()->inobject_properties();
1191 ASSERT(index < 0);
1192 int offset = map()->instance_size() + (index * kPointerSize);
1193 return READ_FIELD(this, offset);
1194}
1195
1196
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001197Object* JSObject::InObjectPropertyAtPut(int index,
1198 Object* value,
1199 WriteBarrierMode mode) {
1200 // Adjust for the number of properties stored in the object.
1201 index -= map()->inobject_properties();
1202 ASSERT(index < 0);
1203 int offset = map()->instance_size() + (index * kPointerSize);
1204 WRITE_FIELD(this, offset, value);
1205 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1206 return value;
1207}
1208
1209
1210
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001211void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001212 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001213 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001214 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001215 }
1216}
1217
1218
1219void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001220 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001221 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001222 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223 }
1224}
1225
1226
1227bool JSObject::HasFastProperties() {
1228 return !properties()->IsDictionary();
1229}
1230
1231
1232bool Array::IndexFromObject(Object* object, uint32_t* index) {
1233 if (object->IsSmi()) {
1234 int value = Smi::cast(object)->value();
1235 if (value < 0) return false;
1236 *index = value;
1237 return true;
1238 }
1239 if (object->IsHeapNumber()) {
1240 double value = HeapNumber::cast(object)->value();
1241 uint32_t uint_value = static_cast<uint32_t>(value);
1242 if (value == static_cast<double>(uint_value)) {
1243 *index = uint_value;
1244 return true;
1245 }
1246 }
1247 return false;
1248}
1249
1250
1251bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1252 if (!this->IsJSValue()) return false;
1253
1254 JSValue* js_value = JSValue::cast(this);
1255 if (!js_value->value()->IsString()) return false;
1256
1257 String* str = String::cast(js_value->value());
1258 if (index >= (uint32_t)str->length()) return false;
1259
1260 return true;
1261}
1262
1263
1264Object* FixedArray::get(int index) {
1265 ASSERT(index >= 0 && index < this->length());
1266 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1267}
1268
1269
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001270void FixedArray::set(int index, Smi* value) {
1271 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1272 int offset = kHeaderSize + index * kPointerSize;
1273 WRITE_FIELD(this, offset, value);
1274}
1275
1276
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277void FixedArray::set(int index, Object* value) {
1278 ASSERT(index >= 0 && index < this->length());
1279 int offset = kHeaderSize + index * kPointerSize;
1280 WRITE_FIELD(this, offset, value);
1281 WRITE_BARRIER(this, offset);
1282}
1283
1284
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001285WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001286 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1287 return UPDATE_WRITE_BARRIER;
1288}
1289
1290
1291void FixedArray::set(int index,
1292 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001293 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294 ASSERT(index >= 0 && index < this->length());
1295 int offset = kHeaderSize + index * kPointerSize;
1296 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001297 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001298}
1299
1300
1301void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1302 ASSERT(index >= 0 && index < array->length());
1303 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1304}
1305
1306
1307void FixedArray::set_undefined(int index) {
1308 ASSERT(index >= 0 && index < this->length());
1309 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1310 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1311 Heap::undefined_value());
1312}
1313
1314
ager@chromium.org236ad962008-09-25 09:45:57 +00001315void FixedArray::set_null(int index) {
1316 ASSERT(index >= 0 && index < this->length());
1317 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1318 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1319}
1320
1321
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001322void FixedArray::set_the_hole(int index) {
1323 ASSERT(index >= 0 && index < this->length());
1324 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1325 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1326}
1327
1328
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001329bool DescriptorArray::IsEmpty() {
1330 ASSERT(this == Heap::empty_descriptor_array() ||
1331 this->length() > 2);
1332 return this == Heap::empty_descriptor_array();
1333}
1334
1335
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001336void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1337 Object* tmp = array->get(first);
1338 fast_set(array, first, array->get(second));
1339 fast_set(array, second, tmp);
1340}
1341
1342
1343int DescriptorArray::Search(String* name) {
1344 SLOW_ASSERT(IsSortedNoDuplicates());
1345
1346 // Check for empty descriptor array.
1347 int nof = number_of_descriptors();
1348 if (nof == 0) return kNotFound;
1349
1350 // Fast case: do linear search for small arrays.
1351 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001352 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001353 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354 }
1355
1356 // Slow case: perform binary search.
1357 return BinarySearch(name, 0, nof - 1);
1358}
1359
1360
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361String* DescriptorArray::GetKey(int descriptor_number) {
1362 ASSERT(descriptor_number < number_of_descriptors());
1363 return String::cast(get(ToKeyIndex(descriptor_number)));
1364}
1365
1366
1367Object* DescriptorArray::GetValue(int descriptor_number) {
1368 ASSERT(descriptor_number < number_of_descriptors());
1369 return GetContentArray()->get(ToValueIndex(descriptor_number));
1370}
1371
1372
1373Smi* DescriptorArray::GetDetails(int descriptor_number) {
1374 ASSERT(descriptor_number < number_of_descriptors());
1375 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1376}
1377
1378
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001379PropertyType DescriptorArray::GetType(int descriptor_number) {
1380 ASSERT(descriptor_number < number_of_descriptors());
1381 return PropertyDetails(GetDetails(descriptor_number)).type();
1382}
1383
1384
1385int DescriptorArray::GetFieldIndex(int descriptor_number) {
1386 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1387}
1388
1389
1390JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1391 return JSFunction::cast(GetValue(descriptor_number));
1392}
1393
1394
1395Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1396 ASSERT(GetType(descriptor_number) == CALLBACKS);
1397 return GetValue(descriptor_number);
1398}
1399
1400
1401AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1402 ASSERT(GetType(descriptor_number) == CALLBACKS);
1403 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1404 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1405}
1406
1407
1408bool DescriptorArray::IsProperty(int descriptor_number) {
1409 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1410}
1411
1412
1413bool DescriptorArray::IsTransition(int descriptor_number) {
1414 PropertyType t = GetType(descriptor_number);
1415 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1416}
1417
1418
1419bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1420 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1421}
1422
1423
1424bool DescriptorArray::IsDontEnum(int descriptor_number) {
1425 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1426}
1427
1428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001429void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1430 desc->Init(GetKey(descriptor_number),
1431 GetValue(descriptor_number),
1432 GetDetails(descriptor_number));
1433}
1434
1435
1436void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1437 // Range check.
1438 ASSERT(descriptor_number < number_of_descriptors());
1439
1440 // Make sure non of the elements in desc are in new space.
1441 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1442 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1443
1444 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1445 FixedArray* content_array = GetContentArray();
1446 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1447 fast_set(content_array, ToDetailsIndex(descriptor_number),
1448 desc->GetDetails().AsSmi());
1449}
1450
1451
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001452void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1453 Descriptor desc;
1454 src->Get(src_index, &desc);
1455 Set(index, &desc);
1456}
1457
1458
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001459void DescriptorArray::Swap(int first, int second) {
1460 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1461 FixedArray* content_array = GetContentArray();
1462 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1463 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1464}
1465
1466
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001467bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001468 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001469 if (!max_index_object->IsSmi()) return false;
1470 return 0 !=
1471 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1472}
1473
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001474uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001475 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001476 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001477 if (!max_index_object->IsSmi()) return 0;
1478 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1479 return value >> kRequiresSlowElementsTagSize;
1480}
1481
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001482void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001483 set(kMaxNumberKeyIndex,
1484 Smi::FromInt(kRequiresSlowElementsMask),
1485 SKIP_WRITE_BARRIER);
1486}
1487
1488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001489// ------------------------------------
1490// Cast operations
1491
1492
1493CAST_ACCESSOR(FixedArray)
1494CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001495CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001496CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001497CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498CAST_ACCESSOR(String)
1499CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001500CAST_ACCESSOR(SeqAsciiString)
1501CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502CAST_ACCESSOR(ConsString)
1503CAST_ACCESSOR(SlicedString)
1504CAST_ACCESSOR(ExternalString)
1505CAST_ACCESSOR(ExternalAsciiString)
1506CAST_ACCESSOR(ExternalTwoByteString)
1507CAST_ACCESSOR(JSObject)
1508CAST_ACCESSOR(Smi)
1509CAST_ACCESSOR(Failure)
1510CAST_ACCESSOR(HeapObject)
1511CAST_ACCESSOR(HeapNumber)
1512CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001513CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514CAST_ACCESSOR(SharedFunctionInfo)
1515CAST_ACCESSOR(Map)
1516CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001517CAST_ACCESSOR(GlobalObject)
1518CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001519CAST_ACCESSOR(JSGlobalObject)
1520CAST_ACCESSOR(JSBuiltinsObject)
1521CAST_ACCESSOR(Code)
1522CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001523CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001524CAST_ACCESSOR(Proxy)
1525CAST_ACCESSOR(ByteArray)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001526CAST_ACCESSOR(PixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001527CAST_ACCESSOR(Struct)
1528
1529
1530#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1531 STRUCT_LIST(MAKE_STRUCT_CAST)
1532#undef MAKE_STRUCT_CAST
1533
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001534
1535template <typename Shape, typename Key>
1536HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 ASSERT(obj->IsHashTable());
1538 return reinterpret_cast<HashTable*>(obj);
1539}
1540
1541
1542INT_ACCESSORS(Array, length, kLengthOffset)
1543
1544
1545bool String::Equals(String* other) {
1546 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001547 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1548 return false;
1549 }
1550 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551}
1552
1553
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001554int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001555 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1556
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001557 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1558 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1559 ASSERT(kLongStringTag == 0);
1560
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001561 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001562}
1563
1564
1565void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001566 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1567 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1568 ASSERT(kLongStringTag == 0);
1569
1570 WRITE_INT_FIELD(this,
1571 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001572 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001573}
1574
1575
ager@chromium.org7c537e22008-10-16 08:43:32 +00001576uint32_t String::length_field() {
1577 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001578}
1579
1580
ager@chromium.org7c537e22008-10-16 08:43:32 +00001581void String::set_length_field(uint32_t value) {
1582 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583}
1584
1585
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001586Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001587 // We don't need to flatten strings that are already flat. Since this code
1588 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001589 if (!IsFlat()) {
1590 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001591 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001592 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001593}
1594
1595
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001596uint16_t String::Get(int index) {
1597 ASSERT(index >= 0 && index < length());
1598 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001599 case kSeqStringTag | kAsciiStringTag:
1600 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1601 case kSeqStringTag | kTwoByteStringTag:
1602 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1603 case kConsStringTag | kAsciiStringTag:
1604 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001605 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001606 case kSlicedStringTag | kAsciiStringTag:
1607 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001608 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001609 case kExternalStringTag | kAsciiStringTag:
1610 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1611 case kExternalStringTag | kTwoByteStringTag:
1612 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001613 default:
1614 break;
1615 }
1616
1617 UNREACHABLE();
1618 return 0;
1619}
1620
1621
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001622void String::Set(int index, uint16_t value) {
1623 ASSERT(index >= 0 && index < length());
1624 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625
ager@chromium.org5ec48922009-05-05 07:25:34 +00001626 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001627 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1628 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001629}
1630
1631
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001632bool String::IsFlat() {
1633 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001634 case kConsStringTag: {
1635 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001636 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001637 return second->length() == 0;
1638 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001639 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001640 StringRepresentationTag tag =
1641 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001642 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001644 default:
1645 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001646 }
1647}
1648
1649
ager@chromium.org7c537e22008-10-16 08:43:32 +00001650uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001651 ASSERT(index >= 0 && index < length());
1652 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1653}
1654
1655
ager@chromium.org7c537e22008-10-16 08:43:32 +00001656void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001657 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1658 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1659 static_cast<byte>(value));
1660}
1661
1662
ager@chromium.org7c537e22008-10-16 08:43:32 +00001663Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664 return FIELD_ADDR(this, kHeaderSize);
1665}
1666
1667
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001668char* SeqAsciiString::GetChars() {
1669 return reinterpret_cast<char*>(GetCharsAddress());
1670}
1671
1672
ager@chromium.org7c537e22008-10-16 08:43:32 +00001673Address SeqTwoByteString::GetCharsAddress() {
1674 return FIELD_ADDR(this, kHeaderSize);
1675}
1676
1677
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001678uc16* SeqTwoByteString::GetChars() {
1679 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1680}
1681
1682
ager@chromium.org7c537e22008-10-16 08:43:32 +00001683uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001684 ASSERT(index >= 0 && index < length());
1685 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1686}
1687
1688
ager@chromium.org7c537e22008-10-16 08:43:32 +00001689void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001690 ASSERT(index >= 0 && index < length());
1691 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1692}
1693
1694
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001695int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001696 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1697
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001698 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1699 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1700 ASSERT(kLongStringTag == 0);
1701
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001702 // Use the map (and not 'this') to compute the size tag, since
1703 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001704 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001705
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001706 return SizeFor(length);
1707}
1708
1709
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001710int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001711 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1712
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001713 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1714 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1715 ASSERT(kLongStringTag == 0);
1716
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001717 // Use the map (and not 'this') to compute the size tag, since
1718 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001719 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001720
1721 return SizeFor(length);
1722}
1723
1724
ager@chromium.org870a0b62008-11-04 11:43:05 +00001725String* ConsString::first() {
1726 return String::cast(READ_FIELD(this, kFirstOffset));
1727}
1728
1729
1730Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001731 return READ_FIELD(this, kFirstOffset);
1732}
1733
1734
ager@chromium.org870a0b62008-11-04 11:43:05 +00001735void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001736 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001737 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001738}
1739
1740
ager@chromium.org870a0b62008-11-04 11:43:05 +00001741String* ConsString::second() {
1742 return String::cast(READ_FIELD(this, kSecondOffset));
1743}
1744
1745
1746Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001747 return READ_FIELD(this, kSecondOffset);
1748}
1749
1750
ager@chromium.org870a0b62008-11-04 11:43:05 +00001751void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001752 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001753 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001754}
1755
1756
ager@chromium.org870a0b62008-11-04 11:43:05 +00001757String* SlicedString::buffer() {
1758 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001759}
1760
1761
ager@chromium.org870a0b62008-11-04 11:43:05 +00001762void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001763 WRITE_FIELD(this, kBufferOffset, buffer);
1764 WRITE_BARRIER(this, kBufferOffset);
1765}
1766
1767
1768int SlicedString::start() {
1769 return READ_INT_FIELD(this, kStartOffset);
1770}
1771
1772
1773void SlicedString::set_start(int start) {
1774 WRITE_INT_FIELD(this, kStartOffset, start);
1775}
1776
1777
1778ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1779 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1780}
1781
1782
1783void ExternalAsciiString::set_resource(
1784 ExternalAsciiString::Resource* resource) {
1785 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1786}
1787
1788
ager@chromium.org6f10e412009-02-13 10:11:16 +00001789Map* ExternalAsciiString::StringMap(int length) {
1790 Map* map;
1791 // Number of characters: determines the map.
1792 if (length <= String::kMaxShortStringSize) {
1793 map = Heap::short_external_ascii_string_map();
1794 } else if (length <= String::kMaxMediumStringSize) {
1795 map = Heap::medium_external_ascii_string_map();
1796 } else {
1797 map = Heap::long_external_ascii_string_map();
1798 }
1799 return map;
1800}
1801
1802
1803Map* ExternalAsciiString::SymbolMap(int length) {
1804 Map* map;
1805 // Number of characters: determines the map.
1806 if (length <= String::kMaxShortStringSize) {
1807 map = Heap::short_external_ascii_symbol_map();
1808 } else if (length <= String::kMaxMediumStringSize) {
1809 map = Heap::medium_external_ascii_symbol_map();
1810 } else {
1811 map = Heap::long_external_ascii_symbol_map();
1812 }
1813 return map;
1814}
1815
1816
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001817ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1818 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1819}
1820
1821
1822void ExternalTwoByteString::set_resource(
1823 ExternalTwoByteString::Resource* resource) {
1824 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1825}
1826
1827
ager@chromium.org6f10e412009-02-13 10:11:16 +00001828Map* ExternalTwoByteString::StringMap(int length) {
1829 Map* map;
1830 // Number of characters: determines the map.
1831 if (length <= String::kMaxShortStringSize) {
1832 map = Heap::short_external_string_map();
1833 } else if (length <= String::kMaxMediumStringSize) {
1834 map = Heap::medium_external_string_map();
1835 } else {
1836 map = Heap::long_external_string_map();
1837 }
1838 return map;
1839}
1840
1841
1842Map* ExternalTwoByteString::SymbolMap(int length) {
1843 Map* map;
1844 // Number of characters: determines the map.
1845 if (length <= String::kMaxShortStringSize) {
1846 map = Heap::short_external_symbol_map();
1847 } else if (length <= String::kMaxMediumStringSize) {
1848 map = Heap::medium_external_symbol_map();
1849 } else {
1850 map = Heap::long_external_symbol_map();
1851 }
1852 return map;
1853}
1854
1855
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001856byte ByteArray::get(int index) {
1857 ASSERT(index >= 0 && index < this->length());
1858 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1859}
1860
1861
1862void ByteArray::set(int index, byte value) {
1863 ASSERT(index >= 0 && index < this->length());
1864 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1865}
1866
1867
1868int ByteArray::get_int(int index) {
1869 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1870 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1871}
1872
1873
1874ByteArray* ByteArray::FromDataStartAddress(Address address) {
1875 ASSERT_TAG_ALIGNED(address);
1876 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1877}
1878
1879
1880Address ByteArray::GetDataStartAddress() {
1881 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1882}
1883
1884
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001885uint8_t* PixelArray::external_pointer() {
1886 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1887 return reinterpret_cast<uint8_t*>(ptr);
1888}
1889
1890
1891void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1892 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1893 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1894}
1895
1896
1897uint8_t PixelArray::get(int index) {
1898 ASSERT((index >= 0) && (index < this->length()));
1899 uint8_t* ptr = external_pointer();
1900 return ptr[index];
1901}
1902
1903
1904void PixelArray::set(int index, uint8_t value) {
1905 ASSERT((index >= 0) && (index < this->length()));
1906 uint8_t* ptr = external_pointer();
1907 ptr[index] = value;
1908}
1909
1910
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001911int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001912 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1913}
1914
1915
1916int Map::inobject_properties() {
1917 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001918}
1919
1920
1921int HeapObject::SizeFromMap(Map* map) {
1922 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001923 // Only inline the most frequent cases.
1924 if (instance_type == JS_OBJECT_TYPE ||
1925 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1926 (kStringTag | kConsStringTag) ||
1927 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001928 if (instance_type == FIXED_ARRAY_TYPE) {
1929 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1930 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001931 if (instance_type == BYTE_ARRAY_TYPE) {
1932 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1933 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001934 // Otherwise do the general size computation.
1935 return SlowSizeFromMap(map);
1936}
1937
1938
1939void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001940 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001941 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942 ASSERT(0 <= value && value < 256);
1943 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1944}
1945
1946
ager@chromium.org7c537e22008-10-16 08:43:32 +00001947void Map::set_inobject_properties(int value) {
1948 ASSERT(0 <= value && value < 256);
1949 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1950}
1951
1952
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001953InstanceType Map::instance_type() {
1954 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1955}
1956
1957
1958void Map::set_instance_type(InstanceType value) {
1959 ASSERT(0 <= value && value < 256);
1960 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1961}
1962
1963
1964int Map::unused_property_fields() {
1965 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1966}
1967
1968
1969void Map::set_unused_property_fields(int value) {
1970 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1971}
1972
1973
1974byte Map::bit_field() {
1975 return READ_BYTE_FIELD(this, kBitFieldOffset);
1976}
1977
1978
1979void Map::set_bit_field(byte value) {
1980 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1981}
1982
1983
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001984byte Map::bit_field2() {
1985 return READ_BYTE_FIELD(this, kBitField2Offset);
1986}
1987
1988
1989void Map::set_bit_field2(byte value) {
1990 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1991}
1992
1993
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001994void Map::set_non_instance_prototype(bool value) {
1995 if (value) {
1996 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1997 } else {
1998 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1999 }
2000}
2001
2002
2003bool Map::has_non_instance_prototype() {
2004 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2005}
2006
2007
ager@chromium.org870a0b62008-11-04 11:43:05 +00002008void Map::set_is_access_check_needed(bool access_check_needed) {
2009 if (access_check_needed) {
2010 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2011 } else {
2012 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2013 }
2014}
2015
2016
2017bool Map::is_access_check_needed() {
2018 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2019}
2020
2021
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002022Code::Flags Code::flags() {
2023 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2024}
2025
2026
2027void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002028 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002029 // Make sure that all call stubs have an arguments count.
2030 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2031 ExtractArgumentsCountFromFlags(flags) >= 0);
2032 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2033}
2034
2035
2036Code::Kind Code::kind() {
2037 return ExtractKindFromFlags(flags());
2038}
2039
2040
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002041InLoopFlag Code::ic_in_loop() {
2042 return ExtractICInLoopFromFlags(flags());
2043}
2044
2045
kasper.lund7276f142008-07-30 08:49:36 +00002046InlineCacheState Code::ic_state() {
2047 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002048 // Only allow uninitialized or debugger states for non-IC code
2049 // objects. This is used in the debugger to determine whether or not
2050 // a call to code object has been replaced with a debug break call.
2051 ASSERT(is_inline_cache_stub() ||
2052 result == UNINITIALIZED ||
2053 result == DEBUG_BREAK ||
2054 result == DEBUG_PREPARE_STEP_IN);
2055 return result;
2056}
2057
2058
2059PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002060 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002061 return ExtractTypeFromFlags(flags());
2062}
2063
2064
2065int Code::arguments_count() {
2066 ASSERT(is_call_stub() || kind() == STUB);
2067 return ExtractArgumentsCountFromFlags(flags());
2068}
2069
2070
2071CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002072 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002073 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2074 kStubMajorKeyOffset));
2075}
2076
2077
2078void Code::set_major_key(CodeStub::Major major) {
2079 ASSERT(kind() == STUB);
2080 ASSERT(0 <= major && major < 256);
2081 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002082}
2083
2084
2085bool Code::is_inline_cache_stub() {
2086 Kind kind = this->kind();
2087 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2088}
2089
2090
2091Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002092 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002093 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002094 PropertyType type,
2095 int argc) {
2096 // Compute the bit mask.
2097 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002098 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002099 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002100 bits |= type << kFlagsTypeShift;
2101 bits |= argc << kFlagsArgumentsCountShift;
2102 // Cast to flags and validate result before returning it.
2103 Flags result = static_cast<Flags>(bits);
2104 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002105 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002106 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002107 ASSERT(ExtractTypeFromFlags(result) == type);
2108 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2109 return result;
2110}
2111
2112
2113Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2114 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002115 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002116 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002117 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002118}
2119
2120
2121Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2122 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2123 return static_cast<Kind>(bits);
2124}
2125
2126
kasper.lund7276f142008-07-30 08:49:36 +00002127InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2128 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002129 return static_cast<InlineCacheState>(bits);
2130}
2131
2132
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002133InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2134 int bits = (flags & kFlagsICInLoopMask);
2135 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2136}
2137
2138
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002139PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2140 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2141 return static_cast<PropertyType>(bits);
2142}
2143
2144
2145int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2146 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2147}
2148
2149
2150Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2151 int bits = flags & ~kFlagsTypeMask;
2152 return static_cast<Flags>(bits);
2153}
2154
2155
ager@chromium.org8bb60582008-12-11 12:02:20 +00002156Code* Code::GetCodeFromTargetAddress(Address address) {
2157 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2158 // GetCodeFromTargetAddress might be called when marking objects during mark
2159 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2160 // Code::cast. Code::cast does not work when the object's map is
2161 // marked.
2162 Code* result = reinterpret_cast<Code*>(code);
2163 return result;
2164}
2165
2166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002167Object* Map::prototype() {
2168 return READ_FIELD(this, kPrototypeOffset);
2169}
2170
2171
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002172void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002173 ASSERT(value->IsNull() || value->IsJSObject());
2174 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002175 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002176}
2177
2178
2179ACCESSORS(Map, instance_descriptors, DescriptorArray,
2180 kInstanceDescriptorsOffset)
2181ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2182ACCESSORS(Map, constructor, Object, kConstructorOffset)
2183
2184ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2185ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2186
2187ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2188ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002189ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002190
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002191ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192
2193ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2194ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2195ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2196ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2197ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2198
2199ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2200ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2201ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2202
2203ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2204ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2205ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2206ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2207ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2208ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2209
2210ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2211ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2212
2213ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2214ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2215
2216ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2217ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002218ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2219 kPropertyAccessorsOffset)
2220ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2221 kPrototypeTemplateOffset)
2222ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2223ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2224 kNamedPropertyHandlerOffset)
2225ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2226 kIndexedPropertyHandlerOffset)
2227ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2228 kInstanceTemplateOffset)
2229ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2230ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002231ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2232 kInstanceCallHandlerOffset)
2233ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2234 kAccessCheckInfoOffset)
2235ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2236
2237ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002238ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2239 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002240
2241ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2242ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2243
2244ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2245
2246ACCESSORS(Script, source, Object, kSourceOffset)
2247ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002248ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002249ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2250ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002251ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002252ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002253ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2254ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002255ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002256ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002257ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2258ACCESSORS(Script, eval_from_instructions_offset, Smi,
2259 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002260
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002261#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002262ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2263ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2264ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2265ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2266
2267ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2268ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2269ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2270ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002271#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002272
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002273ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002274ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2275ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2276 kInstanceClassNameOffset)
2277ACCESSORS(SharedFunctionInfo, function_data, Object,
2278 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002279ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2280ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002281ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002282
2283BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2284 kHiddenPrototypeBit)
2285BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2286BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2287 kNeedsAccessCheckBit)
2288BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2289 kIsExpressionBit)
2290BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2291 kIsTopLevelBit)
2292
2293INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2294INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2295 kFormalParameterCountOffset)
2296INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2297 kExpectedNofPropertiesOffset)
2298INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2299 kStartPositionAndTypeOffset)
2300INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2301INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2302 kFunctionTokenPositionOffset)
2303
2304
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002305void SharedFunctionInfo::DontAdaptArguments() {
2306 ASSERT(code()->kind() == Code::BUILTIN);
2307 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2308}
2309
2310
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311int SharedFunctionInfo::start_position() {
2312 return start_position_and_type() >> kStartPositionShift;
2313}
2314
2315
2316void SharedFunctionInfo::set_start_position(int start_position) {
2317 set_start_position_and_type((start_position << kStartPositionShift)
2318 | (start_position_and_type() & ~kStartPositionMask));
2319}
2320
2321
2322Code* SharedFunctionInfo::code() {
2323 return Code::cast(READ_FIELD(this, kCodeOffset));
2324}
2325
2326
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002327void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002328 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002329 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002330}
2331
2332
2333bool SharedFunctionInfo::is_compiled() {
2334 // TODO(1242782): Create a code kind for uncompiled code.
2335 return code()->kind() != Code::STUB;
2336}
2337
2338
2339bool JSFunction::IsBoilerplate() {
2340 return map() == Heap::boilerplate_function_map();
2341}
2342
2343
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002344bool JSFunction::IsBuiltin() {
2345 return context()->global()->IsJSBuiltinsObject();
2346}
2347
2348
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002349bool JSObject::IsLoaded() {
2350 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002351}
2352
2353
2354Code* JSFunction::code() {
2355 return shared()->code();
2356}
2357
2358
2359void JSFunction::set_code(Code* value) {
2360 shared()->set_code(value);
2361}
2362
2363
2364Context* JSFunction::context() {
2365 return Context::cast(READ_FIELD(this, kContextOffset));
2366}
2367
2368
2369Object* JSFunction::unchecked_context() {
2370 return READ_FIELD(this, kContextOffset);
2371}
2372
2373
2374void JSFunction::set_context(Object* value) {
2375 ASSERT(value == Heap::undefined_value() || value->IsContext());
2376 WRITE_FIELD(this, kContextOffset, value);
2377 WRITE_BARRIER(this, kContextOffset);
2378}
2379
2380ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2381 kPrototypeOrInitialMapOffset)
2382
2383
2384Map* JSFunction::initial_map() {
2385 return Map::cast(prototype_or_initial_map());
2386}
2387
2388
2389void JSFunction::set_initial_map(Map* value) {
2390 set_prototype_or_initial_map(value);
2391}
2392
2393
2394bool JSFunction::has_initial_map() {
2395 return prototype_or_initial_map()->IsMap();
2396}
2397
2398
2399bool JSFunction::has_instance_prototype() {
2400 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2401}
2402
2403
2404bool JSFunction::has_prototype() {
2405 return map()->has_non_instance_prototype() || has_instance_prototype();
2406}
2407
2408
2409Object* JSFunction::instance_prototype() {
2410 ASSERT(has_instance_prototype());
2411 if (has_initial_map()) return initial_map()->prototype();
2412 // When there is no initial map and the prototype is a JSObject, the
2413 // initial map field is used for the prototype field.
2414 return prototype_or_initial_map();
2415}
2416
2417
2418Object* JSFunction::prototype() {
2419 ASSERT(has_prototype());
2420 // If the function's prototype property has been set to a non-JSObject
2421 // value, that value is stored in the constructor field of the map.
2422 if (map()->has_non_instance_prototype()) return map()->constructor();
2423 return instance_prototype();
2424}
2425
2426
2427bool JSFunction::is_compiled() {
2428 return shared()->is_compiled();
2429}
2430
2431
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002432int JSFunction::NumberOfLiterals() {
2433 return literals()->length();
2434}
2435
2436
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002437Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2438 ASSERT(0 <= id && id < kJSBuiltinsCount);
2439 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2440}
2441
2442
2443void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2444 Object* value) {
2445 ASSERT(0 <= id && id < kJSBuiltinsCount);
2446 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2447 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2448}
2449
2450
2451Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002452 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002453}
2454
2455
2456void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002457 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002458}
2459
2460
2461void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2462 visitor->VisitExternalReference(
2463 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2464}
2465
2466
2467ACCESSORS(JSValue, value, Object, kValueOffset)
2468
2469
2470JSValue* JSValue::cast(Object* obj) {
2471 ASSERT(obj->IsJSValue());
2472 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2473 return reinterpret_cast<JSValue*>(obj);
2474}
2475
2476
2477INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2478INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2479INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2480
2481
2482Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002483 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002484}
2485
2486
2487void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002488 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002489}
2490
2491
2492byte* Code::instruction_start() {
2493 return FIELD_ADDR(this, kHeaderSize);
2494}
2495
2496
2497int Code::body_size() {
2498 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2499}
2500
2501
2502byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002503 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002504}
2505
2506
2507byte* Code::entry() {
2508 return instruction_start();
2509}
2510
2511
2512bool Code::contains(byte* pc) {
2513 return (instruction_start() <= pc) &&
2514 (pc < instruction_start() + instruction_size());
2515}
2516
2517
2518byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002519 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002520}
2521
2522
2523ACCESSORS(JSArray, length, Object, kLengthOffset)
2524
2525
ager@chromium.org236ad962008-09-25 09:45:57 +00002526ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002527
2528
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002529JSRegExp::Type JSRegExp::TypeTag() {
2530 Object* data = this->data();
2531 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2532 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2533 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002534}
2535
2536
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002537int JSRegExp::CaptureCount() {
2538 switch (TypeTag()) {
2539 case ATOM:
2540 return 0;
2541 case IRREGEXP:
2542 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2543 default:
2544 UNREACHABLE();
2545 return -1;
2546 }
2547}
2548
2549
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002550JSRegExp::Flags JSRegExp::GetFlags() {
2551 ASSERT(this->data()->IsFixedArray());
2552 Object* data = this->data();
2553 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2554 return Flags(smi->value());
2555}
2556
2557
2558String* JSRegExp::Pattern() {
2559 ASSERT(this->data()->IsFixedArray());
2560 Object* data = this->data();
2561 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2562 return pattern;
2563}
2564
2565
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002566Object* JSRegExp::DataAt(int index) {
2567 ASSERT(TypeTag() != NOT_COMPILED);
2568 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002569}
2570
2571
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002572void JSRegExp::SetDataAt(int index, Object* value) {
2573 ASSERT(TypeTag() != NOT_COMPILED);
2574 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2575 FixedArray::cast(data())->set(index, value);
2576}
2577
2578
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002579JSObject::ElementsKind JSObject::GetElementsKind() {
2580 Array* array = elements();
2581 if (array->IsFixedArray()) {
2582 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2583 if (array->map() == Heap::fixed_array_map()) {
2584 return FAST_ELEMENTS;
2585 }
2586 ASSERT(array->IsDictionary());
2587 return DICTIONARY_ELEMENTS;
2588 }
2589 ASSERT(array->IsPixelArray());
2590 return PIXEL_ELEMENTS;
2591}
2592
2593
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002594bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002595 return GetElementsKind() == FAST_ELEMENTS;
2596}
2597
2598
2599bool JSObject::HasDictionaryElements() {
2600 return GetElementsKind() == DICTIONARY_ELEMENTS;
2601}
2602
2603
2604bool JSObject::HasPixelElements() {
2605 return GetElementsKind() == PIXEL_ELEMENTS;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002606}
2607
2608
2609bool JSObject::HasNamedInterceptor() {
2610 return map()->has_named_interceptor();
2611}
2612
2613
2614bool JSObject::HasIndexedInterceptor() {
2615 return map()->has_indexed_interceptor();
2616}
2617
2618
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002619StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002620 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002621 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002622}
2623
2624
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002625NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002626 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002627 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002628}
2629
2630
2631bool String::HasHashCode() {
2632 return (length_field() & kHashComputedMask) != 0;
2633}
2634
2635
2636uint32_t String::Hash() {
2637 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002638 uint32_t field = length_field();
2639 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002640 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002641 return ComputeAndSetHash();
2642}
2643
2644
ager@chromium.org7c537e22008-10-16 08:43:32 +00002645StringHasher::StringHasher(int length)
2646 : length_(length),
2647 raw_running_hash_(0),
2648 array_index_(0),
2649 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2650 is_first_char_(true),
2651 is_valid_(true) { }
2652
2653
2654bool StringHasher::has_trivial_hash() {
2655 return length_ > String::kMaxMediumStringSize;
2656}
2657
2658
2659void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002660 // Use the Jenkins one-at-a-time hash function to update the hash
2661 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002662 raw_running_hash_ += c;
2663 raw_running_hash_ += (raw_running_hash_ << 10);
2664 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002665 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002666 if (is_array_index_) {
2667 if (c < '0' || c > '9') {
2668 is_array_index_ = false;
2669 } else {
2670 int d = c - '0';
2671 if (is_first_char_) {
2672 is_first_char_ = false;
2673 if (c == '0' && length_ > 1) {
2674 is_array_index_ = false;
2675 return;
2676 }
2677 }
2678 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2679 is_array_index_ = false;
2680 } else {
2681 array_index_ = array_index_ * 10 + d;
2682 }
2683 }
2684 }
2685}
2686
2687
2688void StringHasher::AddCharacterNoIndex(uc32 c) {
2689 ASSERT(!is_array_index());
2690 raw_running_hash_ += c;
2691 raw_running_hash_ += (raw_running_hash_ << 10);
2692 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2693}
2694
2695
2696uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002697 // Get the calculated raw hash value and do some more bit ops to distribute
2698 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002699 uint32_t result = raw_running_hash_;
2700 result += (result << 3);
2701 result ^= (result >> 11);
2702 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002703 if (result == 0) {
2704 result = 27;
2705 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002706 return result;
2707}
2708
2709
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002710bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002711 uint32_t field = length_field();
2712 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002713 return SlowAsArrayIndex(index);
2714}
2715
2716
2717Object* JSObject::GetPrototype() {
2718 return JSObject::cast(this)->map()->prototype();
2719}
2720
2721
2722PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2723 return GetPropertyAttributeWithReceiver(this, key);
2724}
2725
2726
2727bool JSObject::HasElement(uint32_t index) {
2728 return HasElementWithReceiver(this, index);
2729}
2730
2731
2732bool AccessorInfo::all_can_read() {
2733 return BooleanBit::get(flag(), kAllCanReadBit);
2734}
2735
2736
2737void AccessorInfo::set_all_can_read(bool value) {
2738 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2739}
2740
2741
2742bool AccessorInfo::all_can_write() {
2743 return BooleanBit::get(flag(), kAllCanWriteBit);
2744}
2745
2746
2747void AccessorInfo::set_all_can_write(bool value) {
2748 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2749}
2750
2751
ager@chromium.org870a0b62008-11-04 11:43:05 +00002752bool AccessorInfo::prohibits_overwriting() {
2753 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2754}
2755
2756
2757void AccessorInfo::set_prohibits_overwriting(bool value) {
2758 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2759}
2760
2761
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002762PropertyAttributes AccessorInfo::property_attributes() {
2763 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2764}
2765
2766
2767void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2768 ASSERT(AttributesField::is_valid(attributes));
2769 int rest_value = flag()->value() & ~AttributesField::mask();
2770 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2771}
2772
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002773template<typename Shape, typename Key>
2774void Dictionary<Shape, Key>::SetEntry(int entry,
2775 Object* key,
2776 Object* value,
2777 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002778 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002779 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2780 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2781 FixedArray::set(index, key, mode);
2782 FixedArray::set(index+1, value, mode);
2783 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002784}
2785
2786
2787void Map::ClearCodeCache() {
2788 // No write barrier is needed since empty_fixed_array is not in new space.
2789 // Please note this function is used during marking:
2790 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002791 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2792 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002793}
2794
2795
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002796void JSArray::EnsureSize(int required_size) {
2797 ASSERT(HasFastElements());
2798 if (elements()->length() >= required_size) return;
2799 Expand(required_size);
2800}
2801
2802
ager@chromium.org7c537e22008-10-16 08:43:32 +00002803void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002804 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002805 set_elements(storage);
2806}
2807
2808
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002809Object* FixedArray::Copy() {
2810 if (length() == 0) return this;
2811 return Heap::CopyFixedArray(this);
2812}
2813
2814
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002815#undef CAST_ACCESSOR
2816#undef INT_ACCESSORS
2817#undef SMI_ACCESSORS
2818#undef ACCESSORS
2819#undef FIELD_ADDR
2820#undef READ_FIELD
2821#undef WRITE_FIELD
2822#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002823#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002824#undef READ_MEMADDR_FIELD
2825#undef WRITE_MEMADDR_FIELD
2826#undef READ_DOUBLE_FIELD
2827#undef WRITE_DOUBLE_FIELD
2828#undef READ_INT_FIELD
2829#undef WRITE_INT_FIELD
2830#undef READ_SHORT_FIELD
2831#undef WRITE_SHORT_FIELD
2832#undef READ_BYTE_FIELD
2833#undef WRITE_BYTE_FIELD
2834
2835
2836} } // namespace v8::internal
2837
2838#endif // V8_OBJECTS_INL_H_