blob: 37c9b8b61d9544431b753b38ef0b55cbd1759702 [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() {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000484 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000485}
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) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000771 // Assert that the space encoding fits in the three bytes allotted for it.
772 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000773 int requested = requested_bytes >> kObjectAlignmentBits;
774 int value = (requested << kSpaceTagSize) | NEW_SPACE;
775 ASSERT(value >> kSpaceTagSize == requested);
776 ASSERT(Smi::IsValid(value));
777 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
778 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
779 return Construct(RETRY_AFTER_GC, value);
780}
781
782
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000783Failure* Failure::Construct(Type type, int value) {
784 int info = (value << kFailureTypeTagSize) | type;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000785 // TODO(X64): Stop using Smi validation for non-smi checks, even if they
786 // happen to be identical at the moment.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
ager@chromium.org5ec48922009-05-05 07:25:34 +0000788 return reinterpret_cast<Failure*>(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000789 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000790}
791
792
793bool Smi::IsValid(int value) {
794#ifdef DEBUG
795 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
796#endif
797 // To be representable as an tagged small integer, the two
798 // most-significant bits of 'value' must be either 00 or 11 due to
799 // sign-extension. To check this we add 01 to the two
800 // most-significant bits, and check if the most-significant bit is 0
801 //
802 // CAUTION: The original code below:
803 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
804 // may lead to incorrect results according to the C language spec, and
805 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
806 // compiler may produce undefined results in case of signed integer
807 // overflow. The computation must be done w/ unsigned ints.
808 bool result =
809 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
810 ASSERT(result == in_range);
811 return result;
812}
813
814
ager@chromium.org9085a012009-05-11 19:22:57 +0000815bool Smi::IsIntptrValid(intptr_t value) {
816#ifdef DEBUG
817 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
818#endif
819 // See Smi::IsValid(int) for description.
820 bool result =
821 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
822 ASSERT(result == in_range);
823 return result;
824}
825
826
kasper.lund7276f142008-07-30 08:49:36 +0000827MapWord MapWord::FromMap(Map* map) {
828 return MapWord(reinterpret_cast<uintptr_t>(map));
829}
830
831
832Map* MapWord::ToMap() {
833 return reinterpret_cast<Map*>(value_);
834}
835
836
837bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000838 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000839}
840
841
842MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000843 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
844 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000845}
846
847
848HeapObject* MapWord::ToForwardingAddress() {
849 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000850 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000851}
852
853
854bool MapWord::IsMarked() {
855 return (value_ & kMarkingMask) == 0;
856}
857
858
859void MapWord::SetMark() {
860 value_ &= ~kMarkingMask;
861}
862
863
864void MapWord::ClearMark() {
865 value_ |= kMarkingMask;
866}
867
868
869bool MapWord::IsOverflowed() {
870 return (value_ & kOverflowMask) != 0;
871}
872
873
874void MapWord::SetOverflow() {
875 value_ |= kOverflowMask;
876}
877
878
879void MapWord::ClearOverflow() {
880 value_ &= ~kOverflowMask;
881}
882
883
884MapWord MapWord::EncodeAddress(Address map_address, int offset) {
885 // Offset is the distance in live bytes from the first live object in the
886 // same page. The offset between two objects in the same page should not
887 // exceed the object area size of a page.
888 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
889
890 int compact_offset = offset >> kObjectAlignmentBits;
891 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
892
893 Page* map_page = Page::FromAddress(map_address);
894 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
895
896 int map_page_offset =
897 map_page->Offset(map_address) >> kObjectAlignmentBits;
898
899 uintptr_t encoding =
900 (compact_offset << kForwardingOffsetShift) |
901 (map_page_offset << kMapPageOffsetShift) |
902 (map_page->mc_page_index << kMapPageIndexShift);
903 return MapWord(encoding);
904}
905
906
907Address MapWord::DecodeMapAddress(MapSpace* map_space) {
908 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
909 ASSERT_MAP_PAGE_INDEX(map_page_index);
910
911 int map_page_offset =
912 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
913 << kObjectAlignmentBits;
914
915 return (map_space->PageAddress(map_page_index) + map_page_offset);
916}
917
918
919int MapWord::DecodeOffset() {
920 // The offset field is represented in the kForwardingOffsetBits
921 // most-significant bits.
922 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
923 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
924 return offset;
925}
926
927
928MapWord MapWord::FromEncodedAddress(Address address) {
929 return MapWord(reinterpret_cast<uintptr_t>(address));
930}
931
932
933Address MapWord::ToEncodedAddress() {
934 return reinterpret_cast<Address>(value_);
935}
936
937
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000938#ifdef DEBUG
939void HeapObject::VerifyObjectField(int offset) {
940 VerifyPointer(READ_FIELD(this, offset));
941}
942#endif
943
944
945Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000946 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000947}
948
949
950void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000951 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000952}
953
954
kasper.lund7276f142008-07-30 08:49:36 +0000955MapWord HeapObject::map_word() {
956 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
957}
958
959
960void HeapObject::set_map_word(MapWord map_word) {
961 // WRITE_FIELD does not update the remembered set, but there is no need
962 // here.
963 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
964}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000965
966
967HeapObject* HeapObject::FromAddress(Address address) {
968 ASSERT_TAG_ALIGNED(address);
969 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
970}
971
972
973Address HeapObject::address() {
974 return reinterpret_cast<Address>(this) - kHeapObjectTag;
975}
976
977
978int HeapObject::Size() {
979 return SizeFromMap(map());
980}
981
982
983void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
984 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
985 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
986}
987
988
989void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
990 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
991}
992
993
kasper.lund7276f142008-07-30 08:49:36 +0000994bool HeapObject::IsMarked() {
995 return map_word().IsMarked();
996}
997
998
999void HeapObject::SetMark() {
1000 ASSERT(!IsMarked());
1001 MapWord first_word = map_word();
1002 first_word.SetMark();
1003 set_map_word(first_word);
1004}
1005
1006
1007void HeapObject::ClearMark() {
1008 ASSERT(IsMarked());
1009 MapWord first_word = map_word();
1010 first_word.ClearMark();
1011 set_map_word(first_word);
1012}
1013
1014
1015bool HeapObject::IsOverflowed() {
1016 return map_word().IsOverflowed();
1017}
1018
1019
1020void HeapObject::SetOverflow() {
1021 MapWord first_word = map_word();
1022 first_word.SetOverflow();
1023 set_map_word(first_word);
1024}
1025
1026
1027void HeapObject::ClearOverflow() {
1028 ASSERT(IsOverflowed());
1029 MapWord first_word = map_word();
1030 first_word.ClearOverflow();
1031 set_map_word(first_word);
1032}
1033
1034
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001035double HeapNumber::value() {
1036 return READ_DOUBLE_FIELD(this, kValueOffset);
1037}
1038
1039
1040void HeapNumber::set_value(double value) {
1041 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1042}
1043
1044
1045ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001046ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001047
1048
1049void JSObject::initialize_properties() {
1050 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1051 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1052}
1053
1054
1055void JSObject::initialize_elements() {
1056 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1057 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1058}
1059
1060
1061ACCESSORS(Oddball, to_string, String, kToStringOffset)
1062ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1063
1064
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001065Object* JSGlobalPropertyCell::value() {
1066 return READ_FIELD(this, kValueOffset);
1067}
1068
1069
1070void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1071 // The write barrier is not used for global property cells.
1072 ASSERT(!val->IsJSGlobalPropertyCell());
1073 WRITE_FIELD(this, kValueOffset, val);
1074}
1075
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001076
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001077int JSObject::GetHeaderSize() {
1078 switch (map()->instance_type()) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001079 case JS_GLOBAL_PROXY_TYPE:
1080 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001081 case JS_GLOBAL_OBJECT_TYPE:
1082 return JSGlobalObject::kSize;
1083 case JS_BUILTINS_OBJECT_TYPE:
1084 return JSBuiltinsObject::kSize;
1085 case JS_FUNCTION_TYPE:
1086 return JSFunction::kSize;
1087 case JS_VALUE_TYPE:
1088 return JSValue::kSize;
1089 case JS_ARRAY_TYPE:
1090 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001091 case JS_REGEXP_TYPE:
1092 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001093 case JS_OBJECT_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00001094 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001095 return JSObject::kHeaderSize;
1096 default:
1097 UNREACHABLE();
1098 return 0;
1099 }
1100}
1101
1102
1103int JSObject::GetInternalFieldCount() {
1104 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001105 // Make sure to adjust for the number of in-object properties. These
1106 // properties do contribute to the size, but are not internal fields.
1107 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1108 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001109}
1110
1111
1112Object* JSObject::GetInternalField(int index) {
1113 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001114 // Internal objects do follow immediately after the header, whereas in-object
1115 // properties are at the end of the object. Therefore there is no need
1116 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001117 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1118}
1119
1120
1121void JSObject::SetInternalField(int index, Object* value) {
1122 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001123 // Internal objects do follow immediately after the header, whereas in-object
1124 // properties are at the end of the object. Therefore there is no need
1125 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001126 int offset = GetHeaderSize() + (kPointerSize * index);
1127 WRITE_FIELD(this, offset, value);
1128 WRITE_BARRIER(this, offset);
1129}
1130
1131
ager@chromium.org7c537e22008-10-16 08:43:32 +00001132// Access fast-case object properties at index. The use of these routines
1133// is needed to correctly distinguish between properties stored in-object and
1134// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001135Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001136 // Adjust for the number of properties stored in the object.
1137 index -= map()->inobject_properties();
1138 if (index < 0) {
1139 int offset = map()->instance_size() + (index * kPointerSize);
1140 return READ_FIELD(this, offset);
1141 } else {
1142 ASSERT(index < properties()->length());
1143 return properties()->get(index);
1144 }
1145}
1146
1147
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001148Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001149 // Adjust for the number of properties stored in the object.
1150 index -= map()->inobject_properties();
1151 if (index < 0) {
1152 int offset = map()->instance_size() + (index * kPointerSize);
1153 WRITE_FIELD(this, offset, value);
1154 WRITE_BARRIER(this, offset);
1155 } else {
1156 ASSERT(index < properties()->length());
1157 properties()->set(index, value);
1158 }
1159 return value;
1160}
1161
1162
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001163Object* JSObject::InObjectPropertyAt(int index) {
1164 // Adjust for the number of properties stored in the object.
1165 index -= map()->inobject_properties();
1166 ASSERT(index < 0);
1167 int offset = map()->instance_size() + (index * kPointerSize);
1168 return READ_FIELD(this, offset);
1169}
1170
1171
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001172Object* JSObject::InObjectPropertyAtPut(int index,
1173 Object* value,
1174 WriteBarrierMode mode) {
1175 // Adjust for the number of properties stored in the object.
1176 index -= map()->inobject_properties();
1177 ASSERT(index < 0);
1178 int offset = map()->instance_size() + (index * kPointerSize);
1179 WRITE_FIELD(this, offset, value);
1180 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1181 return value;
1182}
1183
1184
1185
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001187 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001188 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001189 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001190 }
1191}
1192
1193
1194void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001195 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001196 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001197 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001198 }
1199}
1200
1201
1202bool JSObject::HasFastProperties() {
1203 return !properties()->IsDictionary();
1204}
1205
1206
1207bool Array::IndexFromObject(Object* object, uint32_t* index) {
1208 if (object->IsSmi()) {
1209 int value = Smi::cast(object)->value();
1210 if (value < 0) return false;
1211 *index = value;
1212 return true;
1213 }
1214 if (object->IsHeapNumber()) {
1215 double value = HeapNumber::cast(object)->value();
1216 uint32_t uint_value = static_cast<uint32_t>(value);
1217 if (value == static_cast<double>(uint_value)) {
1218 *index = uint_value;
1219 return true;
1220 }
1221 }
1222 return false;
1223}
1224
1225
1226bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1227 if (!this->IsJSValue()) return false;
1228
1229 JSValue* js_value = JSValue::cast(this);
1230 if (!js_value->value()->IsString()) return false;
1231
1232 String* str = String::cast(js_value->value());
1233 if (index >= (uint32_t)str->length()) return false;
1234
1235 return true;
1236}
1237
1238
1239Object* FixedArray::get(int index) {
1240 ASSERT(index >= 0 && index < this->length());
1241 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1242}
1243
1244
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001245void FixedArray::set(int index, Smi* value) {
1246 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1247 int offset = kHeaderSize + index * kPointerSize;
1248 WRITE_FIELD(this, offset, value);
1249}
1250
1251
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252void FixedArray::set(int index, Object* value) {
1253 ASSERT(index >= 0 && index < this->length());
1254 int offset = kHeaderSize + index * kPointerSize;
1255 WRITE_FIELD(this, offset, value);
1256 WRITE_BARRIER(this, offset);
1257}
1258
1259
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001260WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001261 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1262 return UPDATE_WRITE_BARRIER;
1263}
1264
1265
1266void FixedArray::set(int index,
1267 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001268 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001269 ASSERT(index >= 0 && index < this->length());
1270 int offset = kHeaderSize + index * kPointerSize;
1271 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001272 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273}
1274
1275
1276void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1277 ASSERT(index >= 0 && index < array->length());
1278 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1279}
1280
1281
1282void FixedArray::set_undefined(int index) {
1283 ASSERT(index >= 0 && index < this->length());
1284 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1285 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1286 Heap::undefined_value());
1287}
1288
1289
ager@chromium.org236ad962008-09-25 09:45:57 +00001290void FixedArray::set_null(int index) {
1291 ASSERT(index >= 0 && index < this->length());
1292 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1293 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1294}
1295
1296
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297void FixedArray::set_the_hole(int index) {
1298 ASSERT(index >= 0 && index < this->length());
1299 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1300 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1301}
1302
1303
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001304bool DescriptorArray::IsEmpty() {
1305 ASSERT(this == Heap::empty_descriptor_array() ||
1306 this->length() > 2);
1307 return this == Heap::empty_descriptor_array();
1308}
1309
1310
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001311void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1312 Object* tmp = array->get(first);
1313 fast_set(array, first, array->get(second));
1314 fast_set(array, second, tmp);
1315}
1316
1317
1318int DescriptorArray::Search(String* name) {
1319 SLOW_ASSERT(IsSortedNoDuplicates());
1320
1321 // Check for empty descriptor array.
1322 int nof = number_of_descriptors();
1323 if (nof == 0) return kNotFound;
1324
1325 // Fast case: do linear search for small arrays.
1326 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001327 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001328 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329 }
1330
1331 // Slow case: perform binary search.
1332 return BinarySearch(name, 0, nof - 1);
1333}
1334
1335
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001336String* DescriptorArray::GetKey(int descriptor_number) {
1337 ASSERT(descriptor_number < number_of_descriptors());
1338 return String::cast(get(ToKeyIndex(descriptor_number)));
1339}
1340
1341
1342Object* DescriptorArray::GetValue(int descriptor_number) {
1343 ASSERT(descriptor_number < number_of_descriptors());
1344 return GetContentArray()->get(ToValueIndex(descriptor_number));
1345}
1346
1347
1348Smi* DescriptorArray::GetDetails(int descriptor_number) {
1349 ASSERT(descriptor_number < number_of_descriptors());
1350 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1351}
1352
1353
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001354PropertyType DescriptorArray::GetType(int descriptor_number) {
1355 ASSERT(descriptor_number < number_of_descriptors());
1356 return PropertyDetails(GetDetails(descriptor_number)).type();
1357}
1358
1359
1360int DescriptorArray::GetFieldIndex(int descriptor_number) {
1361 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1362}
1363
1364
1365JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1366 return JSFunction::cast(GetValue(descriptor_number));
1367}
1368
1369
1370Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1371 ASSERT(GetType(descriptor_number) == CALLBACKS);
1372 return GetValue(descriptor_number);
1373}
1374
1375
1376AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1377 ASSERT(GetType(descriptor_number) == CALLBACKS);
1378 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1379 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1380}
1381
1382
1383bool DescriptorArray::IsProperty(int descriptor_number) {
1384 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1385}
1386
1387
1388bool DescriptorArray::IsTransition(int descriptor_number) {
1389 PropertyType t = GetType(descriptor_number);
1390 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1391}
1392
1393
1394bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1395 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1396}
1397
1398
1399bool DescriptorArray::IsDontEnum(int descriptor_number) {
1400 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1401}
1402
1403
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001404void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1405 desc->Init(GetKey(descriptor_number),
1406 GetValue(descriptor_number),
1407 GetDetails(descriptor_number));
1408}
1409
1410
1411void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1412 // Range check.
1413 ASSERT(descriptor_number < number_of_descriptors());
1414
1415 // Make sure non of the elements in desc are in new space.
1416 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1417 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1418
1419 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1420 FixedArray* content_array = GetContentArray();
1421 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1422 fast_set(content_array, ToDetailsIndex(descriptor_number),
1423 desc->GetDetails().AsSmi());
1424}
1425
1426
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001427void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1428 Descriptor desc;
1429 src->Get(src_index, &desc);
1430 Set(index, &desc);
1431}
1432
1433
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001434void DescriptorArray::Swap(int first, int second) {
1435 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1436 FixedArray* content_array = GetContentArray();
1437 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1438 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1439}
1440
1441
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001442bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001443 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001444 if (!max_index_object->IsSmi()) return false;
1445 return 0 !=
1446 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1447}
1448
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001449uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001450 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001451 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001452 if (!max_index_object->IsSmi()) return 0;
1453 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1454 return value >> kRequiresSlowElementsTagSize;
1455}
1456
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001457void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001458 set(kMaxNumberKeyIndex,
1459 Smi::FromInt(kRequiresSlowElementsMask),
1460 SKIP_WRITE_BARRIER);
1461}
1462
1463
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001464// ------------------------------------
1465// Cast operations
1466
1467
1468CAST_ACCESSOR(FixedArray)
1469CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001470CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001471CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001472CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001473CAST_ACCESSOR(String)
1474CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001475CAST_ACCESSOR(SeqAsciiString)
1476CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001477CAST_ACCESSOR(ConsString)
1478CAST_ACCESSOR(SlicedString)
1479CAST_ACCESSOR(ExternalString)
1480CAST_ACCESSOR(ExternalAsciiString)
1481CAST_ACCESSOR(ExternalTwoByteString)
1482CAST_ACCESSOR(JSObject)
1483CAST_ACCESSOR(Smi)
1484CAST_ACCESSOR(Failure)
1485CAST_ACCESSOR(HeapObject)
1486CAST_ACCESSOR(HeapNumber)
1487CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001488CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001489CAST_ACCESSOR(SharedFunctionInfo)
1490CAST_ACCESSOR(Map)
1491CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001492CAST_ACCESSOR(GlobalObject)
1493CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494CAST_ACCESSOR(JSGlobalObject)
1495CAST_ACCESSOR(JSBuiltinsObject)
1496CAST_ACCESSOR(Code)
1497CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001498CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001499CAST_ACCESSOR(Proxy)
1500CAST_ACCESSOR(ByteArray)
1501CAST_ACCESSOR(Struct)
1502
1503
1504#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1505 STRUCT_LIST(MAKE_STRUCT_CAST)
1506#undef MAKE_STRUCT_CAST
1507
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001508
1509template <typename Shape, typename Key>
1510HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001511 ASSERT(obj->IsHashTable());
1512 return reinterpret_cast<HashTable*>(obj);
1513}
1514
1515
1516INT_ACCESSORS(Array, length, kLengthOffset)
1517
1518
1519bool String::Equals(String* other) {
1520 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001521 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1522 return false;
1523 }
1524 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001525}
1526
1527
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001528int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001529 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1530
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001531 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1532 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1533 ASSERT(kLongStringTag == 0);
1534
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001535 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001536}
1537
1538
1539void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001540 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1541 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1542 ASSERT(kLongStringTag == 0);
1543
1544 WRITE_INT_FIELD(this,
1545 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001546 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001547}
1548
1549
ager@chromium.org7c537e22008-10-16 08:43:32 +00001550uint32_t String::length_field() {
1551 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552}
1553
1554
ager@chromium.org7c537e22008-10-16 08:43:32 +00001555void String::set_length_field(uint32_t value) {
1556 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557}
1558
1559
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001560Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001561 // We don't need to flatten strings that are already flat. Since this code
1562 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001563 if (!IsFlat()) {
1564 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001565 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001566 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001567}
1568
1569
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001570uint16_t String::Get(int index) {
1571 ASSERT(index >= 0 && index < length());
1572 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001573 case kSeqStringTag | kAsciiStringTag:
1574 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1575 case kSeqStringTag | kTwoByteStringTag:
1576 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1577 case kConsStringTag | kAsciiStringTag:
1578 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001580 case kSlicedStringTag | kAsciiStringTag:
1581 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001582 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001583 case kExternalStringTag | kAsciiStringTag:
1584 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1585 case kExternalStringTag | kTwoByteStringTag:
1586 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001587 default:
1588 break;
1589 }
1590
1591 UNREACHABLE();
1592 return 0;
1593}
1594
1595
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001596void String::Set(int index, uint16_t value) {
1597 ASSERT(index >= 0 && index < length());
1598 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599
ager@chromium.org5ec48922009-05-05 07:25:34 +00001600 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001601 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1602 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001603}
1604
1605
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001606bool String::IsFlat() {
1607 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001608 case kConsStringTag: {
1609 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001610 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001611 return second->length() == 0;
1612 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001613 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001614 StringRepresentationTag tag =
1615 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001616 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001617 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001618 default:
1619 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001620 }
1621}
1622
1623
ager@chromium.org7c537e22008-10-16 08:43:32 +00001624uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625 ASSERT(index >= 0 && index < length());
1626 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1627}
1628
1629
ager@chromium.org7c537e22008-10-16 08:43:32 +00001630void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001631 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1632 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1633 static_cast<byte>(value));
1634}
1635
1636
ager@chromium.org7c537e22008-10-16 08:43:32 +00001637Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001638 return FIELD_ADDR(this, kHeaderSize);
1639}
1640
1641
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001642char* SeqAsciiString::GetChars() {
1643 return reinterpret_cast<char*>(GetCharsAddress());
1644}
1645
1646
ager@chromium.org7c537e22008-10-16 08:43:32 +00001647Address SeqTwoByteString::GetCharsAddress() {
1648 return FIELD_ADDR(this, kHeaderSize);
1649}
1650
1651
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001652uc16* SeqTwoByteString::GetChars() {
1653 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1654}
1655
1656
ager@chromium.org7c537e22008-10-16 08:43:32 +00001657uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001658 ASSERT(index >= 0 && index < length());
1659 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1660}
1661
1662
ager@chromium.org7c537e22008-10-16 08:43:32 +00001663void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664 ASSERT(index >= 0 && index < length());
1665 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1666}
1667
1668
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001669int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001670 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1671
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001672 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1673 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1674 ASSERT(kLongStringTag == 0);
1675
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676 // Use the map (and not 'this') to compute the size tag, since
1677 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001678 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001679
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001680 return SizeFor(length);
1681}
1682
1683
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001684int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001685 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1686
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001687 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1688 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1689 ASSERT(kLongStringTag == 0);
1690
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001691 // Use the map (and not 'this') to compute the size tag, since
1692 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001693 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001694
1695 return SizeFor(length);
1696}
1697
1698
ager@chromium.org870a0b62008-11-04 11:43:05 +00001699String* ConsString::first() {
1700 return String::cast(READ_FIELD(this, kFirstOffset));
1701}
1702
1703
1704Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001705 return READ_FIELD(this, kFirstOffset);
1706}
1707
1708
ager@chromium.org870a0b62008-11-04 11:43:05 +00001709void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001710 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001711 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001712}
1713
1714
ager@chromium.org870a0b62008-11-04 11:43:05 +00001715String* ConsString::second() {
1716 return String::cast(READ_FIELD(this, kSecondOffset));
1717}
1718
1719
1720Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001721 return READ_FIELD(this, kSecondOffset);
1722}
1723
1724
ager@chromium.org870a0b62008-11-04 11:43:05 +00001725void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001726 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001727 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001728}
1729
1730
ager@chromium.org870a0b62008-11-04 11:43:05 +00001731String* SlicedString::buffer() {
1732 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001733}
1734
1735
ager@chromium.org870a0b62008-11-04 11:43:05 +00001736void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001737 WRITE_FIELD(this, kBufferOffset, buffer);
1738 WRITE_BARRIER(this, kBufferOffset);
1739}
1740
1741
1742int SlicedString::start() {
1743 return READ_INT_FIELD(this, kStartOffset);
1744}
1745
1746
1747void SlicedString::set_start(int start) {
1748 WRITE_INT_FIELD(this, kStartOffset, start);
1749}
1750
1751
1752ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1753 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1754}
1755
1756
1757void ExternalAsciiString::set_resource(
1758 ExternalAsciiString::Resource* resource) {
1759 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1760}
1761
1762
ager@chromium.org6f10e412009-02-13 10:11:16 +00001763Map* ExternalAsciiString::StringMap(int length) {
1764 Map* map;
1765 // Number of characters: determines the map.
1766 if (length <= String::kMaxShortStringSize) {
1767 map = Heap::short_external_ascii_string_map();
1768 } else if (length <= String::kMaxMediumStringSize) {
1769 map = Heap::medium_external_ascii_string_map();
1770 } else {
1771 map = Heap::long_external_ascii_string_map();
1772 }
1773 return map;
1774}
1775
1776
1777Map* ExternalAsciiString::SymbolMap(int length) {
1778 Map* map;
1779 // Number of characters: determines the map.
1780 if (length <= String::kMaxShortStringSize) {
1781 map = Heap::short_external_ascii_symbol_map();
1782 } else if (length <= String::kMaxMediumStringSize) {
1783 map = Heap::medium_external_ascii_symbol_map();
1784 } else {
1785 map = Heap::long_external_ascii_symbol_map();
1786 }
1787 return map;
1788}
1789
1790
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001791ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1792 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1793}
1794
1795
1796void ExternalTwoByteString::set_resource(
1797 ExternalTwoByteString::Resource* resource) {
1798 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1799}
1800
1801
ager@chromium.org6f10e412009-02-13 10:11:16 +00001802Map* ExternalTwoByteString::StringMap(int length) {
1803 Map* map;
1804 // Number of characters: determines the map.
1805 if (length <= String::kMaxShortStringSize) {
1806 map = Heap::short_external_string_map();
1807 } else if (length <= String::kMaxMediumStringSize) {
1808 map = Heap::medium_external_string_map();
1809 } else {
1810 map = Heap::long_external_string_map();
1811 }
1812 return map;
1813}
1814
1815
1816Map* ExternalTwoByteString::SymbolMap(int length) {
1817 Map* map;
1818 // Number of characters: determines the map.
1819 if (length <= String::kMaxShortStringSize) {
1820 map = Heap::short_external_symbol_map();
1821 } else if (length <= String::kMaxMediumStringSize) {
1822 map = Heap::medium_external_symbol_map();
1823 } else {
1824 map = Heap::long_external_symbol_map();
1825 }
1826 return map;
1827}
1828
1829
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001830byte ByteArray::get(int index) {
1831 ASSERT(index >= 0 && index < this->length());
1832 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1833}
1834
1835
1836void ByteArray::set(int index, byte value) {
1837 ASSERT(index >= 0 && index < this->length());
1838 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1839}
1840
1841
1842int ByteArray::get_int(int index) {
1843 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1844 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1845}
1846
1847
1848ByteArray* ByteArray::FromDataStartAddress(Address address) {
1849 ASSERT_TAG_ALIGNED(address);
1850 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1851}
1852
1853
1854Address ByteArray::GetDataStartAddress() {
1855 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1856}
1857
1858
1859int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001860 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1861}
1862
1863
1864int Map::inobject_properties() {
1865 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001866}
1867
1868
1869int HeapObject::SizeFromMap(Map* map) {
1870 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001871 // Only inline the most frequent cases.
1872 if (instance_type == JS_OBJECT_TYPE ||
1873 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1874 (kStringTag | kConsStringTag) ||
1875 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001876 if (instance_type == FIXED_ARRAY_TYPE) {
1877 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1878 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001879 if (instance_type == BYTE_ARRAY_TYPE) {
1880 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1881 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001882 // Otherwise do the general size computation.
1883 return SlowSizeFromMap(map);
1884}
1885
1886
1887void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001888 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001889 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001890 ASSERT(0 <= value && value < 256);
1891 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1892}
1893
1894
ager@chromium.org7c537e22008-10-16 08:43:32 +00001895void Map::set_inobject_properties(int value) {
1896 ASSERT(0 <= value && value < 256);
1897 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1898}
1899
1900
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001901InstanceType Map::instance_type() {
1902 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1903}
1904
1905
1906void Map::set_instance_type(InstanceType value) {
1907 ASSERT(0 <= value && value < 256);
1908 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1909}
1910
1911
1912int Map::unused_property_fields() {
1913 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1914}
1915
1916
1917void Map::set_unused_property_fields(int value) {
1918 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1919}
1920
1921
1922byte Map::bit_field() {
1923 return READ_BYTE_FIELD(this, kBitFieldOffset);
1924}
1925
1926
1927void Map::set_bit_field(byte value) {
1928 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1929}
1930
1931
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001932byte Map::bit_field2() {
1933 return READ_BYTE_FIELD(this, kBitField2Offset);
1934}
1935
1936
1937void Map::set_bit_field2(byte value) {
1938 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1939}
1940
1941
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942void Map::set_non_instance_prototype(bool value) {
1943 if (value) {
1944 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1945 } else {
1946 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1947 }
1948}
1949
1950
1951bool Map::has_non_instance_prototype() {
1952 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1953}
1954
1955
ager@chromium.org870a0b62008-11-04 11:43:05 +00001956void Map::set_is_access_check_needed(bool access_check_needed) {
1957 if (access_check_needed) {
1958 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1959 } else {
1960 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1961 }
1962}
1963
1964
1965bool Map::is_access_check_needed() {
1966 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1967}
1968
1969
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001970Code::Flags Code::flags() {
1971 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1972}
1973
1974
1975void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001976 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001977 // Make sure that all call stubs have an arguments count.
1978 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1979 ExtractArgumentsCountFromFlags(flags) >= 0);
1980 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1981}
1982
1983
1984Code::Kind Code::kind() {
1985 return ExtractKindFromFlags(flags());
1986}
1987
1988
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001989InLoopFlag Code::ic_in_loop() {
1990 return ExtractICInLoopFromFlags(flags());
1991}
1992
1993
kasper.lund7276f142008-07-30 08:49:36 +00001994InlineCacheState Code::ic_state() {
1995 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001996 // Only allow uninitialized or debugger states for non-IC code
1997 // objects. This is used in the debugger to determine whether or not
1998 // a call to code object has been replaced with a debug break call.
1999 ASSERT(is_inline_cache_stub() ||
2000 result == UNINITIALIZED ||
2001 result == DEBUG_BREAK ||
2002 result == DEBUG_PREPARE_STEP_IN);
2003 return result;
2004}
2005
2006
2007PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002008 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002009 return ExtractTypeFromFlags(flags());
2010}
2011
2012
2013int Code::arguments_count() {
2014 ASSERT(is_call_stub() || kind() == STUB);
2015 return ExtractArgumentsCountFromFlags(flags());
2016}
2017
2018
2019CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002020 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002021 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2022 kStubMajorKeyOffset));
2023}
2024
2025
2026void Code::set_major_key(CodeStub::Major major) {
2027 ASSERT(kind() == STUB);
2028 ASSERT(0 <= major && major < 256);
2029 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002030}
2031
2032
2033bool Code::is_inline_cache_stub() {
2034 Kind kind = this->kind();
2035 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2036}
2037
2038
2039Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002040 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002041 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002042 PropertyType type,
2043 int argc) {
2044 // Compute the bit mask.
2045 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002046 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002047 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002048 bits |= type << kFlagsTypeShift;
2049 bits |= argc << kFlagsArgumentsCountShift;
2050 // Cast to flags and validate result before returning it.
2051 Flags result = static_cast<Flags>(bits);
2052 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002053 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002054 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002055 ASSERT(ExtractTypeFromFlags(result) == type);
2056 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2057 return result;
2058}
2059
2060
2061Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2062 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002063 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002064 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002065 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002066}
2067
2068
2069Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2070 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2071 return static_cast<Kind>(bits);
2072}
2073
2074
kasper.lund7276f142008-07-30 08:49:36 +00002075InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2076 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002077 return static_cast<InlineCacheState>(bits);
2078}
2079
2080
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002081InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2082 int bits = (flags & kFlagsICInLoopMask);
2083 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2084}
2085
2086
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002087PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2088 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2089 return static_cast<PropertyType>(bits);
2090}
2091
2092
2093int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2094 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2095}
2096
2097
2098Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2099 int bits = flags & ~kFlagsTypeMask;
2100 return static_cast<Flags>(bits);
2101}
2102
2103
ager@chromium.org8bb60582008-12-11 12:02:20 +00002104Code* Code::GetCodeFromTargetAddress(Address address) {
2105 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2106 // GetCodeFromTargetAddress might be called when marking objects during mark
2107 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2108 // Code::cast. Code::cast does not work when the object's map is
2109 // marked.
2110 Code* result = reinterpret_cast<Code*>(code);
2111 return result;
2112}
2113
2114
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002115Object* Map::prototype() {
2116 return READ_FIELD(this, kPrototypeOffset);
2117}
2118
2119
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002120void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002121 ASSERT(value->IsNull() || value->IsJSObject());
2122 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002123 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002124}
2125
2126
2127ACCESSORS(Map, instance_descriptors, DescriptorArray,
2128 kInstanceDescriptorsOffset)
2129ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2130ACCESSORS(Map, constructor, Object, kConstructorOffset)
2131
2132ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2133ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2134
2135ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2136ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002137ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002138
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002139ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002140
2141ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2142ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2143ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2144ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2145ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2146
2147ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2148ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2149ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2150
2151ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2152ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2153ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2154ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2155ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2156ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2157
2158ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2159ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2160
2161ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2162ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2163
2164ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2165ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002166ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2167 kPropertyAccessorsOffset)
2168ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2169 kPrototypeTemplateOffset)
2170ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2171ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2172 kNamedPropertyHandlerOffset)
2173ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2174 kIndexedPropertyHandlerOffset)
2175ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2176 kInstanceTemplateOffset)
2177ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2178ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002179ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2180 kInstanceCallHandlerOffset)
2181ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2182 kAccessCheckInfoOffset)
2183ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2184
2185ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002186ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2187 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002188
2189ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2190ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2191
2192ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2193
2194ACCESSORS(Script, source, Object, kSourceOffset)
2195ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002196ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002197ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2198ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002199ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002200ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002201ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2202ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002203ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002204ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002205ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2206ACCESSORS(Script, eval_from_instructions_offset, Smi,
2207 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002208
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002209#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002210ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2211ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2212ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2213ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2214
2215ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2216ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2217ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2218ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002219#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002220
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002221ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002222ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2223ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2224 kInstanceClassNameOffset)
2225ACCESSORS(SharedFunctionInfo, function_data, Object,
2226 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002227ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2228ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002229ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002230
2231BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2232 kHiddenPrototypeBit)
2233BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2234BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2235 kNeedsAccessCheckBit)
2236BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2237 kIsExpressionBit)
2238BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2239 kIsTopLevelBit)
2240
2241INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2242INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2243 kFormalParameterCountOffset)
2244INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2245 kExpectedNofPropertiesOffset)
2246INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2247 kStartPositionAndTypeOffset)
2248INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2249INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2250 kFunctionTokenPositionOffset)
2251
2252
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002253void SharedFunctionInfo::DontAdaptArguments() {
2254 ASSERT(code()->kind() == Code::BUILTIN);
2255 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2256}
2257
2258
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259int SharedFunctionInfo::start_position() {
2260 return start_position_and_type() >> kStartPositionShift;
2261}
2262
2263
2264void SharedFunctionInfo::set_start_position(int start_position) {
2265 set_start_position_and_type((start_position << kStartPositionShift)
2266 | (start_position_and_type() & ~kStartPositionMask));
2267}
2268
2269
2270Code* SharedFunctionInfo::code() {
2271 return Code::cast(READ_FIELD(this, kCodeOffset));
2272}
2273
2274
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002275void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002276 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002277 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002278}
2279
2280
2281bool SharedFunctionInfo::is_compiled() {
2282 // TODO(1242782): Create a code kind for uncompiled code.
2283 return code()->kind() != Code::STUB;
2284}
2285
2286
2287bool JSFunction::IsBoilerplate() {
2288 return map() == Heap::boilerplate_function_map();
2289}
2290
2291
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002292bool JSObject::IsLoaded() {
2293 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002294}
2295
2296
2297Code* JSFunction::code() {
2298 return shared()->code();
2299}
2300
2301
2302void JSFunction::set_code(Code* value) {
2303 shared()->set_code(value);
2304}
2305
2306
2307Context* JSFunction::context() {
2308 return Context::cast(READ_FIELD(this, kContextOffset));
2309}
2310
2311
2312Object* JSFunction::unchecked_context() {
2313 return READ_FIELD(this, kContextOffset);
2314}
2315
2316
2317void JSFunction::set_context(Object* value) {
2318 ASSERT(value == Heap::undefined_value() || value->IsContext());
2319 WRITE_FIELD(this, kContextOffset, value);
2320 WRITE_BARRIER(this, kContextOffset);
2321}
2322
2323ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2324 kPrototypeOrInitialMapOffset)
2325
2326
2327Map* JSFunction::initial_map() {
2328 return Map::cast(prototype_or_initial_map());
2329}
2330
2331
2332void JSFunction::set_initial_map(Map* value) {
2333 set_prototype_or_initial_map(value);
2334}
2335
2336
2337bool JSFunction::has_initial_map() {
2338 return prototype_or_initial_map()->IsMap();
2339}
2340
2341
2342bool JSFunction::has_instance_prototype() {
2343 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2344}
2345
2346
2347bool JSFunction::has_prototype() {
2348 return map()->has_non_instance_prototype() || has_instance_prototype();
2349}
2350
2351
2352Object* JSFunction::instance_prototype() {
2353 ASSERT(has_instance_prototype());
2354 if (has_initial_map()) return initial_map()->prototype();
2355 // When there is no initial map and the prototype is a JSObject, the
2356 // initial map field is used for the prototype field.
2357 return prototype_or_initial_map();
2358}
2359
2360
2361Object* JSFunction::prototype() {
2362 ASSERT(has_prototype());
2363 // If the function's prototype property has been set to a non-JSObject
2364 // value, that value is stored in the constructor field of the map.
2365 if (map()->has_non_instance_prototype()) return map()->constructor();
2366 return instance_prototype();
2367}
2368
2369
2370bool JSFunction::is_compiled() {
2371 return shared()->is_compiled();
2372}
2373
2374
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002375int JSFunction::NumberOfLiterals() {
2376 return literals()->length();
2377}
2378
2379
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002380Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2381 ASSERT(0 <= id && id < kJSBuiltinsCount);
2382 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2383}
2384
2385
2386void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2387 Object* value) {
2388 ASSERT(0 <= id && id < kJSBuiltinsCount);
2389 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2390 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2391}
2392
2393
2394Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002395 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002396}
2397
2398
2399void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002400 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002401}
2402
2403
2404void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2405 visitor->VisitExternalReference(
2406 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2407}
2408
2409
2410ACCESSORS(JSValue, value, Object, kValueOffset)
2411
2412
2413JSValue* JSValue::cast(Object* obj) {
2414 ASSERT(obj->IsJSValue());
2415 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2416 return reinterpret_cast<JSValue*>(obj);
2417}
2418
2419
2420INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2421INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2422INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2423
2424
2425Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002426 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002427}
2428
2429
2430void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002431 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002432}
2433
2434
2435byte* Code::instruction_start() {
2436 return FIELD_ADDR(this, kHeaderSize);
2437}
2438
2439
2440int Code::body_size() {
2441 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2442}
2443
2444
2445byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002446 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002447}
2448
2449
2450byte* Code::entry() {
2451 return instruction_start();
2452}
2453
2454
2455bool Code::contains(byte* pc) {
2456 return (instruction_start() <= pc) &&
2457 (pc < instruction_start() + instruction_size());
2458}
2459
2460
2461byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002462 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002463}
2464
2465
2466ACCESSORS(JSArray, length, Object, kLengthOffset)
2467
2468
ager@chromium.org236ad962008-09-25 09:45:57 +00002469ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002470
2471
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002472JSRegExp::Type JSRegExp::TypeTag() {
2473 Object* data = this->data();
2474 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2475 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2476 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002477}
2478
2479
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002480int JSRegExp::CaptureCount() {
2481 switch (TypeTag()) {
2482 case ATOM:
2483 return 0;
2484 case IRREGEXP:
2485 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2486 default:
2487 UNREACHABLE();
2488 return -1;
2489 }
2490}
2491
2492
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002493JSRegExp::Flags JSRegExp::GetFlags() {
2494 ASSERT(this->data()->IsFixedArray());
2495 Object* data = this->data();
2496 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2497 return Flags(smi->value());
2498}
2499
2500
2501String* JSRegExp::Pattern() {
2502 ASSERT(this->data()->IsFixedArray());
2503 Object* data = this->data();
2504 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2505 return pattern;
2506}
2507
2508
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002509Object* JSRegExp::DataAt(int index) {
2510 ASSERT(TypeTag() != NOT_COMPILED);
2511 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002512}
2513
2514
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002515void JSRegExp::SetDataAt(int index, Object* value) {
2516 ASSERT(TypeTag() != NOT_COMPILED);
2517 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2518 FixedArray::cast(data())->set(index, value);
2519}
2520
2521
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002522bool JSObject::HasFastElements() {
2523 return !elements()->IsDictionary();
2524}
2525
2526
2527bool JSObject::HasNamedInterceptor() {
2528 return map()->has_named_interceptor();
2529}
2530
2531
2532bool JSObject::HasIndexedInterceptor() {
2533 return map()->has_indexed_interceptor();
2534}
2535
2536
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002537StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002538 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002539 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002540}
2541
2542
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002543NumberDictionary* JSObject::element_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002544 ASSERT(!HasFastElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002545 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002546}
2547
2548
2549bool String::HasHashCode() {
2550 return (length_field() & kHashComputedMask) != 0;
2551}
2552
2553
2554uint32_t String::Hash() {
2555 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002556 uint32_t field = length_field();
2557 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002558 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002559 return ComputeAndSetHash();
2560}
2561
2562
ager@chromium.org7c537e22008-10-16 08:43:32 +00002563StringHasher::StringHasher(int length)
2564 : length_(length),
2565 raw_running_hash_(0),
2566 array_index_(0),
2567 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2568 is_first_char_(true),
2569 is_valid_(true) { }
2570
2571
2572bool StringHasher::has_trivial_hash() {
2573 return length_ > String::kMaxMediumStringSize;
2574}
2575
2576
2577void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002578 // Use the Jenkins one-at-a-time hash function to update the hash
2579 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002580 raw_running_hash_ += c;
2581 raw_running_hash_ += (raw_running_hash_ << 10);
2582 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002583 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002584 if (is_array_index_) {
2585 if (c < '0' || c > '9') {
2586 is_array_index_ = false;
2587 } else {
2588 int d = c - '0';
2589 if (is_first_char_) {
2590 is_first_char_ = false;
2591 if (c == '0' && length_ > 1) {
2592 is_array_index_ = false;
2593 return;
2594 }
2595 }
2596 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2597 is_array_index_ = false;
2598 } else {
2599 array_index_ = array_index_ * 10 + d;
2600 }
2601 }
2602 }
2603}
2604
2605
2606void StringHasher::AddCharacterNoIndex(uc32 c) {
2607 ASSERT(!is_array_index());
2608 raw_running_hash_ += c;
2609 raw_running_hash_ += (raw_running_hash_ << 10);
2610 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2611}
2612
2613
2614uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002615 // Get the calculated raw hash value and do some more bit ops to distribute
2616 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002617 uint32_t result = raw_running_hash_;
2618 result += (result << 3);
2619 result ^= (result >> 11);
2620 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002621 if (result == 0) {
2622 result = 27;
2623 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002624 return result;
2625}
2626
2627
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002628bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002629 uint32_t field = length_field();
2630 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002631 return SlowAsArrayIndex(index);
2632}
2633
2634
2635Object* JSObject::GetPrototype() {
2636 return JSObject::cast(this)->map()->prototype();
2637}
2638
2639
2640PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2641 return GetPropertyAttributeWithReceiver(this, key);
2642}
2643
2644
2645bool JSObject::HasElement(uint32_t index) {
2646 return HasElementWithReceiver(this, index);
2647}
2648
2649
ager@chromium.orge2902be2009-06-08 12:21:35 +00002650Smi* JSObject::InterceptorPropertyLookupHint(String* name) {
2651 // TODO(antonm): Do we want to do any shortcuts for global object?
2652 if (HasFastProperties()) {
2653 LookupResult lookup;
2654 LocalLookupRealNamedProperty(name, &lookup);
2655 if (lookup.IsValid()) {
2656 if (lookup.type() == FIELD && lookup.IsCacheable()) {
2657 return Smi::FromInt(lookup.GetFieldIndex());
2658 }
2659 } else {
2660 return Smi::FromInt(kLookupInPrototype);
2661 }
2662 }
2663
2664 return Smi::FromInt(kLookupInHolder);
2665}
2666
2667
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002668bool AccessorInfo::all_can_read() {
2669 return BooleanBit::get(flag(), kAllCanReadBit);
2670}
2671
2672
2673void AccessorInfo::set_all_can_read(bool value) {
2674 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2675}
2676
2677
2678bool AccessorInfo::all_can_write() {
2679 return BooleanBit::get(flag(), kAllCanWriteBit);
2680}
2681
2682
2683void AccessorInfo::set_all_can_write(bool value) {
2684 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2685}
2686
2687
ager@chromium.org870a0b62008-11-04 11:43:05 +00002688bool AccessorInfo::prohibits_overwriting() {
2689 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2690}
2691
2692
2693void AccessorInfo::set_prohibits_overwriting(bool value) {
2694 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2695}
2696
2697
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002698PropertyAttributes AccessorInfo::property_attributes() {
2699 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2700}
2701
2702
2703void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2704 ASSERT(AttributesField::is_valid(attributes));
2705 int rest_value = flag()->value() & ~AttributesField::mask();
2706 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2707}
2708
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002709template<typename Shape, typename Key>
2710void Dictionary<Shape, Key>::SetEntry(int entry,
2711 Object* key,
2712 Object* value,
2713 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002714 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002715 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2716 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2717 FixedArray::set(index, key, mode);
2718 FixedArray::set(index+1, value, mode);
2719 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002720}
2721
2722
2723void Map::ClearCodeCache() {
2724 // No write barrier is needed since empty_fixed_array is not in new space.
2725 // Please note this function is used during marking:
2726 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002727 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2728 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002729}
2730
2731
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002732void JSArray::EnsureSize(int required_size) {
2733 ASSERT(HasFastElements());
2734 if (elements()->length() >= required_size) return;
2735 Expand(required_size);
2736}
2737
2738
ager@chromium.org7c537e22008-10-16 08:43:32 +00002739void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002740 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002741 set_elements(storage);
2742}
2743
2744
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002745Object* FixedArray::Copy() {
2746 if (length() == 0) return this;
2747 return Heap::CopyFixedArray(this);
2748}
2749
2750
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002751#undef CAST_ACCESSOR
2752#undef INT_ACCESSORS
2753#undef SMI_ACCESSORS
2754#undef ACCESSORS
2755#undef FIELD_ADDR
2756#undef READ_FIELD
2757#undef WRITE_FIELD
2758#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002759#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002760#undef READ_MEMADDR_FIELD
2761#undef WRITE_MEMADDR_FIELD
2762#undef READ_DOUBLE_FIELD
2763#undef WRITE_DOUBLE_FIELD
2764#undef READ_INT_FIELD
2765#undef WRITE_INT_FIELD
2766#undef READ_SHORT_FIELD
2767#undef WRITE_SHORT_FIELD
2768#undef READ_BYTE_FIELD
2769#undef WRITE_BYTE_FIELD
2770
2771
2772} } // namespace v8::internal
2773
2774#endif // V8_OBJECTS_INL_H_