blob: ff0f2e5446980e581b2260f794d8abcd21b892d2 [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
324bool Object::IsFailure() {
325 return HAS_FAILURE_TAG(this);
326}
327
328
329bool Object::IsRetryAfterGC() {
330 return HAS_FAILURE_TAG(this)
331 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
332}
333
334
ager@chromium.org7c537e22008-10-16 08:43:32 +0000335bool Object::IsOutOfMemoryFailure() {
336 return HAS_FAILURE_TAG(this)
337 && Failure::cast(this)->IsOutOfMemoryException();
338}
339
340
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000341bool Object::IsException() {
342 return this == Failure::Exception();
343}
344
345
346bool Object::IsJSObject() {
347 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000348 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349}
350
351
ager@chromium.org32912102009-01-16 10:38:43 +0000352bool Object::IsJSContextExtensionObject() {
353 return IsHeapObject()
354 && (HeapObject::cast(this)->map()->instance_type() ==
355 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
356}
357
358
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000359bool Object::IsMap() {
360 return Object::IsHeapObject()
361 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
362}
363
364
365bool Object::IsFixedArray() {
366 return Object::IsHeapObject()
367 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
368}
369
370
371bool Object::IsDescriptorArray() {
372 return IsFixedArray();
373}
374
375
376bool Object::IsContext() {
377 return Object::IsHeapObject()
378 && (HeapObject::cast(this)->map() == Heap::context_map() ||
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000379 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380 HeapObject::cast(this)->map() == Heap::global_context_map());
381}
382
383
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000384bool Object::IsCatchContext() {
385 return Object::IsHeapObject()
386 && HeapObject::cast(this)->map() == Heap::catch_context_map();
387}
388
389
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390bool Object::IsGlobalContext() {
391 return Object::IsHeapObject()
392 && HeapObject::cast(this)->map() == Heap::global_context_map();
393}
394
395
396bool Object::IsJSFunction() {
397 return Object::IsHeapObject()
398 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
399}
400
401
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000402template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000403 return obj->IsJSFunction();
404}
405
406
407bool Object::IsCode() {
408 return Object::IsHeapObject()
409 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
410}
411
412
413bool Object::IsOddball() {
414 return Object::IsHeapObject()
415 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
416}
417
418
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000419bool Object::IsJSGlobalPropertyCell() {
420 return Object::IsHeapObject()
421 && HeapObject::cast(this)->map()->instance_type()
422 == JS_GLOBAL_PROPERTY_CELL_TYPE;
423}
424
425
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000426bool Object::IsSharedFunctionInfo() {
427 return Object::IsHeapObject() &&
428 (HeapObject::cast(this)->map()->instance_type() ==
429 SHARED_FUNCTION_INFO_TYPE);
430}
431
432
433bool Object::IsJSValue() {
434 return Object::IsHeapObject()
435 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
436}
437
438
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000439bool Object::IsStringWrapper() {
440 return IsJSValue() && JSValue::cast(this)->value()->IsString();
441}
442
443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444bool Object::IsProxy() {
445 return Object::IsHeapObject()
446 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
447}
448
449
450bool Object::IsBoolean() {
451 return IsTrue() || IsFalse();
452}
453
454
455bool Object::IsJSArray() {
456 return Object::IsHeapObject()
457 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
458}
459
460
ager@chromium.org236ad962008-09-25 09:45:57 +0000461bool Object::IsJSRegExp() {
462 return Object::IsHeapObject()
463 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
464}
465
466
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000467template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468 return obj->IsJSArray();
469}
470
471
472bool Object::IsHashTable() {
473 return Object::IsHeapObject()
474 && HeapObject::cast(this)->map() == Heap::hash_table_map();
475}
476
477
478bool Object::IsDictionary() {
479 return IsHashTable() && this != Heap::symbol_table();
480}
481
482
483bool Object::IsSymbolTable() {
484 return IsHashTable() && this == Heap::symbol_table();
485}
486
487
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000488bool Object::IsCompilationCacheTable() {
489 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000490}
491
492
ager@chromium.org236ad962008-09-25 09:45:57 +0000493bool Object::IsMapCache() {
494 return IsHashTable();
495}
496
497
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000498bool Object::IsPrimitive() {
499 return IsOddball() || IsNumber() || IsString();
500}
501
502
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000503bool Object::IsJSGlobalProxy() {
504 bool result = IsHeapObject() &&
505 (HeapObject::cast(this)->map()->instance_type() ==
506 JS_GLOBAL_PROXY_TYPE);
507 ASSERT(!result || IsAccessCheckNeeded());
508 return result;
509}
510
511
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000512bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000513 if (!IsHeapObject()) return false;
514
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000515 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000516 return type == JS_GLOBAL_OBJECT_TYPE ||
517 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518}
519
520
521bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522 return IsHeapObject() &&
523 (HeapObject::cast(this)->map()->instance_type() ==
524 JS_GLOBAL_OBJECT_TYPE);
525}
526
527
528bool Object::IsJSBuiltinsObject() {
529 return IsHeapObject() &&
530 (HeapObject::cast(this)->map()->instance_type() ==
531 JS_BUILTINS_OBJECT_TYPE);
532}
533
534
535bool Object::IsUndetectableObject() {
536 return IsHeapObject()
537 && HeapObject::cast(this)->map()->is_undetectable();
538}
539
540
541bool Object::IsAccessCheckNeeded() {
542 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000543 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544}
545
546
547bool Object::IsStruct() {
548 if (!IsHeapObject()) return false;
549 switch (HeapObject::cast(this)->map()->instance_type()) {
550#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
551 STRUCT_LIST(MAKE_STRUCT_CASE)
552#undef MAKE_STRUCT_CASE
553 default: return false;
554 }
555}
556
557
558#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
559 bool Object::Is##Name() { \
560 return Object::IsHeapObject() \
561 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
562 }
563 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
564#undef MAKE_STRUCT_PREDICATE
565
566
567bool Object::IsUndefined() {
568 return this == Heap::undefined_value();
569}
570
571
572bool Object::IsTheHole() {
573 return this == Heap::the_hole_value();
574}
575
576
577bool Object::IsNull() {
578 return this == Heap::null_value();
579}
580
581
582bool Object::IsTrue() {
583 return this == Heap::true_value();
584}
585
586
587bool Object::IsFalse() {
588 return this == Heap::false_value();
589}
590
591
592double Object::Number() {
593 ASSERT(IsNumber());
594 return IsSmi()
595 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
596 : reinterpret_cast<HeapNumber*>(this)->value();
597}
598
599
600
601Object* Object::ToSmi() {
602 if (IsSmi()) return this;
603 if (IsHeapNumber()) {
604 double value = HeapNumber::cast(this)->value();
605 int int_value = FastD2I(value);
606 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
607 return Smi::FromInt(int_value);
608 }
609 }
610 return Failure::Exception();
611}
612
613
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000614bool Object::HasSpecificClassOf(String* name) {
615 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
616}
617
618
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619Object* Object::GetElement(uint32_t index) {
620 return GetElementWithReceiver(this, index);
621}
622
623
624Object* Object::GetProperty(String* key) {
625 PropertyAttributes attributes;
626 return GetPropertyWithReceiver(this, key, &attributes);
627}
628
629
630Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
631 return GetPropertyWithReceiver(this, key, attributes);
632}
633
634
635#define FIELD_ADDR(p, offset) \
636 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
637
638#define READ_FIELD(p, offset) \
639 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
640
641#define WRITE_FIELD(p, offset, value) \
642 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
643
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000644
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000645#define WRITE_BARRIER(object, offset) \
646 Heap::RecordWrite(object->address(), offset);
647
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000648// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000649// write due to the assert validating the written value.
650#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
651 if (mode == UPDATE_WRITE_BARRIER) { \
652 Heap::RecordWrite(object->address(), offset); \
653 } else { \
654 ASSERT(mode == SKIP_WRITE_BARRIER); \
655 ASSERT(Heap::InNewSpace(object) || \
656 !Heap::InNewSpace(READ_FIELD(object, offset))); \
657 }
658
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000659#define READ_DOUBLE_FIELD(p, offset) \
660 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
661
662#define WRITE_DOUBLE_FIELD(p, offset, value) \
663 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
664
665#define READ_INT_FIELD(p, offset) \
666 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
667
668#define WRITE_INT_FIELD(p, offset, value) \
669 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
670
ager@chromium.org3e875802009-06-29 08:26:34 +0000671#define READ_INTPTR_FIELD(p, offset) \
672 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
673
674#define WRITE_INTPTR_FIELD(p, offset, value) \
675 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
676
ager@chromium.org7c537e22008-10-16 08:43:32 +0000677#define READ_UINT32_FIELD(p, offset) \
678 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
679
680#define WRITE_UINT32_FIELD(p, offset, value) \
681 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
682
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683#define READ_SHORT_FIELD(p, offset) \
684 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
685
686#define WRITE_SHORT_FIELD(p, offset, value) \
687 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
688
689#define READ_BYTE_FIELD(p, offset) \
690 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
691
692#define WRITE_BYTE_FIELD(p, offset, value) \
693 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
694
695
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000696Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
697 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000698}
699
700
701int Smi::value() {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000702 return static_cast<int>(reinterpret_cast<intptr_t>(this)) >> kSmiTagSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000703}
704
705
706Smi* Smi::FromInt(int value) {
707 ASSERT(Smi::IsValid(value));
ager@chromium.org9085a012009-05-11 19:22:57 +0000708 intptr_t tagged_value =
709 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
710 return reinterpret_cast<Smi*>(tagged_value);
711}
712
713
714Smi* Smi::FromIntptr(intptr_t value) {
715 ASSERT(Smi::IsValid(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000716 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
717}
718
719
720Failure::Type Failure::type() const {
721 return static_cast<Type>(value() & kFailureTypeTagMask);
722}
723
724
725bool Failure::IsInternalError() const {
726 return type() == INTERNAL_ERROR;
727}
728
729
730bool Failure::IsOutOfMemoryException() const {
731 return type() == OUT_OF_MEMORY_EXCEPTION;
732}
733
734
735int Failure::requested() const {
736 const int kShiftBits =
737 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
738 STATIC_ASSERT(kShiftBits >= 0);
739 ASSERT(type() == RETRY_AFTER_GC);
740 return value() >> kShiftBits;
741}
742
743
744AllocationSpace Failure::allocation_space() const {
745 ASSERT_EQ(RETRY_AFTER_GC, type());
746 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
747 & kSpaceTagMask);
748}
749
750
751Failure* Failure::InternalError() {
752 return Construct(INTERNAL_ERROR);
753}
754
755
756Failure* Failure::Exception() {
757 return Construct(EXCEPTION);
758}
759
760Failure* Failure::OutOfMemoryException() {
761 return Construct(OUT_OF_MEMORY_EXCEPTION);
762}
763
764
765int Failure::value() const {
ager@chromium.org5ec48922009-05-05 07:25:34 +0000766 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000767}
768
769
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000770Failure* Failure::RetryAfterGC(int requested_bytes) {
771 int requested = requested_bytes >> kObjectAlignmentBits;
772 int value = (requested << kSpaceTagSize) | NEW_SPACE;
773 ASSERT(value >> kSpaceTagSize == requested);
774 ASSERT(Smi::IsValid(value));
775 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
776 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
777 return Construct(RETRY_AFTER_GC, value);
778}
779
780
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781Failure* Failure::Construct(Type type, int value) {
782 int info = (value << kFailureTypeTagSize) | type;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000783 // TODO(X64): Stop using Smi validation for non-smi checks, even if they
784 // happen to be identical at the moment.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000785 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000786 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000787 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788}
789
790
791bool Smi::IsValid(int value) {
792#ifdef DEBUG
793 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
794#endif
795 // To be representable as an tagged small integer, the two
796 // most-significant bits of 'value' must be either 00 or 11 due to
797 // sign-extension. To check this we add 01 to the two
798 // most-significant bits, and check if the most-significant bit is 0
799 //
800 // CAUTION: The original code below:
801 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
802 // may lead to incorrect results according to the C language spec, and
803 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
804 // compiler may produce undefined results in case of signed integer
805 // overflow. The computation must be done w/ unsigned ints.
806 bool result =
807 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
808 ASSERT(result == in_range);
809 return result;
810}
811
812
ager@chromium.org9085a012009-05-11 19:22:57 +0000813bool Smi::IsIntptrValid(intptr_t value) {
814#ifdef DEBUG
815 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
816#endif
817 // See Smi::IsValid(int) for description.
818 bool result =
819 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
820 ASSERT(result == in_range);
821 return result;
822}
823
824
kasper.lund7276f142008-07-30 08:49:36 +0000825MapWord MapWord::FromMap(Map* map) {
826 return MapWord(reinterpret_cast<uintptr_t>(map));
827}
828
829
830Map* MapWord::ToMap() {
831 return reinterpret_cast<Map*>(value_);
832}
833
834
835bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000836 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000837}
838
839
840MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000841 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
842 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000843}
844
845
846HeapObject* MapWord::ToForwardingAddress() {
847 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000848 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000849}
850
851
852bool MapWord::IsMarked() {
853 return (value_ & kMarkingMask) == 0;
854}
855
856
857void MapWord::SetMark() {
858 value_ &= ~kMarkingMask;
859}
860
861
862void MapWord::ClearMark() {
863 value_ |= kMarkingMask;
864}
865
866
867bool MapWord::IsOverflowed() {
868 return (value_ & kOverflowMask) != 0;
869}
870
871
872void MapWord::SetOverflow() {
873 value_ |= kOverflowMask;
874}
875
876
877void MapWord::ClearOverflow() {
878 value_ &= ~kOverflowMask;
879}
880
881
882MapWord MapWord::EncodeAddress(Address map_address, int offset) {
883 // Offset is the distance in live bytes from the first live object in the
884 // same page. The offset between two objects in the same page should not
885 // exceed the object area size of a page.
886 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
887
888 int compact_offset = offset >> kObjectAlignmentBits;
889 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
890
891 Page* map_page = Page::FromAddress(map_address);
892 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
893
894 int map_page_offset =
895 map_page->Offset(map_address) >> kObjectAlignmentBits;
896
897 uintptr_t encoding =
898 (compact_offset << kForwardingOffsetShift) |
899 (map_page_offset << kMapPageOffsetShift) |
900 (map_page->mc_page_index << kMapPageIndexShift);
901 return MapWord(encoding);
902}
903
904
905Address MapWord::DecodeMapAddress(MapSpace* map_space) {
906 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
907 ASSERT_MAP_PAGE_INDEX(map_page_index);
908
909 int map_page_offset =
910 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
911 << kObjectAlignmentBits;
912
913 return (map_space->PageAddress(map_page_index) + map_page_offset);
914}
915
916
917int MapWord::DecodeOffset() {
918 // The offset field is represented in the kForwardingOffsetBits
919 // most-significant bits.
920 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
921 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
922 return offset;
923}
924
925
926MapWord MapWord::FromEncodedAddress(Address address) {
927 return MapWord(reinterpret_cast<uintptr_t>(address));
928}
929
930
931Address MapWord::ToEncodedAddress() {
932 return reinterpret_cast<Address>(value_);
933}
934
935
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000936#ifdef DEBUG
937void HeapObject::VerifyObjectField(int offset) {
938 VerifyPointer(READ_FIELD(this, offset));
939}
940#endif
941
942
943Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000944 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000945}
946
947
948void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000949 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000950}
951
952
kasper.lund7276f142008-07-30 08:49:36 +0000953MapWord HeapObject::map_word() {
954 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
955}
956
957
958void HeapObject::set_map_word(MapWord map_word) {
959 // WRITE_FIELD does not update the remembered set, but there is no need
960 // here.
961 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
962}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000963
964
965HeapObject* HeapObject::FromAddress(Address address) {
966 ASSERT_TAG_ALIGNED(address);
967 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
968}
969
970
971Address HeapObject::address() {
972 return reinterpret_cast<Address>(this) - kHeapObjectTag;
973}
974
975
976int HeapObject::Size() {
977 return SizeFromMap(map());
978}
979
980
981void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
982 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
983 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
984}
985
986
987void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
988 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
989}
990
991
kasper.lund7276f142008-07-30 08:49:36 +0000992bool HeapObject::IsMarked() {
993 return map_word().IsMarked();
994}
995
996
997void HeapObject::SetMark() {
998 ASSERT(!IsMarked());
999 MapWord first_word = map_word();
1000 first_word.SetMark();
1001 set_map_word(first_word);
1002}
1003
1004
1005void HeapObject::ClearMark() {
1006 ASSERT(IsMarked());
1007 MapWord first_word = map_word();
1008 first_word.ClearMark();
1009 set_map_word(first_word);
1010}
1011
1012
1013bool HeapObject::IsOverflowed() {
1014 return map_word().IsOverflowed();
1015}
1016
1017
1018void HeapObject::SetOverflow() {
1019 MapWord first_word = map_word();
1020 first_word.SetOverflow();
1021 set_map_word(first_word);
1022}
1023
1024
1025void HeapObject::ClearOverflow() {
1026 ASSERT(IsOverflowed());
1027 MapWord first_word = map_word();
1028 first_word.ClearOverflow();
1029 set_map_word(first_word);
1030}
1031
1032
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001033double HeapNumber::value() {
1034 return READ_DOUBLE_FIELD(this, kValueOffset);
1035}
1036
1037
1038void HeapNumber::set_value(double value) {
1039 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1040}
1041
1042
1043ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001044ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045
1046
1047void JSObject::initialize_properties() {
1048 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1049 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1050}
1051
1052
1053void JSObject::initialize_elements() {
1054 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1055 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1056}
1057
1058
1059ACCESSORS(Oddball, to_string, String, kToStringOffset)
1060ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1061
1062
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001063ACCESSORS(JSGlobalPropertyCell, value, Object, kValueOffset)
1064
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001065int JSObject::GetHeaderSize() {
1066 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001067 case JS_GLOBAL_PROXY_TYPE:
1068 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001069 case JS_GLOBAL_OBJECT_TYPE:
1070 return JSGlobalObject::kSize;
1071 case JS_BUILTINS_OBJECT_TYPE:
1072 return JSBuiltinsObject::kSize;
1073 case JS_FUNCTION_TYPE:
1074 return JSFunction::kSize;
1075 case JS_VALUE_TYPE:
1076 return JSValue::kSize;
1077 case JS_ARRAY_TYPE:
1078 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001079 case JS_REGEXP_TYPE:
1080 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001081 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001082 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001083 return JSObject::kHeaderSize;
1084 default:
1085 UNREACHABLE();
1086 return 0;
1087 }
1088}
1089
1090
1091int JSObject::GetInternalFieldCount() {
1092 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001093 // Make sure to adjust for the number of in-object properties. These
1094 // properties do contribute to the size, but are not internal fields.
1095 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1096 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001097}
1098
1099
1100Object* JSObject::GetInternalField(int index) {
1101 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001102 // Internal objects do follow immediately after the header, whereas in-object
1103 // properties are at the end of the object. Therefore there is no need
1104 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001105 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1106}
1107
1108
1109void JSObject::SetInternalField(int index, Object* value) {
1110 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001111 // Internal objects do follow immediately after the header, whereas in-object
1112 // properties are at the end of the object. Therefore there is no need
1113 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001114 int offset = GetHeaderSize() + (kPointerSize * index);
1115 WRITE_FIELD(this, offset, value);
1116 WRITE_BARRIER(this, offset);
1117}
1118
1119
ager@chromium.org7c537e22008-10-16 08:43:32 +00001120// Access fast-case object properties at index. The use of these routines
1121// is needed to correctly distinguish between properties stored in-object and
1122// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001123Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001124 // Adjust for the number of properties stored in the object.
1125 index -= map()->inobject_properties();
1126 if (index < 0) {
1127 int offset = map()->instance_size() + (index * kPointerSize);
1128 return READ_FIELD(this, offset);
1129 } else {
1130 ASSERT(index < properties()->length());
1131 return properties()->get(index);
1132 }
1133}
1134
1135
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001136Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001137 // Adjust for the number of properties stored in the object.
1138 index -= map()->inobject_properties();
1139 if (index < 0) {
1140 int offset = map()->instance_size() + (index * kPointerSize);
1141 WRITE_FIELD(this, offset, value);
1142 WRITE_BARRIER(this, offset);
1143 } else {
1144 ASSERT(index < properties()->length());
1145 properties()->set(index, value);
1146 }
1147 return value;
1148}
1149
1150
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001151Object* JSObject::InObjectPropertyAt(int index) {
1152 // Adjust for the number of properties stored in the object.
1153 index -= map()->inobject_properties();
1154 ASSERT(index < 0);
1155 int offset = map()->instance_size() + (index * kPointerSize);
1156 return READ_FIELD(this, offset);
1157}
1158
1159
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001160Object* JSObject::InObjectPropertyAtPut(int index,
1161 Object* value,
1162 WriteBarrierMode mode) {
1163 // Adjust for the number of properties stored in the object.
1164 index -= map()->inobject_properties();
1165 ASSERT(index < 0);
1166 int offset = map()->instance_size() + (index * kPointerSize);
1167 WRITE_FIELD(this, offset, value);
1168 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1169 return value;
1170}
1171
1172
1173
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001174void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001175 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001176 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001177 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001178 }
1179}
1180
1181
1182void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001183 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001184 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001185 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186 }
1187}
1188
1189
1190bool JSObject::HasFastProperties() {
1191 return !properties()->IsDictionary();
1192}
1193
1194
1195bool Array::IndexFromObject(Object* object, uint32_t* index) {
1196 if (object->IsSmi()) {
1197 int value = Smi::cast(object)->value();
1198 if (value < 0) return false;
1199 *index = value;
1200 return true;
1201 }
1202 if (object->IsHeapNumber()) {
1203 double value = HeapNumber::cast(object)->value();
1204 uint32_t uint_value = static_cast<uint32_t>(value);
1205 if (value == static_cast<double>(uint_value)) {
1206 *index = uint_value;
1207 return true;
1208 }
1209 }
1210 return false;
1211}
1212
1213
1214bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1215 if (!this->IsJSValue()) return false;
1216
1217 JSValue* js_value = JSValue::cast(this);
1218 if (!js_value->value()->IsString()) return false;
1219
1220 String* str = String::cast(js_value->value());
1221 if (index >= (uint32_t)str->length()) return false;
1222
1223 return true;
1224}
1225
1226
1227Object* FixedArray::get(int index) {
1228 ASSERT(index >= 0 && index < this->length());
1229 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1230}
1231
1232
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001233void FixedArray::set(int index, Smi* value) {
1234 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1235 int offset = kHeaderSize + index * kPointerSize;
1236 WRITE_FIELD(this, offset, value);
1237}
1238
1239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240void FixedArray::set(int index, Object* value) {
1241 ASSERT(index >= 0 && index < this->length());
1242 int offset = kHeaderSize + index * kPointerSize;
1243 WRITE_FIELD(this, offset, value);
1244 WRITE_BARRIER(this, offset);
1245}
1246
1247
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001248WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1250 return UPDATE_WRITE_BARRIER;
1251}
1252
1253
1254void FixedArray::set(int index,
1255 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001256 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001257 ASSERT(index >= 0 && index < this->length());
1258 int offset = kHeaderSize + index * kPointerSize;
1259 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001260 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001261}
1262
1263
1264void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1265 ASSERT(index >= 0 && index < array->length());
1266 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1267}
1268
1269
1270void FixedArray::set_undefined(int index) {
1271 ASSERT(index >= 0 && index < this->length());
1272 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1273 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1274 Heap::undefined_value());
1275}
1276
1277
ager@chromium.org236ad962008-09-25 09:45:57 +00001278void FixedArray::set_null(int index) {
1279 ASSERT(index >= 0 && index < this->length());
1280 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1281 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1282}
1283
1284
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001285void FixedArray::set_the_hole(int index) {
1286 ASSERT(index >= 0 && index < this->length());
1287 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1288 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1289}
1290
1291
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001292bool DescriptorArray::IsEmpty() {
1293 ASSERT(this == Heap::empty_descriptor_array() ||
1294 this->length() > 2);
1295 return this == Heap::empty_descriptor_array();
1296}
1297
1298
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001299void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1300 Object* tmp = array->get(first);
1301 fast_set(array, first, array->get(second));
1302 fast_set(array, second, tmp);
1303}
1304
1305
1306int DescriptorArray::Search(String* name) {
1307 SLOW_ASSERT(IsSortedNoDuplicates());
1308
1309 // Check for empty descriptor array.
1310 int nof = number_of_descriptors();
1311 if (nof == 0) return kNotFound;
1312
1313 // Fast case: do linear search for small arrays.
1314 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001315 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001316 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001317 }
1318
1319 // Slow case: perform binary search.
1320 return BinarySearch(name, 0, nof - 1);
1321}
1322
1323
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324String* DescriptorArray::GetKey(int descriptor_number) {
1325 ASSERT(descriptor_number < number_of_descriptors());
1326 return String::cast(get(ToKeyIndex(descriptor_number)));
1327}
1328
1329
1330Object* DescriptorArray::GetValue(int descriptor_number) {
1331 ASSERT(descriptor_number < number_of_descriptors());
1332 return GetContentArray()->get(ToValueIndex(descriptor_number));
1333}
1334
1335
1336Smi* DescriptorArray::GetDetails(int descriptor_number) {
1337 ASSERT(descriptor_number < number_of_descriptors());
1338 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1339}
1340
1341
1342void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1343 desc->Init(GetKey(descriptor_number),
1344 GetValue(descriptor_number),
1345 GetDetails(descriptor_number));
1346}
1347
1348
1349void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1350 // Range check.
1351 ASSERT(descriptor_number < number_of_descriptors());
1352
1353 // Make sure non of the elements in desc are in new space.
1354 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1355 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1356
1357 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1358 FixedArray* content_array = GetContentArray();
1359 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1360 fast_set(content_array, ToDetailsIndex(descriptor_number),
1361 desc->GetDetails().AsSmi());
1362}
1363
1364
1365void DescriptorArray::Swap(int first, int second) {
1366 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1367 FixedArray* content_array = GetContentArray();
1368 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1369 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1370}
1371
1372
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001373bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001374 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001375 if (!max_index_object->IsSmi()) return false;
1376 return 0 !=
1377 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1378}
1379
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001380uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001381 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001382 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001383 if (!max_index_object->IsSmi()) return 0;
1384 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1385 return value >> kRequiresSlowElementsTagSize;
1386}
1387
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001388void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001389 set(kMaxNumberKeyIndex,
1390 Smi::FromInt(kRequiresSlowElementsMask),
1391 SKIP_WRITE_BARRIER);
1392}
1393
1394
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001395// ------------------------------------
1396// Cast operations
1397
1398
1399CAST_ACCESSOR(FixedArray)
1400CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001401CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001402CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001403CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001404CAST_ACCESSOR(String)
1405CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001406CAST_ACCESSOR(SeqAsciiString)
1407CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001408CAST_ACCESSOR(ConsString)
1409CAST_ACCESSOR(SlicedString)
1410CAST_ACCESSOR(ExternalString)
1411CAST_ACCESSOR(ExternalAsciiString)
1412CAST_ACCESSOR(ExternalTwoByteString)
1413CAST_ACCESSOR(JSObject)
1414CAST_ACCESSOR(Smi)
1415CAST_ACCESSOR(Failure)
1416CAST_ACCESSOR(HeapObject)
1417CAST_ACCESSOR(HeapNumber)
1418CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001419CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001420CAST_ACCESSOR(SharedFunctionInfo)
1421CAST_ACCESSOR(Map)
1422CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001423CAST_ACCESSOR(GlobalObject)
1424CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001425CAST_ACCESSOR(JSGlobalObject)
1426CAST_ACCESSOR(JSBuiltinsObject)
1427CAST_ACCESSOR(Code)
1428CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001429CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001430CAST_ACCESSOR(Proxy)
1431CAST_ACCESSOR(ByteArray)
1432CAST_ACCESSOR(Struct)
1433
1434
1435#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1436 STRUCT_LIST(MAKE_STRUCT_CAST)
1437#undef MAKE_STRUCT_CAST
1438
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001439
1440template <typename Shape, typename Key>
1441HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001442 ASSERT(obj->IsHashTable());
1443 return reinterpret_cast<HashTable*>(obj);
1444}
1445
1446
1447INT_ACCESSORS(Array, length, kLengthOffset)
1448
1449
1450bool String::Equals(String* other) {
1451 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001452 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1453 return false;
1454 }
1455 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456}
1457
1458
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001459int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001460 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1461
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001462 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1463 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1464 ASSERT(kLongStringTag == 0);
1465
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001466 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001467}
1468
1469
1470void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001471 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1472 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1473 ASSERT(kLongStringTag == 0);
1474
1475 WRITE_INT_FIELD(this,
1476 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001477 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001478}
1479
1480
ager@chromium.org7c537e22008-10-16 08:43:32 +00001481uint32_t String::length_field() {
1482 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001483}
1484
1485
ager@chromium.org7c537e22008-10-16 08:43:32 +00001486void String::set_length_field(uint32_t value) {
1487 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001488}
1489
1490
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001491Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001492 // We don't need to flatten strings that are already flat. Since this code
1493 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001494 if (!IsFlat()) {
1495 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001496 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001497 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498}
1499
1500
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001501uint16_t String::Get(int index) {
1502 ASSERT(index >= 0 && index < length());
1503 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001504 case kSeqStringTag | kAsciiStringTag:
1505 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1506 case kSeqStringTag | kTwoByteStringTag:
1507 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1508 case kConsStringTag | kAsciiStringTag:
1509 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001511 case kSlicedStringTag | kAsciiStringTag:
1512 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001513 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001514 case kExternalStringTag | kAsciiStringTag:
1515 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1516 case kExternalStringTag | kTwoByteStringTag:
1517 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001518 default:
1519 break;
1520 }
1521
1522 UNREACHABLE();
1523 return 0;
1524}
1525
1526
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001527void String::Set(int index, uint16_t value) {
1528 ASSERT(index >= 0 && index < length());
1529 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001530
ager@chromium.org5ec48922009-05-05 07:25:34 +00001531 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001532 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1533 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001534}
1535
1536
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001537bool String::IsFlat() {
1538 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001539 case kConsStringTag: {
1540 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001541 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001542 return second->length() == 0;
1543 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001544 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001545 StringRepresentationTag tag =
1546 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001547 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001548 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001549 default:
1550 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551 }
1552}
1553
1554
ager@chromium.org7c537e22008-10-16 08:43:32 +00001555uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556 ASSERT(index >= 0 && index < length());
1557 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1558}
1559
1560
ager@chromium.org7c537e22008-10-16 08:43:32 +00001561void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001562 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1563 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1564 static_cast<byte>(value));
1565}
1566
1567
ager@chromium.org7c537e22008-10-16 08:43:32 +00001568Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001569 return FIELD_ADDR(this, kHeaderSize);
1570}
1571
1572
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001573char* SeqAsciiString::GetChars() {
1574 return reinterpret_cast<char*>(GetCharsAddress());
1575}
1576
1577
ager@chromium.org7c537e22008-10-16 08:43:32 +00001578Address SeqTwoByteString::GetCharsAddress() {
1579 return FIELD_ADDR(this, kHeaderSize);
1580}
1581
1582
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001583uc16* SeqTwoByteString::GetChars() {
1584 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1585}
1586
1587
ager@chromium.org7c537e22008-10-16 08:43:32 +00001588uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589 ASSERT(index >= 0 && index < length());
1590 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1591}
1592
1593
ager@chromium.org7c537e22008-10-16 08:43:32 +00001594void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001595 ASSERT(index >= 0 && index < length());
1596 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1597}
1598
1599
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001600int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001601 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1602
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001603 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1604 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1605 ASSERT(kLongStringTag == 0);
1606
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001607 // Use the map (and not 'this') to compute the size tag, since
1608 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001609 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001610
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611 return SizeFor(length);
1612}
1613
1614
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001615int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001616 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1617
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001618 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1619 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1620 ASSERT(kLongStringTag == 0);
1621
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001622 // Use the map (and not 'this') to compute the size tag, since
1623 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001624 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625
1626 return SizeFor(length);
1627}
1628
1629
ager@chromium.org870a0b62008-11-04 11:43:05 +00001630String* ConsString::first() {
1631 return String::cast(READ_FIELD(this, kFirstOffset));
1632}
1633
1634
1635Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001636 return READ_FIELD(this, kFirstOffset);
1637}
1638
1639
ager@chromium.org870a0b62008-11-04 11:43:05 +00001640void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001641 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001642 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001643}
1644
1645
ager@chromium.org870a0b62008-11-04 11:43:05 +00001646String* ConsString::second() {
1647 return String::cast(READ_FIELD(this, kSecondOffset));
1648}
1649
1650
1651Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001652 return READ_FIELD(this, kSecondOffset);
1653}
1654
1655
ager@chromium.org870a0b62008-11-04 11:43:05 +00001656void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001657 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001658 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001659}
1660
1661
ager@chromium.org870a0b62008-11-04 11:43:05 +00001662String* SlicedString::buffer() {
1663 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664}
1665
1666
ager@chromium.org870a0b62008-11-04 11:43:05 +00001667void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668 WRITE_FIELD(this, kBufferOffset, buffer);
1669 WRITE_BARRIER(this, kBufferOffset);
1670}
1671
1672
1673int SlicedString::start() {
1674 return READ_INT_FIELD(this, kStartOffset);
1675}
1676
1677
1678void SlicedString::set_start(int start) {
1679 WRITE_INT_FIELD(this, kStartOffset, start);
1680}
1681
1682
1683ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1684 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1685}
1686
1687
1688void ExternalAsciiString::set_resource(
1689 ExternalAsciiString::Resource* resource) {
1690 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1691}
1692
1693
ager@chromium.org6f10e412009-02-13 10:11:16 +00001694Map* ExternalAsciiString::StringMap(int length) {
1695 Map* map;
1696 // Number of characters: determines the map.
1697 if (length <= String::kMaxShortStringSize) {
1698 map = Heap::short_external_ascii_string_map();
1699 } else if (length <= String::kMaxMediumStringSize) {
1700 map = Heap::medium_external_ascii_string_map();
1701 } else {
1702 map = Heap::long_external_ascii_string_map();
1703 }
1704 return map;
1705}
1706
1707
1708Map* ExternalAsciiString::SymbolMap(int length) {
1709 Map* map;
1710 // Number of characters: determines the map.
1711 if (length <= String::kMaxShortStringSize) {
1712 map = Heap::short_external_ascii_symbol_map();
1713 } else if (length <= String::kMaxMediumStringSize) {
1714 map = Heap::medium_external_ascii_symbol_map();
1715 } else {
1716 map = Heap::long_external_ascii_symbol_map();
1717 }
1718 return map;
1719}
1720
1721
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001722ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1723 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1724}
1725
1726
1727void ExternalTwoByteString::set_resource(
1728 ExternalTwoByteString::Resource* resource) {
1729 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1730}
1731
1732
ager@chromium.org6f10e412009-02-13 10:11:16 +00001733Map* ExternalTwoByteString::StringMap(int length) {
1734 Map* map;
1735 // Number of characters: determines the map.
1736 if (length <= String::kMaxShortStringSize) {
1737 map = Heap::short_external_string_map();
1738 } else if (length <= String::kMaxMediumStringSize) {
1739 map = Heap::medium_external_string_map();
1740 } else {
1741 map = Heap::long_external_string_map();
1742 }
1743 return map;
1744}
1745
1746
1747Map* ExternalTwoByteString::SymbolMap(int length) {
1748 Map* map;
1749 // Number of characters: determines the map.
1750 if (length <= String::kMaxShortStringSize) {
1751 map = Heap::short_external_symbol_map();
1752 } else if (length <= String::kMaxMediumStringSize) {
1753 map = Heap::medium_external_symbol_map();
1754 } else {
1755 map = Heap::long_external_symbol_map();
1756 }
1757 return map;
1758}
1759
1760
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001761byte ByteArray::get(int index) {
1762 ASSERT(index >= 0 && index < this->length());
1763 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1764}
1765
1766
1767void ByteArray::set(int index, byte value) {
1768 ASSERT(index >= 0 && index < this->length());
1769 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1770}
1771
1772
1773int ByteArray::get_int(int index) {
1774 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1775 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1776}
1777
1778
1779ByteArray* ByteArray::FromDataStartAddress(Address address) {
1780 ASSERT_TAG_ALIGNED(address);
1781 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1782}
1783
1784
1785Address ByteArray::GetDataStartAddress() {
1786 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1787}
1788
1789
1790int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001791 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1792}
1793
1794
1795int Map::inobject_properties() {
1796 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001797}
1798
1799
1800int HeapObject::SizeFromMap(Map* map) {
1801 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001802 // Only inline the most frequent cases.
1803 if (instance_type == JS_OBJECT_TYPE ||
1804 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1805 (kStringTag | kConsStringTag) ||
1806 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001807 if (instance_type == FIXED_ARRAY_TYPE) {
1808 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1809 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001810 if (instance_type == BYTE_ARRAY_TYPE) {
1811 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1812 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001813 // Otherwise do the general size computation.
1814 return SlowSizeFromMap(map);
1815}
1816
1817
1818void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001819 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001820 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001821 ASSERT(0 <= value && value < 256);
1822 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1823}
1824
1825
ager@chromium.org7c537e22008-10-16 08:43:32 +00001826void Map::set_inobject_properties(int value) {
1827 ASSERT(0 <= value && value < 256);
1828 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1829}
1830
1831
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001832InstanceType Map::instance_type() {
1833 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1834}
1835
1836
1837void Map::set_instance_type(InstanceType value) {
1838 ASSERT(0 <= value && value < 256);
1839 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1840}
1841
1842
1843int Map::unused_property_fields() {
1844 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1845}
1846
1847
1848void Map::set_unused_property_fields(int value) {
1849 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1850}
1851
1852
1853byte Map::bit_field() {
1854 return READ_BYTE_FIELD(this, kBitFieldOffset);
1855}
1856
1857
1858void Map::set_bit_field(byte value) {
1859 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1860}
1861
1862
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001863byte Map::bit_field2() {
1864 return READ_BYTE_FIELD(this, kBitField2Offset);
1865}
1866
1867
1868void Map::set_bit_field2(byte value) {
1869 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1870}
1871
1872
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001873void Map::set_non_instance_prototype(bool value) {
1874 if (value) {
1875 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1876 } else {
1877 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1878 }
1879}
1880
1881
1882bool Map::has_non_instance_prototype() {
1883 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1884}
1885
1886
ager@chromium.org870a0b62008-11-04 11:43:05 +00001887void Map::set_is_access_check_needed(bool access_check_needed) {
1888 if (access_check_needed) {
1889 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1890 } else {
1891 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1892 }
1893}
1894
1895
1896bool Map::is_access_check_needed() {
1897 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1898}
1899
1900
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001901Code::Flags Code::flags() {
1902 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1903}
1904
1905
1906void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001907 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001908 // Make sure that all call stubs have an arguments count.
1909 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1910 ExtractArgumentsCountFromFlags(flags) >= 0);
1911 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1912}
1913
1914
1915Code::Kind Code::kind() {
1916 return ExtractKindFromFlags(flags());
1917}
1918
1919
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001920InLoopFlag Code::ic_in_loop() {
1921 return ExtractICInLoopFromFlags(flags());
1922}
1923
1924
kasper.lund7276f142008-07-30 08:49:36 +00001925InlineCacheState Code::ic_state() {
1926 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001927 // Only allow uninitialized or debugger states for non-IC code
1928 // objects. This is used in the debugger to determine whether or not
1929 // a call to code object has been replaced with a debug break call.
1930 ASSERT(is_inline_cache_stub() ||
1931 result == UNINITIALIZED ||
1932 result == DEBUG_BREAK ||
1933 result == DEBUG_PREPARE_STEP_IN);
1934 return result;
1935}
1936
1937
1938PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001939 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001940 return ExtractTypeFromFlags(flags());
1941}
1942
1943
1944int Code::arguments_count() {
1945 ASSERT(is_call_stub() || kind() == STUB);
1946 return ExtractArgumentsCountFromFlags(flags());
1947}
1948
1949
1950CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001951 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001952 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1953 kStubMajorKeyOffset));
1954}
1955
1956
1957void Code::set_major_key(CodeStub::Major major) {
1958 ASSERT(kind() == STUB);
1959 ASSERT(0 <= major && major < 256);
1960 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001961}
1962
1963
1964bool Code::is_inline_cache_stub() {
1965 Kind kind = this->kind();
1966 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1967}
1968
1969
1970Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001971 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00001972 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001973 PropertyType type,
1974 int argc) {
1975 // Compute the bit mask.
1976 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001977 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00001978 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001979 bits |= type << kFlagsTypeShift;
1980 bits |= argc << kFlagsArgumentsCountShift;
1981 // Cast to flags and validate result before returning it.
1982 Flags result = static_cast<Flags>(bits);
1983 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001984 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001985 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001986 ASSERT(ExtractTypeFromFlags(result) == type);
1987 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1988 return result;
1989}
1990
1991
1992Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1993 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001994 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001996 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001997}
1998
1999
2000Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2001 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2002 return static_cast<Kind>(bits);
2003}
2004
2005
kasper.lund7276f142008-07-30 08:49:36 +00002006InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2007 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002008 return static_cast<InlineCacheState>(bits);
2009}
2010
2011
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002012InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2013 int bits = (flags & kFlagsICInLoopMask);
2014 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2015}
2016
2017
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002018PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2019 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2020 return static_cast<PropertyType>(bits);
2021}
2022
2023
2024int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2025 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2026}
2027
2028
2029Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2030 int bits = flags & ~kFlagsTypeMask;
2031 return static_cast<Flags>(bits);
2032}
2033
2034
ager@chromium.org8bb60582008-12-11 12:02:20 +00002035Code* Code::GetCodeFromTargetAddress(Address address) {
2036 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2037 // GetCodeFromTargetAddress might be called when marking objects during mark
2038 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2039 // Code::cast. Code::cast does not work when the object's map is
2040 // marked.
2041 Code* result = reinterpret_cast<Code*>(code);
2042 return result;
2043}
2044
2045
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002046Object* Map::prototype() {
2047 return READ_FIELD(this, kPrototypeOffset);
2048}
2049
2050
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002051void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002052 ASSERT(value->IsNull() || value->IsJSObject());
2053 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002054 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002055}
2056
2057
2058ACCESSORS(Map, instance_descriptors, DescriptorArray,
2059 kInstanceDescriptorsOffset)
2060ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2061ACCESSORS(Map, constructor, Object, kConstructorOffset)
2062
2063ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2064ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2065
2066ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2067ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002068ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002069
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002070ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002071
2072ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2073ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2074ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2075ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2076ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2077
2078ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2079ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2080ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2081
2082ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2083ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2084ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2085ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2086ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2087ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2088
2089ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2090ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2091
2092ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2093ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2094
2095ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2096ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002097ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2098 kPropertyAccessorsOffset)
2099ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2100 kPrototypeTemplateOffset)
2101ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2102ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2103 kNamedPropertyHandlerOffset)
2104ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2105 kIndexedPropertyHandlerOffset)
2106ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2107 kInstanceTemplateOffset)
2108ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2109ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002110ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2111 kInstanceCallHandlerOffset)
2112ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2113 kAccessCheckInfoOffset)
2114ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2115
2116ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002117ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2118 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002119
2120ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2121ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2122
2123ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2124
2125ACCESSORS(Script, source, Object, kSourceOffset)
2126ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002127ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2129ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002130ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002131ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002132ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2133ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002134ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002135ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002136ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2137ACCESSORS(Script, eval_from_instructions_offset, Smi,
2138 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002139
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002140#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002141ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2142ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2143ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2144ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2145
2146ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2147ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2148ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2149ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002150#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002151
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002152ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002153ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2154ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2155 kInstanceClassNameOffset)
2156ACCESSORS(SharedFunctionInfo, function_data, Object,
2157 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002158ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2159ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002160ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002161
2162BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2163 kHiddenPrototypeBit)
2164BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2165BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2166 kNeedsAccessCheckBit)
2167BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2168 kIsExpressionBit)
2169BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2170 kIsTopLevelBit)
2171
2172INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2173INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2174 kFormalParameterCountOffset)
2175INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2176 kExpectedNofPropertiesOffset)
2177INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2178 kStartPositionAndTypeOffset)
2179INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2180INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2181 kFunctionTokenPositionOffset)
2182
2183
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002184void SharedFunctionInfo::DontAdaptArguments() {
2185 ASSERT(code()->kind() == Code::BUILTIN);
2186 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2187}
2188
2189
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002190int SharedFunctionInfo::start_position() {
2191 return start_position_and_type() >> kStartPositionShift;
2192}
2193
2194
2195void SharedFunctionInfo::set_start_position(int start_position) {
2196 set_start_position_and_type((start_position << kStartPositionShift)
2197 | (start_position_and_type() & ~kStartPositionMask));
2198}
2199
2200
2201Code* SharedFunctionInfo::code() {
2202 return Code::cast(READ_FIELD(this, kCodeOffset));
2203}
2204
2205
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002206void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002207 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002208 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002209}
2210
2211
2212bool SharedFunctionInfo::is_compiled() {
2213 // TODO(1242782): Create a code kind for uncompiled code.
2214 return code()->kind() != Code::STUB;
2215}
2216
2217
2218bool JSFunction::IsBoilerplate() {
2219 return map() == Heap::boilerplate_function_map();
2220}
2221
2222
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002223bool JSObject::IsLoaded() {
2224 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002225}
2226
2227
2228Code* JSFunction::code() {
2229 return shared()->code();
2230}
2231
2232
2233void JSFunction::set_code(Code* value) {
2234 shared()->set_code(value);
2235}
2236
2237
2238Context* JSFunction::context() {
2239 return Context::cast(READ_FIELD(this, kContextOffset));
2240}
2241
2242
2243Object* JSFunction::unchecked_context() {
2244 return READ_FIELD(this, kContextOffset);
2245}
2246
2247
2248void JSFunction::set_context(Object* value) {
2249 ASSERT(value == Heap::undefined_value() || value->IsContext());
2250 WRITE_FIELD(this, kContextOffset, value);
2251 WRITE_BARRIER(this, kContextOffset);
2252}
2253
2254ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2255 kPrototypeOrInitialMapOffset)
2256
2257
2258Map* JSFunction::initial_map() {
2259 return Map::cast(prototype_or_initial_map());
2260}
2261
2262
2263void JSFunction::set_initial_map(Map* value) {
2264 set_prototype_or_initial_map(value);
2265}
2266
2267
2268bool JSFunction::has_initial_map() {
2269 return prototype_or_initial_map()->IsMap();
2270}
2271
2272
2273bool JSFunction::has_instance_prototype() {
2274 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2275}
2276
2277
2278bool JSFunction::has_prototype() {
2279 return map()->has_non_instance_prototype() || has_instance_prototype();
2280}
2281
2282
2283Object* JSFunction::instance_prototype() {
2284 ASSERT(has_instance_prototype());
2285 if (has_initial_map()) return initial_map()->prototype();
2286 // When there is no initial map and the prototype is a JSObject, the
2287 // initial map field is used for the prototype field.
2288 return prototype_or_initial_map();
2289}
2290
2291
2292Object* JSFunction::prototype() {
2293 ASSERT(has_prototype());
2294 // If the function's prototype property has been set to a non-JSObject
2295 // value, that value is stored in the constructor field of the map.
2296 if (map()->has_non_instance_prototype()) return map()->constructor();
2297 return instance_prototype();
2298}
2299
2300
2301bool JSFunction::is_compiled() {
2302 return shared()->is_compiled();
2303}
2304
2305
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002306int JSFunction::NumberOfLiterals() {
2307 return literals()->length();
2308}
2309
2310
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2312 ASSERT(0 <= id && id < kJSBuiltinsCount);
2313 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2314}
2315
2316
2317void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2318 Object* value) {
2319 ASSERT(0 <= id && id < kJSBuiltinsCount);
2320 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2321 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2322}
2323
2324
2325Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002326 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002327}
2328
2329
2330void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002331 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002332}
2333
2334
2335void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2336 visitor->VisitExternalReference(
2337 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2338}
2339
2340
2341ACCESSORS(JSValue, value, Object, kValueOffset)
2342
2343
2344JSValue* JSValue::cast(Object* obj) {
2345 ASSERT(obj->IsJSValue());
2346 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2347 return reinterpret_cast<JSValue*>(obj);
2348}
2349
2350
2351INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2352INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2353INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2354
2355
2356Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002357 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002358}
2359
2360
2361void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002362 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002363}
2364
2365
2366byte* Code::instruction_start() {
2367 return FIELD_ADDR(this, kHeaderSize);
2368}
2369
2370
2371int Code::body_size() {
2372 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2373}
2374
2375
2376byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002377 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002378}
2379
2380
2381byte* Code::entry() {
2382 return instruction_start();
2383}
2384
2385
2386bool Code::contains(byte* pc) {
2387 return (instruction_start() <= pc) &&
2388 (pc < instruction_start() + instruction_size());
2389}
2390
2391
2392byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002393 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002394}
2395
2396
2397ACCESSORS(JSArray, length, Object, kLengthOffset)
2398
2399
ager@chromium.org236ad962008-09-25 09:45:57 +00002400ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002401
2402
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002403JSRegExp::Type JSRegExp::TypeTag() {
2404 Object* data = this->data();
2405 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2406 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2407 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002408}
2409
2410
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002411int JSRegExp::CaptureCount() {
2412 switch (TypeTag()) {
2413 case ATOM:
2414 return 0;
2415 case IRREGEXP:
2416 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2417 default:
2418 UNREACHABLE();
2419 return -1;
2420 }
2421}
2422
2423
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002424JSRegExp::Flags JSRegExp::GetFlags() {
2425 ASSERT(this->data()->IsFixedArray());
2426 Object* data = this->data();
2427 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2428 return Flags(smi->value());
2429}
2430
2431
2432String* JSRegExp::Pattern() {
2433 ASSERT(this->data()->IsFixedArray());
2434 Object* data = this->data();
2435 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2436 return pattern;
2437}
2438
2439
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002440Object* JSRegExp::DataAt(int index) {
2441 ASSERT(TypeTag() != NOT_COMPILED);
2442 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002443}
2444
2445
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002446void JSRegExp::SetDataAt(int index, Object* value) {
2447 ASSERT(TypeTag() != NOT_COMPILED);
2448 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2449 FixedArray::cast(data())->set(index, value);
2450}
2451
2452
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002453bool JSObject::HasFastElements() {
2454 return !elements()->IsDictionary();
2455}
2456
2457
2458bool JSObject::HasNamedInterceptor() {
2459 return map()->has_named_interceptor();
2460}
2461
2462
2463bool JSObject::HasIndexedInterceptor() {
2464 return map()->has_indexed_interceptor();
2465}
2466
2467
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002468StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002469 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002470 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002471}
2472
2473
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002474NumberDictionary* JSObject::element_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002475 ASSERT(!HasFastElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002476 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002477}
2478
2479
2480bool String::HasHashCode() {
2481 return (length_field() & kHashComputedMask) != 0;
2482}
2483
2484
2485uint32_t String::Hash() {
2486 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002487 uint32_t field = length_field();
2488 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002489 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002490 return ComputeAndSetHash();
2491}
2492
2493
ager@chromium.org7c537e22008-10-16 08:43:32 +00002494StringHasher::StringHasher(int length)
2495 : length_(length),
2496 raw_running_hash_(0),
2497 array_index_(0),
2498 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2499 is_first_char_(true),
2500 is_valid_(true) { }
2501
2502
2503bool StringHasher::has_trivial_hash() {
2504 return length_ > String::kMaxMediumStringSize;
2505}
2506
2507
2508void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002509 // Use the Jenkins one-at-a-time hash function to update the hash
2510 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002511 raw_running_hash_ += c;
2512 raw_running_hash_ += (raw_running_hash_ << 10);
2513 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002514 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002515 if (is_array_index_) {
2516 if (c < '0' || c > '9') {
2517 is_array_index_ = false;
2518 } else {
2519 int d = c - '0';
2520 if (is_first_char_) {
2521 is_first_char_ = false;
2522 if (c == '0' && length_ > 1) {
2523 is_array_index_ = false;
2524 return;
2525 }
2526 }
2527 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2528 is_array_index_ = false;
2529 } else {
2530 array_index_ = array_index_ * 10 + d;
2531 }
2532 }
2533 }
2534}
2535
2536
2537void StringHasher::AddCharacterNoIndex(uc32 c) {
2538 ASSERT(!is_array_index());
2539 raw_running_hash_ += c;
2540 raw_running_hash_ += (raw_running_hash_ << 10);
2541 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2542}
2543
2544
2545uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002546 // Get the calculated raw hash value and do some more bit ops to distribute
2547 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002548 uint32_t result = raw_running_hash_;
2549 result += (result << 3);
2550 result ^= (result >> 11);
2551 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002552 if (result == 0) {
2553 result = 27;
2554 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002555 return result;
2556}
2557
2558
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002559bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002560 uint32_t field = length_field();
2561 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002562 return SlowAsArrayIndex(index);
2563}
2564
2565
2566Object* JSObject::GetPrototype() {
2567 return JSObject::cast(this)->map()->prototype();
2568}
2569
2570
2571PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2572 return GetPropertyAttributeWithReceiver(this, key);
2573}
2574
2575
2576bool JSObject::HasElement(uint32_t index) {
2577 return HasElementWithReceiver(this, index);
2578}
2579
2580
ager@chromium.orge2902be2009-06-08 12:21:35 +00002581Smi* JSObject::InterceptorPropertyLookupHint(String* name) {
2582 // TODO(antonm): Do we want to do any shortcuts for global object?
2583 if (HasFastProperties()) {
2584 LookupResult lookup;
2585 LocalLookupRealNamedProperty(name, &lookup);
2586 if (lookup.IsValid()) {
2587 if (lookup.type() == FIELD && lookup.IsCacheable()) {
2588 return Smi::FromInt(lookup.GetFieldIndex());
2589 }
2590 } else {
2591 return Smi::FromInt(kLookupInPrototype);
2592 }
2593 }
2594
2595 return Smi::FromInt(kLookupInHolder);
2596}
2597
2598
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002599bool AccessorInfo::all_can_read() {
2600 return BooleanBit::get(flag(), kAllCanReadBit);
2601}
2602
2603
2604void AccessorInfo::set_all_can_read(bool value) {
2605 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2606}
2607
2608
2609bool AccessorInfo::all_can_write() {
2610 return BooleanBit::get(flag(), kAllCanWriteBit);
2611}
2612
2613
2614void AccessorInfo::set_all_can_write(bool value) {
2615 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2616}
2617
2618
ager@chromium.org870a0b62008-11-04 11:43:05 +00002619bool AccessorInfo::prohibits_overwriting() {
2620 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2621}
2622
2623
2624void AccessorInfo::set_prohibits_overwriting(bool value) {
2625 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2626}
2627
2628
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002629PropertyAttributes AccessorInfo::property_attributes() {
2630 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2631}
2632
2633
2634void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2635 ASSERT(AttributesField::is_valid(attributes));
2636 int rest_value = flag()->value() & ~AttributesField::mask();
2637 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2638}
2639
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002640template<typename Shape, typename Key>
2641void Dictionary<Shape, Key>::SetEntry(int entry,
2642 Object* key,
2643 Object* value,
2644 PropertyDetails details) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002645 ASSERT(!key->IsString() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002646 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2647 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2648 FixedArray::set(index, key, mode);
2649 FixedArray::set(index+1, value, mode);
2650 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002651}
2652
2653
2654void Map::ClearCodeCache() {
2655 // No write barrier is needed since empty_fixed_array is not in new space.
2656 // Please note this function is used during marking:
2657 // - MarkCompactCollector::MarkUnmarkedObject
2658 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2659 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2660}
2661
2662
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002663void JSArray::EnsureSize(int required_size) {
2664 ASSERT(HasFastElements());
2665 if (elements()->length() >= required_size) return;
2666 Expand(required_size);
2667}
2668
2669
ager@chromium.org7c537e22008-10-16 08:43:32 +00002670void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002671 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002672 set_elements(storage);
2673}
2674
2675
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002676Object* FixedArray::Copy() {
2677 if (length() == 0) return this;
2678 return Heap::CopyFixedArray(this);
2679}
2680
2681
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002682#undef CAST_ACCESSOR
2683#undef INT_ACCESSORS
2684#undef SMI_ACCESSORS
2685#undef ACCESSORS
2686#undef FIELD_ADDR
2687#undef READ_FIELD
2688#undef WRITE_FIELD
2689#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002690#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002691#undef READ_MEMADDR_FIELD
2692#undef WRITE_MEMADDR_FIELD
2693#undef READ_DOUBLE_FIELD
2694#undef WRITE_DOUBLE_FIELD
2695#undef READ_INT_FIELD
2696#undef WRITE_INT_FIELD
2697#undef READ_SHORT_FIELD
2698#undef WRITE_SHORT_FIELD
2699#undef READ_BYTE_FIELD
2700#undef WRITE_BYTE_FIELD
2701
2702
2703} } // namespace v8::internal
2704
2705#endif // V8_OBJECTS_INL_H_