blob: 6870ce06dd53c00f224a6be9c582aee55b1e61fb [file] [log] [blame]
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001// Copyright 2011 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
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000038#include "objects.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#include "contexts.h"
40#include "conversions-inl.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000041#include "heap.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000042#include "isolate.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043#include "property.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000044#include "spaces.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000045#include "v8memory.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
kasperl@chromium.org71affb52009-05-26 05:44:31 +000047namespace v8 {
48namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
50PropertyDetails::PropertyDetails(Smi* smi) {
51 value_ = smi->value();
52}
53
54
55Smi* PropertyDetails::AsSmi() {
56 return Smi::FromInt(value_);
57}
58
59
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000060PropertyDetails PropertyDetails::AsDeleted() {
ager@chromium.org378b34e2011-01-28 08:04:38 +000061 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000062 return PropertyDetails(smi);
63}
64
65
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066#define CAST_ACCESSOR(type) \
67 type* type::cast(Object* object) { \
68 ASSERT(object->Is##type()); \
69 return reinterpret_cast<type*>(object); \
70 }
71
72
73#define INT_ACCESSORS(holder, name, offset) \
74 int holder::name() { return READ_INT_FIELD(this, offset); } \
75 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
76
77
78#define ACCESSORS(holder, name, type, offset) \
79 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000080 void holder::set_##name(type* value, WriteBarrierMode mode) { \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000081 WRITE_FIELD(this, offset, value); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000082 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); \
83 }
84
85
86// GC-safe accessors do not use HeapObject::GetHeap(), but access TLS instead.
87#define ACCESSORS_GCSAFE(holder, name, type, offset) \
88 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
89 void holder::set_##name(type* value, WriteBarrierMode mode) { \
90 WRITE_FIELD(this, offset, value); \
91 CONDITIONAL_WRITE_BARRIER(HEAP, this, offset, mode); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092 }
93
94
95#define SMI_ACCESSORS(holder, name, offset) \
96 int holder::name() { \
97 Object* value = READ_FIELD(this, offset); \
98 return Smi::cast(value)->value(); \
99 } \
100 void holder::set_##name(int value) { \
101 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
102 }
103
104
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000105#define BOOL_GETTER(holder, field, name, offset) \
106 bool holder::name() { \
107 return BooleanBit::get(field(), offset); \
108 } \
109
110
111#define BOOL_ACCESSORS(holder, field, name, offset) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112 bool holder::name() { \
113 return BooleanBit::get(field(), offset); \
114 } \
115 void holder::set_##name(bool value) { \
116 set_##field(BooleanBit::set(field(), offset, value)); \
117 }
118
119
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000120bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
121 // There is a constraint on the object; check.
122 if (!this->IsJSObject()) return false;
123 // Fetch the constructor function of the object.
124 Object* cons_obj = JSObject::cast(this)->map()->constructor();
125 if (!cons_obj->IsJSFunction()) return false;
126 JSFunction* fun = JSFunction::cast(cons_obj);
127 // Iterate through the chain of inheriting function templates to
128 // see if the required one occurs.
129 for (Object* type = fun->shared()->function_data();
130 type->IsFunctionTemplateInfo();
131 type = FunctionTemplateInfo::cast(type)->parent_template()) {
132 if (type == expected) return true;
133 }
134 // Didn't find the required type in the inheritance chain.
135 return false;
136}
137
138
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000139bool Object::IsSmi() {
140 return HAS_SMI_TAG(this);
141}
142
143
144bool Object::IsHeapObject() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000145 return Internals::HasHeapObjectTag(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146}
147
148
149bool Object::IsHeapNumber() {
150 return Object::IsHeapObject()
151 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
152}
153
154
155bool Object::IsString() {
156 return Object::IsHeapObject()
157 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
158}
159
160
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000161bool Object::IsSpecObject() {
162 return Object::IsHeapObject()
163 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
164}
165
166
ager@chromium.org870a0b62008-11-04 11:43:05 +0000167bool Object::IsSymbol() {
168 if (!this->IsHeapObject()) return false;
169 uint32_t type = HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000170 // Because the symbol tag is non-zero and no non-string types have the
171 // symbol bit set we can test for symbols with a very simple test
172 // operation.
173 ASSERT(kSymbolTag != 0);
174 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
175 return (type & kIsSymbolMask) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176}
177
178
179bool Object::IsConsString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000180 if (!this->IsHeapObject()) return false;
181 uint32_t type = HeapObject::cast(this)->map()->instance_type();
182 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
183 (kStringTag | kConsStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184}
185
186
ager@chromium.org870a0b62008-11-04 11:43:05 +0000187bool Object::IsSeqString() {
188 if (!IsString()) return false;
189 return StringShape(String::cast(this)).IsSequential();
190}
191
192
193bool Object::IsSeqAsciiString() {
194 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000195 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000196 String::cast(this)->IsAsciiRepresentation();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000197}
198
199
200bool Object::IsSeqTwoByteString() {
201 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000202 return StringShape(String::cast(this)).IsSequential() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000203 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204}
205
206
207bool Object::IsExternalString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000208 if (!IsString()) return false;
209 return StringShape(String::cast(this)).IsExternal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210}
211
212
213bool Object::IsExternalAsciiString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000214 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000215 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000216 String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217}
218
219
220bool Object::IsExternalTwoByteString() {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000221 if (!IsString()) return false;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000222 return StringShape(String::cast(this)).IsExternal() &&
ager@chromium.org5ec48922009-05-05 07:25:34 +0000223 String::cast(this)->IsTwoByteRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224}
225
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000226bool Object::HasValidElements() {
227 // Dictionary is covered under FixedArray.
228 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
229}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230
ager@chromium.org870a0b62008-11-04 11:43:05 +0000231StringShape::StringShape(String* str)
232 : type_(str->map()->instance_type()) {
233 set_valid();
234 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235}
236
237
ager@chromium.org870a0b62008-11-04 11:43:05 +0000238StringShape::StringShape(Map* map)
239 : type_(map->instance_type()) {
240 set_valid();
241 ASSERT((type_ & kIsNotStringMask) == kStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000242}
243
244
ager@chromium.org870a0b62008-11-04 11:43:05 +0000245StringShape::StringShape(InstanceType t)
246 : type_(static_cast<uint32_t>(t)) {
247 set_valid();
248 ASSERT((type_ & kIsNotStringMask) == kStringTag);
249}
250
251
252bool StringShape::IsSymbol() {
253 ASSERT(valid());
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000254 ASSERT(kSymbolTag != 0);
255 return (type_ & kIsSymbolMask) != 0;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000256}
257
258
ager@chromium.org5ec48922009-05-05 07:25:34 +0000259bool String::IsAsciiRepresentation() {
260 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000261 return (type & kStringEncodingMask) == kAsciiStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000262}
263
264
ager@chromium.org5ec48922009-05-05 07:25:34 +0000265bool String::IsTwoByteRepresentation() {
266 uint32_t type = map()->instance_type();
ager@chromium.org5ec48922009-05-05 07:25:34 +0000267 return (type & kStringEncodingMask) == kTwoByteStringTag;
ager@chromium.org870a0b62008-11-04 11:43:05 +0000268}
269
270
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000271bool String::HasOnlyAsciiChars() {
272 uint32_t type = map()->instance_type();
273 return (type & kStringEncodingMask) == kAsciiStringTag ||
274 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000275}
276
277
ager@chromium.org870a0b62008-11-04 11:43:05 +0000278bool StringShape::IsCons() {
279 return (type_ & kStringRepresentationMask) == kConsStringTag;
280}
281
282
ager@chromium.org870a0b62008-11-04 11:43:05 +0000283bool StringShape::IsExternal() {
284 return (type_ & kStringRepresentationMask) == kExternalStringTag;
285}
286
287
288bool StringShape::IsSequential() {
289 return (type_ & kStringRepresentationMask) == kSeqStringTag;
290}
291
292
293StringRepresentationTag StringShape::representation_tag() {
294 uint32_t tag = (type_ & kStringRepresentationMask);
295 return static_cast<StringRepresentationTag>(tag);
296}
297
298
299uint32_t StringShape::full_representation_tag() {
300 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
301}
302
303
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000304STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
305 Internals::kFullStringRepresentationMask);
306
307
ager@chromium.org870a0b62008-11-04 11:43:05 +0000308bool StringShape::IsSequentialAscii() {
309 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
310}
311
312
313bool StringShape::IsSequentialTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000314 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000315}
316
317
318bool StringShape::IsExternalAscii() {
319 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
320}
321
322
323bool StringShape::IsExternalTwoByte() {
ager@chromium.org80787b72009-04-17 10:24:24 +0000324 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000325}
326
327
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000328STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
329 Internals::kExternalTwoByteRepresentationTag);
330
331
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000332uc32 FlatStringReader::Get(int index) {
333 ASSERT(0 <= index && index <= length_);
334 if (is_ascii_) {
335 return static_cast<const byte*>(start_)[index];
336 } else {
337 return static_cast<const uc16*>(start_)[index];
338 }
339}
340
341
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342bool Object::IsNumber() {
343 return IsSmi() || IsHeapNumber();
344}
345
346
347bool Object::IsByteArray() {
348 return Object::IsHeapObject()
349 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
350}
351
352
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000353bool Object::IsExternalPixelArray() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000354 return Object::IsHeapObject() &&
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000355 HeapObject::cast(this)->map()->instance_type() ==
356 EXTERNAL_PIXEL_ARRAY_TYPE;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000357}
358
359
ager@chromium.org3811b432009-10-28 14:53:37 +0000360bool Object::IsExternalArray() {
361 if (!Object::IsHeapObject())
362 return false;
363 InstanceType instance_type =
364 HeapObject::cast(this)->map()->instance_type();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000365 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
366 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
ager@chromium.org3811b432009-10-28 14:53:37 +0000367}
368
369
370bool Object::IsExternalByteArray() {
371 return Object::IsHeapObject() &&
372 HeapObject::cast(this)->map()->instance_type() ==
373 EXTERNAL_BYTE_ARRAY_TYPE;
374}
375
376
377bool Object::IsExternalUnsignedByteArray() {
378 return Object::IsHeapObject() &&
379 HeapObject::cast(this)->map()->instance_type() ==
380 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
381}
382
383
384bool Object::IsExternalShortArray() {
385 return Object::IsHeapObject() &&
386 HeapObject::cast(this)->map()->instance_type() ==
387 EXTERNAL_SHORT_ARRAY_TYPE;
388}
389
390
391bool Object::IsExternalUnsignedShortArray() {
392 return Object::IsHeapObject() &&
393 HeapObject::cast(this)->map()->instance_type() ==
394 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
395}
396
397
398bool Object::IsExternalIntArray() {
399 return Object::IsHeapObject() &&
400 HeapObject::cast(this)->map()->instance_type() ==
401 EXTERNAL_INT_ARRAY_TYPE;
402}
403
404
405bool Object::IsExternalUnsignedIntArray() {
406 return Object::IsHeapObject() &&
407 HeapObject::cast(this)->map()->instance_type() ==
408 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
409}
410
411
412bool Object::IsExternalFloatArray() {
413 return Object::IsHeapObject() &&
414 HeapObject::cast(this)->map()->instance_type() ==
415 EXTERNAL_FLOAT_ARRAY_TYPE;
416}
417
418
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000419bool Object::IsExternalDoubleArray() {
420 return Object::IsHeapObject() &&
421 HeapObject::cast(this)->map()->instance_type() ==
422 EXTERNAL_DOUBLE_ARRAY_TYPE;
423}
424
425
lrn@chromium.org303ada72010-10-27 09:33:13 +0000426bool MaybeObject::IsFailure() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 return HAS_FAILURE_TAG(this);
428}
429
430
lrn@chromium.org303ada72010-10-27 09:33:13 +0000431bool MaybeObject::IsRetryAfterGC() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 return HAS_FAILURE_TAG(this)
433 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
434}
435
436
lrn@chromium.org303ada72010-10-27 09:33:13 +0000437bool MaybeObject::IsOutOfMemory() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000438 return HAS_FAILURE_TAG(this)
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000439 && Failure::cast(this)->IsOutOfMemoryException();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000440}
441
442
lrn@chromium.org303ada72010-10-27 09:33:13 +0000443bool MaybeObject::IsException() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444 return this == Failure::Exception();
445}
446
447
lrn@chromium.org303ada72010-10-27 09:33:13 +0000448bool MaybeObject::IsTheHole() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000449 return !IsFailure() && ToObjectUnchecked()->IsTheHole();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000450}
451
452
453Failure* Failure::cast(MaybeObject* obj) {
454 ASSERT(HAS_FAILURE_TAG(obj));
455 return reinterpret_cast<Failure*>(obj);
456}
457
458
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000459bool Object::IsJSReceiver() {
460 return IsHeapObject() &&
461 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
462}
463
464
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000465bool Object::IsJSObject() {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000466 return IsJSReceiver() && !IsJSProxy();
467}
468
469
470bool Object::IsJSProxy() {
471 return Object::IsHeapObject() &&
472 (HeapObject::cast(this)->map()->instance_type() == JS_PROXY_TYPE ||
473 HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_PROXY_TYPE);
474}
475
476
477bool Object::IsJSFunctionProxy() {
478 return Object::IsHeapObject() &&
479 HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_PROXY_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000480}
481
482
ager@chromium.org32912102009-01-16 10:38:43 +0000483bool Object::IsJSContextExtensionObject() {
484 return IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000485 && (HeapObject::cast(this)->map()->instance_type() ==
486 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
ager@chromium.org32912102009-01-16 10:38:43 +0000487}
488
489
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490bool Object::IsMap() {
491 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000492 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493}
494
495
496bool Object::IsFixedArray() {
497 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000498 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499}
500
501
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000502bool Object::IsFixedDoubleArray() {
503 return Object::IsHeapObject()
504 && HeapObject::cast(this)->map()->instance_type() ==
505 FIXED_DOUBLE_ARRAY_TYPE;
506}
507
508
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509bool Object::IsDescriptorArray() {
510 return IsFixedArray();
511}
512
513
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514bool Object::IsDeoptimizationInputData() {
515 // Must be a fixed array.
516 if (!IsFixedArray()) return false;
517
518 // There's no sure way to detect the difference between a fixed array and
519 // a deoptimization data array. Since this is used for asserts we can
520 // check that the length is zero or else the fixed size plus a multiple of
521 // the entry size.
522 int length = FixedArray::cast(this)->length();
523 if (length == 0) return true;
524
525 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
526 return length >= 0 &&
527 length % DeoptimizationInputData::kDeoptEntrySize == 0;
528}
529
530
531bool Object::IsDeoptimizationOutputData() {
532 if (!IsFixedArray()) return false;
533 // There's actually no way to see the difference between a fixed array and
534 // a deoptimization data array. Since this is used for asserts we can check
535 // that the length is plausible though.
536 if (FixedArray::cast(this)->length() % 2 != 0) return false;
537 return true;
538}
539
540
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000541bool Object::IsContext() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542 if (Object::IsHeapObject()) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000543 Map* map = HeapObject::cast(this)->map();
544 Heap* heap = map->GetHeap();
545 return (map == heap->function_context_map() ||
546 map == heap->catch_context_map() ||
547 map == heap->with_context_map() ||
548 map == heap->global_context_map());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000549 }
550 return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551}
552
553
554bool Object::IsGlobalContext() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000555 return Object::IsHeapObject() &&
556 HeapObject::cast(this)->map() ==
557 HeapObject::cast(this)->GetHeap()->global_context_map();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558}
559
560
561bool Object::IsJSFunction() {
562 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000563 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564}
565
566
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000567template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 return obj->IsJSFunction();
569}
570
571
572bool Object::IsCode() {
573 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000574 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000575}
576
577
578bool Object::IsOddball() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000579 ASSERT(HEAP->is_safe_to_read_maps());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 return Object::IsHeapObject()
581 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
582}
583
584
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000585bool Object::IsJSGlobalPropertyCell() {
586 return Object::IsHeapObject()
587 && HeapObject::cast(this)->map()->instance_type()
588 == JS_GLOBAL_PROPERTY_CELL_TYPE;
589}
590
591
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592bool Object::IsSharedFunctionInfo() {
593 return Object::IsHeapObject() &&
594 (HeapObject::cast(this)->map()->instance_type() ==
595 SHARED_FUNCTION_INFO_TYPE);
596}
597
598
599bool Object::IsJSValue() {
600 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000601 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
602}
603
604
605bool Object::IsJSMessageObject() {
606 return Object::IsHeapObject()
607 && (HeapObject::cast(this)->map()->instance_type() ==
608 JS_MESSAGE_OBJECT_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609}
610
611
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000612bool Object::IsStringWrapper() {
613 return IsJSValue() && JSValue::cast(this)->value()->IsString();
614}
615
616
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000617bool Object::IsForeign() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618 return Object::IsHeapObject()
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000619 && HeapObject::cast(this)->map()->instance_type() == FOREIGN_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000620}
621
622
623bool Object::IsBoolean() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000624 return IsOddball() &&
625 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626}
627
628
629bool Object::IsJSArray() {
630 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000631 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000632}
633
634
ager@chromium.org236ad962008-09-25 09:45:57 +0000635bool Object::IsJSRegExp() {
636 return Object::IsHeapObject()
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000637 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
ager@chromium.org236ad962008-09-25 09:45:57 +0000638}
639
640
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000641template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000642 return obj->IsJSArray();
643}
644
645
646bool Object::IsHashTable() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000647 return Object::IsHeapObject() &&
648 HeapObject::cast(this)->map() ==
649 HeapObject::cast(this)->GetHeap()->hash_table_map();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650}
651
652
653bool Object::IsDictionary() {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000654 return IsHashTable() &&
655 this != HeapObject::cast(this)->GetHeap()->symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000656}
657
658
659bool Object::IsSymbolTable() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000660 return IsHashTable() && this ==
661 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662}
663
664
ager@chromium.orgac091b72010-05-05 07:34:42 +0000665bool Object::IsJSFunctionResultCache() {
666 if (!IsFixedArray()) return false;
667 FixedArray* self = FixedArray::cast(this);
668 int length = self->length();
669 if (length < JSFunctionResultCache::kEntriesIndex) return false;
670 if ((length - JSFunctionResultCache::kEntriesIndex)
671 % JSFunctionResultCache::kEntrySize != 0) {
672 return false;
673 }
674#ifdef DEBUG
675 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
676#endif
677 return true;
678}
679
680
ricow@chromium.org65fae842010-08-25 15:26:24 +0000681bool Object::IsNormalizedMapCache() {
682 if (!IsFixedArray()) return false;
683 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
684 return false;
685 }
686#ifdef DEBUG
687 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
688#endif
689 return true;
690}
691
692
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000693bool Object::IsCompilationCacheTable() {
694 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000695}
696
697
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000698bool Object::IsCodeCacheHashTable() {
699 return IsHashTable();
700}
701
702
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000703bool Object::IsPolymorphicCodeCacheHashTable() {
704 return IsHashTable();
705}
706
707
ager@chromium.org236ad962008-09-25 09:45:57 +0000708bool Object::IsMapCache() {
709 return IsHashTable();
710}
711
712
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713bool Object::IsPrimitive() {
714 return IsOddball() || IsNumber() || IsString();
715}
716
717
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000718bool Object::IsJSGlobalProxy() {
719 bool result = IsHeapObject() &&
720 (HeapObject::cast(this)->map()->instance_type() ==
721 JS_GLOBAL_PROXY_TYPE);
722 ASSERT(!result || IsAccessCheckNeeded());
723 return result;
724}
725
726
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000727bool Object::IsGlobalObject() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000728 if (!IsHeapObject()) return false;
729
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000730 InstanceType type = HeapObject::cast(this)->map()->instance_type();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000731 return type == JS_GLOBAL_OBJECT_TYPE ||
732 type == JS_BUILTINS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000733}
734
735
736bool Object::IsJSGlobalObject() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737 return IsHeapObject() &&
738 (HeapObject::cast(this)->map()->instance_type() ==
739 JS_GLOBAL_OBJECT_TYPE);
740}
741
742
743bool Object::IsJSBuiltinsObject() {
744 return IsHeapObject() &&
745 (HeapObject::cast(this)->map()->instance_type() ==
746 JS_BUILTINS_OBJECT_TYPE);
747}
748
749
750bool Object::IsUndetectableObject() {
751 return IsHeapObject()
752 && HeapObject::cast(this)->map()->is_undetectable();
753}
754
755
756bool Object::IsAccessCheckNeeded() {
757 return IsHeapObject()
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000758 && HeapObject::cast(this)->map()->is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000759}
760
761
762bool Object::IsStruct() {
763 if (!IsHeapObject()) return false;
764 switch (HeapObject::cast(this)->map()->instance_type()) {
765#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
766 STRUCT_LIST(MAKE_STRUCT_CASE)
767#undef MAKE_STRUCT_CASE
768 default: return false;
769 }
770}
771
772
773#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
774 bool Object::Is##Name() { \
775 return Object::IsHeapObject() \
776 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
777 }
778 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
779#undef MAKE_STRUCT_PREDICATE
780
781
782bool Object::IsUndefined() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000783 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000784}
785
786
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787bool Object::IsNull() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000788 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
789}
790
791
792bool Object::IsTheHole() {
793 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794}
795
796
797bool Object::IsTrue() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000798 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799}
800
801
802bool Object::IsFalse() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000803 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000804}
805
806
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000807bool Object::IsArgumentsMarker() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000808 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000809}
810
811
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812double Object::Number() {
813 ASSERT(IsNumber());
814 return IsSmi()
815 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
816 : reinterpret_cast<HeapNumber*>(this)->value();
817}
818
819
lrn@chromium.org303ada72010-10-27 09:33:13 +0000820MaybeObject* Object::ToSmi() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000821 if (IsSmi()) return this;
822 if (IsHeapNumber()) {
823 double value = HeapNumber::cast(this)->value();
824 int int_value = FastD2I(value);
825 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
826 return Smi::FromInt(int_value);
827 }
828 }
829 return Failure::Exception();
830}
831
832
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000833bool Object::HasSpecificClassOf(String* name) {
834 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
835}
836
837
lrn@chromium.org303ada72010-10-27 09:33:13 +0000838MaybeObject* Object::GetElement(uint32_t index) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000839 // GetElement can trigger a getter which can cause allocation.
840 // This was not always the case. This ASSERT is here to catch
841 // leftover incorrect uses.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000842 ASSERT(HEAP->IsAllocationAllowed());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843 return GetElementWithReceiver(this, index);
844}
845
846
lrn@chromium.org303ada72010-10-27 09:33:13 +0000847Object* Object::GetElementNoExceptionThrown(uint32_t index) {
848 MaybeObject* maybe = GetElementWithReceiver(this, index);
849 ASSERT(!maybe->IsFailure());
850 Object* result = NULL; // Initialization to please compiler.
851 maybe->ToObject(&result);
852 return result;
853}
854
855
856MaybeObject* Object::GetProperty(String* key) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857 PropertyAttributes attributes;
858 return GetPropertyWithReceiver(this, key, &attributes);
859}
860
861
lrn@chromium.org303ada72010-10-27 09:33:13 +0000862MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000863 return GetPropertyWithReceiver(this, key, attributes);
864}
865
866
867#define FIELD_ADDR(p, offset) \
868 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
869
870#define READ_FIELD(p, offset) \
871 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
872
873#define WRITE_FIELD(p, offset, value) \
874 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
875
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000876// TODO(isolates): Pass heap in to these macros.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877#define WRITE_BARRIER(object, offset) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000878 object->GetHeap()->RecordWrite(object->address(), offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000880// CONDITIONAL_WRITE_BARRIER must be issued after the actual
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000881// write due to the assert validating the written value.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000882#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, mode) \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000883 if (mode == UPDATE_WRITE_BARRIER) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000884 heap->RecordWrite(object->address(), offset); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000885 } else { \
886 ASSERT(mode == SKIP_WRITE_BARRIER); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000887 ASSERT(heap->InNewSpace(object) || \
888 !heap->InNewSpace(READ_FIELD(object, offset)) || \
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000889 Page::FromAddress(object->address())-> \
890 IsRegionDirty(object->address() + offset)); \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000891 }
892
lrn@chromium.org7516f052011-03-30 08:52:27 +0000893#ifndef V8_TARGET_ARCH_MIPS
894 #define READ_DOUBLE_FIELD(p, offset) \
895 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
896#else // V8_TARGET_ARCH_MIPS
897 // Prevent gcc from using load-double (mips ldc1) on (possibly)
898 // non-64-bit aligned HeapNumber::value.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000899 static inline double read_double_field(void* p, int offset) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000900 union conversion {
901 double d;
902 uint32_t u[2];
903 } c;
904 c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
905 c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
906 return c.d;
907 }
908 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
909#endif // V8_TARGET_ARCH_MIPS
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910
lrn@chromium.org7516f052011-03-30 08:52:27 +0000911
912#ifndef V8_TARGET_ARCH_MIPS
913 #define WRITE_DOUBLE_FIELD(p, offset, value) \
914 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
915#else // V8_TARGET_ARCH_MIPS
916 // Prevent gcc from using store-double (mips sdc1) on (possibly)
917 // non-64-bit aligned HeapNumber::value.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000918 static inline void write_double_field(void* p, int offset,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000919 double value) {
920 union conversion {
921 double d;
922 uint32_t u[2];
923 } c;
924 c.d = value;
925 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
926 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
927 }
928 #define WRITE_DOUBLE_FIELD(p, offset, value) \
929 write_double_field(p, offset, value)
930#endif // V8_TARGET_ARCH_MIPS
931
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000932
933#define READ_INT_FIELD(p, offset) \
934 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
935
936#define WRITE_INT_FIELD(p, offset, value) \
937 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
938
ager@chromium.org3e875802009-06-29 08:26:34 +0000939#define READ_INTPTR_FIELD(p, offset) \
940 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
941
942#define WRITE_INTPTR_FIELD(p, offset, value) \
943 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
944
ager@chromium.org7c537e22008-10-16 08:43:32 +0000945#define READ_UINT32_FIELD(p, offset) \
946 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
947
948#define WRITE_UINT32_FIELD(p, offset, value) \
949 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
950
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000951#define READ_SHORT_FIELD(p, offset) \
952 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
953
954#define WRITE_SHORT_FIELD(p, offset, value) \
955 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
956
957#define READ_BYTE_FIELD(p, offset) \
958 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
959
960#define WRITE_BYTE_FIELD(p, offset, value) \
961 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
962
963
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000964Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
965 return &READ_FIELD(obj, byte_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000966}
967
968
969int Smi::value() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000970 return Internals::SmiValue(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000971}
972
973
974Smi* Smi::FromInt(int value) {
975 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000976 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
ager@chromium.org9085a012009-05-11 19:22:57 +0000977 intptr_t tagged_value =
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000978 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
ager@chromium.org9085a012009-05-11 19:22:57 +0000979 return reinterpret_cast<Smi*>(tagged_value);
980}
981
982
983Smi* Smi::FromIntptr(intptr_t value) {
984 ASSERT(Smi::IsValid(value));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000985 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
986 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000987}
988
989
990Failure::Type Failure::type() const {
991 return static_cast<Type>(value() & kFailureTypeTagMask);
992}
993
994
995bool Failure::IsInternalError() const {
996 return type() == INTERNAL_ERROR;
997}
998
999
1000bool Failure::IsOutOfMemoryException() const {
1001 return type() == OUT_OF_MEMORY_EXCEPTION;
1002}
1003
1004
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001005AllocationSpace Failure::allocation_space() const {
1006 ASSERT_EQ(RETRY_AFTER_GC, type());
1007 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1008 & kSpaceTagMask);
1009}
1010
1011
1012Failure* Failure::InternalError() {
1013 return Construct(INTERNAL_ERROR);
1014}
1015
1016
1017Failure* Failure::Exception() {
1018 return Construct(EXCEPTION);
1019}
1020
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +00001021
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001022Failure* Failure::OutOfMemoryException() {
1023 return Construct(OUT_OF_MEMORY_EXCEPTION);
1024}
1025
1026
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001027intptr_t Failure::value() const {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001028 return static_cast<intptr_t>(
1029 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001030}
1031
1032
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001033Failure* Failure::RetryAfterGC() {
1034 return RetryAfterGC(NEW_SPACE);
1035}
1036
1037
1038Failure* Failure::RetryAfterGC(AllocationSpace space) {
1039 ASSERT((space & ~kSpaceTagMask) == 0);
1040 return Construct(RETRY_AFTER_GC, space);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001041}
1042
1043
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001044Failure* Failure::Construct(Type type, intptr_t value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001045 uintptr_t info =
1046 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001047 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001048 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049}
1050
1051
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001052bool Smi::IsValid(intptr_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001053#ifdef DEBUG
1054 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1055#endif
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001056
1057#ifdef V8_TARGET_ARCH_X64
1058 // To be representable as a long smi, the value must be a 32-bit integer.
1059 bool result = (value == static_cast<int32_t>(value));
1060#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061 // To be representable as an tagged small integer, the two
1062 // most-significant bits of 'value' must be either 00 or 11 due to
1063 // sign-extension. To check this we add 01 to the two
1064 // most-significant bits, and check if the most-significant bit is 0
1065 //
1066 // CAUTION: The original code below:
1067 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1068 // may lead to incorrect results according to the C language spec, and
1069 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1070 // compiler may produce undefined results in case of signed integer
1071 // overflow. The computation must be done w/ unsigned ints.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001072 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
ager@chromium.org9085a012009-05-11 19:22:57 +00001073#endif
ager@chromium.org9085a012009-05-11 19:22:57 +00001074 ASSERT(result == in_range);
1075 return result;
1076}
1077
1078
kasper.lund7276f142008-07-30 08:49:36 +00001079MapWord MapWord::FromMap(Map* map) {
1080 return MapWord(reinterpret_cast<uintptr_t>(map));
1081}
1082
1083
1084Map* MapWord::ToMap() {
1085 return reinterpret_cast<Map*>(value_);
1086}
1087
1088
1089bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001090 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +00001091}
1092
1093
1094MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001095 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1096 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +00001097}
1098
1099
1100HeapObject* MapWord::ToForwardingAddress() {
1101 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +00001102 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +00001103}
1104
1105
1106bool MapWord::IsMarked() {
1107 return (value_ & kMarkingMask) == 0;
1108}
1109
1110
1111void MapWord::SetMark() {
1112 value_ &= ~kMarkingMask;
1113}
1114
1115
1116void MapWord::ClearMark() {
1117 value_ |= kMarkingMask;
1118}
1119
1120
1121bool MapWord::IsOverflowed() {
1122 return (value_ & kOverflowMask) != 0;
1123}
1124
1125
1126void MapWord::SetOverflow() {
1127 value_ |= kOverflowMask;
1128}
1129
1130
1131void MapWord::ClearOverflow() {
1132 value_ &= ~kOverflowMask;
1133}
1134
1135
1136MapWord MapWord::EncodeAddress(Address map_address, int offset) {
1137 // Offset is the distance in live bytes from the first live object in the
1138 // same page. The offset between two objects in the same page should not
1139 // exceed the object area size of a page.
1140 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
1141
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001142 uintptr_t compact_offset = offset >> kObjectAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001143 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1144
1145 Page* map_page = Page::FromAddress(map_address);
1146 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1147
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001148 uintptr_t map_page_offset =
1149 map_page->Offset(map_address) >> kMapAlignmentBits;
kasper.lund7276f142008-07-30 08:49:36 +00001150
1151 uintptr_t encoding =
1152 (compact_offset << kForwardingOffsetShift) |
1153 (map_page_offset << kMapPageOffsetShift) |
1154 (map_page->mc_page_index << kMapPageIndexShift);
1155 return MapWord(encoding);
1156}
1157
1158
1159Address MapWord::DecodeMapAddress(MapSpace* map_space) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001160 int map_page_index =
1161 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
kasper.lund7276f142008-07-30 08:49:36 +00001162 ASSERT_MAP_PAGE_INDEX(map_page_index);
1163
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001164 int map_page_offset = static_cast<int>(
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001165 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1166 kMapAlignmentBits);
kasper.lund7276f142008-07-30 08:49:36 +00001167
1168 return (map_space->PageAddress(map_page_index) + map_page_offset);
1169}
1170
1171
1172int MapWord::DecodeOffset() {
1173 // The offset field is represented in the kForwardingOffsetBits
1174 // most-significant bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001175 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1176 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1177 return static_cast<int>(offset);
kasper.lund7276f142008-07-30 08:49:36 +00001178}
1179
1180
1181MapWord MapWord::FromEncodedAddress(Address address) {
1182 return MapWord(reinterpret_cast<uintptr_t>(address));
1183}
1184
1185
1186Address MapWord::ToEncodedAddress() {
1187 return reinterpret_cast<Address>(value_);
1188}
1189
1190
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001191#ifdef DEBUG
1192void HeapObject::VerifyObjectField(int offset) {
1193 VerifyPointer(READ_FIELD(this, offset));
1194}
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001195
1196void HeapObject::VerifySmiField(int offset) {
1197 ASSERT(READ_FIELD(this, offset)->IsSmi());
1198}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001199#endif
1200
1201
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001202Heap* HeapObject::GetHeap() {
1203 // During GC, the map pointer in HeapObject is used in various ways that
1204 // prevent us from retrieving Heap from the map.
1205 // Assert that we are not in GC, implement GC code in a way that it doesn't
1206 // pull heap from the map.
1207 ASSERT(HEAP->is_safe_to_read_maps());
1208 return map()->heap();
1209}
1210
1211
1212Isolate* HeapObject::GetIsolate() {
1213 return GetHeap()->isolate();
1214}
1215
1216
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001217Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +00001218 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001219}
1220
1221
1222void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +00001223 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001224}
1225
1226
kasper.lund7276f142008-07-30 08:49:36 +00001227MapWord HeapObject::map_word() {
1228 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1229}
1230
1231
1232void HeapObject::set_map_word(MapWord map_word) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001233 // WRITE_FIELD does not invoke write barrier, but there is no need
kasper.lund7276f142008-07-30 08:49:36 +00001234 // here.
1235 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1236}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001237
1238
1239HeapObject* HeapObject::FromAddress(Address address) {
1240 ASSERT_TAG_ALIGNED(address);
1241 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1242}
1243
1244
1245Address HeapObject::address() {
1246 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1247}
1248
1249
1250int HeapObject::Size() {
1251 return SizeFromMap(map());
1252}
1253
1254
1255void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1256 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1257 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1258}
1259
1260
1261void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1262 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1263}
1264
1265
kasper.lund7276f142008-07-30 08:49:36 +00001266bool HeapObject::IsMarked() {
1267 return map_word().IsMarked();
1268}
1269
1270
1271void HeapObject::SetMark() {
1272 ASSERT(!IsMarked());
1273 MapWord first_word = map_word();
1274 first_word.SetMark();
1275 set_map_word(first_word);
1276}
1277
1278
1279void HeapObject::ClearMark() {
1280 ASSERT(IsMarked());
1281 MapWord first_word = map_word();
1282 first_word.ClearMark();
1283 set_map_word(first_word);
1284}
1285
1286
1287bool HeapObject::IsOverflowed() {
1288 return map_word().IsOverflowed();
1289}
1290
1291
1292void HeapObject::SetOverflow() {
1293 MapWord first_word = map_word();
1294 first_word.SetOverflow();
1295 set_map_word(first_word);
1296}
1297
1298
1299void HeapObject::ClearOverflow() {
1300 ASSERT(IsOverflowed());
1301 MapWord first_word = map_word();
1302 first_word.ClearOverflow();
1303 set_map_word(first_word);
1304}
1305
1306
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001307double HeapNumber::value() {
1308 return READ_DOUBLE_FIELD(this, kValueOffset);
1309}
1310
1311
1312void HeapNumber::set_value(double value) {
1313 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1314}
1315
1316
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001317int HeapNumber::get_exponent() {
1318 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1319 kExponentShift) - kExponentBias;
1320}
1321
1322
1323int HeapNumber::get_sign() {
1324 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1325}
1326
1327
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001328ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001329
1330
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001331HeapObject* JSObject::elements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001332 Object* array = READ_FIELD(this, kElementsOffset);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001333 ASSERT(array->HasValidElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001334 return reinterpret_cast<HeapObject*>(array);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001335}
1336
1337
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001338void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001339 ASSERT(map()->has_fast_elements() ==
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001340 (value->map() == GetHeap()->fixed_array_map() ||
1341 value->map() == GetHeap()->fixed_cow_array_map()));
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +00001342 ASSERT(map()->has_fast_double_elements() ==
1343 value->IsFixedDoubleArray());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001344 ASSERT(value->HasValidElements());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001345 WRITE_FIELD(this, kElementsOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001346 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, mode);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001347}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001348
1349
1350void JSObject::initialize_properties() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001351 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1352 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353}
1354
1355
1356void JSObject::initialize_elements() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001357 ASSERT(map()->has_fast_elements());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001358 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1359 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001360}
1361
1362
lrn@chromium.org303ada72010-10-27 09:33:13 +00001363MaybeObject* JSObject::ResetElements() {
1364 Object* obj;
1365 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
1366 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1367 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001368 set_map(Map::cast(obj));
1369 initialize_elements();
1370 return this;
1371}
1372
1373
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001374ACCESSORS(Oddball, to_string, String, kToStringOffset)
1375ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1376
1377
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001378byte Oddball::kind() {
1379 return READ_BYTE_FIELD(this, kKindOffset);
1380}
1381
1382
1383void Oddball::set_kind(byte value) {
1384 WRITE_BYTE_FIELD(this, kKindOffset, value);
1385}
1386
1387
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001388Object* JSGlobalPropertyCell::value() {
1389 return READ_FIELD(this, kValueOffset);
1390}
1391
1392
1393void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1394 // The write barrier is not used for global property cells.
1395 ASSERT(!val->IsJSGlobalPropertyCell());
1396 WRITE_FIELD(this, kValueOffset, val);
1397}
1398
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001399
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001400int JSObject::GetHeaderSize() {
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001401 InstanceType type = map()->instance_type();
1402 // Check for the most common kind of JavaScript object before
1403 // falling into the generic switch. This speeds up the internal
1404 // field operations considerably on average.
1405 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1406 switch (type) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001407 case JS_GLOBAL_PROXY_TYPE:
1408 return JSGlobalProxy::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001409 case JS_GLOBAL_OBJECT_TYPE:
1410 return JSGlobalObject::kSize;
1411 case JS_BUILTINS_OBJECT_TYPE:
1412 return JSBuiltinsObject::kSize;
1413 case JS_FUNCTION_TYPE:
1414 return JSFunction::kSize;
1415 case JS_VALUE_TYPE:
1416 return JSValue::kSize;
1417 case JS_ARRAY_TYPE:
1418 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +00001419 case JS_REGEXP_TYPE:
1420 return JSValue::kSize;
ager@chromium.org32912102009-01-16 10:38:43 +00001421 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001422 return JSObject::kHeaderSize;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001423 case JS_MESSAGE_OBJECT_TYPE:
1424 return JSMessageObject::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001425 default:
1426 UNREACHABLE();
1427 return 0;
1428 }
1429}
1430
1431
1432int JSObject::GetInternalFieldCount() {
1433 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001434 // Make sure to adjust for the number of in-object properties. These
1435 // properties do contribute to the size, but are not internal fields.
1436 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1437 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001438}
1439
1440
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001441int JSObject::GetInternalFieldOffset(int index) {
1442 ASSERT(index < GetInternalFieldCount() && index >= 0);
1443 return GetHeaderSize() + (kPointerSize * index);
1444}
1445
1446
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001447Object* JSObject::GetInternalField(int index) {
1448 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001449 // Internal objects do follow immediately after the header, whereas in-object
1450 // properties are at the end of the object. Therefore there is no need
1451 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001452 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1453}
1454
1455
1456void JSObject::SetInternalField(int index, Object* value) {
1457 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001458 // Internal objects do follow immediately after the header, whereas in-object
1459 // properties are at the end of the object. Therefore there is no need
1460 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461 int offset = GetHeaderSize() + (kPointerSize * index);
1462 WRITE_FIELD(this, offset, value);
1463 WRITE_BARRIER(this, offset);
1464}
1465
1466
ager@chromium.org7c537e22008-10-16 08:43:32 +00001467// Access fast-case object properties at index. The use of these routines
1468// is needed to correctly distinguish between properties stored in-object and
1469// properties stored in the properties array.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001470Object* JSObject::FastPropertyAt(int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001471 // Adjust for the number of properties stored in the object.
1472 index -= map()->inobject_properties();
1473 if (index < 0) {
1474 int offset = map()->instance_size() + (index * kPointerSize);
1475 return READ_FIELD(this, offset);
1476 } else {
1477 ASSERT(index < properties()->length());
1478 return properties()->get(index);
1479 }
1480}
1481
1482
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001483Object* JSObject::FastPropertyAtPut(int index, Object* value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001484 // Adjust for the number of properties stored in the object.
1485 index -= map()->inobject_properties();
1486 if (index < 0) {
1487 int offset = map()->instance_size() + (index * kPointerSize);
1488 WRITE_FIELD(this, offset, value);
1489 WRITE_BARRIER(this, offset);
1490 } else {
1491 ASSERT(index < properties()->length());
1492 properties()->set(index, value);
1493 }
1494 return value;
1495}
1496
1497
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001498int JSObject::GetInObjectPropertyOffset(int index) {
1499 // Adjust for the number of properties stored in the object.
1500 index -= map()->inobject_properties();
1501 ASSERT(index < 0);
1502 return map()->instance_size() + (index * kPointerSize);
1503}
1504
1505
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001506Object* JSObject::InObjectPropertyAt(int index) {
1507 // Adjust for the number of properties stored in the object.
1508 index -= map()->inobject_properties();
1509 ASSERT(index < 0);
1510 int offset = map()->instance_size() + (index * kPointerSize);
1511 return READ_FIELD(this, offset);
1512}
1513
1514
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001515Object* JSObject::InObjectPropertyAtPut(int index,
1516 Object* value,
1517 WriteBarrierMode mode) {
1518 // Adjust for the number of properties stored in the object.
1519 index -= map()->inobject_properties();
1520 ASSERT(index < 0);
1521 int offset = map()->instance_size() + (index * kPointerSize);
1522 WRITE_FIELD(this, offset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001523 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001524 return value;
1525}
1526
1527
1528
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001529void JSObject::InitializeBody(int object_size, Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001530 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001531 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001532 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001533 }
1534}
1535
1536
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001537bool JSObject::HasFastProperties() {
1538 return !properties()->IsDictionary();
1539}
1540
1541
1542int JSObject::MaxFastProperties() {
1543 // Allow extra fast properties if the object has more than
1544 // kMaxFastProperties in-object properties. When this is the case,
1545 // it is very unlikely that the object is being used as a dictionary
1546 // and there is a good chance that allowing more map transitions
1547 // will be worth it.
1548 return Max(map()->inobject_properties(), kMaxFastProperties);
1549}
1550
1551
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552void Struct::InitializeBody(int object_size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001553 Object* value = GetHeap()->undefined_value();
ager@chromium.org236ad962008-09-25 09:45:57 +00001554 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001555 WRITE_FIELD(this, offset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556 }
1557}
1558
1559
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001560bool Object::ToArrayIndex(uint32_t* index) {
1561 if (IsSmi()) {
1562 int value = Smi::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001563 if (value < 0) return false;
1564 *index = value;
1565 return true;
1566 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001567 if (IsHeapNumber()) {
1568 double value = HeapNumber::cast(this)->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001569 uint32_t uint_value = static_cast<uint32_t>(value);
1570 if (value == static_cast<double>(uint_value)) {
1571 *index = uint_value;
1572 return true;
1573 }
1574 }
1575 return false;
1576}
1577
1578
1579bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1580 if (!this->IsJSValue()) return false;
1581
1582 JSValue* js_value = JSValue::cast(this);
1583 if (!js_value->value()->IsString()) return false;
1584
1585 String* str = String::cast(js_value->value());
1586 if (index >= (uint32_t)str->length()) return false;
1587
1588 return true;
1589}
1590
1591
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001592FixedArrayBase* FixedArrayBase::cast(Object* object) {
1593 ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1594 return reinterpret_cast<FixedArrayBase*>(object);
1595}
1596
1597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001598Object* FixedArray::get(int index) {
1599 ASSERT(index >= 0 && index < this->length());
1600 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1601}
1602
1603
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001604void FixedArray::set(int index, Smi* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001605 ASSERT(map() != HEAP->fixed_cow_array_map());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001606 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1607 int offset = kHeaderSize + index * kPointerSize;
1608 WRITE_FIELD(this, offset, value);
1609}
1610
1611
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612void FixedArray::set(int index, Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001613 ASSERT(map() != HEAP->fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001614 ASSERT(index >= 0 && index < this->length());
1615 int offset = kHeaderSize + index * kPointerSize;
1616 WRITE_FIELD(this, offset, value);
1617 WRITE_BARRIER(this, offset);
1618}
1619
1620
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001621inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1622 return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1623}
1624
1625
1626inline double FixedDoubleArray::hole_nan_as_double() {
1627 return BitCast<double, uint64_t>(kHoleNanInt64);
1628}
1629
1630
1631inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1632 ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1633 ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1634 return OS::nan_value();
1635}
1636
1637
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001638double FixedDoubleArray::get(int index) {
1639 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1640 map() != HEAP->fixed_array_map());
1641 ASSERT(index >= 0 && index < this->length());
1642 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1643 ASSERT(!is_the_hole_nan(result));
1644 return result;
1645}
1646
1647
1648void FixedDoubleArray::set(int index, double value) {
1649 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1650 map() != HEAP->fixed_array_map());
1651 int offset = kHeaderSize + index * kDoubleSize;
1652 if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1653 WRITE_DOUBLE_FIELD(this, offset, value);
1654}
1655
1656
1657void FixedDoubleArray::set_the_hole(int index) {
1658 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1659 map() != HEAP->fixed_array_map());
1660 int offset = kHeaderSize + index * kDoubleSize;
1661 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1662}
1663
1664
1665bool FixedDoubleArray::is_the_hole(int index) {
1666 int offset = kHeaderSize + index * kDoubleSize;
1667 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1668}
1669
1670
1671void FixedDoubleArray::Initialize(FixedDoubleArray* from) {
1672 int old_length = from->length();
1673 ASSERT(old_length < length());
1674 OS::MemCopy(FIELD_ADDR(this, kHeaderSize),
1675 FIELD_ADDR(from, kHeaderSize),
1676 old_length * kDoubleSize);
1677 int offset = kHeaderSize + old_length * kDoubleSize;
1678 for (int current = from->length(); current < length(); ++current) {
1679 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1680 offset += kDoubleSize;
1681 }
1682}
1683
1684
1685void FixedDoubleArray::Initialize(FixedArray* from) {
1686 int old_length = from->length();
1687 ASSERT(old_length < length());
1688 for (int i = 0; i < old_length; i++) {
1689 Object* hole_or_object = from->get(i);
1690 if (hole_or_object->IsTheHole()) {
1691 set_the_hole(i);
1692 } else {
1693 set(i, hole_or_object->Number());
1694 }
1695 }
1696 int offset = kHeaderSize + old_length * kDoubleSize;
1697 for (int current = from->length(); current < length(); ++current) {
1698 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1699 offset += kDoubleSize;
1700 }
1701}
1702
1703
1704void FixedDoubleArray::Initialize(NumberDictionary* from) {
1705 int offset = kHeaderSize;
1706 for (int current = 0; current < length(); ++current) {
1707 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1708 offset += kDoubleSize;
1709 }
1710 for (int i = 0; i < from->Capacity(); i++) {
1711 Object* key = from->KeyAt(i);
1712 if (key->IsNumber()) {
1713 uint32_t entry = static_cast<uint32_t>(key->Number());
1714 set(entry, from->ValueAt(i)->Number());
1715 }
1716 }
1717}
1718
1719
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001720WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001721 if (GetHeap()->InNewSpace(this)) return SKIP_WRITE_BARRIER;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001722 return UPDATE_WRITE_BARRIER;
1723}
1724
1725
1726void FixedArray::set(int index,
1727 Object* value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001728 WriteBarrierMode mode) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001729 ASSERT(map() != HEAP->fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730 ASSERT(index >= 0 && index < this->length());
1731 int offset = kHeaderSize + index * kPointerSize;
1732 WRITE_FIELD(this, offset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001733 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001734}
1735
1736
1737void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001738 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001739 ASSERT(index >= 0 && index < array->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001740 ASSERT(!HEAP->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001741 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1742}
1743
1744
1745void FixedArray::set_undefined(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001746 ASSERT(map() != HEAP->fixed_cow_array_map());
1747 set_undefined(GetHeap(), index);
1748}
1749
1750
1751void FixedArray::set_undefined(Heap* heap, int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001752 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001753 ASSERT(!heap->InNewSpace(heap->undefined_value()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001754 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001755 heap->undefined_value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756}
1757
1758
ager@chromium.org236ad962008-09-25 09:45:57 +00001759void FixedArray::set_null(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001760 set_null(GetHeap(), index);
1761}
1762
1763
1764void FixedArray::set_null(Heap* heap, int index) {
ager@chromium.org236ad962008-09-25 09:45:57 +00001765 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001766 ASSERT(!heap->InNewSpace(heap->null_value()));
1767 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
ager@chromium.org236ad962008-09-25 09:45:57 +00001768}
1769
1770
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001771void FixedArray::set_the_hole(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001772 ASSERT(map() != HEAP->fixed_cow_array_map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001773 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001774 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1775 WRITE_FIELD(this,
1776 kHeaderSize + index * kPointerSize,
1777 GetHeap()->the_hole_value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001778}
1779
1780
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001781void FixedArray::set_unchecked(int index, Smi* value) {
1782 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1783 int offset = kHeaderSize + index * kPointerSize;
1784 WRITE_FIELD(this, offset, value);
1785}
1786
1787
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001788void FixedArray::set_unchecked(Heap* heap,
1789 int index,
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001790 Object* value,
1791 WriteBarrierMode mode) {
1792 int offset = kHeaderSize + index * kPointerSize;
1793 WRITE_FIELD(this, offset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001794 CONDITIONAL_WRITE_BARRIER(heap, this, offset, mode);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001795}
1796
1797
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001798void FixedArray::set_null_unchecked(Heap* heap, int index) {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001799 ASSERT(index >= 0 && index < this->length());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001800 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1801 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001802}
1803
1804
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001805Object** FixedArray::data_start() {
1806 return HeapObject::RawField(this, kHeaderSize);
1807}
1808
1809
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001810bool DescriptorArray::IsEmpty() {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001811 ASSERT(this->IsSmi() ||
1812 this->length() > kFirstIndex ||
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001813 this == HEAP->empty_descriptor_array());
danno@chromium.org40cb8782011-05-25 07:58:50 +00001814 return this->IsSmi() || length() <= kFirstIndex;
1815}
1816
1817
1818int DescriptorArray::bit_field3_storage() {
1819 Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1820 return Smi::cast(storage)->value();
1821}
1822
1823void DescriptorArray::set_bit_field3_storage(int value) {
1824 ASSERT(!IsEmpty());
1825 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001826}
1827
1828
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001829void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1830 Object* tmp = array->get(first);
1831 fast_set(array, first, array->get(second));
1832 fast_set(array, second, tmp);
1833}
1834
1835
1836int DescriptorArray::Search(String* name) {
1837 SLOW_ASSERT(IsSortedNoDuplicates());
1838
1839 // Check for empty descriptor array.
1840 int nof = number_of_descriptors();
1841 if (nof == 0) return kNotFound;
1842
1843 // Fast case: do linear search for small arrays.
1844 const int kMaxElementsForLinearSearch = 8;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001845 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001846 return LinearSearch(name, nof);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001847 }
1848
1849 // Slow case: perform binary search.
1850 return BinarySearch(name, 0, nof - 1);
1851}
1852
1853
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001854int DescriptorArray::SearchWithCache(String* name) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001855 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001856 if (number == DescriptorLookupCache::kAbsent) {
1857 number = Search(name);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001858 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001859 }
1860 return number;
1861}
1862
1863
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001864String* DescriptorArray::GetKey(int descriptor_number) {
1865 ASSERT(descriptor_number < number_of_descriptors());
1866 return String::cast(get(ToKeyIndex(descriptor_number)));
1867}
1868
1869
1870Object* DescriptorArray::GetValue(int descriptor_number) {
1871 ASSERT(descriptor_number < number_of_descriptors());
1872 return GetContentArray()->get(ToValueIndex(descriptor_number));
1873}
1874
1875
1876Smi* DescriptorArray::GetDetails(int descriptor_number) {
1877 ASSERT(descriptor_number < number_of_descriptors());
1878 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1879}
1880
1881
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001882PropertyType DescriptorArray::GetType(int descriptor_number) {
1883 ASSERT(descriptor_number < number_of_descriptors());
1884 return PropertyDetails(GetDetails(descriptor_number)).type();
1885}
1886
1887
1888int DescriptorArray::GetFieldIndex(int descriptor_number) {
1889 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1890}
1891
1892
1893JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1894 return JSFunction::cast(GetValue(descriptor_number));
1895}
1896
1897
1898Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1899 ASSERT(GetType(descriptor_number) == CALLBACKS);
1900 return GetValue(descriptor_number);
1901}
1902
1903
1904AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1905 ASSERT(GetType(descriptor_number) == CALLBACKS);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001906 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
1907 return reinterpret_cast<AccessorDescriptor*>(p->address());
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001908}
1909
1910
1911bool DescriptorArray::IsProperty(int descriptor_number) {
1912 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1913}
1914
1915
1916bool DescriptorArray::IsTransition(int descriptor_number) {
1917 PropertyType t = GetType(descriptor_number);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001918 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
1919 t == EXTERNAL_ARRAY_TRANSITION;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001920}
1921
1922
1923bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1924 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1925}
1926
1927
1928bool DescriptorArray::IsDontEnum(int descriptor_number) {
1929 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1930}
1931
1932
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001933void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1934 desc->Init(GetKey(descriptor_number),
1935 GetValue(descriptor_number),
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001936 PropertyDetails(GetDetails(descriptor_number)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001937}
1938
1939
1940void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1941 // Range check.
1942 ASSERT(descriptor_number < number_of_descriptors());
1943
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001944 // Make sure none of the elements in desc are in new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001945 ASSERT(!HEAP->InNewSpace(desc->GetKey()));
1946 ASSERT(!HEAP->InNewSpace(desc->GetValue()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001947
1948 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1949 FixedArray* content_array = GetContentArray();
1950 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1951 fast_set(content_array, ToDetailsIndex(descriptor_number),
1952 desc->GetDetails().AsSmi());
1953}
1954
1955
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001956void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1957 Descriptor desc;
1958 src->Get(src_index, &desc);
1959 Set(index, &desc);
1960}
1961
1962
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001963void DescriptorArray::Swap(int first, int second) {
1964 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1965 FixedArray* content_array = GetContentArray();
1966 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1967 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1968}
1969
1970
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001971template<typename Shape, typename Key>
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001972int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
1973 const int kMinCapacity = 32;
1974 int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
1975 if (capacity < kMinCapacity) {
1976 capacity = kMinCapacity; // Guarantee min capacity.
1977 }
1978 return capacity;
1979}
1980
1981
1982template<typename Shape, typename Key>
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001983int HashTable<Shape, Key>::FindEntry(Key key) {
1984 return FindEntry(GetIsolate(), key);
1985}
1986
1987
1988// Find entry for key otherwise return kNotFound.
1989template<typename Shape, typename Key>
1990int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
1991 uint32_t capacity = Capacity();
1992 uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
1993 uint32_t count = 1;
1994 // EnsureCapacity will guarantee the hash table is never full.
1995 while (true) {
1996 Object* element = KeyAt(entry);
1997 if (element == isolate->heap()->undefined_value()) break; // Empty entry.
1998 if (element != isolate->heap()->null_value() &&
1999 Shape::IsMatch(key, element)) return entry;
2000 entry = NextProbe(entry, count++, capacity);
2001 }
2002 return kNotFound;
2003}
2004
2005
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002006bool NumberDictionary::requires_slow_elements() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002007 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002008 if (!max_index_object->IsSmi()) return false;
2009 return 0 !=
2010 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2011}
2012
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002013uint32_t NumberDictionary::max_number_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002014 ASSERT(!requires_slow_elements());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002015 Object* max_index_object = get(kMaxNumberKeyIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002016 if (!max_index_object->IsSmi()) return 0;
2017 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2018 return value >> kRequiresSlowElementsTagSize;
2019}
2020
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002021void NumberDictionary::set_requires_slow_elements() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002022 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002023}
2024
2025
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002026// ------------------------------------
2027// Cast operations
2028
2029
2030CAST_ACCESSOR(FixedArray)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002031CAST_ACCESSOR(FixedDoubleArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002032CAST_ACCESSOR(DescriptorArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002033CAST_ACCESSOR(DeoptimizationInputData)
2034CAST_ACCESSOR(DeoptimizationOutputData)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002035CAST_ACCESSOR(SymbolTable)
ager@chromium.orgac091b72010-05-05 07:34:42 +00002036CAST_ACCESSOR(JSFunctionResultCache)
ricow@chromium.org65fae842010-08-25 15:26:24 +00002037CAST_ACCESSOR(NormalizedMapCache)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00002038CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002039CAST_ACCESSOR(CodeCacheHashTable)
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00002040CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00002041CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002042CAST_ACCESSOR(String)
2043CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00002044CAST_ACCESSOR(SeqAsciiString)
2045CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002046CAST_ACCESSOR(ConsString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002047CAST_ACCESSOR(ExternalString)
2048CAST_ACCESSOR(ExternalAsciiString)
2049CAST_ACCESSOR(ExternalTwoByteString)
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002050CAST_ACCESSOR(JSReceiver)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002051CAST_ACCESSOR(JSObject)
2052CAST_ACCESSOR(Smi)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002053CAST_ACCESSOR(HeapObject)
2054CAST_ACCESSOR(HeapNumber)
2055CAST_ACCESSOR(Oddball)
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00002056CAST_ACCESSOR(JSGlobalPropertyCell)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002057CAST_ACCESSOR(SharedFunctionInfo)
2058CAST_ACCESSOR(Map)
2059CAST_ACCESSOR(JSFunction)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002060CAST_ACCESSOR(GlobalObject)
2061CAST_ACCESSOR(JSGlobalProxy)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002062CAST_ACCESSOR(JSGlobalObject)
2063CAST_ACCESSOR(JSBuiltinsObject)
2064CAST_ACCESSOR(Code)
2065CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00002066CAST_ACCESSOR(JSRegExp)
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00002067CAST_ACCESSOR(JSProxy)
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002068CAST_ACCESSOR(JSFunctionProxy)
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002069CAST_ACCESSOR(Foreign)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002070CAST_ACCESSOR(ByteArray)
ager@chromium.org3811b432009-10-28 14:53:37 +00002071CAST_ACCESSOR(ExternalArray)
2072CAST_ACCESSOR(ExternalByteArray)
2073CAST_ACCESSOR(ExternalUnsignedByteArray)
2074CAST_ACCESSOR(ExternalShortArray)
2075CAST_ACCESSOR(ExternalUnsignedShortArray)
2076CAST_ACCESSOR(ExternalIntArray)
2077CAST_ACCESSOR(ExternalUnsignedIntArray)
2078CAST_ACCESSOR(ExternalFloatArray)
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002079CAST_ACCESSOR(ExternalDoubleArray)
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002080CAST_ACCESSOR(ExternalPixelArray)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002081CAST_ACCESSOR(Struct)
2082
2083
2084#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2085 STRUCT_LIST(MAKE_STRUCT_CAST)
2086#undef MAKE_STRUCT_CAST
2087
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002088
2089template <typename Shape, typename Key>
2090HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091 ASSERT(obj->IsHashTable());
2092 return reinterpret_cast<HashTable*>(obj);
2093}
2094
2095
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002096SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002097SMI_ACCESSORS(ByteArray, length, kLengthOffset)
2098
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002099// TODO(1493): Investigate if it's possible to s/INT/SMI/ here (and
whesse@chromium.org7b260152011-06-20 15:33:18 +00002100// subsequently unify H{Fixed,External}ArrayLength).
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002101INT_ACCESSORS(ExternalArray, length, kLengthOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002102
2103
ager@chromium.orgac091b72010-05-05 07:34:42 +00002104SMI_ACCESSORS(String, length, kLengthOffset)
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002105
2106
2107uint32_t String::hash_field() {
2108 return READ_UINT32_FIELD(this, kHashFieldOffset);
2109}
2110
2111
2112void String::set_hash_field(uint32_t value) {
2113 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002114#if V8_HOST_ARCH_64_BIT
2115 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2116#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002117}
2118
2119
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002120bool String::Equals(String* other) {
2121 if (other == this) return true;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002122 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2123 return false;
2124 }
2125 return SlowEquals(other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002126}
2127
2128
lrn@chromium.org303ada72010-10-27 09:33:13 +00002129MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00002130 if (!StringShape(this).IsCons()) return this;
2131 ConsString* cons = ConsString::cast(this);
2132 if (cons->second()->length() == 0) return cons->first();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002133 return SlowTryFlatten(pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002134}
2135
2136
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00002137String* String::TryFlattenGetString(PretenureFlag pretenure) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00002138 MaybeObject* flat = TryFlatten(pretenure);
2139 Object* successfully_flattened;
2140 if (flat->ToObject(&successfully_flattened)) {
2141 return String::cast(successfully_flattened);
2142 }
2143 return this;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00002144}
2145
2146
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002147uint16_t String::Get(int index) {
2148 ASSERT(index >= 0 && index < length());
2149 switch (StringShape(this).full_representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002150 case kSeqStringTag | kAsciiStringTag:
2151 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2152 case kSeqStringTag | kTwoByteStringTag:
2153 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2154 case kConsStringTag | kAsciiStringTag:
2155 case kConsStringTag | kTwoByteStringTag:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002156 return ConsString::cast(this)->ConsStringGet(index);
ager@chromium.org870a0b62008-11-04 11:43:05 +00002157 case kExternalStringTag | kAsciiStringTag:
2158 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2159 case kExternalStringTag | kTwoByteStringTag:
2160 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002161 default:
2162 break;
2163 }
2164
2165 UNREACHABLE();
2166 return 0;
2167}
2168
2169
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002170void String::Set(int index, uint16_t value) {
2171 ASSERT(index >= 0 && index < length());
2172 ASSERT(StringShape(this).IsSequential());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002173
ager@chromium.org5ec48922009-05-05 07:25:34 +00002174 return this->IsAsciiRepresentation()
ager@chromium.org7c537e22008-10-16 08:43:32 +00002175 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2176 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002177}
2178
2179
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002180bool String::IsFlat() {
2181 switch (StringShape(this).representation_tag()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002182 case kConsStringTag: {
2183 String* second = ConsString::cast(this)->second();
ager@chromium.org7c537e22008-10-16 08:43:32 +00002184 // Only flattened strings have second part empty.
ager@chromium.org870a0b62008-11-04 11:43:05 +00002185 return second->length() == 0;
2186 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00002187 default:
2188 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002189 }
2190}
2191
2192
ager@chromium.org7c537e22008-10-16 08:43:32 +00002193uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002194 ASSERT(index >= 0 && index < length());
2195 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2196}
2197
2198
ager@chromium.org7c537e22008-10-16 08:43:32 +00002199void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002200 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2201 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2202 static_cast<byte>(value));
2203}
2204
2205
ager@chromium.org7c537e22008-10-16 08:43:32 +00002206Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002207 return FIELD_ADDR(this, kHeaderSize);
2208}
2209
2210
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002211char* SeqAsciiString::GetChars() {
2212 return reinterpret_cast<char*>(GetCharsAddress());
2213}
2214
2215
ager@chromium.org7c537e22008-10-16 08:43:32 +00002216Address SeqTwoByteString::GetCharsAddress() {
2217 return FIELD_ADDR(this, kHeaderSize);
2218}
2219
2220
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002221uc16* SeqTwoByteString::GetChars() {
2222 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2223}
2224
2225
ager@chromium.org7c537e22008-10-16 08:43:32 +00002226uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002227 ASSERT(index >= 0 && index < length());
2228 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2229}
2230
2231
ager@chromium.org7c537e22008-10-16 08:43:32 +00002232void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002233 ASSERT(index >= 0 && index < length());
2234 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2235}
2236
2237
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002238int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00002239 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002240}
2241
2242
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002243int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
ager@chromium.orgac091b72010-05-05 07:34:42 +00002244 return SizeFor(length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002245}
2246
2247
ager@chromium.org870a0b62008-11-04 11:43:05 +00002248String* ConsString::first() {
2249 return String::cast(READ_FIELD(this, kFirstOffset));
2250}
2251
2252
2253Object* ConsString::unchecked_first() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002254 return READ_FIELD(this, kFirstOffset);
2255}
2256
2257
ager@chromium.org870a0b62008-11-04 11:43:05 +00002258void ConsString::set_first(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259 WRITE_FIELD(this, kFirstOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002260 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002261}
2262
2263
ager@chromium.org870a0b62008-11-04 11:43:05 +00002264String* ConsString::second() {
2265 return String::cast(READ_FIELD(this, kSecondOffset));
2266}
2267
2268
2269Object* ConsString::unchecked_second() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002270 return READ_FIELD(this, kSecondOffset);
2271}
2272
2273
ager@chromium.org870a0b62008-11-04 11:43:05 +00002274void ConsString::set_second(String* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002275 WRITE_FIELD(this, kSecondOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002276 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002277}
2278
2279
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002280ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2281 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2282}
2283
2284
2285void ExternalAsciiString::set_resource(
2286 ExternalAsciiString::Resource* resource) {
2287 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
2288}
2289
2290
2291ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2292 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2293}
2294
2295
2296void ExternalTwoByteString::set_resource(
2297 ExternalTwoByteString::Resource* resource) {
2298 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
2299}
2300
2301
ager@chromium.orgac091b72010-05-05 07:34:42 +00002302void JSFunctionResultCache::MakeZeroSize() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002303 set_finger_index(kEntriesIndex);
2304 set_size(kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002305}
2306
2307
2308void JSFunctionResultCache::Clear() {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002309 int cache_size = size();
ager@chromium.orgac091b72010-05-05 07:34:42 +00002310 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00002311 MemsetPointer(entries_start,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002312 GetHeap()->the_hole_value(),
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00002313 cache_size - kEntriesIndex);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002314 MakeZeroSize();
2315}
2316
2317
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002318int JSFunctionResultCache::size() {
2319 return Smi::cast(get(kCacheSizeIndex))->value();
2320}
2321
2322
2323void JSFunctionResultCache::set_size(int size) {
2324 set(kCacheSizeIndex, Smi::FromInt(size));
2325}
2326
2327
2328int JSFunctionResultCache::finger_index() {
2329 return Smi::cast(get(kFingerIndex))->value();
2330}
2331
2332
2333void JSFunctionResultCache::set_finger_index(int finger_index) {
2334 set(kFingerIndex, Smi::FromInt(finger_index));
2335}
2336
2337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002338byte ByteArray::get(int index) {
2339 ASSERT(index >= 0 && index < this->length());
2340 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2341}
2342
2343
2344void ByteArray::set(int index, byte value) {
2345 ASSERT(index >= 0 && index < this->length());
2346 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2347}
2348
2349
2350int ByteArray::get_int(int index) {
2351 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2352 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2353}
2354
2355
2356ByteArray* ByteArray::FromDataStartAddress(Address address) {
2357 ASSERT_TAG_ALIGNED(address);
2358 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2359}
2360
2361
2362Address ByteArray::GetDataStartAddress() {
2363 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2364}
2365
2366
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002367uint8_t* ExternalPixelArray::external_pixel_pointer() {
2368 return reinterpret_cast<uint8_t*>(external_pointer());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002369}
2370
2371
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002372uint8_t ExternalPixelArray::get(int index) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002373 ASSERT((index >= 0) && (index < this->length()));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002374 uint8_t* ptr = external_pixel_pointer();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002375 return ptr[index];
2376}
2377
2378
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002379void ExternalPixelArray::set(int index, uint8_t value) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002380 ASSERT((index >= 0) && (index < this->length()));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002381 uint8_t* ptr = external_pixel_pointer();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00002382 ptr[index] = value;
2383}
2384
2385
ager@chromium.org3811b432009-10-28 14:53:37 +00002386void* ExternalArray::external_pointer() {
2387 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2388 return reinterpret_cast<void*>(ptr);
2389}
2390
2391
2392void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2393 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2394 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2395}
2396
2397
2398int8_t ExternalByteArray::get(int index) {
2399 ASSERT((index >= 0) && (index < this->length()));
2400 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2401 return ptr[index];
2402}
2403
2404
2405void ExternalByteArray::set(int index, int8_t value) {
2406 ASSERT((index >= 0) && (index < this->length()));
2407 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2408 ptr[index] = value;
2409}
2410
2411
2412uint8_t ExternalUnsignedByteArray::get(int index) {
2413 ASSERT((index >= 0) && (index < this->length()));
2414 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2415 return ptr[index];
2416}
2417
2418
2419void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2420 ASSERT((index >= 0) && (index < this->length()));
2421 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2422 ptr[index] = value;
2423}
2424
2425
2426int16_t ExternalShortArray::get(int index) {
2427 ASSERT((index >= 0) && (index < this->length()));
2428 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2429 return ptr[index];
2430}
2431
2432
2433void ExternalShortArray::set(int index, int16_t value) {
2434 ASSERT((index >= 0) && (index < this->length()));
2435 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2436 ptr[index] = value;
2437}
2438
2439
2440uint16_t ExternalUnsignedShortArray::get(int index) {
2441 ASSERT((index >= 0) && (index < this->length()));
2442 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2443 return ptr[index];
2444}
2445
2446
2447void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2448 ASSERT((index >= 0) && (index < this->length()));
2449 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2450 ptr[index] = value;
2451}
2452
2453
2454int32_t ExternalIntArray::get(int index) {
2455 ASSERT((index >= 0) && (index < this->length()));
2456 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2457 return ptr[index];
2458}
2459
2460
2461void ExternalIntArray::set(int index, int32_t value) {
2462 ASSERT((index >= 0) && (index < this->length()));
2463 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2464 ptr[index] = value;
2465}
2466
2467
2468uint32_t ExternalUnsignedIntArray::get(int index) {
2469 ASSERT((index >= 0) && (index < this->length()));
2470 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2471 return ptr[index];
2472}
2473
2474
2475void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2476 ASSERT((index >= 0) && (index < this->length()));
2477 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2478 ptr[index] = value;
2479}
2480
2481
2482float ExternalFloatArray::get(int index) {
2483 ASSERT((index >= 0) && (index < this->length()));
2484 float* ptr = static_cast<float*>(external_pointer());
2485 return ptr[index];
2486}
2487
2488
2489void ExternalFloatArray::set(int index, float value) {
2490 ASSERT((index >= 0) && (index < this->length()));
2491 float* ptr = static_cast<float*>(external_pointer());
2492 ptr[index] = value;
2493}
2494
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00002495
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002496double ExternalDoubleArray::get(int index) {
2497 ASSERT((index >= 0) && (index < this->length()));
2498 double* ptr = static_cast<double*>(external_pointer());
2499 return ptr[index];
2500}
2501
2502
2503void ExternalDoubleArray::set(int index, double value) {
2504 ASSERT((index >= 0) && (index < this->length()));
2505 double* ptr = static_cast<double*>(external_pointer());
2506 ptr[index] = value;
2507}
2508
2509
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00002510int Map::visitor_id() {
2511 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2512}
2513
2514
2515void Map::set_visitor_id(int id) {
2516 ASSERT(0 <= id && id < 256);
2517 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2518}
2519
ager@chromium.org3811b432009-10-28 14:53:37 +00002520
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002521int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002522 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2523}
2524
2525
2526int Map::inobject_properties() {
2527 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002528}
2529
2530
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002531int Map::pre_allocated_property_fields() {
2532 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2533}
2534
2535
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002536int HeapObject::SizeFromMap(Map* map) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002537 int instance_size = map->instance_size();
2538 if (instance_size != kVariableSizeSentinel) return instance_size;
2539 // We can ignore the "symbol" bit becase it is only set for symbols
2540 // and implies a string type.
2541 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002542 // Only inline the most frequent cases.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002543 if (instance_type == FIXED_ARRAY_TYPE) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002544 return FixedArray::BodyDescriptor::SizeOf(map, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002545 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002546 if (instance_type == ASCII_STRING_TYPE) {
2547 return SeqAsciiString::SizeFor(
2548 reinterpret_cast<SeqAsciiString*>(this)->length());
2549 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002550 if (instance_type == BYTE_ARRAY_TYPE) {
2551 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2552 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002553 if (instance_type == STRING_TYPE) {
2554 return SeqTwoByteString::SizeFor(
2555 reinterpret_cast<SeqTwoByteString*>(this)->length());
2556 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002557 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2558 return FixedDoubleArray::SizeFor(
2559 reinterpret_cast<FixedDoubleArray*>(this)->length());
2560 }
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00002561 ASSERT(instance_type == CODE_TYPE);
2562 return reinterpret_cast<Code*>(this)->CodeSize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002563}
2564
2565
2566void Map::set_instance_size(int value) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002567 ASSERT_EQ(0, value & (kPointerSize - 1));
ager@chromium.org7c537e22008-10-16 08:43:32 +00002568 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002569 ASSERT(0 <= value && value < 256);
2570 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2571}
2572
2573
ager@chromium.org7c537e22008-10-16 08:43:32 +00002574void Map::set_inobject_properties(int value) {
2575 ASSERT(0 <= value && value < 256);
2576 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2577}
2578
2579
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00002580void Map::set_pre_allocated_property_fields(int value) {
2581 ASSERT(0 <= value && value < 256);
2582 WRITE_BYTE_FIELD(this,
2583 kPreAllocatedPropertyFieldsOffset,
2584 static_cast<byte>(value));
2585}
2586
2587
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002588InstanceType Map::instance_type() {
2589 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2590}
2591
2592
2593void Map::set_instance_type(InstanceType value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002594 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2595}
2596
2597
2598int Map::unused_property_fields() {
2599 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2600}
2601
2602
2603void Map::set_unused_property_fields(int value) {
2604 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2605}
2606
2607
2608byte Map::bit_field() {
2609 return READ_BYTE_FIELD(this, kBitFieldOffset);
2610}
2611
2612
2613void Map::set_bit_field(byte value) {
2614 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2615}
2616
2617
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00002618byte Map::bit_field2() {
2619 return READ_BYTE_FIELD(this, kBitField2Offset);
2620}
2621
2622
2623void Map::set_bit_field2(byte value) {
2624 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2625}
2626
2627
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002628void Map::set_non_instance_prototype(bool value) {
2629 if (value) {
2630 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2631 } else {
2632 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2633 }
2634}
2635
2636
2637bool Map::has_non_instance_prototype() {
2638 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2639}
2640
2641
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002642void Map::set_function_with_prototype(bool value) {
2643 if (value) {
2644 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2645 } else {
2646 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2647 }
2648}
2649
2650
2651bool Map::function_with_prototype() {
2652 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2653}
2654
2655
ager@chromium.org870a0b62008-11-04 11:43:05 +00002656void Map::set_is_access_check_needed(bool access_check_needed) {
2657 if (access_check_needed) {
2658 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2659 } else {
2660 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2661 }
2662}
2663
2664
2665bool Map::is_access_check_needed() {
2666 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2667}
2668
2669
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002670void Map::set_is_extensible(bool value) {
2671 if (value) {
2672 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2673 } else {
2674 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2675 }
2676}
2677
2678bool Map::is_extensible() {
2679 return ((1 << kIsExtensible) & bit_field2()) != 0;
2680}
2681
2682
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002683void Map::set_attached_to_shared_function_info(bool value) {
2684 if (value) {
2685 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2686 } else {
2687 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2688 }
2689}
2690
2691bool Map::attached_to_shared_function_info() {
2692 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2693}
2694
2695
2696void Map::set_is_shared(bool value) {
2697 if (value) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00002698 set_bit_field3(bit_field3() | (1 << kIsShared));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002699 } else {
danno@chromium.org40cb8782011-05-25 07:58:50 +00002700 set_bit_field3(bit_field3() & ~(1 << kIsShared));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002701 }
2702}
2703
2704bool Map::is_shared() {
danno@chromium.org40cb8782011-05-25 07:58:50 +00002705 return ((1 << kIsShared) & bit_field3()) != 0;
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00002706}
2707
2708
2709JSFunction* Map::unchecked_constructor() {
2710 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2711}
2712
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002713
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002714FixedArray* Map::unchecked_prototype_transitions() {
2715 return reinterpret_cast<FixedArray*>(
2716 READ_FIELD(this, kPrototypeTransitionsOffset));
2717}
2718
2719
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002720Code::Flags Code::flags() {
2721 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2722}
2723
2724
2725void Code::set_flags(Code::Flags flags) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002726 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002727 // Make sure that all call stubs have an arguments count.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002728 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2729 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002730 ExtractArgumentsCountFromFlags(flags) >= 0);
2731 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2732}
2733
2734
2735Code::Kind Code::kind() {
2736 return ExtractKindFromFlags(flags());
2737}
2738
2739
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002740InLoopFlag Code::ic_in_loop() {
2741 return ExtractICInLoopFromFlags(flags());
2742}
2743
2744
kasper.lund7276f142008-07-30 08:49:36 +00002745InlineCacheState Code::ic_state() {
2746 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002747 // Only allow uninitialized or debugger states for non-IC code
2748 // objects. This is used in the debugger to determine whether or not
2749 // a call to code object has been replaced with a debug break call.
2750 ASSERT(is_inline_cache_stub() ||
2751 result == UNINITIALIZED ||
2752 result == DEBUG_BREAK ||
2753 result == DEBUG_PREPARE_STEP_IN);
2754 return result;
2755}
2756
2757
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002758Code::ExtraICState Code::extra_ic_state() {
2759 ASSERT(is_inline_cache_stub());
2760 return ExtractExtraICStateFromFlags(flags());
2761}
2762
2763
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002764PropertyType Code::type() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002765 return ExtractTypeFromFlags(flags());
2766}
2767
2768
2769int Code::arguments_count() {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002770 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002771 return ExtractArgumentsCountFromFlags(flags());
2772}
2773
2774
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002775int Code::major_key() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002776 ASSERT(kind() == STUB ||
danno@chromium.org40cb8782011-05-25 07:58:50 +00002777 kind() == UNARY_OP_IC ||
2778 kind() == BINARY_OP_IC ||
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002779 kind() == COMPARE_IC ||
2780 kind() == TO_BOOLEAN_IC);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002781 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
kasper.lund7276f142008-07-30 08:49:36 +00002782}
2783
2784
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002785void Code::set_major_key(int major) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002786 ASSERT(kind() == STUB ||
danno@chromium.org40cb8782011-05-25 07:58:50 +00002787 kind() == UNARY_OP_IC ||
2788 kind() == BINARY_OP_IC ||
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002789 kind() == COMPARE_IC ||
2790 kind() == TO_BOOLEAN_IC);
kasper.lund7276f142008-07-30 08:49:36 +00002791 ASSERT(0 <= major && major < 256);
2792 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002793}
2794
2795
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002796bool Code::optimizable() {
2797 ASSERT(kind() == FUNCTION);
2798 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2799}
2800
2801
2802void Code::set_optimizable(bool value) {
2803 ASSERT(kind() == FUNCTION);
2804 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2805}
2806
2807
2808bool Code::has_deoptimization_support() {
2809 ASSERT(kind() == FUNCTION);
2810 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1;
2811}
2812
2813
2814void Code::set_has_deoptimization_support(bool value) {
2815 ASSERT(kind() == FUNCTION);
2816 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0);
2817}
2818
2819
2820int Code::allow_osr_at_loop_nesting_level() {
2821 ASSERT(kind() == FUNCTION);
2822 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2823}
2824
2825
2826void Code::set_allow_osr_at_loop_nesting_level(int level) {
2827 ASSERT(kind() == FUNCTION);
2828 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2829 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2830}
2831
2832
2833unsigned Code::stack_slots() {
2834 ASSERT(kind() == OPTIMIZED_FUNCTION);
2835 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2836}
2837
2838
2839void Code::set_stack_slots(unsigned slots) {
2840 ASSERT(kind() == OPTIMIZED_FUNCTION);
2841 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2842}
2843
2844
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002845unsigned Code::safepoint_table_offset() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002846 ASSERT(kind() == OPTIMIZED_FUNCTION);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002847 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002848}
2849
2850
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002851void Code::set_safepoint_table_offset(unsigned offset) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002852 ASSERT(kind() == OPTIMIZED_FUNCTION);
2853 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002854 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002855}
2856
2857
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002858unsigned Code::stack_check_table_offset() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002859 ASSERT(kind() == FUNCTION);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002860 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002861}
2862
2863
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002864void Code::set_stack_check_table_offset(unsigned offset) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002865 ASSERT(kind() == FUNCTION);
2866 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002867 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002868}
2869
2870
2871CheckType Code::check_type() {
2872 ASSERT(is_call_stub() || is_keyed_call_stub());
2873 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2874 return static_cast<CheckType>(type);
2875}
2876
2877
2878void Code::set_check_type(CheckType value) {
2879 ASSERT(is_call_stub() || is_keyed_call_stub());
2880 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2881}
2882
2883
danno@chromium.org40cb8782011-05-25 07:58:50 +00002884byte Code::unary_op_type() {
2885 ASSERT(is_unary_op_stub());
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002886 return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
2887}
2888
2889
danno@chromium.org40cb8782011-05-25 07:58:50 +00002890void Code::set_unary_op_type(byte value) {
2891 ASSERT(is_unary_op_stub());
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002892 WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
2893}
2894
2895
danno@chromium.org40cb8782011-05-25 07:58:50 +00002896byte Code::binary_op_type() {
2897 ASSERT(is_binary_op_stub());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002898 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
2899}
2900
2901
danno@chromium.org40cb8782011-05-25 07:58:50 +00002902void Code::set_binary_op_type(byte value) {
2903 ASSERT(is_binary_op_stub());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002904 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
2905}
2906
2907
danno@chromium.org40cb8782011-05-25 07:58:50 +00002908byte Code::binary_op_result_type() {
2909 ASSERT(is_binary_op_stub());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002910 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
2911}
2912
2913
danno@chromium.org40cb8782011-05-25 07:58:50 +00002914void Code::set_binary_op_result_type(byte value) {
2915 ASSERT(is_binary_op_stub());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002916 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
2917}
2918
2919
2920byte Code::compare_state() {
2921 ASSERT(is_compare_ic_stub());
2922 return READ_BYTE_FIELD(this, kCompareStateOffset);
2923}
2924
2925
2926void Code::set_compare_state(byte value) {
2927 ASSERT(is_compare_ic_stub());
2928 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
2929}
2930
2931
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002932byte Code::to_boolean_state() {
2933 ASSERT(is_to_boolean_ic_stub());
2934 return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
2935}
2936
2937
2938void Code::set_to_boolean_state(byte value) {
2939 ASSERT(is_to_boolean_ic_stub());
2940 WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
2941}
2942
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002943bool Code::is_inline_cache_stub() {
2944 Kind kind = this->kind();
2945 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2946}
2947
2948
2949Code::Flags Code::ComputeFlags(Kind kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002950 InLoopFlag in_loop,
kasper.lund7276f142008-07-30 08:49:36 +00002951 InlineCacheState ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002952 ExtraICState extra_ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002953 PropertyType type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002954 int argc,
2955 InlineCacheHolderFlag holder) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00002956 // Extra IC state is only allowed for call IC stubs or for store IC
2957 // stubs.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002958 ASSERT(extra_ic_state == kNoExtraICState ||
danno@chromium.org40cb8782011-05-25 07:58:50 +00002959 (kind == CALL_IC) ||
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00002960 (kind == STORE_IC) ||
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002961 (kind == KEYED_STORE_IC));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002962 // Compute the bit mask.
2963 int bits = kind << kFlagsKindShift;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002964 if (in_loop) bits |= kFlagsICInLoopMask;
kasper.lund7276f142008-07-30 08:49:36 +00002965 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002966 bits |= type << kFlagsTypeShift;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002967 bits |= extra_ic_state << kFlagsExtraICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002968 bits |= argc << kFlagsArgumentsCountShift;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002969 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002970 // Cast to flags and validate result before returning it.
2971 Flags result = static_cast<Flags>(bits);
2972 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00002973 ASSERT(ExtractICStateFromFlags(result) == ic_state);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002974 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002975 ASSERT(ExtractTypeFromFlags(result) == type);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002976 ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002977 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2978 return result;
2979}
2980
2981
2982Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2983 PropertyType type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002984 ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002985 InlineCacheHolderFlag holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002986 InLoopFlag in_loop,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002987 int argc) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002988 return ComputeFlags(
2989 kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002990}
2991
2992
2993Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2994 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2995 return static_cast<Kind>(bits);
2996}
2997
2998
kasper.lund7276f142008-07-30 08:49:36 +00002999InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
3000 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003001 return static_cast<InlineCacheState>(bits);
3002}
3003
3004
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003005Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
3006 int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
3007 return static_cast<ExtraICState>(bits);
3008}
3009
3010
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003011InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
3012 int bits = (flags & kFlagsICInLoopMask);
3013 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
3014}
3015
3016
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003017PropertyType Code::ExtractTypeFromFlags(Flags flags) {
3018 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
3019 return static_cast<PropertyType>(bits);
3020}
3021
3022
3023int Code::ExtractArgumentsCountFromFlags(Flags flags) {
3024 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
3025}
3026
3027
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00003028InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
3029 int bits = (flags & kFlagsCacheInPrototypeMapMask);
3030 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
3031}
3032
3033
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003034Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
3035 int bits = flags & ~kFlagsTypeMask;
3036 return static_cast<Flags>(bits);
3037}
3038
3039
ager@chromium.org8bb60582008-12-11 12:02:20 +00003040Code* Code::GetCodeFromTargetAddress(Address address) {
3041 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3042 // GetCodeFromTargetAddress might be called when marking objects during mark
3043 // sweep. reinterpret_cast is therefore used instead of the more appropriate
3044 // Code::cast. Code::cast does not work when the object's map is
3045 // marked.
3046 Code* result = reinterpret_cast<Code*>(code);
3047 return result;
3048}
3049
3050
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003051Isolate* Map::isolate() {
3052 return heap()->isolate();
3053}
3054
3055
3056Heap* Map::heap() {
3057 // NOTE: address() helper is not used to save one instruction.
3058 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
3059 ASSERT(heap != NULL);
3060 ASSERT(heap->isolate() == Isolate::Current());
3061 return heap;
3062}
3063
3064
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00003065Heap* Code::heap() {
3066 // NOTE: address() helper is not used to save one instruction.
3067 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
3068 ASSERT(heap != NULL);
3069 ASSERT(heap->isolate() == Isolate::Current());
3070 return heap;
3071}
3072
3073
3074Isolate* Code::isolate() {
3075 return heap()->isolate();
3076}
3077
3078
3079Heap* JSGlobalPropertyCell::heap() {
3080 // NOTE: address() helper is not used to save one instruction.
3081 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
3082 ASSERT(heap != NULL);
3083 ASSERT(heap->isolate() == Isolate::Current());
3084 return heap;
3085}
3086
3087
3088Isolate* JSGlobalPropertyCell::isolate() {
3089 return heap()->isolate();
3090}
3091
3092
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003093Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3094 return HeapObject::
3095 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3096}
3097
3098
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003099Object* Map::prototype() {
3100 return READ_FIELD(this, kPrototypeOffset);
3101}
3102
3103
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003104void Map::set_prototype(Object* value, WriteBarrierMode mode) {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00003105 ASSERT(value->IsNull() || value->IsJSReceiver());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003106 WRITE_FIELD(this, kPrototypeOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003107 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003108}
3109
3110
lrn@chromium.org303ada72010-10-27 09:33:13 +00003111MaybeObject* Map::GetFastElementsMap() {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00003112 if (has_fast_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003113 Object* obj;
3114 { MaybeObject* maybe_obj = CopyDropTransitions();
3115 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3116 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00003117 Map* new_map = Map::cast(obj);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00003118 new_map->set_elements_kind(JSObject::FAST_ELEMENTS);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003119 isolate()->counters()->map_to_fast_elements()->Increment();
3120 return new_map;
3121}
3122
3123
3124MaybeObject* Map::GetFastDoubleElementsMap() {
3125 if (has_fast_double_elements()) return this;
3126 Object* obj;
3127 { MaybeObject* maybe_obj = CopyDropTransitions();
3128 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3129 }
3130 Map* new_map = Map::cast(obj);
3131 new_map->set_elements_kind(JSObject::FAST_DOUBLE_ELEMENTS);
3132 isolate()->counters()->map_to_fast_double_elements()->Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00003133 return new_map;
3134}
3135
3136
lrn@chromium.org303ada72010-10-27 09:33:13 +00003137MaybeObject* Map::GetSlowElementsMap() {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003138 if (!has_fast_elements() && !has_fast_double_elements()) return this;
lrn@chromium.org303ada72010-10-27 09:33:13 +00003139 Object* obj;
3140 { MaybeObject* maybe_obj = CopyDropTransitions();
3141 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3142 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00003143 Map* new_map = Map::cast(obj);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00003144 new_map->set_elements_kind(JSObject::DICTIONARY_ELEMENTS);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003145 isolate()->counters()->map_to_slow_elements()->Increment();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00003146 return new_map;
3147}
3148
3149
danno@chromium.org40cb8782011-05-25 07:58:50 +00003150DescriptorArray* Map::instance_descriptors() {
3151 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3152 if (object->IsSmi()) {
3153 return HEAP->empty_descriptor_array();
3154 } else {
3155 return DescriptorArray::cast(object);
3156 }
3157}
3158
3159
3160void Map::init_instance_descriptors() {
3161 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3162}
3163
3164
3165void Map::clear_instance_descriptors() {
3166 Object* object = READ_FIELD(this,
3167 kInstanceDescriptorsOrBitField3Offset);
3168 if (!object->IsSmi()) {
3169 WRITE_FIELD(
3170 this,
3171 kInstanceDescriptorsOrBitField3Offset,
3172 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3173 }
3174}
3175
3176
3177void Map::set_instance_descriptors(DescriptorArray* value,
3178 WriteBarrierMode mode) {
3179 Object* object = READ_FIELD(this,
3180 kInstanceDescriptorsOrBitField3Offset);
3181 if (value == isolate()->heap()->empty_descriptor_array()) {
3182 clear_instance_descriptors();
3183 return;
3184 } else {
3185 if (object->IsSmi()) {
3186 value->set_bit_field3_storage(Smi::cast(object)->value());
3187 } else {
3188 value->set_bit_field3_storage(
3189 DescriptorArray::cast(object)->bit_field3_storage());
3190 }
3191 }
3192 ASSERT(!is_shared());
3193 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
3194 CONDITIONAL_WRITE_BARRIER(GetHeap(),
3195 this,
3196 kInstanceDescriptorsOrBitField3Offset,
3197 mode);
3198}
3199
3200
3201int Map::bit_field3() {
3202 Object* object = READ_FIELD(this,
3203 kInstanceDescriptorsOrBitField3Offset);
3204 if (object->IsSmi()) {
3205 return Smi::cast(object)->value();
3206 } else {
3207 return DescriptorArray::cast(object)->bit_field3_storage();
3208 }
3209}
3210
3211
3212void Map::set_bit_field3(int value) {
3213 ASSERT(Smi::IsValid(value));
3214 Object* object = READ_FIELD(this,
3215 kInstanceDescriptorsOrBitField3Offset);
3216 if (object->IsSmi()) {
3217 WRITE_FIELD(this,
3218 kInstanceDescriptorsOrBitField3Offset,
3219 Smi::FromInt(value));
3220 } else {
3221 DescriptorArray::cast(object)->set_bit_field3_storage(value);
3222 }
3223}
3224
3225
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003226ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00003227ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003228ACCESSORS(Map, constructor, Object, kConstructorOffset)
3229
3230ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
3231ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003232ACCESSORS_GCSAFE(JSFunction, next_function_link, Object,
3233 kNextFunctionLinkOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003234
3235ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3236ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003237ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003238
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003239ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003240
3241ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3242ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3243ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3244ACCESSORS(AccessorInfo, name, Object, kNameOffset)
3245ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
3246
3247ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3248ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3249ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3250
3251ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3252ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3253ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3254ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3255ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3256ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3257
3258ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3259ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3260
3261ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3262ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3263
3264ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3265ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003266ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3267 kPropertyAccessorsOffset)
3268ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3269 kPrototypeTemplateOffset)
3270ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3271ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3272 kNamedPropertyHandlerOffset)
3273ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3274 kIndexedPropertyHandlerOffset)
3275ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3276 kInstanceTemplateOffset)
3277ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3278ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003279ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3280 kInstanceCallHandlerOffset)
3281ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3282 kAccessCheckInfoOffset)
3283ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
3284
3285ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00003286ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3287 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003288
3289ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3290ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3291
3292ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3293
3294ACCESSORS(Script, source, Object, kSourceOffset)
3295ACCESSORS(Script, name, Object, kNameOffset)
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003296ACCESSORS(Script, id, Object, kIdOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003297ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
3298ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003299ACCESSORS(Script, data, Object, kDataOffset)
ager@chromium.org9085a012009-05-11 19:22:57 +00003300ACCESSORS(Script, context_data, Object, kContextOffset)
ager@chromium.orgea91cc52011-05-23 06:06:11 +00003301ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003302ACCESSORS(Script, type, Smi, kTypeOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00003303ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00003304ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
sgjesse@chromium.org98180592009-12-02 08:17:28 +00003305ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
ager@chromium.orge2902be2009-06-08 12:21:35 +00003306ACCESSORS(Script, eval_from_instructions_offset, Smi,
3307 kEvalFrominstructionsOffsetOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003308
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003309#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003310ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3311ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3312ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3313ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3314
3315ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
3316ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
3317ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
3318ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003319#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003320
3321ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003322ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3323ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003324ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3325 kInstanceClassNameOffset)
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003326ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003327ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3328ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00003329ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003330ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3331 kThisPropertyAssignmentsOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003332
3333BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3334 kHiddenPrototypeBit)
3335BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3336BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3337 kNeedsAccessCheckBit)
ricow@chromium.org2c99e282011-07-28 09:15:17 +00003338BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3339 kReadOnlyPrototypeBit)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003340BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3341 kIsExpressionBit)
3342BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3343 kIsTopLevelBit)
whesse@chromium.org7b260152011-06-20 15:33:18 +00003344BOOL_GETTER(SharedFunctionInfo,
3345 compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003346 has_only_simple_this_property_assignments,
3347 kHasOnlySimpleThisPropertyAssignments)
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003348BOOL_ACCESSORS(SharedFunctionInfo,
3349 compiler_hints,
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00003350 allows_lazy_compilation,
3351 kAllowLazyCompilation)
whesse@chromium.org7b260152011-06-20 15:33:18 +00003352BOOL_ACCESSORS(SharedFunctionInfo,
3353 compiler_hints,
3354 uses_arguments,
3355 kUsesArguments)
3356BOOL_ACCESSORS(SharedFunctionInfo,
3357 compiler_hints,
3358 has_duplicate_parameters,
3359 kHasDuplicateParameters)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003360
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003361
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003362#if V8_HOST_ARCH_32_BIT
3363SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3364SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003365 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003366SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003367 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003368SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3369SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003370 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003371SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3372SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003373 kFunctionTokenPositionOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003374SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003375 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003376SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003377 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003378SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003379#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003380
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003381#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003382 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003383 int holder::name() { \
3384 int value = READ_INT_FIELD(this, offset); \
3385 ASSERT(kHeapObjectTag == 1); \
3386 ASSERT((value & kHeapObjectTag) == 0); \
3387 return value >> 1; \
3388 } \
3389 void holder::set_##name(int value) { \
3390 ASSERT(kHeapObjectTag == 1); \
3391 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3392 (value & 0xC0000000) == 0x000000000); \
3393 WRITE_INT_FIELD(this, \
3394 offset, \
3395 (value << 1) & ~kHeapObjectTag); \
3396 }
3397
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003398#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3399 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003400 INT_ACCESSORS(holder, name, offset)
3401
3402
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003403PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003404PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3405 formal_parameter_count,
3406 kFormalParameterCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003407
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003408PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3409 expected_nof_properties,
3410 kExpectedNofPropertiesOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003411PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3412
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003413PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3414PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3415 start_position_and_type,
3416 kStartPositionAndTypeOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003417
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003418PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3419 function_token_position,
3420 kFunctionTokenPositionOffset)
3421PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3422 compiler_hints,
3423 kCompilerHintsOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003424
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00003425PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3426 this_property_assignments_count,
3427 kThisPropertyAssignmentsCountOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003428PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003429#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003430
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003431
3432int SharedFunctionInfo::construction_count() {
3433 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3434}
3435
3436
3437void SharedFunctionInfo::set_construction_count(int value) {
3438 ASSERT(0 <= value && value < 256);
3439 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3440}
3441
3442
whesse@chromium.org7b260152011-06-20 15:33:18 +00003443BOOL_ACCESSORS(SharedFunctionInfo,
3444 compiler_hints,
3445 live_objects_may_exist,
3446 kLiveObjectsMayExist)
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003447
3448
3449bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003450 return initial_map() != HEAP->undefined_value();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00003451}
3452
3453
whesse@chromium.org7b260152011-06-20 15:33:18 +00003454BOOL_GETTER(SharedFunctionInfo,
3455 compiler_hints,
3456 optimization_disabled,
3457 kOptimizationDisabled)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003458
3459
3460void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3461 set_compiler_hints(BooleanBit::set(compiler_hints(),
3462 kOptimizationDisabled,
3463 disable));
3464 // If disabling optimizations we reflect that in the code object so
3465 // it will not be counted as optimizable code.
3466 if ((code()->kind() == Code::FUNCTION) && disable) {
3467 code()->set_optimizable(false);
3468 }
3469}
3470
3471
whesse@chromium.org7b260152011-06-20 15:33:18 +00003472BOOL_ACCESSORS(SharedFunctionInfo,
3473 compiler_hints,
3474 strict_mode,
3475 kStrictModeFunction)
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003476
3477
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00003478bool SharedFunctionInfo::native() {
3479 return BooleanBit::get(compiler_hints(), kNative);
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00003480}
3481
3482
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00003483void SharedFunctionInfo::set_native(bool value) {
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00003484 set_compiler_hints(BooleanBit::set(compiler_hints(),
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00003485 kNative,
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00003486 value));
3487}
3488
3489
whesse@chromium.org7b260152011-06-20 15:33:18 +00003490bool SharedFunctionInfo::bound() {
3491 return BooleanBit::get(compiler_hints(), kBoundFunction);
3492}
3493
3494
3495void SharedFunctionInfo::set_bound(bool value) {
3496 set_compiler_hints(BooleanBit::set(compiler_hints(),
3497 kBoundFunction,
3498 value));
3499}
3500
3501
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003502ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3503ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3504
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00003505ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3506
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00003507bool Script::HasValidSource() {
3508 Object* src = this->source();
3509 if (!src->IsString()) return true;
3510 String* src_str = String::cast(src);
3511 if (!StringShape(src_str).IsExternal()) return true;
3512 if (src_str->IsAsciiRepresentation()) {
3513 return ExternalAsciiString::cast(src)->resource() != NULL;
3514 } else if (src_str->IsTwoByteRepresentation()) {
3515 return ExternalTwoByteString::cast(src)->resource() != NULL;
3516 }
3517 return true;
3518}
3519
3520
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003521void SharedFunctionInfo::DontAdaptArguments() {
3522 ASSERT(code()->kind() == Code::BUILTIN);
3523 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3524}
3525
3526
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003527int SharedFunctionInfo::start_position() {
3528 return start_position_and_type() >> kStartPositionShift;
3529}
3530
3531
3532void SharedFunctionInfo::set_start_position(int start_position) {
3533 set_start_position_and_type((start_position << kStartPositionShift)
3534 | (start_position_and_type() & ~kStartPositionMask));
3535}
3536
3537
3538Code* SharedFunctionInfo::code() {
3539 return Code::cast(READ_FIELD(this, kCodeOffset));
3540}
3541
3542
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003543Code* SharedFunctionInfo::unchecked_code() {
3544 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3545}
3546
3547
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003548void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003549 WRITE_FIELD(this, kCodeOffset, value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003550 ASSERT(!Isolate::Current()->heap()->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003551}
3552
3553
ager@chromium.orgb5737492010-07-15 09:29:43 +00003554SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3555 return reinterpret_cast<SerializedScopeInfo*>(
3556 READ_FIELD(this, kScopeInfoOffset));
3557}
3558
3559
3560void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3561 WriteBarrierMode mode) {
3562 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003563 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode);
ager@chromium.orgb5737492010-07-15 09:29:43 +00003564}
3565
3566
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003567Smi* SharedFunctionInfo::deopt_counter() {
3568 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3569}
3570
3571
3572void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3573 WRITE_FIELD(this, kDeoptCounterOffset, value);
3574}
3575
3576
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003577bool SharedFunctionInfo::is_compiled() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003578 return code() !=
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003579 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003580}
3581
3582
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003583bool SharedFunctionInfo::IsApiFunction() {
3584 return function_data()->IsFunctionTemplateInfo();
3585}
3586
3587
3588FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3589 ASSERT(IsApiFunction());
3590 return FunctionTemplateInfo::cast(function_data());
3591}
3592
3593
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003594bool SharedFunctionInfo::HasBuiltinFunctionId() {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003595 return function_data()->IsSmi();
3596}
3597
3598
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00003599BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3600 ASSERT(HasBuiltinFunctionId());
3601 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00003602}
3603
3604
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003605int SharedFunctionInfo::code_age() {
3606 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3607}
3608
3609
3610void SharedFunctionInfo::set_code_age(int code_age) {
3611 set_compiler_hints(compiler_hints() |
3612 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3613}
3614
3615
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003616bool SharedFunctionInfo::has_deoptimization_support() {
3617 Code* code = this->code();
3618 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3619}
3620
3621
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003622bool JSFunction::IsBuiltin() {
3623 return context()->global()->IsJSBuiltinsObject();
3624}
3625
3626
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003627bool JSFunction::NeedsArgumentsAdaption() {
3628 return shared()->formal_parameter_count() !=
3629 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3630}
3631
3632
3633bool JSFunction::IsOptimized() {
3634 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3635}
3636
3637
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +00003638bool JSFunction::IsOptimizable() {
3639 return code()->kind() == Code::FUNCTION && code()->optimizable();
3640}
3641
3642
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003643bool JSFunction::IsMarkedForLazyRecompilation() {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003644 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003645}
3646
3647
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003648Code* JSFunction::code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003649 return Code::cast(unchecked_code());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003650}
3651
3652
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003653Code* JSFunction::unchecked_code() {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003654 return reinterpret_cast<Code*>(
3655 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003656}
3657
3658
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003659void JSFunction::set_code(Code* value) {
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00003660 // Skip the write barrier because code is never in new space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003661 ASSERT(!HEAP->InNewSpace(value));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003662 Address entry = value->entry();
3663 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003664}
3665
3666
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003667void JSFunction::ReplaceCode(Code* code) {
3668 bool was_optimized = IsOptimized();
3669 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3670
3671 set_code(code);
3672
3673 // Add/remove the function from the list of optimized functions for this
3674 // context based on the state change.
3675 if (!was_optimized && is_optimized) {
3676 context()->global_context()->AddOptimizedFunction(this);
3677 }
3678 if (was_optimized && !is_optimized) {
3679 context()->global_context()->RemoveOptimizedFunction(this);
3680 }
3681}
3682
3683
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003684Context* JSFunction::context() {
3685 return Context::cast(READ_FIELD(this, kContextOffset));
3686}
3687
3688
3689Object* JSFunction::unchecked_context() {
3690 return READ_FIELD(this, kContextOffset);
3691}
3692
3693
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003694SharedFunctionInfo* JSFunction::unchecked_shared() {
3695 return reinterpret_cast<SharedFunctionInfo*>(
3696 READ_FIELD(this, kSharedFunctionInfoOffset));
3697}
3698
3699
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003700void JSFunction::set_context(Object* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003701 ASSERT(value->IsUndefined() || value->IsContext());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003702 WRITE_FIELD(this, kContextOffset, value);
3703 WRITE_BARRIER(this, kContextOffset);
3704}
3705
3706ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3707 kPrototypeOrInitialMapOffset)
3708
3709
3710Map* JSFunction::initial_map() {
3711 return Map::cast(prototype_or_initial_map());
3712}
3713
3714
3715void JSFunction::set_initial_map(Map* value) {
3716 set_prototype_or_initial_map(value);
3717}
3718
3719
3720bool JSFunction::has_initial_map() {
3721 return prototype_or_initial_map()->IsMap();
3722}
3723
3724
3725bool JSFunction::has_instance_prototype() {
3726 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3727}
3728
3729
3730bool JSFunction::has_prototype() {
3731 return map()->has_non_instance_prototype() || has_instance_prototype();
3732}
3733
3734
3735Object* JSFunction::instance_prototype() {
3736 ASSERT(has_instance_prototype());
3737 if (has_initial_map()) return initial_map()->prototype();
3738 // When there is no initial map and the prototype is a JSObject, the
3739 // initial map field is used for the prototype field.
3740 return prototype_or_initial_map();
3741}
3742
3743
3744Object* JSFunction::prototype() {
3745 ASSERT(has_prototype());
3746 // If the function's prototype property has been set to a non-JSObject
3747 // value, that value is stored in the constructor field of the map.
3748 if (map()->has_non_instance_prototype()) return map()->constructor();
3749 return instance_prototype();
3750}
3751
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003752bool JSFunction::should_have_prototype() {
3753 return map()->function_with_prototype();
3754}
3755
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003756
3757bool JSFunction::is_compiled() {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003758 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003759}
3760
3761
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003762int JSFunction::NumberOfLiterals() {
3763 return literals()->length();
3764}
3765
3766
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003767Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003768 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003769 return READ_FIELD(this, OffsetOfFunctionWithId(id));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003770}
3771
3772
3773void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3774 Object* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003775 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003776 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3777 WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
3778}
3779
3780
3781Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003782 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003783 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3784}
3785
3786
3787void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3788 Code* value) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003789 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003790 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003791 ASSERT(!HEAP->InNewSpace(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003792}
3793
3794
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00003795ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
rossberg@chromium.org717967f2011-07-20 13:44:42 +00003796ACCESSORS(JSProxy, padding, Object, kPaddingOffset)
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00003797
3798
ager@chromium.orgea91cc52011-05-23 06:06:11 +00003799Address Foreign::address() {
3800 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kAddressOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003801}
3802
3803
ager@chromium.orgea91cc52011-05-23 06:06:11 +00003804void Foreign::set_address(Address value) {
3805 WRITE_INTPTR_FIELD(this, kAddressOffset, OffsetFrom(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003806}
3807
3808
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003809ACCESSORS(JSValue, value, Object, kValueOffset)
3810
3811
3812JSValue* JSValue::cast(Object* obj) {
3813 ASSERT(obj->IsJSValue());
3814 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3815 return reinterpret_cast<JSValue*>(obj);
3816}
3817
3818
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003819ACCESSORS(JSMessageObject, type, String, kTypeOffset)
3820ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
3821ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
3822ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
3823ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
3824SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
3825SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
3826
3827
3828JSMessageObject* JSMessageObject::cast(Object* obj) {
3829 ASSERT(obj->IsJSMessageObject());
3830 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
3831 return reinterpret_cast<JSMessageObject*>(obj);
3832}
3833
3834
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003835INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003836ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003837ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00003838ACCESSORS(Code, next_code_flushing_candidate,
3839 Object, kNextCodeFlushingCandidateOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003840
3841
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003842byte* Code::instruction_start() {
3843 return FIELD_ADDR(this, kHeaderSize);
3844}
3845
3846
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003847byte* Code::instruction_end() {
3848 return instruction_start() + instruction_size();
3849}
3850
3851
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003852int Code::body_size() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003853 return RoundUp(instruction_size(), kObjectAlignment);
3854}
3855
3856
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003857FixedArray* Code::unchecked_deoptimization_data() {
3858 return reinterpret_cast<FixedArray*>(
3859 READ_FIELD(this, kDeoptimizationDataOffset));
3860}
3861
3862
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003863ByteArray* Code::unchecked_relocation_info() {
3864 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003865}
3866
3867
3868byte* Code::relocation_start() {
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003869 return unchecked_relocation_info()->GetDataStartAddress();
3870}
3871
3872
3873int Code::relocation_size() {
3874 return unchecked_relocation_info()->length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003875}
3876
3877
3878byte* Code::entry() {
3879 return instruction_start();
3880}
3881
3882
3883bool Code::contains(byte* pc) {
3884 return (instruction_start() <= pc) &&
ricow@chromium.org65fae842010-08-25 15:26:24 +00003885 (pc <= instruction_start() + instruction_size());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003886}
3887
3888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003889ACCESSORS(JSArray, length, Object, kLengthOffset)
3890
3891
ager@chromium.org236ad962008-09-25 09:45:57 +00003892ACCESSORS(JSRegExp, data, Object, kDataOffset)
ager@chromium.org236ad962008-09-25 09:45:57 +00003893
3894
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003895JSRegExp::Type JSRegExp::TypeTag() {
3896 Object* data = this->data();
3897 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3898 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3899 return static_cast<JSRegExp::Type>(smi->value());
ager@chromium.org236ad962008-09-25 09:45:57 +00003900}
3901
3902
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003903JSRegExp::Type JSRegExp::TypeTagUnchecked() {
3904 Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
3905 return static_cast<JSRegExp::Type>(smi->value());
3906}
3907
3908
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003909int JSRegExp::CaptureCount() {
3910 switch (TypeTag()) {
3911 case ATOM:
3912 return 0;
3913 case IRREGEXP:
3914 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3915 default:
3916 UNREACHABLE();
3917 return -1;
3918 }
3919}
3920
3921
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003922JSRegExp::Flags JSRegExp::GetFlags() {
3923 ASSERT(this->data()->IsFixedArray());
3924 Object* data = this->data();
3925 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3926 return Flags(smi->value());
3927}
3928
3929
3930String* JSRegExp::Pattern() {
3931 ASSERT(this->data()->IsFixedArray());
3932 Object* data = this->data();
3933 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3934 return pattern;
3935}
3936
3937
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00003938Object* JSRegExp::DataAt(int index) {
3939 ASSERT(TypeTag() != NOT_COMPILED);
3940 return FixedArray::cast(data())->get(index);
ager@chromium.org236ad962008-09-25 09:45:57 +00003941}
3942
3943
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003944Object* JSRegExp::DataAtUnchecked(int index) {
3945 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
3946 int offset = FixedArray::kHeaderSize + index * kPointerSize;
3947 return READ_FIELD(fa, offset);
3948}
3949
3950
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003951void JSRegExp::SetDataAt(int index, Object* value) {
3952 ASSERT(TypeTag() != NOT_COMPILED);
3953 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3954 FixedArray::cast(data())->set(index, value);
3955}
3956
3957
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003958void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
3959 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
3960 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
3961 if (value->IsSmi()) {
3962 fa->set_unchecked(index, Smi::cast(value));
3963 } else {
3964 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
3965 }
3966}
3967
3968
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003969JSObject::ElementsKind JSObject::GetElementsKind() {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00003970 ElementsKind kind = map()->elements_kind();
3971 ASSERT((kind == FAST_ELEMENTS &&
3972 (elements()->map() == GetHeap()->fixed_array_map() ||
3973 elements()->map() == GetHeap()->fixed_cow_array_map())) ||
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003974 (kind == FAST_DOUBLE_ELEMENTS &&
3975 elements()->IsFixedDoubleArray()) ||
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00003976 (kind == DICTIONARY_ELEMENTS &&
3977 elements()->IsFixedArray() &&
3978 elements()->IsDictionary()) ||
3979 (kind > DICTIONARY_ELEMENTS));
3980 return kind;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003981}
3982
3983
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003984bool JSObject::HasFastElements() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003985 return GetElementsKind() == FAST_ELEMENTS;
3986}
3987
3988
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003989bool JSObject::HasFastDoubleElements() {
3990 return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
3991}
3992
3993
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00003994bool JSObject::HasDictionaryElements() {
3995 return GetElementsKind() == DICTIONARY_ELEMENTS;
3996}
3997
3998
ager@chromium.org3811b432009-10-28 14:53:37 +00003999bool JSObject::HasExternalArrayElements() {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004000 HeapObject* array = elements();
4001 ASSERT(array != NULL);
4002 return array->IsExternalArray();
ager@chromium.org3811b432009-10-28 14:53:37 +00004003}
4004
4005
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004006#define EXTERNAL_ELEMENTS_CHECK(name, type) \
4007bool JSObject::HasExternal##name##Elements() { \
4008 HeapObject* array = elements(); \
4009 ASSERT(array != NULL); \
4010 if (!array->IsHeapObject()) \
4011 return false; \
4012 return array->map()->instance_type() == type; \
ager@chromium.org3811b432009-10-28 14:53:37 +00004013}
4014
4015
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004016EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4017EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4018EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4019EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4020 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4021EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4022EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4023 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4024EXTERNAL_ELEMENTS_CHECK(Float,
4025 EXTERNAL_FLOAT_ARRAY_TYPE)
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00004026EXTERNAL_ELEMENTS_CHECK(Double,
4027 EXTERNAL_DOUBLE_ARRAY_TYPE)
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004028EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
ager@chromium.org3811b432009-10-28 14:53:37 +00004029
4030
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004031bool JSObject::HasNamedInterceptor() {
4032 return map()->has_named_interceptor();
4033}
4034
4035
4036bool JSObject::HasIndexedInterceptor() {
4037 return map()->has_indexed_interceptor();
4038}
4039
4040
ager@chromium.org5c838252010-02-19 08:53:10 +00004041bool JSObject::AllowsSetElementsLength() {
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004042 bool result = elements()->IsFixedArray() ||
4043 elements()->IsFixedDoubleArray();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004044 ASSERT(result == !HasExternalArrayElements());
ager@chromium.org5c838252010-02-19 08:53:10 +00004045 return result;
4046}
4047
4048
lrn@chromium.org303ada72010-10-27 09:33:13 +00004049MaybeObject* JSObject::EnsureWritableFastElements() {
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004050 ASSERT(HasFastElements());
4051 FixedArray* elems = FixedArray::cast(elements());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004052 Isolate* isolate = GetIsolate();
4053 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
lrn@chromium.org303ada72010-10-27 09:33:13 +00004054 Object* writable_elems;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004055 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4056 elems, isolate->heap()->fixed_array_map());
lrn@chromium.org303ada72010-10-27 09:33:13 +00004057 if (!maybe_writable_elems->ToObject(&writable_elems)) {
4058 return maybe_writable_elems;
4059 }
4060 }
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004061 set_elements(FixedArray::cast(writable_elems));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004062 isolate->counters()->cow_arrays_converted()->Increment();
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004063 return writable_elems;
4064}
4065
4066
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004067StringDictionary* JSObject::property_dictionary() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004068 ASSERT(!HasFastProperties());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004069 return StringDictionary::cast(properties());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004070}
4071
4072
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004073NumberDictionary* JSObject::element_dictionary() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00004074 ASSERT(HasDictionaryElements());
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004075 return NumberDictionary::cast(elements());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004076}
4077
4078
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004079bool String::IsHashFieldComputed(uint32_t field) {
4080 return (field & kHashNotComputedMask) == 0;
4081}
4082
4083
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004084bool String::HasHashCode() {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004085 return IsHashFieldComputed(hash_field());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004086}
4087
4088
4089uint32_t String::Hash() {
4090 // Fast case: has hash code already been computed?
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00004091 uint32_t field = hash_field();
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004092 if (IsHashFieldComputed(field)) return field >> kHashShift;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004093 // Slow case: compute hash code and set it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004094 return ComputeAndSetHash();
4095}
4096
4097
ager@chromium.org7c537e22008-10-16 08:43:32 +00004098StringHasher::StringHasher(int length)
4099 : length_(length),
4100 raw_running_hash_(0),
4101 array_index_(0),
4102 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4103 is_first_char_(true),
4104 is_valid_(true) { }
4105
4106
4107bool StringHasher::has_trivial_hash() {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00004108 return length_ > String::kMaxHashCalcLength;
ager@chromium.org7c537e22008-10-16 08:43:32 +00004109}
4110
4111
4112void StringHasher::AddCharacter(uc32 c) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004113 // Use the Jenkins one-at-a-time hash function to update the hash
4114 // for the given character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00004115 raw_running_hash_ += c;
4116 raw_running_hash_ += (raw_running_hash_ << 10);
4117 raw_running_hash_ ^= (raw_running_hash_ >> 6);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004118 // Incremental array index computation.
ager@chromium.org7c537e22008-10-16 08:43:32 +00004119 if (is_array_index_) {
4120 if (c < '0' || c > '9') {
4121 is_array_index_ = false;
4122 } else {
4123 int d = c - '0';
4124 if (is_first_char_) {
4125 is_first_char_ = false;
4126 if (c == '0' && length_ > 1) {
4127 is_array_index_ = false;
4128 return;
4129 }
4130 }
4131 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4132 is_array_index_ = false;
4133 } else {
4134 array_index_ = array_index_ * 10 + d;
4135 }
4136 }
4137 }
4138}
4139
4140
4141void StringHasher::AddCharacterNoIndex(uc32 c) {
4142 ASSERT(!is_array_index());
4143 raw_running_hash_ += c;
4144 raw_running_hash_ += (raw_running_hash_ << 10);
4145 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4146}
4147
4148
4149uint32_t StringHasher::GetHash() {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00004150 // Get the calculated raw hash value and do some more bit ops to distribute
4151 // the hash further. Ensure that we never return zero as the hash value.
ager@chromium.org7c537e22008-10-16 08:43:32 +00004152 uint32_t result = raw_running_hash_;
4153 result += (result << 3);
4154 result ^= (result >> 11);
4155 result += (result << 15);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00004156 if (result == 0) {
4157 result = 27;
4158 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00004159 return result;
4160}
4161
4162
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00004163template <typename schar>
4164uint32_t HashSequentialString(const schar* chars, int length) {
4165 StringHasher hasher(length);
4166 if (!hasher.has_trivial_hash()) {
4167 int i;
4168 for (i = 0; hasher.is_array_index() && (i < length); i++) {
4169 hasher.AddCharacter(chars[i]);
4170 }
4171 for (; i < length; i++) {
4172 hasher.AddCharacterNoIndex(chars[i]);
4173 }
4174 }
4175 return hasher.GetHashField();
4176}
4177
4178
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004179bool String::AsArrayIndex(uint32_t* index) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00004180 uint32_t field = hash_field();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00004181 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4182 return false;
4183 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004184 return SlowAsArrayIndex(index);
4185}
4186
4187
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004188Object* JSReceiver::GetPrototype() {
4189 return HeapObject::cast(this)->map()->prototype();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004190}
4191
4192
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004193bool JSReceiver::HasProperty(String* name) {
4194 if (IsJSProxy()) {
4195 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4196 }
4197 return GetPropertyAttribute(name) != ABSENT;
4198}
4199
4200
4201bool JSReceiver::HasLocalProperty(String* name) {
4202 if (IsJSProxy()) {
4203 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4204 }
4205 return GetLocalPropertyAttribute(name) != ABSENT;
4206}
4207
4208
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004209PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004210 return GetPropertyAttributeWithReceiver(this, key);
4211}
4212
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004213// TODO(504): this may be useful in other places too where JSGlobalProxy
4214// is used.
4215Object* JSObject::BypassGlobalProxy() {
4216 if (IsJSGlobalProxy()) {
4217 Object* proto = GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004218 if (proto->IsNull()) return GetHeap()->undefined_value();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004219 ASSERT(proto->IsJSGlobalObject());
4220 return proto;
4221 }
4222 return this;
4223}
4224
4225
4226bool JSObject::HasHiddenPropertiesObject() {
4227 ASSERT(!IsJSGlobalProxy());
4228 return GetPropertyAttributePostInterceptor(this,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004229 GetHeap()->hidden_symbol(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004230 false) != ABSENT;
4231}
4232
4233
4234Object* JSObject::GetHiddenPropertiesObject() {
4235 ASSERT(!IsJSGlobalProxy());
4236 PropertyAttributes attributes;
lrn@chromium.org303ada72010-10-27 09:33:13 +00004237 // You can't install a getter on a property indexed by the hidden symbol,
4238 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
4239 // object.
4240 Object* result =
4241 GetLocalPropertyPostInterceptor(this,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004242 GetHeap()->hidden_symbol(),
lrn@chromium.org303ada72010-10-27 09:33:13 +00004243 &attributes)->ToObjectUnchecked();
4244 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004245}
4246
4247
lrn@chromium.org303ada72010-10-27 09:33:13 +00004248MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004249 ASSERT(!IsJSGlobalProxy());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004250 return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004251 hidden_obj,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00004252 DONT_ENUM,
4253 kNonStrictMode);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004254}
4255
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004256
vegorov@chromium.org7943d462011-08-01 11:41:52 +00004257bool JSObject::HasHiddenProperties() {
4258 return !GetHiddenProperties(OMIT_CREATION)->ToObjectChecked()->IsUndefined();
4259}
4260
4261
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004262bool JSObject::HasElement(uint32_t index) {
4263 return HasElementWithReceiver(this, index);
4264}
4265
4266
4267bool AccessorInfo::all_can_read() {
4268 return BooleanBit::get(flag(), kAllCanReadBit);
4269}
4270
4271
4272void AccessorInfo::set_all_can_read(bool value) {
4273 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4274}
4275
4276
4277bool AccessorInfo::all_can_write() {
4278 return BooleanBit::get(flag(), kAllCanWriteBit);
4279}
4280
4281
4282void AccessorInfo::set_all_can_write(bool value) {
4283 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4284}
4285
4286
ager@chromium.org870a0b62008-11-04 11:43:05 +00004287bool AccessorInfo::prohibits_overwriting() {
4288 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4289}
4290
4291
4292void AccessorInfo::set_prohibits_overwriting(bool value) {
4293 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4294}
4295
4296
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004297PropertyAttributes AccessorInfo::property_attributes() {
4298 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4299}
4300
4301
4302void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
4303 ASSERT(AttributesField::is_valid(attributes));
4304 int rest_value = flag()->value() & ~AttributesField::mask();
4305 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
4306}
4307
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004308
4309template<typename Shape, typename Key>
4310void Dictionary<Shape, Key>::SetEntry(int entry,
4311 Object* key,
4312 Object* value) {
4313 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4314}
4315
4316
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004317template<typename Shape, typename Key>
4318void Dictionary<Shape, Key>::SetEntry(int entry,
4319 Object* key,
4320 Object* value,
4321 PropertyDetails details) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00004322 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004323 int index = HashTable<Shape, Key>::EntryToIndex(entry);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00004324 AssertNoAllocation no_gc;
4325 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00004326 FixedArray::set(index, key, mode);
4327 FixedArray::set(index+1, value, mode);
4328 FixedArray::fast_set(this, index+2, details.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004329}
4330
4331
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004332bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4333 ASSERT(other->IsNumber());
4334 return key == static_cast<uint32_t>(other->Number());
4335}
4336
4337
4338uint32_t NumberDictionaryShape::Hash(uint32_t key) {
4339 return ComputeIntegerHash(key);
4340}
4341
4342
4343uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
4344 ASSERT(other->IsNumber());
4345 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
4346}
4347
4348
4349MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4350 return Isolate::Current()->heap()->NumberFromUint32(key);
4351}
4352
4353
4354bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4355 // We know that all entries in a hash table had their hash keys created.
4356 // Use that knowledge to have fast failure.
4357 if (key->Hash() != String::cast(other)->Hash()) return false;
4358 return key->Equals(String::cast(other));
4359}
4360
4361
4362uint32_t StringDictionaryShape::Hash(String* key) {
4363 return key->Hash();
4364}
4365
4366
4367uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4368 return String::cast(other)->Hash();
4369}
4370
4371
4372MaybeObject* StringDictionaryShape::AsObject(String* key) {
4373 return key;
4374}
4375
4376
vegorov@chromium.org7943d462011-08-01 11:41:52 +00004377bool ObjectHashTableShape::IsMatch(JSObject* key, Object* other) {
4378 return key == JSObject::cast(other);
4379}
4380
4381
4382uint32_t ObjectHashTableShape::Hash(JSObject* key) {
4383 MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION);
4384 ASSERT(!maybe_hash->IsFailure());
4385 return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
4386}
4387
4388
4389uint32_t ObjectHashTableShape::HashForObject(JSObject* key, Object* other) {
4390 MaybeObject* maybe_hash = JSObject::cast(other)->GetIdentityHash(
4391 JSObject::OMIT_CREATION);
4392 ASSERT(!maybe_hash->IsFailure());
4393 return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
4394}
4395
4396
4397MaybeObject* ObjectHashTableShape::AsObject(JSObject* key) {
4398 return key;
4399}
4400
4401
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004402void Map::ClearCodeCache(Heap* heap) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004403 // No write barrier is needed since empty_fixed_array is not in new space.
4404 // Please note this function is used during marking:
4405 // - MarkCompactCollector::MarkUnmarkedObject
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004406 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4407 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004408}
4409
4410
ager@chromium.org5aa501c2009-06-23 07:57:28 +00004411void JSArray::EnsureSize(int required_size) {
4412 ASSERT(HasFastElements());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004413 FixedArray* elts = FixedArray::cast(elements());
ager@chromium.org6141cbe2009-11-20 12:14:52 +00004414 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4415 if (elts->length() < required_size) {
4416 // Doubling in size would be overkill, but leave some slack to avoid
4417 // constantly growing.
4418 Expand(required_size + (required_size >> 3));
4419 // It's a performance benefit to keep a frequently used array in new-space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004420 } else if (!GetHeap()->new_space()->Contains(elts) &&
ager@chromium.org6141cbe2009-11-20 12:14:52 +00004421 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4422 // Expand will allocate a new backing store in new space even if the size
4423 // we asked for isn't larger than what we had before.
4424 Expand(required_size);
4425 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00004426}
4427
4428
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00004429void JSArray::set_length(Smi* length) {
4430 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4431}
4432
4433
ager@chromium.org7c537e22008-10-16 08:43:32 +00004434void JSArray::SetContent(FixedArray* storage) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00004435 set_length(Smi::FromInt(storage->length()));
ager@chromium.org7c537e22008-10-16 08:43:32 +00004436 set_elements(storage);
4437}
4438
4439
lrn@chromium.org303ada72010-10-27 09:33:13 +00004440MaybeObject* FixedArray::Copy() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004441 if (length() == 0) return this;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004442 return GetHeap()->CopyFixedArray(this);
4443}
4444
4445
4446Relocatable::Relocatable(Isolate* isolate) {
4447 ASSERT(isolate == Isolate::Current());
4448 isolate_ = isolate;
4449 prev_ = isolate->relocatable_top();
4450 isolate->set_relocatable_top(this);
4451}
4452
4453
4454Relocatable::~Relocatable() {
4455 ASSERT(isolate_ == Isolate::Current());
4456 ASSERT_EQ(isolate_->relocatable_top(), this);
4457 isolate_->set_relocatable_top(prev_);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004458}
4459
4460
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004461int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4462 return map->instance_size();
4463}
4464
4465
ager@chromium.orgea91cc52011-05-23 06:06:11 +00004466void Foreign::ForeignIterateBody(ObjectVisitor* v) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004467 v->VisitExternalReference(
ager@chromium.orgea91cc52011-05-23 06:06:11 +00004468 reinterpret_cast<Address *>(FIELD_ADDR(this, kAddressOffset)));
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004469}
4470
4471
4472template<typename StaticVisitor>
ager@chromium.orgea91cc52011-05-23 06:06:11 +00004473void Foreign::ForeignIterateBody() {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004474 StaticVisitor::VisitExternalReference(
ager@chromium.orgea91cc52011-05-23 06:06:11 +00004475 reinterpret_cast<Address *>(FIELD_ADDR(this, kAddressOffset)));
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004476}
4477
4478
4479void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4480 typedef v8::String::ExternalAsciiStringResource Resource;
4481 v->VisitExternalAsciiString(
4482 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4483}
4484
4485
4486template<typename StaticVisitor>
4487void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4488 typedef v8::String::ExternalAsciiStringResource Resource;
4489 StaticVisitor::VisitExternalAsciiString(
4490 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4491}
4492
4493
4494void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4495 typedef v8::String::ExternalStringResource Resource;
4496 v->VisitExternalTwoByteString(
4497 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4498}
4499
4500
4501template<typename StaticVisitor>
4502void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4503 typedef v8::String::ExternalStringResource Resource;
4504 StaticVisitor::VisitExternalTwoByteString(
4505 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4506}
4507
4508#define SLOT_ADDR(obj, offset) \
4509 reinterpret_cast<Object**>((obj)->address() + offset)
4510
4511template<int start_offset, int end_offset, int size>
4512void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4513 HeapObject* obj,
4514 ObjectVisitor* v) {
4515 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4516}
4517
4518
4519template<int start_offset>
4520void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4521 int object_size,
4522 ObjectVisitor* v) {
4523 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4524}
4525
4526#undef SLOT_ADDR
4527
4528
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004529#undef CAST_ACCESSOR
4530#undef INT_ACCESSORS
4531#undef SMI_ACCESSORS
4532#undef ACCESSORS
4533#undef FIELD_ADDR
4534#undef READ_FIELD
4535#undef WRITE_FIELD
4536#undef WRITE_BARRIER
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004537#undef CONDITIONAL_WRITE_BARRIER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004538#undef READ_MEMADDR_FIELD
4539#undef WRITE_MEMADDR_FIELD
4540#undef READ_DOUBLE_FIELD
4541#undef WRITE_DOUBLE_FIELD
4542#undef READ_INT_FIELD
4543#undef WRITE_INT_FIELD
4544#undef READ_SHORT_FIELD
4545#undef WRITE_SHORT_FIELD
4546#undef READ_BYTE_FIELD
4547#undef WRITE_BYTE_FIELD
4548
4549
4550} } // namespace v8::internal
4551
4552#endif // V8_OBJECTS_INL_H_