blob: 7abc7c3eeaf075e3b7c22d1d34739ba4a974afe6 [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() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001078 InstanceType type = map()->instance_type();
1079 // Check for the most common kind of JavaScript object before
1080 // falling into the generic switch. This speeds up the internal
1081 // field operations considerably on average.
1082 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1083 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001084 case JS_GLOBAL_PROXY_TYPE:
1085 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086 case JS_GLOBAL_OBJECT_TYPE:
1087 return JSGlobalObject::kSize;
1088 case JS_BUILTINS_OBJECT_TYPE:
1089 return JSBuiltinsObject::kSize;
1090 case JS_FUNCTION_TYPE:
1091 return JSFunction::kSize;
1092 case JS_VALUE_TYPE:
1093 return JSValue::kSize;
1094 case JS_ARRAY_TYPE:
1095 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001096 case JS_REGEXP_TYPE:
1097 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001098 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001099 return JSObject::kHeaderSize;
1100 default:
1101 UNREACHABLE();
1102 return 0;
1103 }
1104}
1105
1106
1107int JSObject::GetInternalFieldCount() {
1108 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001109 // Make sure to adjust for the number of in-object properties. These
1110 // properties do contribute to the size, but are not internal fields.
1111 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1112 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001113}
1114
1115
1116Object* JSObject::GetInternalField(int index) {
1117 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001118 // Internal objects do follow immediately after the header, whereas in-object
1119 // properties are at the end of the object. Therefore there is no need
1120 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1122}
1123
1124
1125void JSObject::SetInternalField(int index, Object* value) {
1126 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001127 // Internal objects do follow immediately after the header, whereas in-object
1128 // properties are at the end of the object. Therefore there is no need
1129 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130 int offset = GetHeaderSize() + (kPointerSize * index);
1131 WRITE_FIELD(this, offset, value);
1132 WRITE_BARRIER(this, offset);
1133}
1134
1135
ager@chromium.org7c537e22008-10-16 08:43:32 +00001136// Access fast-case object properties at index. The use of these routines
1137// is needed to correctly distinguish between properties stored in-object and
1138// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001139Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001140 // Adjust for the number of properties stored in the object.
1141 index -= map()->inobject_properties();
1142 if (index < 0) {
1143 int offset = map()->instance_size() + (index * kPointerSize);
1144 return READ_FIELD(this, offset);
1145 } else {
1146 ASSERT(index < properties()->length());
1147 return properties()->get(index);
1148 }
1149}
1150
1151
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001152Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001153 // Adjust for the number of properties stored in the object.
1154 index -= map()->inobject_properties();
1155 if (index < 0) {
1156 int offset = map()->instance_size() + (index * kPointerSize);
1157 WRITE_FIELD(this, offset, value);
1158 WRITE_BARRIER(this, offset);
1159 } else {
1160 ASSERT(index < properties()->length());
1161 properties()->set(index, value);
1162 }
1163 return value;
1164}
1165
1166
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001167Object* JSObject::InObjectPropertyAt(int index) {
1168 // Adjust for the number of properties stored in the object.
1169 index -= map()->inobject_properties();
1170 ASSERT(index < 0);
1171 int offset = map()->instance_size() + (index * kPointerSize);
1172 return READ_FIELD(this, offset);
1173}
1174
1175
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001176Object* JSObject::InObjectPropertyAtPut(int index,
1177 Object* value,
1178 WriteBarrierMode mode) {
1179 // Adjust for the number of properties stored in the object.
1180 index -= map()->inobject_properties();
1181 ASSERT(index < 0);
1182 int offset = map()->instance_size() + (index * kPointerSize);
1183 WRITE_FIELD(this, offset, value);
1184 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1185 return value;
1186}
1187
1188
1189
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001190void JSObject::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001191 Object* value = Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001192 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001193 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001194 }
1195}
1196
1197
1198void Struct::InitializeBody(int object_size) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001199 Object* value = Heap::undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001200 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001201 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001202 }
1203}
1204
1205
1206bool JSObject::HasFastProperties() {
1207 return !properties()->IsDictionary();
1208}
1209
1210
1211bool Array::IndexFromObject(Object* object, uint32_t* index) {
1212 if (object->IsSmi()) {
1213 int value = Smi::cast(object)->value();
1214 if (value < 0) return false;
1215 *index = value;
1216 return true;
1217 }
1218 if (object->IsHeapNumber()) {
1219 double value = HeapNumber::cast(object)->value();
1220 uint32_t uint_value = static_cast<uint32_t>(value);
1221 if (value == static_cast<double>(uint_value)) {
1222 *index = uint_value;
1223 return true;
1224 }
1225 }
1226 return false;
1227}
1228
1229
1230bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1231 if (!this->IsJSValue()) return false;
1232
1233 JSValue* js_value = JSValue::cast(this);
1234 if (!js_value->value()->IsString()) return false;
1235
1236 String* str = String::cast(js_value->value());
1237 if (index >= (uint32_t)str->length()) return false;
1238
1239 return true;
1240}
1241
1242
1243Object* FixedArray::get(int index) {
1244 ASSERT(index >= 0 && index < this->length());
1245 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1246}
1247
1248
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001249void FixedArray::set(int index, Smi* value) {
1250 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1251 int offset = kHeaderSize + index * kPointerSize;
1252 WRITE_FIELD(this, offset, value);
1253}
1254
1255
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001256void FixedArray::set(int index, Object* value) {
1257 ASSERT(index >= 0 && index < this->length());
1258 int offset = kHeaderSize + index * kPointerSize;
1259 WRITE_FIELD(this, offset, value);
1260 WRITE_BARRIER(this, offset);
1261}
1262
1263
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001264WriteBarrierMode HeapObject::GetWriteBarrierMode() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001265 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1266 return UPDATE_WRITE_BARRIER;
1267}
1268
1269
1270void FixedArray::set(int index,
1271 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001272 WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273 ASSERT(index >= 0 && index < this->length());
1274 int offset = kHeaderSize + index * kPointerSize;
1275 WRITE_FIELD(this, offset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001276 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277}
1278
1279
1280void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1281 ASSERT(index >= 0 && index < array->length());
1282 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1283}
1284
1285
1286void FixedArray::set_undefined(int index) {
1287 ASSERT(index >= 0 && index < this->length());
1288 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1289 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1290 Heap::undefined_value());
1291}
1292
1293
ager@chromium.org236ad962008-09-25 09:45:57 +00001294void FixedArray::set_null(int index) {
1295 ASSERT(index >= 0 && index < this->length());
1296 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1297 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1298}
1299
1300
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001301void FixedArray::set_the_hole(int index) {
1302 ASSERT(index >= 0 && index < this->length());
1303 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1304 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1305}
1306
1307
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001308bool DescriptorArray::IsEmpty() {
1309 ASSERT(this == Heap::empty_descriptor_array() ||
1310 this->length() > 2);
1311 return this == Heap::empty_descriptor_array();
1312}
1313
1314
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1316 Object* tmp = array->get(first);
1317 fast_set(array, first, array->get(second));
1318 fast_set(array, second, tmp);
1319}
1320
1321
1322int DescriptorArray::Search(String* name) {
1323 SLOW_ASSERT(IsSortedNoDuplicates());
1324
1325 // Check for empty descriptor array.
1326 int nof = number_of_descriptors();
1327 if (nof == 0) return kNotFound;
1328
1329 // Fast case: do linear search for small arrays.
1330 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001331 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001332 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001333 }
1334
1335 // Slow case: perform binary search.
1336 return BinarySearch(name, 0, nof - 1);
1337}
1338
1339
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001340String* DescriptorArray::GetKey(int descriptor_number) {
1341 ASSERT(descriptor_number < number_of_descriptors());
1342 return String::cast(get(ToKeyIndex(descriptor_number)));
1343}
1344
1345
1346Object* DescriptorArray::GetValue(int descriptor_number) {
1347 ASSERT(descriptor_number < number_of_descriptors());
1348 return GetContentArray()->get(ToValueIndex(descriptor_number));
1349}
1350
1351
1352Smi* DescriptorArray::GetDetails(int descriptor_number) {
1353 ASSERT(descriptor_number < number_of_descriptors());
1354 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1355}
1356
1357
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001358PropertyType DescriptorArray::GetType(int descriptor_number) {
1359 ASSERT(descriptor_number < number_of_descriptors());
1360 return PropertyDetails(GetDetails(descriptor_number)).type();
1361}
1362
1363
1364int DescriptorArray::GetFieldIndex(int descriptor_number) {
1365 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1366}
1367
1368
1369JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1370 return JSFunction::cast(GetValue(descriptor_number));
1371}
1372
1373
1374Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1375 ASSERT(GetType(descriptor_number) == CALLBACKS);
1376 return GetValue(descriptor_number);
1377}
1378
1379
1380AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1381 ASSERT(GetType(descriptor_number) == CALLBACKS);
1382 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1383 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1384}
1385
1386
1387bool DescriptorArray::IsProperty(int descriptor_number) {
1388 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1389}
1390
1391
1392bool DescriptorArray::IsTransition(int descriptor_number) {
1393 PropertyType t = GetType(descriptor_number);
1394 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1395}
1396
1397
1398bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1399 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1400}
1401
1402
1403bool DescriptorArray::IsDontEnum(int descriptor_number) {
1404 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1405}
1406
1407
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001408void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1409 desc->Init(GetKey(descriptor_number),
1410 GetValue(descriptor_number),
1411 GetDetails(descriptor_number));
1412}
1413
1414
1415void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1416 // Range check.
1417 ASSERT(descriptor_number < number_of_descriptors());
1418
1419 // Make sure non of the elements in desc are in new space.
1420 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1421 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1422
1423 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1424 FixedArray* content_array = GetContentArray();
1425 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1426 fast_set(content_array, ToDetailsIndex(descriptor_number),
1427 desc->GetDetails().AsSmi());
1428}
1429
1430
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001431void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1432 Descriptor desc;
1433 src->Get(src_index, &desc);
1434 Set(index, &desc);
1435}
1436
1437
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001438void DescriptorArray::Swap(int first, int second) {
1439 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1440 FixedArray* content_array = GetContentArray();
1441 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1442 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1443}
1444
1445
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001446bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001447 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001448 if (!max_index_object->IsSmi()) return false;
1449 return 0 !=
1450 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1451}
1452
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001453uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001454 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001455 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456 if (!max_index_object->IsSmi()) return 0;
1457 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1458 return value >> kRequiresSlowElementsTagSize;
1459}
1460
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001461void NumberDictionary::set_requires_slow_elements() {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001462 set(kMaxNumberKeyIndex,
1463 Smi::FromInt(kRequiresSlowElementsMask),
1464 SKIP_WRITE_BARRIER);
1465}
1466
1467
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001468// ------------------------------------
1469// Cast operations
1470
1471
1472CAST_ACCESSOR(FixedArray)
1473CAST_ACCESSOR(DescriptorArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001475CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001476CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001477CAST_ACCESSOR(String)
1478CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001479CAST_ACCESSOR(SeqAsciiString)
1480CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001481CAST_ACCESSOR(ConsString)
1482CAST_ACCESSOR(SlicedString)
1483CAST_ACCESSOR(ExternalString)
1484CAST_ACCESSOR(ExternalAsciiString)
1485CAST_ACCESSOR(ExternalTwoByteString)
1486CAST_ACCESSOR(JSObject)
1487CAST_ACCESSOR(Smi)
1488CAST_ACCESSOR(Failure)
1489CAST_ACCESSOR(HeapObject)
1490CAST_ACCESSOR(HeapNumber)
1491CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001492CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001493CAST_ACCESSOR(SharedFunctionInfo)
1494CAST_ACCESSOR(Map)
1495CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001496CAST_ACCESSOR(GlobalObject)
1497CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498CAST_ACCESSOR(JSGlobalObject)
1499CAST_ACCESSOR(JSBuiltinsObject)
1500CAST_ACCESSOR(Code)
1501CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001502CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001503CAST_ACCESSOR(Proxy)
1504CAST_ACCESSOR(ByteArray)
1505CAST_ACCESSOR(Struct)
1506
1507
1508#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1509 STRUCT_LIST(MAKE_STRUCT_CAST)
1510#undef MAKE_STRUCT_CAST
1511
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001512
1513template <typename Shape, typename Key>
1514HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001515 ASSERT(obj->IsHashTable());
1516 return reinterpret_cast<HashTable*>(obj);
1517}
1518
1519
1520INT_ACCESSORS(Array, length, kLengthOffset)
1521
1522
1523bool String::Equals(String* other) {
1524 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001525 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1526 return false;
1527 }
1528 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001529}
1530
1531
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001532int String::length() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001533 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1534
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001535 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1536 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1537 ASSERT(kLongStringTag == 0);
1538
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001539 return len >> (StringShape(this).size_tag() + kLongLengthShift);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540}
1541
1542
1543void String::set_length(int value) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001544 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1545 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1546 ASSERT(kLongStringTag == 0);
1547
1548 WRITE_INT_FIELD(this,
1549 kLengthOffset,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001550 value << (StringShape(this).size_tag() + kLongLengthShift));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551}
1552
1553
ager@chromium.org7c537e22008-10-16 08:43:32 +00001554uint32_t String::length_field() {
1555 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556}
1557
1558
ager@chromium.org7c537e22008-10-16 08:43:32 +00001559void String::set_length_field(uint32_t value) {
1560 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001561}
1562
1563
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001564Object* String::TryFlattenIfNotFlat() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001565 // We don't need to flatten strings that are already flat. Since this code
1566 // is inlined, it can be helpful in the flat case to not call out to Flatten.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001567 if (!IsFlat()) {
1568 return TryFlatten();
ager@chromium.org236ad962008-09-25 09:45:57 +00001569 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001570 return this;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001571}
1572
1573
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001574uint16_t String::Get(int index) {
1575 ASSERT(index >= 0 && index < length());
1576 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001577 case kSeqStringTag | kAsciiStringTag:
1578 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1579 case kSeqStringTag | kTwoByteStringTag:
1580 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1581 case kConsStringTag | kAsciiStringTag:
1582 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001584 case kSlicedStringTag | kAsciiStringTag:
1585 case kSlicedStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001586 return SlicedString::cast(this)->SlicedStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001587 case kExternalStringTag | kAsciiStringTag:
1588 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1589 case kExternalStringTag | kTwoByteStringTag:
1590 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001591 default:
1592 break;
1593 }
1594
1595 UNREACHABLE();
1596 return 0;
1597}
1598
1599
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001600void String::Set(int index, uint16_t value) {
1601 ASSERT(index >= 0 && index < length());
1602 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001603
ager@chromium.org5ec48922009-05-05 07:25:34 +00001604 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00001605 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1606 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001607}
1608
1609
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001610bool String::IsFlat() {
1611 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001612 case kConsStringTag: {
1613 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001614 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00001615 return second->length() == 0;
1616 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001617 case kSlicedStringTag: {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001618 StringRepresentationTag tag =
1619 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
ager@chromium.org7c537e22008-10-16 08:43:32 +00001620 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001621 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001622 default:
1623 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001624 }
1625}
1626
1627
ager@chromium.org7c537e22008-10-16 08:43:32 +00001628uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001629 ASSERT(index >= 0 && index < length());
1630 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1631}
1632
1633
ager@chromium.org7c537e22008-10-16 08:43:32 +00001634void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001635 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1636 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1637 static_cast<byte>(value));
1638}
1639
1640
ager@chromium.org7c537e22008-10-16 08:43:32 +00001641Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001642 return FIELD_ADDR(this, kHeaderSize);
1643}
1644
1645
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001646char* SeqAsciiString::GetChars() {
1647 return reinterpret_cast<char*>(GetCharsAddress());
1648}
1649
1650
ager@chromium.org7c537e22008-10-16 08:43:32 +00001651Address SeqTwoByteString::GetCharsAddress() {
1652 return FIELD_ADDR(this, kHeaderSize);
1653}
1654
1655
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001656uc16* SeqTwoByteString::GetChars() {
1657 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1658}
1659
1660
ager@chromium.org7c537e22008-10-16 08:43:32 +00001661uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001662 ASSERT(index >= 0 && index < length());
1663 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1664}
1665
1666
ager@chromium.org7c537e22008-10-16 08:43:32 +00001667void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668 ASSERT(index >= 0 && index < length());
1669 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1670}
1671
1672
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001673int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001674 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1675
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001676 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1677 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1678 ASSERT(kLongStringTag == 0);
1679
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001680 // Use the map (and not 'this') to compute the size tag, since
1681 // TwoByteStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001682 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001683
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001684 return SizeFor(length);
1685}
1686
1687
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001688int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001689 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1690
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001691 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1692 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1693 ASSERT(kLongStringTag == 0);
1694
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001695 // Use the map (and not 'this') to compute the size tag, since
1696 // AsciiStringSize is called during GC when maps are encoded.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001697 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001698
1699 return SizeFor(length);
1700}
1701
1702
ager@chromium.org870a0b62008-11-04 11:43:05 +00001703String* ConsString::first() {
1704 return String::cast(READ_FIELD(this, kFirstOffset));
1705}
1706
1707
1708Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001709 return READ_FIELD(this, kFirstOffset);
1710}
1711
1712
ager@chromium.org870a0b62008-11-04 11:43:05 +00001713void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001714 WRITE_FIELD(this, kFirstOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001715 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001716}
1717
1718
ager@chromium.org870a0b62008-11-04 11:43:05 +00001719String* ConsString::second() {
1720 return String::cast(READ_FIELD(this, kSecondOffset));
1721}
1722
1723
1724Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725 return READ_FIELD(this, kSecondOffset);
1726}
1727
1728
ager@chromium.org870a0b62008-11-04 11:43:05 +00001729void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730 WRITE_FIELD(this, kSecondOffset, value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001731 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001732}
1733
1734
ager@chromium.org870a0b62008-11-04 11:43:05 +00001735String* SlicedString::buffer() {
1736 return String::cast(READ_FIELD(this, kBufferOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001737}
1738
1739
ager@chromium.org870a0b62008-11-04 11:43:05 +00001740void SlicedString::set_buffer(String* buffer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001741 WRITE_FIELD(this, kBufferOffset, buffer);
1742 WRITE_BARRIER(this, kBufferOffset);
1743}
1744
1745
1746int SlicedString::start() {
1747 return READ_INT_FIELD(this, kStartOffset);
1748}
1749
1750
1751void SlicedString::set_start(int start) {
1752 WRITE_INT_FIELD(this, kStartOffset, start);
1753}
1754
1755
1756ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1757 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1758}
1759
1760
1761void ExternalAsciiString::set_resource(
1762 ExternalAsciiString::Resource* resource) {
1763 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1764}
1765
1766
ager@chromium.org6f10e412009-02-13 10:11:16 +00001767Map* ExternalAsciiString::StringMap(int length) {
1768 Map* map;
1769 // Number of characters: determines the map.
1770 if (length <= String::kMaxShortStringSize) {
1771 map = Heap::short_external_ascii_string_map();
1772 } else if (length <= String::kMaxMediumStringSize) {
1773 map = Heap::medium_external_ascii_string_map();
1774 } else {
1775 map = Heap::long_external_ascii_string_map();
1776 }
1777 return map;
1778}
1779
1780
1781Map* ExternalAsciiString::SymbolMap(int length) {
1782 Map* map;
1783 // Number of characters: determines the map.
1784 if (length <= String::kMaxShortStringSize) {
1785 map = Heap::short_external_ascii_symbol_map();
1786 } else if (length <= String::kMaxMediumStringSize) {
1787 map = Heap::medium_external_ascii_symbol_map();
1788 } else {
1789 map = Heap::long_external_ascii_symbol_map();
1790 }
1791 return map;
1792}
1793
1794
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001795ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1796 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1797}
1798
1799
1800void ExternalTwoByteString::set_resource(
1801 ExternalTwoByteString::Resource* resource) {
1802 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1803}
1804
1805
ager@chromium.org6f10e412009-02-13 10:11:16 +00001806Map* ExternalTwoByteString::StringMap(int length) {
1807 Map* map;
1808 // Number of characters: determines the map.
1809 if (length <= String::kMaxShortStringSize) {
1810 map = Heap::short_external_string_map();
1811 } else if (length <= String::kMaxMediumStringSize) {
1812 map = Heap::medium_external_string_map();
1813 } else {
1814 map = Heap::long_external_string_map();
1815 }
1816 return map;
1817}
1818
1819
1820Map* ExternalTwoByteString::SymbolMap(int length) {
1821 Map* map;
1822 // Number of characters: determines the map.
1823 if (length <= String::kMaxShortStringSize) {
1824 map = Heap::short_external_symbol_map();
1825 } else if (length <= String::kMaxMediumStringSize) {
1826 map = Heap::medium_external_symbol_map();
1827 } else {
1828 map = Heap::long_external_symbol_map();
1829 }
1830 return map;
1831}
1832
1833
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001834byte ByteArray::get(int index) {
1835 ASSERT(index >= 0 && index < this->length());
1836 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1837}
1838
1839
1840void ByteArray::set(int index, byte value) {
1841 ASSERT(index >= 0 && index < this->length());
1842 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1843}
1844
1845
1846int ByteArray::get_int(int index) {
1847 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1848 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1849}
1850
1851
1852ByteArray* ByteArray::FromDataStartAddress(Address address) {
1853 ASSERT_TAG_ALIGNED(address);
1854 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1855}
1856
1857
1858Address ByteArray::GetDataStartAddress() {
1859 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1860}
1861
1862
1863int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001864 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1865}
1866
1867
1868int Map::inobject_properties() {
1869 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001870}
1871
1872
1873int HeapObject::SizeFromMap(Map* map) {
1874 InstanceType instance_type = map->instance_type();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001875 // Only inline the most frequent cases.
1876 if (instance_type == JS_OBJECT_TYPE ||
1877 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1878 (kStringTag | kConsStringTag) ||
1879 instance_type == JS_ARRAY_TYPE) return map->instance_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001880 if (instance_type == FIXED_ARRAY_TYPE) {
1881 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1882 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001883 if (instance_type == BYTE_ARRAY_TYPE) {
1884 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1885 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001886 // Otherwise do the general size computation.
1887 return SlowSizeFromMap(map);
1888}
1889
1890
1891void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001892 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00001893 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001894 ASSERT(0 <= value && value < 256);
1895 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1896}
1897
1898
ager@chromium.org7c537e22008-10-16 08:43:32 +00001899void Map::set_inobject_properties(int value) {
1900 ASSERT(0 <= value && value < 256);
1901 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1902}
1903
1904
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001905InstanceType Map::instance_type() {
1906 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1907}
1908
1909
1910void Map::set_instance_type(InstanceType value) {
1911 ASSERT(0 <= value && value < 256);
1912 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1913}
1914
1915
1916int Map::unused_property_fields() {
1917 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1918}
1919
1920
1921void Map::set_unused_property_fields(int value) {
1922 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1923}
1924
1925
1926byte Map::bit_field() {
1927 return READ_BYTE_FIELD(this, kBitFieldOffset);
1928}
1929
1930
1931void Map::set_bit_field(byte value) {
1932 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1933}
1934
1935
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001936byte Map::bit_field2() {
1937 return READ_BYTE_FIELD(this, kBitField2Offset);
1938}
1939
1940
1941void Map::set_bit_field2(byte value) {
1942 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
1943}
1944
1945
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001946void Map::set_non_instance_prototype(bool value) {
1947 if (value) {
1948 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1949 } else {
1950 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1951 }
1952}
1953
1954
1955bool Map::has_non_instance_prototype() {
1956 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1957}
1958
1959
ager@chromium.org870a0b62008-11-04 11:43:05 +00001960void Map::set_is_access_check_needed(bool access_check_needed) {
1961 if (access_check_needed) {
1962 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
1963 } else {
1964 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
1965 }
1966}
1967
1968
1969bool Map::is_access_check_needed() {
1970 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
1971}
1972
1973
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001974Code::Flags Code::flags() {
1975 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1976}
1977
1978
1979void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001980 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001981 // Make sure that all call stubs have an arguments count.
1982 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1983 ExtractArgumentsCountFromFlags(flags) >= 0);
1984 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1985}
1986
1987
1988Code::Kind Code::kind() {
1989 return ExtractKindFromFlags(flags());
1990}
1991
1992
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001993InLoopFlag Code::ic_in_loop() {
1994 return ExtractICInLoopFromFlags(flags());
1995}
1996
1997
kasper.lund7276f142008-07-30 08:49:36 +00001998InlineCacheState Code::ic_state() {
1999 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002000 // Only allow uninitialized or debugger states for non-IC code
2001 // objects. This is used in the debugger to determine whether or not
2002 // a call to code object has been replaced with a debug break call.
2003 ASSERT(is_inline_cache_stub() ||
2004 result == UNINITIALIZED ||
2005 result == DEBUG_BREAK ||
2006 result == DEBUG_PREPARE_STEP_IN);
2007 return result;
2008}
2009
2010
2011PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00002012 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002013 return ExtractTypeFromFlags(flags());
2014}
2015
2016
2017int Code::arguments_count() {
2018 ASSERT(is_call_stub() || kind() == STUB);
2019 return ExtractArgumentsCountFromFlags(flags());
2020}
2021
2022
2023CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002024 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00002025 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2026 kStubMajorKeyOffset));
2027}
2028
2029
2030void Code::set_major_key(CodeStub::Major major) {
2031 ASSERT(kind() == STUB);
2032 ASSERT(0 <= major && major < 256);
2033 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002034}
2035
2036
2037bool Code::is_inline_cache_stub() {
2038 Kind kind = this->kind();
2039 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2040}
2041
2042
2043Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002044 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002045 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002046 PropertyType type,
2047 int argc) {
2048 // Compute the bit mask.
2049 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002050 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002051 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002052 bits |= type << kFlagsTypeShift;
2053 bits |= argc << kFlagsArgumentsCountShift;
2054 // Cast to flags and validate result before returning it.
2055 Flags result = static_cast<Flags>(bits);
2056 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002057 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002058 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002059 ASSERT(ExtractTypeFromFlags(result) == type);
2060 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2061 return result;
2062}
2063
2064
2065Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2066 PropertyType type,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002067 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002068 int argc) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002069 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002070}
2071
2072
2073Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2074 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2075 return static_cast<Kind>(bits);
2076}
2077
2078
kasper.lund7276f142008-07-30 08:49:36 +00002079InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2080 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002081 return static_cast<InlineCacheState>(bits);
2082}
2083
2084
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002085InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2086 int bits = (flags & kFlagsICInLoopMask);
2087 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2088}
2089
2090
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2092 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2093 return static_cast<PropertyType>(bits);
2094}
2095
2096
2097int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2098 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2099}
2100
2101
2102Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2103 int bits = flags & ~kFlagsTypeMask;
2104 return static_cast<Flags>(bits);
2105}
2106
2107
ager@chromium.org8bb60582008-12-11 12:02:20 +00002108Code* Code::GetCodeFromTargetAddress(Address address) {
2109 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2110 // GetCodeFromTargetAddress might be called when marking objects during mark
2111 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2112 // Code::cast. Code::cast does not work when the object's map is
2113 // marked.
2114 Code* result = reinterpret_cast<Code*>(code);
2115 return result;
2116}
2117
2118
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002119Object* Map::prototype() {
2120 return READ_FIELD(this, kPrototypeOffset);
2121}
2122
2123
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002124void Map::set_prototype(Object* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002125 ASSERT(value->IsNull() || value->IsJSObject());
2126 WRITE_FIELD(this, kPrototypeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002127 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128}
2129
2130
2131ACCESSORS(Map, instance_descriptors, DescriptorArray,
2132 kInstanceDescriptorsOffset)
2133ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2134ACCESSORS(Map, constructor, Object, kConstructorOffset)
2135
2136ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2137ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2138
2139ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2140ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002141ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002142
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002143ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002144
2145ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2146ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2147ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2148ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2149ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2150
2151ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2152ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2153ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2154
2155ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2156ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2157ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2158ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2159ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2160ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2161
2162ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2163ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2164
2165ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2166ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2167
2168ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2169ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002170ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2171 kPropertyAccessorsOffset)
2172ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2173 kPrototypeTemplateOffset)
2174ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2175ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2176 kNamedPropertyHandlerOffset)
2177ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2178 kIndexedPropertyHandlerOffset)
2179ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2180 kInstanceTemplateOffset)
2181ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2182ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002183ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2184 kInstanceCallHandlerOffset)
2185ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2186 kAccessCheckInfoOffset)
2187ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2188
2189ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00002190ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2191 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002192
2193ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2194ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2195
2196ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2197
2198ACCESSORS(Script, source, Object, kSourceOffset)
2199ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002200ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002201ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2202ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002203ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00002204ACCESSORS(Script, context_data, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002205ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2206ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002207ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
iposva@chromium.org245aa852009-02-10 00:49:54 +00002208ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00002209ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2210ACCESSORS(Script, eval_from_instructions_offset, Smi,
2211 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002212
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002213#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002214ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2215ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2216ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2217ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2218
2219ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2220ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2221ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2222ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002223#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002224
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002225ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002226ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2227ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2228 kInstanceClassNameOffset)
2229ACCESSORS(SharedFunctionInfo, function_data, Object,
2230 kExternalReferenceDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002231ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2232ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00002233ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002234
2235BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2236 kHiddenPrototypeBit)
2237BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2238BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2239 kNeedsAccessCheckBit)
2240BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2241 kIsExpressionBit)
2242BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2243 kIsTopLevelBit)
2244
2245INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2246INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2247 kFormalParameterCountOffset)
2248INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2249 kExpectedNofPropertiesOffset)
2250INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2251 kStartPositionAndTypeOffset)
2252INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2253INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2254 kFunctionTokenPositionOffset)
2255
2256
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002257void SharedFunctionInfo::DontAdaptArguments() {
2258 ASSERT(code()->kind() == Code::BUILTIN);
2259 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2260}
2261
2262
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002263int SharedFunctionInfo::start_position() {
2264 return start_position_and_type() >> kStartPositionShift;
2265}
2266
2267
2268void SharedFunctionInfo::set_start_position(int start_position) {
2269 set_start_position_and_type((start_position << kStartPositionShift)
2270 | (start_position_and_type() & ~kStartPositionMask));
2271}
2272
2273
2274Code* SharedFunctionInfo::code() {
2275 return Code::cast(READ_FIELD(this, kCodeOffset));
2276}
2277
2278
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002279void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002280 WRITE_FIELD(this, kCodeOffset, value);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002281 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002282}
2283
2284
2285bool SharedFunctionInfo::is_compiled() {
2286 // TODO(1242782): Create a code kind for uncompiled code.
2287 return code()->kind() != Code::STUB;
2288}
2289
2290
2291bool JSFunction::IsBoilerplate() {
2292 return map() == Heap::boilerplate_function_map();
2293}
2294
2295
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002296bool JSObject::IsLoaded() {
2297 return !map()->needs_loading();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002298}
2299
2300
2301Code* JSFunction::code() {
2302 return shared()->code();
2303}
2304
2305
2306void JSFunction::set_code(Code* value) {
2307 shared()->set_code(value);
2308}
2309
2310
2311Context* JSFunction::context() {
2312 return Context::cast(READ_FIELD(this, kContextOffset));
2313}
2314
2315
2316Object* JSFunction::unchecked_context() {
2317 return READ_FIELD(this, kContextOffset);
2318}
2319
2320
2321void JSFunction::set_context(Object* value) {
2322 ASSERT(value == Heap::undefined_value() || value->IsContext());
2323 WRITE_FIELD(this, kContextOffset, value);
2324 WRITE_BARRIER(this, kContextOffset);
2325}
2326
2327ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2328 kPrototypeOrInitialMapOffset)
2329
2330
2331Map* JSFunction::initial_map() {
2332 return Map::cast(prototype_or_initial_map());
2333}
2334
2335
2336void JSFunction::set_initial_map(Map* value) {
2337 set_prototype_or_initial_map(value);
2338}
2339
2340
2341bool JSFunction::has_initial_map() {
2342 return prototype_or_initial_map()->IsMap();
2343}
2344
2345
2346bool JSFunction::has_instance_prototype() {
2347 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2348}
2349
2350
2351bool JSFunction::has_prototype() {
2352 return map()->has_non_instance_prototype() || has_instance_prototype();
2353}
2354
2355
2356Object* JSFunction::instance_prototype() {
2357 ASSERT(has_instance_prototype());
2358 if (has_initial_map()) return initial_map()->prototype();
2359 // When there is no initial map and the prototype is a JSObject, the
2360 // initial map field is used for the prototype field.
2361 return prototype_or_initial_map();
2362}
2363
2364
2365Object* JSFunction::prototype() {
2366 ASSERT(has_prototype());
2367 // If the function's prototype property has been set to a non-JSObject
2368 // value, that value is stored in the constructor field of the map.
2369 if (map()->has_non_instance_prototype()) return map()->constructor();
2370 return instance_prototype();
2371}
2372
2373
2374bool JSFunction::is_compiled() {
2375 return shared()->is_compiled();
2376}
2377
2378
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002379int JSFunction::NumberOfLiterals() {
2380 return literals()->length();
2381}
2382
2383
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002384Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2385 ASSERT(0 <= id && id < kJSBuiltinsCount);
2386 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2387}
2388
2389
2390void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2391 Object* value) {
2392 ASSERT(0 <= id && id < kJSBuiltinsCount);
2393 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2394 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2395}
2396
2397
2398Address Proxy::proxy() {
ager@chromium.org3e875802009-06-29 08:26:34 +00002399 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002400}
2401
2402
2403void Proxy::set_proxy(Address value) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002404 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002405}
2406
2407
2408void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2409 visitor->VisitExternalReference(
2410 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2411}
2412
2413
2414ACCESSORS(JSValue, value, Object, kValueOffset)
2415
2416
2417JSValue* JSValue::cast(Object* obj) {
2418 ASSERT(obj->IsJSValue());
2419 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2420 return reinterpret_cast<JSValue*>(obj);
2421}
2422
2423
2424INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2425INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2426INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2427
2428
2429Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002430 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002431}
2432
2433
2434void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002435 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002436}
2437
2438
2439byte* Code::instruction_start() {
2440 return FIELD_ADDR(this, kHeaderSize);
2441}
2442
2443
2444int Code::body_size() {
2445 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2446}
2447
2448
2449byte* Code::relocation_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002450 return FIELD_ADDR(this, kHeaderSize + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002451}
2452
2453
2454byte* Code::entry() {
2455 return instruction_start();
2456}
2457
2458
2459bool Code::contains(byte* pc) {
2460 return (instruction_start() <= pc) &&
2461 (pc < instruction_start() + instruction_size());
2462}
2463
2464
2465byte* Code::sinfo_start() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00002466 return FIELD_ADDR(this, kHeaderSize + body_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002467}
2468
2469
2470ACCESSORS(JSArray, length, Object, kLengthOffset)
2471
2472
ager@chromium.org236ad962008-09-25 09:45:57 +00002473ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00002474
2475
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002476JSRegExp::Type JSRegExp::TypeTag() {
2477 Object* data = this->data();
2478 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2479 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2480 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00002481}
2482
2483
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002484int JSRegExp::CaptureCount() {
2485 switch (TypeTag()) {
2486 case ATOM:
2487 return 0;
2488 case IRREGEXP:
2489 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2490 default:
2491 UNREACHABLE();
2492 return -1;
2493 }
2494}
2495
2496
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002497JSRegExp::Flags JSRegExp::GetFlags() {
2498 ASSERT(this->data()->IsFixedArray());
2499 Object* data = this->data();
2500 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2501 return Flags(smi->value());
2502}
2503
2504
2505String* JSRegExp::Pattern() {
2506 ASSERT(this->data()->IsFixedArray());
2507 Object* data = this->data();
2508 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2509 return pattern;
2510}
2511
2512
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002513Object* JSRegExp::DataAt(int index) {
2514 ASSERT(TypeTag() != NOT_COMPILED);
2515 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002516}
2517
2518
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002519void JSRegExp::SetDataAt(int index, Object* value) {
2520 ASSERT(TypeTag() != NOT_COMPILED);
2521 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2522 FixedArray::cast(data())->set(index, value);
2523}
2524
2525
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002526bool JSObject::HasFastElements() {
2527 return !elements()->IsDictionary();
2528}
2529
2530
2531bool JSObject::HasNamedInterceptor() {
2532 return map()->has_named_interceptor();
2533}
2534
2535
2536bool JSObject::HasIndexedInterceptor() {
2537 return map()->has_indexed_interceptor();
2538}
2539
2540
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002541StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002542 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002543 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002544}
2545
2546
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002547NumberDictionary* JSObject::element_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002548 ASSERT(!HasFastElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002549 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002550}
2551
2552
2553bool String::HasHashCode() {
2554 return (length_field() & kHashComputedMask) != 0;
2555}
2556
2557
2558uint32_t String::Hash() {
2559 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002560 uint32_t field = length_field();
2561 if (field & kHashComputedMask) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002562 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002563 return ComputeAndSetHash();
2564}
2565
2566
ager@chromium.org7c537e22008-10-16 08:43:32 +00002567StringHasher::StringHasher(int length)
2568 : length_(length),
2569 raw_running_hash_(0),
2570 array_index_(0),
2571 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2572 is_first_char_(true),
2573 is_valid_(true) { }
2574
2575
2576bool StringHasher::has_trivial_hash() {
2577 return length_ > String::kMaxMediumStringSize;
2578}
2579
2580
2581void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002582 // Use the Jenkins one-at-a-time hash function to update the hash
2583 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002584 raw_running_hash_ += c;
2585 raw_running_hash_ += (raw_running_hash_ << 10);
2586 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002587 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002588 if (is_array_index_) {
2589 if (c < '0' || c > '9') {
2590 is_array_index_ = false;
2591 } else {
2592 int d = c - '0';
2593 if (is_first_char_) {
2594 is_first_char_ = false;
2595 if (c == '0' && length_ > 1) {
2596 is_array_index_ = false;
2597 return;
2598 }
2599 }
2600 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2601 is_array_index_ = false;
2602 } else {
2603 array_index_ = array_index_ * 10 + d;
2604 }
2605 }
2606 }
2607}
2608
2609
2610void StringHasher::AddCharacterNoIndex(uc32 c) {
2611 ASSERT(!is_array_index());
2612 raw_running_hash_ += c;
2613 raw_running_hash_ += (raw_running_hash_ << 10);
2614 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2615}
2616
2617
2618uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002619 // Get the calculated raw hash value and do some more bit ops to distribute
2620 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00002621 uint32_t result = raw_running_hash_;
2622 result += (result << 3);
2623 result ^= (result >> 11);
2624 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002625 if (result == 0) {
2626 result = 27;
2627 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002628 return result;
2629}
2630
2631
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002632bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002633 uint32_t field = length_field();
2634 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002635 return SlowAsArrayIndex(index);
2636}
2637
2638
2639Object* JSObject::GetPrototype() {
2640 return JSObject::cast(this)->map()->prototype();
2641}
2642
2643
2644PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2645 return GetPropertyAttributeWithReceiver(this, key);
2646}
2647
2648
2649bool JSObject::HasElement(uint32_t index) {
2650 return HasElementWithReceiver(this, index);
2651}
2652
2653
ager@chromium.orge2902be2009-06-08 12:21:35 +00002654Smi* JSObject::InterceptorPropertyLookupHint(String* name) {
2655 // TODO(antonm): Do we want to do any shortcuts for global object?
2656 if (HasFastProperties()) {
2657 LookupResult lookup;
2658 LocalLookupRealNamedProperty(name, &lookup);
2659 if (lookup.IsValid()) {
2660 if (lookup.type() == FIELD && lookup.IsCacheable()) {
2661 return Smi::FromInt(lookup.GetFieldIndex());
2662 }
2663 } else {
2664 return Smi::FromInt(kLookupInPrototype);
2665 }
2666 }
2667
2668 return Smi::FromInt(kLookupInHolder);
2669}
2670
2671
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002672bool AccessorInfo::all_can_read() {
2673 return BooleanBit::get(flag(), kAllCanReadBit);
2674}
2675
2676
2677void AccessorInfo::set_all_can_read(bool value) {
2678 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2679}
2680
2681
2682bool AccessorInfo::all_can_write() {
2683 return BooleanBit::get(flag(), kAllCanWriteBit);
2684}
2685
2686
2687void AccessorInfo::set_all_can_write(bool value) {
2688 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2689}
2690
2691
ager@chromium.org870a0b62008-11-04 11:43:05 +00002692bool AccessorInfo::prohibits_overwriting() {
2693 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2694}
2695
2696
2697void AccessorInfo::set_prohibits_overwriting(bool value) {
2698 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2699}
2700
2701
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002702PropertyAttributes AccessorInfo::property_attributes() {
2703 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2704}
2705
2706
2707void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2708 ASSERT(AttributesField::is_valid(attributes));
2709 int rest_value = flag()->value() & ~AttributesField::mask();
2710 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2711}
2712
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002713template<typename Shape, typename Key>
2714void Dictionary<Shape, Key>::SetEntry(int entry,
2715 Object* key,
2716 Object* value,
2717 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002718 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002719 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2720 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2721 FixedArray::set(index, key, mode);
2722 FixedArray::set(index+1, value, mode);
2723 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002724}
2725
2726
2727void Map::ClearCodeCache() {
2728 // No write barrier is needed since empty_fixed_array is not in new space.
2729 // Please note this function is used during marking:
2730 // - MarkCompactCollector::MarkUnmarkedObject
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00002731 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2732 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002733}
2734
2735
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002736void JSArray::EnsureSize(int required_size) {
2737 ASSERT(HasFastElements());
2738 if (elements()->length() >= required_size) return;
2739 Expand(required_size);
2740}
2741
2742
ager@chromium.org7c537e22008-10-16 08:43:32 +00002743void JSArray::SetContent(FixedArray* storage) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002744 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002745 set_elements(storage);
2746}
2747
2748
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002749Object* FixedArray::Copy() {
2750 if (length() == 0) return this;
2751 return Heap::CopyFixedArray(this);
2752}
2753
2754
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002755#undef CAST_ACCESSOR
2756#undef INT_ACCESSORS
2757#undef SMI_ACCESSORS
2758#undef ACCESSORS
2759#undef FIELD_ADDR
2760#undef READ_FIELD
2761#undef WRITE_FIELD
2762#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002763#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002764#undef READ_MEMADDR_FIELD
2765#undef WRITE_MEMADDR_FIELD
2766#undef READ_DOUBLE_FIELD
2767#undef WRITE_DOUBLE_FIELD
2768#undef READ_INT_FIELD
2769#undef WRITE_INT_FIELD
2770#undef READ_SHORT_FIELD
2771#undef WRITE_SHORT_FIELD
2772#undef READ_BYTE_FIELD
2773#undef WRITE_BYTE_FIELD
2774
2775
2776} } // namespace v8::internal
2777
2778#endif // V8_OBJECTS_INL_H_