blob: c963f6f5cd17c9a5e11469612888945460d97184 [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#ifndef V8_OBJECTS_H_
29#define V8_OBJECTS_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include "builtins.h"
ager@chromium.orgea91cc52011-05-23 06:06:11 +000033#include "list.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034#include "smart-pointer.h"
35#include "unicode-inl.h"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000036#if V8_TARGET_ARCH_ARM
37#include "arm/constants-arm.h"
ager@chromium.org5c838252010-02-19 08:53:10 +000038#elif V8_TARGET_ARCH_MIPS
39#include "mips/constants-mips.h"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000040#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
42//
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +000043// Most object types in the V8 JavaScript are described in this file.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044//
45// Inheritance hierarchy:
lrn@chromium.org303ada72010-10-27 09:33:13 +000046// - MaybeObject (an object or a failure)
47// - Failure (immediate for marking failed operation)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000048// - Object
49// - Smi (immediate small integer)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050// - HeapObject (superclass for everything allocated in the heap)
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000051// - JSReceiver (suitable for property access)
52// - JSObject
53// - JSArray
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000054// - JSWeakMap
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000055// - JSRegExp
56// - JSFunction
57// - GlobalObject
58// - JSGlobalObject
59// - JSBuiltinsObject
60// - JSGlobalProxy
61// - JSValue
62// - JSMessageObject
63// - JSProxy
64// - JSFunctionProxy
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000065// - FixedArrayBase
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000066// - ByteArray
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000067// - FixedArray
68// - DescriptorArray
69// - HashTable
70// - Dictionary
71// - SymbolTable
72// - CompilationCacheTable
73// - CodeCacheHashTable
74// - MapCache
75// - Context
76// - JSFunctionResultCache
77// - SerializedScopeInfo
78// - FixedDoubleArray
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000079// - ExternalArray
80// - ExternalPixelArray
81// - ExternalByteArray
82// - ExternalUnsignedByteArray
83// - ExternalShortArray
84// - ExternalUnsignedShortArray
85// - ExternalIntArray
86// - ExternalUnsignedIntArray
87// - ExternalFloatArray
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000088// - String
89// - SeqString
ager@chromium.org7c537e22008-10-16 08:43:32 +000090// - SeqAsciiString
91// - SeqTwoByteString
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092// - ConsString
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000093// - ExternalString
94// - ExternalAsciiString
95// - ExternalTwoByteString
96// - HeapNumber
97// - Code
98// - Map
99// - Oddball
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000100// - Foreign
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101// - SharedFunctionInfo
102// - Struct
103// - AccessorInfo
104// - AccessCheckInfo
105// - InterceptorInfo
106// - CallHandlerInfo
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000107// - TemplateInfo
108// - FunctionTemplateInfo
109// - ObjectTemplateInfo
110// - Script
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111// - SignatureInfo
112// - TypeSwitchInfo
113// - DebugInfo
114// - BreakPointInfo
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000115// - CodeCache
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116//
117// Formats of Object*:
118// Smi: [31 bit signed int] 0
119// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
120// Failure: [30 bit signed int] 11
121
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122// Ecma-262 3rd 8.6.1
123enum PropertyAttributes {
124 NONE = v8::None,
125 READ_ONLY = v8::ReadOnly,
126 DONT_ENUM = v8::DontEnum,
127 DONT_DELETE = v8::DontDelete,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 ABSENT = 16 // Used in runtime to indicate a property is absent.
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000129 // ABSENT can never be stored in or returned from a descriptor's attributes
130 // bitfield. It is only used as a return value meaning the attributes of
131 // a non-existent property.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000132};
133
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000134namespace v8 {
135namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136
137
138// PropertyDetails captures type and attributes for a property.
139// They are used both in property dictionaries and instance descriptors.
140class PropertyDetails BASE_EMBEDDED {
141 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142 PropertyDetails(PropertyAttributes attributes,
143 PropertyType type,
144 int index = 0) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000145 ASSERT(type != EXTERNAL_ARRAY_TRANSITION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146 ASSERT(TypeField::is_valid(type));
147 ASSERT(AttributesField::is_valid(attributes));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000148 ASSERT(StorageField::is_valid(index));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149
150 value_ = TypeField::encode(type)
151 | AttributesField::encode(attributes)
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000152 | StorageField::encode(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000153
154 ASSERT(type == this->type());
155 ASSERT(attributes == this->attributes());
156 ASSERT(index == this->index());
157 }
158
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000159 PropertyDetails(PropertyAttributes attributes,
160 PropertyType type,
161 ExternalArrayType array_type) {
162 ASSERT(type == EXTERNAL_ARRAY_TRANSITION);
163 ASSERT(TypeField::is_valid(type));
164 ASSERT(AttributesField::is_valid(attributes));
165 ASSERT(StorageField::is_valid(static_cast<int>(array_type)));
166
167 value_ = TypeField::encode(type)
168 | AttributesField::encode(attributes)
169 | StorageField::encode(static_cast<int>(array_type));
170
171 ASSERT(type == this->type());
172 ASSERT(attributes == this->attributes());
173 ASSERT(array_type == this->array_type());
174 }
175
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176 // Conversion for storing details as Object*.
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000177 explicit inline PropertyDetails(Smi* smi);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 inline Smi* AsSmi();
179
180 PropertyType type() { return TypeField::decode(value_); }
181
182 bool IsTransition() {
183 PropertyType t = type();
184 ASSERT(t != INTERCEPTOR);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000185 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
186 t == EXTERNAL_ARRAY_TRANSITION;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187 }
188
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000189 bool IsProperty() {
190 return type() < FIRST_PHANTOM_PROPERTY_TYPE;
191 }
192
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193 PropertyAttributes attributes() { return AttributesField::decode(value_); }
194
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000195 int index() { return StorageField::decode(value_); }
196
197 ExternalArrayType array_type() {
198 ASSERT(type() == EXTERNAL_ARRAY_TRANSITION);
199 return static_cast<ExternalArrayType>(StorageField::decode(value_));
200 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000202 inline PropertyDetails AsDeleted();
203
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000204 static bool IsValidIndex(int index) {
205 return StorageField::is_valid(index);
206 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207
208 bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
209 bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; }
210 bool IsDontEnum() { return (attributes() & DONT_ENUM) != 0; }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000211 bool IsDeleted() { return DeletedField::decode(value_) != 0;}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212
213 // Bit fields in value_ (type, shift, size). Must be public so the
214 // constants can be embedded in generated code.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000215 class TypeField: public BitField<PropertyType, 0, 4> {};
216 class AttributesField: public BitField<PropertyAttributes, 4, 3> {};
217 class DeletedField: public BitField<uint32_t, 7, 1> {};
218 class StorageField: public BitField<uint32_t, 8, 32-8> {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219
220 static const int kInitialIndex = 1;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000221
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 private:
223 uint32_t value_;
224};
225
ager@chromium.org32912102009-01-16 10:38:43 +0000226
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000227// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
228enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
229
ager@chromium.org32912102009-01-16 10:38:43 +0000230
231// PropertyNormalizationMode is used to specify whether to keep
232// inobject properties when normalizing properties of a JSObject.
233enum PropertyNormalizationMode {
234 CLEAR_INOBJECT_PROPERTIES,
235 KEEP_INOBJECT_PROPERTIES
236};
237
238
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000239// NormalizedMapSharingMode is used to specify whether a map may be shared
240// by different objects with normalized properties.
241enum NormalizedMapSharingMode {
242 UNIQUE_NORMALIZED_MAP,
243 SHARED_NORMALIZED_MAP
244};
245
246
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000247// Instance size sentinel for objects of variable size.
248static const int kVariableSizeSentinel = 0;
249
250
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251// All Maps have a field instance_type containing a InstanceType.
252// It describes the type of the instances.
253//
254// As an example, a JavaScript object is a heap object and its map
255// instance_type is JS_OBJECT_TYPE.
256//
257// The names of the string instance types are intended to systematically
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000258// mirror their encoding in the instance_type field of the map. The default
259// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
260// encoding is mentioned explicitly in the name. Likewise, the default
261// representation is considered sequential. It is not mentioned in the
262// name. The other representations (eg, CONS, EXTERNAL) are explicitly
263// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
264// symbol) or a STRING_TYPE (if it is not a symbol).
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265//
266// NOTE: The following things are some that depend on the string types having
267// instance_types that are less than those of all other types:
268// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
269// Object::IsString.
270//
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000271// NOTE: Everything following JS_VALUE_TYPE is considered a
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000272// JSObject for GC purposes. The first four entries here have typeof
273// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000274#define INSTANCE_TYPE_LIST_ALL(V) \
275 V(SYMBOL_TYPE) \
276 V(ASCII_SYMBOL_TYPE) \
277 V(CONS_SYMBOL_TYPE) \
278 V(CONS_ASCII_SYMBOL_TYPE) \
279 V(EXTERNAL_SYMBOL_TYPE) \
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000280 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000281 V(EXTERNAL_ASCII_SYMBOL_TYPE) \
282 V(STRING_TYPE) \
283 V(ASCII_STRING_TYPE) \
284 V(CONS_STRING_TYPE) \
285 V(CONS_ASCII_STRING_TYPE) \
286 V(EXTERNAL_STRING_TYPE) \
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000287 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000288 V(EXTERNAL_ASCII_STRING_TYPE) \
289 V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
290 \
291 V(MAP_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000292 V(CODE_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000293 V(ODDBALL_TYPE) \
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000294 V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000295 \
296 V(HEAP_NUMBER_TYPE) \
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000297 V(FOREIGN_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000298 V(BYTE_ARRAY_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000299 /* Note: the order of these external array */ \
300 /* types is relied upon in */ \
301 /* Object::IsExternalArray(). */ \
302 V(EXTERNAL_BYTE_ARRAY_TYPE) \
303 V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
304 V(EXTERNAL_SHORT_ARRAY_TYPE) \
305 V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
306 V(EXTERNAL_INT_ARRAY_TYPE) \
307 V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
308 V(EXTERNAL_FLOAT_ARRAY_TYPE) \
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000309 V(EXTERNAL_PIXEL_ARRAY_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000310 V(FILLER_TYPE) \
311 \
312 V(ACCESSOR_INFO_TYPE) \
313 V(ACCESS_CHECK_INFO_TYPE) \
314 V(INTERCEPTOR_INFO_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000315 V(CALL_HANDLER_INFO_TYPE) \
316 V(FUNCTION_TEMPLATE_INFO_TYPE) \
317 V(OBJECT_TEMPLATE_INFO_TYPE) \
318 V(SIGNATURE_INFO_TYPE) \
319 V(TYPE_SWITCH_INFO_TYPE) \
320 V(SCRIPT_TYPE) \
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000321 V(CODE_CACHE_TYPE) \
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000322 V(POLYMORPHIC_CODE_CACHE_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000323 \
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000324 V(FIXED_ARRAY_TYPE) \
325 V(SHARED_FUNCTION_INFO_TYPE) \
326 \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000327 V(JS_MESSAGE_OBJECT_TYPE) \
328 \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000329 V(JS_VALUE_TYPE) \
330 V(JS_OBJECT_TYPE) \
331 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
332 V(JS_GLOBAL_OBJECT_TYPE) \
333 V(JS_BUILTINS_OBJECT_TYPE) \
334 V(JS_GLOBAL_PROXY_TYPE) \
335 V(JS_ARRAY_TYPE) \
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000336 V(JS_PROXY_TYPE) \
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000337 V(JS_WEAK_MAP_TYPE) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000338 V(JS_REGEXP_TYPE) \
339 \
340 V(JS_FUNCTION_TYPE) \
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000341 V(JS_FUNCTION_PROXY_TYPE) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000343#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000344#define INSTANCE_TYPE_LIST_DEBUGGER(V) \
345 V(DEBUG_INFO_TYPE) \
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000346 V(BREAK_POINT_INFO_TYPE)
347#else
348#define INSTANCE_TYPE_LIST_DEBUGGER(V)
349#endif
350
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000351#define INSTANCE_TYPE_LIST(V) \
352 INSTANCE_TYPE_LIST_ALL(V) \
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000353 INSTANCE_TYPE_LIST_DEBUGGER(V)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000354
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000355
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000356// Since string types are not consecutive, this macro is used to
357// iterate over them.
358#define STRING_TYPE_LIST(V) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000359 V(SYMBOL_TYPE, \
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000360 kVariableSizeSentinel, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000361 symbol, \
362 Symbol) \
363 V(ASCII_SYMBOL_TYPE, \
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000364 kVariableSizeSentinel, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000365 ascii_symbol, \
366 AsciiSymbol) \
367 V(CONS_SYMBOL_TYPE, \
368 ConsString::kSize, \
369 cons_symbol, \
370 ConsSymbol) \
371 V(CONS_ASCII_SYMBOL_TYPE, \
372 ConsString::kSize, \
373 cons_ascii_symbol, \
374 ConsAsciiSymbol) \
375 V(EXTERNAL_SYMBOL_TYPE, \
376 ExternalTwoByteString::kSize, \
377 external_symbol, \
378 ExternalSymbol) \
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000379 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
380 ExternalTwoByteString::kSize, \
381 external_symbol_with_ascii_data, \
382 ExternalSymbolWithAsciiData) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000383 V(EXTERNAL_ASCII_SYMBOL_TYPE, \
384 ExternalAsciiString::kSize, \
385 external_ascii_symbol, \
386 ExternalAsciiSymbol) \
387 V(STRING_TYPE, \
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000388 kVariableSizeSentinel, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000389 string, \
390 String) \
391 V(ASCII_STRING_TYPE, \
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000392 kVariableSizeSentinel, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000393 ascii_string, \
394 AsciiString) \
395 V(CONS_STRING_TYPE, \
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000396 ConsString::kSize, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000397 cons_string, \
398 ConsString) \
399 V(CONS_ASCII_STRING_TYPE, \
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000400 ConsString::kSize, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000401 cons_ascii_string, \
402 ConsAsciiString) \
403 V(EXTERNAL_STRING_TYPE, \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404 ExternalTwoByteString::kSize, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000405 external_string, \
406 ExternalString) \
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000407 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
408 ExternalTwoByteString::kSize, \
409 external_string_with_ascii_data, \
410 ExternalStringWithAsciiData) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000411 V(EXTERNAL_ASCII_STRING_TYPE, \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000412 ExternalAsciiString::kSize, \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000413 external_ascii_string, \
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000414 ExternalAsciiString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415
416// A struct is a simple object a set of object-valued fields. Including an
417// object type in this causes the compiler to generate most of the boilerplate
418// code for the class including allocation and garbage collection routines,
419// casts and predicates. All you need to define is the class, methods and
420// object verification routines. Easy, no?
421//
422// Note that for subtle reasons related to the ordering or numerical values of
423// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
424// manually.
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000425#define STRUCT_LIST_ALL(V) \
426 V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
427 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
428 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
429 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
430 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
431 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
432 V(SIGNATURE_INFO, SignatureInfo, signature_info) \
433 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000434 V(SCRIPT, Script, script) \
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000435 V(CODE_CACHE, CodeCache, code_cache) \
436 V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000437
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000438#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000439#define STRUCT_LIST_DEBUGGER(V) \
440 V(DEBUG_INFO, DebugInfo, debug_info) \
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000441 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
442#else
443#define STRUCT_LIST_DEBUGGER(V)
444#endif
445
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000446#define STRUCT_LIST(V) \
447 STRUCT_LIST_ALL(V) \
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000448 STRUCT_LIST_DEBUGGER(V)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000449
450// We use the full 8 bits of the instance_type field to encode heap object
451// instance types. The high-order bit (bit 7) is set if the object is not a
452// string, and cleared if it is a string.
453const uint32_t kIsNotStringMask = 0x80;
454const uint32_t kStringTag = 0x0;
455const uint32_t kNotStringTag = 0x80;
456
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000457// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
458// There are not enough types that the non-string types (with bit 7 set) can
459// have bit 6 set too.
460const uint32_t kIsSymbolMask = 0x40;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461const uint32_t kNotSymbolTag = 0x0;
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000462const uint32_t kSymbolTag = 0x40;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000463
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000464// If bit 7 is clear then bit 2 indicates whether the string consists of
465// two-byte characters or one-byte characters.
466const uint32_t kStringEncodingMask = 0x4;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467const uint32_t kTwoByteStringTag = 0x0;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000468const uint32_t kAsciiStringTag = 0x4;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000470// If bit 7 is clear, the low-order 2 bits indicate the representation
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000471// of the string.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000472const uint32_t kStringRepresentationMask = 0x03;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473enum StringRepresentationTag {
474 kSeqStringTag = 0x0,
475 kConsStringTag = 0x1,
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000476 kExternalStringTag = 0x2
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477};
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000478const uint32_t kIsConsStringMask = 0x1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000479
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000480// If bit 7 is clear, then bit 3 indicates whether this two-byte
481// string actually contains ascii data.
482const uint32_t kAsciiDataHintMask = 0x08;
483const uint32_t kAsciiDataHintTag = 0x08;
484
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000485
486// A ConsString with an empty string as the right side is a candidate
487// for being shortcut by the garbage collector unless it is a
488// symbol. It's not common to have non-flat symbols, so we do not
489// shortcut them thereby avoiding turning symbols into strings. See
490// heap.cc and mark-compact.cc.
491const uint32_t kShortcutTypeMask =
492 kIsNotStringMask |
493 kIsSymbolMask |
494 kStringRepresentationMask;
495const uint32_t kShortcutTypeTag = kConsStringTag;
496
497
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000498enum InstanceType {
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000499 // String types.
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000500 SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000501 ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000502 CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000503 CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000504 EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
505 EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
506 kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000507 EXTERNAL_ASCII_SYMBOL_TYPE =
508 kAsciiStringTag | kSymbolTag | kExternalStringTag,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000509 STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000510 ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000511 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000512 CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000513 EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
514 EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
515 kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000516 // LAST_STRING_TYPE
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000517 EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
518 PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000520 // Objects allocated in their own spaces (never in new space).
521 MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522 CODE_TYPE,
523 ODDBALL_TYPE,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000524 JS_GLOBAL_PROPERTY_CELL_TYPE,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000525
526 // "Data", objects that cannot contain non-map-word pointers to heap
527 // objects.
528 HEAP_NUMBER_TYPE,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000529 FOREIGN_TYPE,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000530 BYTE_ARRAY_TYPE,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000531 EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
ager@chromium.org3811b432009-10-28 14:53:37 +0000532 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
533 EXTERNAL_SHORT_ARRAY_TYPE,
534 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
535 EXTERNAL_INT_ARRAY_TYPE,
536 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000537 EXTERNAL_FLOAT_ARRAY_TYPE,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000538 EXTERNAL_DOUBLE_ARRAY_TYPE,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000539 EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000540 FIXED_DOUBLE_ARRAY_TYPE,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000541 FILLER_TYPE, // LAST_DATA_TYPE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000543 // Structs.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544 ACCESSOR_INFO_TYPE,
545 ACCESS_CHECK_INFO_TYPE,
546 INTERCEPTOR_INFO_TYPE,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000547 CALL_HANDLER_INFO_TYPE,
548 FUNCTION_TEMPLATE_INFO_TYPE,
549 OBJECT_TEMPLATE_INFO_TYPE,
550 SIGNATURE_INFO_TYPE,
551 TYPE_SWITCH_INFO_TYPE,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000552 SCRIPT_TYPE,
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000553 CODE_CACHE_TYPE,
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000554 POLYMORPHIC_CODE_CACHE_TYPE,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000555 // The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
556 // is defined. However as include/v8.h contain some of the instance type
557 // constants always having them avoids them getting different numbers
558 // depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559 DEBUG_INFO_TYPE,
560 BREAK_POINT_INFO_TYPE,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000562 FIXED_ARRAY_TYPE,
563 SHARED_FUNCTION_INFO_TYPE,
564
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000565 JS_MESSAGE_OBJECT_TYPE,
566
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000567 JS_VALUE_TYPE, // FIRST_NON_CALLABLE_OBJECT_TYPE, FIRST_JS_RECEIVER_TYPE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 JS_OBJECT_TYPE,
ager@chromium.org32912102009-01-16 10:38:43 +0000569 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000570 JS_GLOBAL_OBJECT_TYPE,
571 JS_BUILTINS_OBJECT_TYPE,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000572 JS_GLOBAL_PROXY_TYPE,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573 JS_ARRAY_TYPE,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000574 JS_PROXY_TYPE,
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000575 JS_WEAK_MAP_TYPE,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000576
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000577 JS_REGEXP_TYPE, // LAST_NONCALLABLE_SPEC_OBJECT_TYPE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000578
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000579 JS_FUNCTION_TYPE, // FIRST_CALLABLE_SPEC_OBJECT_TYPE
580 JS_FUNCTION_PROXY_TYPE, // LAST_CALLABLE_SPEC_OBJECT_TYPE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581
582 // Pseudo-types
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583 FIRST_TYPE = 0x0,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000584 LAST_TYPE = JS_FUNCTION_PROXY_TYPE,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000585 INVALID_TYPE = FIRST_TYPE - 1,
586 FIRST_NONSTRING_TYPE = MAP_TYPE,
587 // Boundaries for testing for an external array.
588 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000589 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000590 // Boundary for promotion to old data space/old pointer space.
591 LAST_DATA_TYPE = FILLER_TYPE,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000592 // Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
593 // Note that there is no range for JSObject or JSProxy, since their subtypes
594 // are not continuous in this enum! The enum ranges instead reflect the
595 // external class names, where proxies are treated as either ordinary objects,
596 // or functions.
597 FIRST_JS_RECEIVER_TYPE = JS_VALUE_TYPE,
598 LAST_JS_RECEIVER_TYPE = LAST_TYPE,
599 // Boundaries for testing the types for which typeof is "object".
600 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_VALUE_TYPE,
601 LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE,
602 // Boundaries for testing the types for which typeof is "function".
603 FIRST_CALLABLE_SPEC_OBJECT_TYPE = JS_FUNCTION_TYPE,
604 LAST_CALLABLE_SPEC_OBJECT_TYPE = JS_FUNCTION_PROXY_TYPE,
605 // Boundaries for testing whether the type is a JavaScript object.
606 FIRST_SPEC_OBJECT_TYPE = FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
607 LAST_SPEC_OBJECT_TYPE = LAST_CALLABLE_SPEC_OBJECT_TYPE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000608};
609
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000610static const int kExternalArrayTypeCount = LAST_EXTERNAL_ARRAY_TYPE -
611 FIRST_EXTERNAL_ARRAY_TYPE + 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000613STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
614STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000615STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000616
617
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618enum CompareResult {
619 LESS = -1,
620 EQUAL = 0,
621 GREATER = 1,
622
623 NOT_EQUAL = GREATER
624};
625
626
627#define DECL_BOOLEAN_ACCESSORS(name) \
628 inline bool name(); \
629 inline void set_##name(bool value); \
630
631
ager@chromium.org32912102009-01-16 10:38:43 +0000632#define DECL_ACCESSORS(name, type) \
633 inline type* name(); \
634 inline void set_##name(type* value, \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000635 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636
637
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000638class DictionaryElementsAccessor;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000639class ElementsAccessor;
640class FixedArrayBase;
641class ObjectVisitor;
642class StringStream;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643
644struct ValueInfo : public Malloced {
645 ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
646 InstanceType type;
647 Object* ptr;
648 const char* str;
649 double number;
650};
651
652
653// A template-ized version of the IsXXX functions.
654template <class C> static inline bool Is(Object* obj);
655
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000656class Failure;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000657
lrn@chromium.org303ada72010-10-27 09:33:13 +0000658class MaybeObject BASE_EMBEDDED {
659 public:
660 inline bool IsFailure();
661 inline bool IsRetryAfterGC();
662 inline bool IsOutOfMemory();
663 inline bool IsException();
664 INLINE(bool IsTheHole());
665 inline bool ToObject(Object** obj) {
666 if (IsFailure()) return false;
667 *obj = reinterpret_cast<Object*>(this);
668 return true;
669 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000670 inline Failure* ToFailureUnchecked() {
671 ASSERT(IsFailure());
672 return reinterpret_cast<Failure*>(this);
673 }
lrn@chromium.org303ada72010-10-27 09:33:13 +0000674 inline Object* ToObjectUnchecked() {
675 ASSERT(!IsFailure());
676 return reinterpret_cast<Object*>(this);
677 }
678 inline Object* ToObjectChecked() {
679 CHECK(!IsFailure());
680 return reinterpret_cast<Object*>(this);
681 }
682
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000683 template<typename T>
684 inline bool To(T** obj) {
685 if (IsFailure()) return false;
686 *obj = T::cast(reinterpret_cast<Object*>(this));
687 return true;
688 }
689
whesse@chromium.org023421e2010-12-21 12:19:12 +0000690#ifdef OBJECT_PRINT
lrn@chromium.org303ada72010-10-27 09:33:13 +0000691 // Prints this object with details.
whesse@chromium.org023421e2010-12-21 12:19:12 +0000692 inline void Print() {
693 Print(stdout);
694 };
695 inline void PrintLn() {
696 PrintLn(stdout);
697 }
698 void Print(FILE* out);
699 void PrintLn(FILE* out);
700#endif
701#ifdef DEBUG
lrn@chromium.org303ada72010-10-27 09:33:13 +0000702 // Verifies the object.
703 void Verify();
704#endif
705};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000706
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000707
708#define OBJECT_TYPE_LIST(V) \
709 V(Smi) \
710 V(HeapObject) \
711 V(Number) \
712
713#define HEAP_OBJECT_TYPE_LIST(V) \
714 V(HeapNumber) \
715 V(String) \
716 V(Symbol) \
717 V(SeqString) \
718 V(ExternalString) \
719 V(ConsString) \
720 V(ExternalTwoByteString) \
721 V(ExternalAsciiString) \
722 V(SeqTwoByteString) \
723 V(SeqAsciiString) \
724 \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000725 V(ExternalArray) \
726 V(ExternalByteArray) \
727 V(ExternalUnsignedByteArray) \
728 V(ExternalShortArray) \
729 V(ExternalUnsignedShortArray) \
730 V(ExternalIntArray) \
731 V(ExternalUnsignedIntArray) \
732 V(ExternalFloatArray) \
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000733 V(ExternalDoubleArray) \
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000734 V(ExternalPixelArray) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000735 V(ByteArray) \
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000736 V(JSReceiver) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000737 V(JSObject) \
738 V(JSContextExtensionObject) \
739 V(Map) \
740 V(DescriptorArray) \
741 V(DeoptimizationInputData) \
742 V(DeoptimizationOutputData) \
743 V(FixedArray) \
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000744 V(FixedDoubleArray) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000745 V(Context) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000746 V(GlobalContext) \
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000747 V(SerializedScopeInfo) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000748 V(JSFunction) \
749 V(Code) \
750 V(Oddball) \
751 V(SharedFunctionInfo) \
752 V(JSValue) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000753 V(JSMessageObject) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000754 V(StringWrapper) \
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000755 V(Foreign) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000756 V(Boolean) \
757 V(JSArray) \
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000758 V(JSProxy) \
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000759 V(JSFunctionProxy) \
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000760 V(JSWeakMap) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000761 V(JSRegExp) \
762 V(HashTable) \
763 V(Dictionary) \
764 V(SymbolTable) \
765 V(JSFunctionResultCache) \
766 V(NormalizedMapCache) \
767 V(CompilationCacheTable) \
768 V(CodeCacheHashTable) \
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000769 V(PolymorphicCodeCacheHashTable) \
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000770 V(MapCache) \
771 V(Primitive) \
772 V(GlobalObject) \
773 V(JSGlobalObject) \
774 V(JSBuiltinsObject) \
775 V(JSGlobalProxy) \
776 V(UndetectableObject) \
777 V(AccessCheckNeeded) \
778 V(JSGlobalPropertyCell) \
779
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780// Object is the abstract superclass for all classes in the
781// object hierarchy.
782// Object does not use any virtual functions to avoid the
783// allocation of the C++ vtable.
784// Since Smi and Failure are subclasses of Object no
785// data members can be present in Object.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000786class Object : public MaybeObject {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787 public:
788 // Type testing.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000789#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
790 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
791 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
792#undef IS_TYPE_FUNCTION_DECL
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793
794 // Returns true if this object is an instance of the specified
795 // function template.
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000796 inline bool IsInstanceOf(FunctionTemplateInfo* type);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000797
798 inline bool IsStruct();
799#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
800 STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
801#undef DECLARE_STRUCT_PREDICATE
802
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000803 INLINE(bool IsSpecObject());
804
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805 // Oddball testing.
806 INLINE(bool IsUndefined());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000807 INLINE(bool IsNull());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000808 INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000809 INLINE(bool IsTrue());
810 INLINE(bool IsFalse());
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000811 inline bool IsArgumentsMarker();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812
813 // Extract the number.
814 inline double Number();
815
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000816 // Returns true if the object is of the correct type to be used as a
817 // implementation of a JSObject's elements.
818 inline bool HasValidElements();
819
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000820 inline bool HasSpecificClassOf(String* name);
821
lrn@chromium.org303ada72010-10-27 09:33:13 +0000822 MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9.
823 Object* ToBoolean(); // ECMA-262 9.2.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824
825 // Convert to a JSObject if needed.
826 // global_context is used when creating wrapper object.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000827 MUST_USE_RESULT MaybeObject* ToObject(Context* global_context);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000828
829 // Converts this to a Smi if possible.
830 // Failure is returned otherwise.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000831 MUST_USE_RESULT inline MaybeObject* ToSmi();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832
833 void Lookup(String* name, LookupResult* result);
834
835 // Property access.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000836 MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
837 MUST_USE_RESULT inline MaybeObject* GetProperty(
838 String* key,
839 PropertyAttributes* attributes);
840 MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
841 Object* receiver,
842 String* key,
843 PropertyAttributes* attributes);
844 MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
845 LookupResult* result,
846 String* key,
847 PropertyAttributes* attributes);
848 MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
849 Object* structure,
850 String* name,
851 Object* holder);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000852 MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(Object* receiver,
853 String* name,
854 Object* handler);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000855 MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
856 JSFunction* getter);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857
lrn@chromium.org303ada72010-10-27 09:33:13 +0000858 inline MaybeObject* GetElement(uint32_t index);
859 // For use when we know that no exception can be thrown.
860 inline Object* GetElementNoExceptionThrown(uint32_t index);
861 MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862
863 // Return the object's prototype (might be Heap::null_value()).
864 Object* GetPrototype();
865
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000866 // Tries to convert an object to an array index. Returns true and sets
867 // the output parameter if it succeeds.
868 inline bool ToArrayIndex(uint32_t* index);
869
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870 // Returns true if this is a JSValue containing a string and the index is
871 // < the length of the string. Used to implement [] on strings.
872 inline bool IsStringObjectWithCharacterAt(uint32_t index);
873
874#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 // Verify a pointer is a valid object pointer.
876 static void VerifyPointer(Object* p);
877#endif
878
879 // Prints this object without details.
whesse@chromium.org023421e2010-12-21 12:19:12 +0000880 inline void ShortPrint() {
881 ShortPrint(stdout);
882 }
883 void ShortPrint(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000884
885 // Prints this object without details to a message accumulator.
886 void ShortPrint(StringStream* accumulator);
887
888 // Casting: This cast is only needed to satisfy macros in objects-inl.h.
889 static Object* cast(Object* value) { return value; }
890
891 // Layout description.
ager@chromium.org236ad962008-09-25 09:45:57 +0000892 static const int kHeaderSize = 0; // Object does not take up any space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893
894 private:
895 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
896};
897
898
899// Smi represents integer Numbers that can be stored in 31 bits.
900// Smis are immediate which means they are NOT allocated in the heap.
ager@chromium.org4af710e2009-09-15 12:20:11 +0000901// The this pointer has the following format: [31 bit signed int] 0
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000902// For long smis it has the following format:
903// [32 bit signed int] [31 bits zero padding] 0
904// Smi stands for small integer.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000905class Smi: public Object {
906 public:
907 // Returns the integer value.
908 inline int value();
909
910 // Convert a value to a Smi object.
911 static inline Smi* FromInt(int value);
912
ager@chromium.org9085a012009-05-11 19:22:57 +0000913 static inline Smi* FromIntptr(intptr_t value);
914
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915 // Returns whether value can be represented in a Smi.
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000916 static inline bool IsValid(intptr_t value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000917
918 // Casting.
919 static inline Smi* cast(Object* object);
920
921 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +0000922 inline void SmiPrint() {
923 SmiPrint(stdout);
924 }
925 void SmiPrint(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000926 void SmiPrint(StringStream* accumulator);
927#ifdef DEBUG
928 void SmiVerify();
929#endif
930
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000931 static const int kMinValue = (-1 << (kSmiValueSize - 1));
932 static const int kMaxValue = -(kMinValue + 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000933
934 private:
935 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
936};
937
938
ager@chromium.org6f10e412009-02-13 10:11:16 +0000939// Failure is used for reporting out of memory situations and
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000940// propagating exceptions through the runtime system. Failure objects
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000941// are transient and cannot occur as part of the object graph.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000942//
943// Failures are a single word, encoded as follows:
944// +-------------------------+---+--+--+
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000945// |.........unused..........|sss|tt|11|
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000946// +-------------------------+---+--+--+
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000947// 7 6 4 32 10
948//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000949//
950// The low two bits, 0-1, are the failure tag, 11. The next two bits,
951// 2-3, are a failure type tag 'tt' with possible values:
952// 00 RETRY_AFTER_GC
953// 01 EXCEPTION
954// 10 INTERNAL_ERROR
955// 11 OUT_OF_MEMORY_EXCEPTION
956//
957// The next three bits, 4-6, are an allocation space tag 'sss'. The
958// allocation space tag is 000 for all failure types except
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000959// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
960// allocation spaces (the encoding is found in globals.h).
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000961
962// Failure type tag info.
963const int kFailureTypeTagSize = 2;
964const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
965
lrn@chromium.org303ada72010-10-27 09:33:13 +0000966class Failure: public MaybeObject {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000967 public:
968 // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
969 enum Type {
970 RETRY_AFTER_GC = 0,
971 EXCEPTION = 1, // Returning this marker tells the real exception
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000972 // is in Isolate::pending_exception.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973 INTERNAL_ERROR = 2,
974 OUT_OF_MEMORY_EXCEPTION = 3
975 };
976
977 inline Type type() const;
978
979 // Returns the space that needs to be collected for RetryAfterGC failures.
980 inline AllocationSpace allocation_space() const;
981
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000982 inline bool IsInternalError() const;
983 inline bool IsOutOfMemoryException() const;
984
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000985 static inline Failure* RetryAfterGC(AllocationSpace space);
986 static inline Failure* RetryAfterGC(); // NEW_SPACE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000987 static inline Failure* Exception();
988 static inline Failure* InternalError();
989 static inline Failure* OutOfMemoryException();
990 // Casting.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000991 static inline Failure* cast(MaybeObject* object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000992
993 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +0000994 inline void FailurePrint() {
995 FailurePrint(stdout);
996 }
997 void FailurePrint(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000998 void FailurePrint(StringStream* accumulator);
999#ifdef DEBUG
1000 void FailureVerify();
1001#endif
1002
1003 private:
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001004 inline intptr_t value() const;
1005 static inline Failure* Construct(Type type, intptr_t value = 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001006
1007 DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
1008};
1009
1010
kasper.lund7276f142008-07-30 08:49:36 +00001011// Heap objects typically have a map pointer in their first word. However,
1012// during GC other data (eg, mark bits, forwarding addresses) is sometimes
1013// encoded in the first word. The class MapWord is an abstraction of the
1014// value in a heap object's first word.
1015class MapWord BASE_EMBEDDED {
1016 public:
1017 // Normal state: the map word contains a map pointer.
1018
1019 // Create a map word from a map pointer.
1020 static inline MapWord FromMap(Map* map);
1021
1022 // View this map word as a map pointer.
1023 inline Map* ToMap();
1024
1025
1026 // Scavenge collection: the map word of live objects in the from space
1027 // contains a forwarding address (a heap object pointer in the to space).
1028
1029 // True if this map word is a forwarding address for a scavenge
1030 // collection. Only valid during a scavenge collection (specifically,
1031 // when all map words are heap object pointers, ie. not during a full GC).
1032 inline bool IsForwardingAddress();
1033
1034 // Create a map word from a forwarding address.
1035 static inline MapWord FromForwardingAddress(HeapObject* object);
1036
1037 // View this map word as a forwarding address.
1038 inline HeapObject* ToForwardingAddress();
1039
kasper.lund7276f142008-07-30 08:49:36 +00001040 // Marking phase of full collection: the map word of live objects is
1041 // marked, and may be marked as overflowed (eg, the object is live, its
1042 // children have not been visited, and it does not fit in the marking
1043 // stack).
1044
1045 // True if this map word's mark bit is set.
1046 inline bool IsMarked();
1047
1048 // Return this map word but with its mark bit set.
1049 inline void SetMark();
1050
1051 // Return this map word but with its mark bit cleared.
1052 inline void ClearMark();
1053
1054 // True if this map word's overflow bit is set.
1055 inline bool IsOverflowed();
1056
1057 // Return this map word but with its overflow bit set.
1058 inline void SetOverflow();
1059
1060 // Return this map word but with its overflow bit cleared.
1061 inline void ClearOverflow();
1062
1063
1064 // Compacting phase of a full compacting collection: the map word of live
1065 // objects contains an encoding of the original map address along with the
1066 // forwarding address (represented as an offset from the first live object
1067 // in the same page as the (old) object address).
1068
1069 // Create a map word from a map address and a forwarding address offset.
1070 static inline MapWord EncodeAddress(Address map_address, int offset);
1071
1072 // Return the map address encoded in this map word.
1073 inline Address DecodeMapAddress(MapSpace* map_space);
1074
1075 // Return the forwarding offset encoded in this map word.
1076 inline int DecodeOffset();
1077
1078
1079 // During serialization: the map word is used to hold an encoded
1080 // address, and possibly a mark bit (set and cleared with SetMark
1081 // and ClearMark).
1082
1083 // Create a map word from an encoded address.
1084 static inline MapWord FromEncodedAddress(Address address);
1085
1086 inline Address ToEncodedAddress();
1087
kasper.lund7276f142008-07-30 08:49:36 +00001088 // Bits used by the marking phase of the garbage collector.
1089 //
ager@chromium.org6f10e412009-02-13 10:11:16 +00001090 // The first word of a heap object is normally a map pointer. The last two
kasper.lund7276f142008-07-30 08:49:36 +00001091 // bits are tagged as '01' (kHeapObjectTag). We reuse the last two bits to
1092 // mark an object as live and/or overflowed:
1093 // last bit = 0, marked as alive
1094 // second bit = 1, overflowed
1095 // An object is only marked as overflowed when it is marked as live while
1096 // the marking stack is overflowed.
1097 static const int kMarkingBit = 0; // marking bit
1098 static const int kMarkingMask = (1 << kMarkingBit); // marking mask
1099 static const int kOverflowBit = 1; // overflow bit
1100 static const int kOverflowMask = (1 << kOverflowBit); // overflow mask
1101
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001102 // Forwarding pointers and map pointer encoding. On 32 bit all the bits are
1103 // used.
kasper.lund7276f142008-07-30 08:49:36 +00001104 // +-----------------+------------------+-----------------+
1105 // |forwarding offset|page offset of map|page index of map|
1106 // +-----------------+------------------+-----------------+
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001107 // ^ ^ ^
1108 // | | |
1109 // | | kMapPageIndexBits
1110 // | kMapPageOffsetBits
1111 // kForwardingOffsetBits
1112 static const int kMapPageOffsetBits = kPageSizeBits - kMapAlignmentBits;
1113 static const int kForwardingOffsetBits = kPageSizeBits - kObjectAlignmentBits;
1114#ifdef V8_HOST_ARCH_64_BIT
1115 static const int kMapPageIndexBits = 16;
1116#else
1117 // Use all the 32-bits to encode on a 32-bit platform.
1118 static const int kMapPageIndexBits =
1119 32 - (kMapPageOffsetBits + kForwardingOffsetBits);
1120#endif
kasper.lund7276f142008-07-30 08:49:36 +00001121
1122 static const int kMapPageIndexShift = 0;
1123 static const int kMapPageOffsetShift =
1124 kMapPageIndexShift + kMapPageIndexBits;
1125 static const int kForwardingOffsetShift =
1126 kMapPageOffsetShift + kMapPageOffsetBits;
1127
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001128 // Bit masks covering the different parts the encoding.
1129 static const uintptr_t kMapPageIndexMask =
kasper.lund7276f142008-07-30 08:49:36 +00001130 (1 << kMapPageOffsetShift) - 1;
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001131 static const uintptr_t kMapPageOffsetMask =
kasper.lund7276f142008-07-30 08:49:36 +00001132 ((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask;
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001133 static const uintptr_t kForwardingOffsetMask =
kasper.lund7276f142008-07-30 08:49:36 +00001134 ~(kMapPageIndexMask | kMapPageOffsetMask);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001135
1136 private:
1137 // HeapObject calls the private constructor and directly reads the value.
1138 friend class HeapObject;
1139
1140 explicit MapWord(uintptr_t value) : value_(value) {}
1141
1142 uintptr_t value_;
kasper.lund7276f142008-07-30 08:49:36 +00001143};
1144
1145
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146// HeapObject is the superclass for all classes describing heap allocated
1147// objects.
1148class HeapObject: public Object {
1149 public:
kasper.lund7276f142008-07-30 08:49:36 +00001150 // [map]: Contains a map which contains the object's reflective
1151 // information.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001152 inline Map* map();
1153 inline void set_map(Map* value);
1154
kasper.lund7276f142008-07-30 08:49:36 +00001155 // During garbage collection, the map word of a heap object does not
1156 // necessarily contain a map pointer.
1157 inline MapWord map_word();
1158 inline void set_map_word(MapWord map_word);
1159
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001160 // The Heap the object was allocated in. Used also to access Isolate.
1161 // This method can not be used during GC, it ASSERTs this.
1162 inline Heap* GetHeap();
1163 // Convenience method to get current isolate. This method can be
1164 // accessed only when its result is the same as
1165 // Isolate::Current(), it ASSERTs this. See also comment for GetHeap.
1166 inline Isolate* GetIsolate();
1167
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001168 // Converts an address to a HeapObject pointer.
1169 static inline HeapObject* FromAddress(Address address);
1170
1171 // Returns the address of this HeapObject.
1172 inline Address address();
1173
1174 // Iterates over pointers contained in the object (including the Map)
1175 void Iterate(ObjectVisitor* v);
1176
1177 // Iterates over all pointers contained in the object except the
1178 // first map pointer. The object type is given in the first
1179 // parameter. This function does not access the map pointer in the
1180 // object, and so is safe to call while the map pointer is modified.
1181 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
1182
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001183 // Returns the heap object's size in bytes
1184 inline int Size();
1185
1186 // Given a heap object's map pointer, returns the heap size in bytes
1187 // Useful when the map pointer field is used for other purposes.
1188 // GC internal.
1189 inline int SizeFromMap(Map* map);
1190
kasper.lund7276f142008-07-30 08:49:36 +00001191 // Support for the marking heap objects during the marking phase of GC.
1192 // True if the object is marked live.
1193 inline bool IsMarked();
1194
1195 // Mutate this object's map pointer to indicate that the object is live.
1196 inline void SetMark();
1197
1198 // Mutate this object's map pointer to remove the indication that the
1199 // object is live (ie, partially restore the map pointer).
1200 inline void ClearMark();
1201
1202 // True if this object is marked as overflowed. Overflowed objects have
1203 // been reached and marked during marking of the heap, but their children
1204 // have not necessarily been marked and they have not been pushed on the
1205 // marking stack.
1206 inline bool IsOverflowed();
1207
1208 // Mutate this object's map pointer to indicate that the object is
1209 // overflowed.
1210 inline void SetOverflow();
1211
1212 // Mutate this object's map pointer to remove the indication that the
1213 // object is overflowed (ie, partially restore the map pointer).
1214 inline void ClearOverflow();
1215
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00001216 // Returns the field at offset in obj, as a read/write Object* reference.
1217 // Does no checking, and is safe to use during GC, while maps are invalid.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001218 // Does not invoke write barrier, so should only be assigned to
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00001219 // during marking GC.
1220 static inline Object** RawField(HeapObject* obj, int offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001221
1222 // Casting.
1223 static inline HeapObject* cast(Object* obj);
1224
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001225 // Return the write barrier mode for this. Callers of this function
1226 // must be able to present a reference to an AssertNoAllocation
1227 // object as a sign that they are not going to use this function
1228 // from code that allocates and thus invalidates the returned write
1229 // barrier mode.
1230 inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001231
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001232 // Dispatched behavior.
1233 void HeapObjectShortPrint(StringStream* accumulator);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001234#ifdef OBJECT_PRINT
1235 inline void HeapObjectPrint() {
1236 HeapObjectPrint(stdout);
1237 }
1238 void HeapObjectPrint(FILE* out);
1239#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001241 void HeapObjectVerify();
1242 inline void VerifyObjectField(int offset);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001243 inline void VerifySmiField(int offset);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001244#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245
whesse@chromium.org023421e2010-12-21 12:19:12 +00001246#ifdef OBJECT_PRINT
1247 void PrintHeader(FILE* out, const char* id);
1248#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249
whesse@chromium.org023421e2010-12-21 12:19:12 +00001250#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001251 // Verify a pointer is a valid HeapObject pointer that points to object
1252 // areas in the heap.
1253 static void VerifyHeapPointer(Object* p);
1254#endif
1255
1256 // Layout description.
1257 // First field in a heap object is map.
ager@chromium.org236ad962008-09-25 09:45:57 +00001258 static const int kMapOffset = Object::kHeaderSize;
1259 static const int kHeaderSize = kMapOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001260
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001261 STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
1262
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001263 protected:
1264 // helpers for calling an ObjectVisitor to iterate over pointers in the
1265 // half-open range [start, end) specified as integer offsets
1266 inline void IteratePointers(ObjectVisitor* v, int start, int end);
1267 // as above, for the single element at "offset"
1268 inline void IteratePointer(ObjectVisitor* v, int offset);
1269
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 private:
1271 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
1272};
1273
1274
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001275#define SLOT_ADDR(obj, offset) \
1276 reinterpret_cast<Object**>((obj)->address() + offset)
1277
1278// This class describes a body of an object of a fixed size
1279// in which all pointer fields are located in the [start_offset, end_offset)
1280// interval.
1281template<int start_offset, int end_offset, int size>
1282class FixedBodyDescriptor {
1283 public:
1284 static const int kStartOffset = start_offset;
1285 static const int kEndOffset = end_offset;
1286 static const int kSize = size;
1287
1288 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
1289
1290 template<typename StaticVisitor>
1291 static inline void IterateBody(HeapObject* obj) {
1292 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1293 SLOT_ADDR(obj, end_offset));
1294 }
1295};
1296
1297
1298// This class describes a body of an object of a variable size
1299// in which all pointer fields are located in the [start_offset, object_size)
1300// interval.
1301template<int start_offset>
1302class FlexibleBodyDescriptor {
1303 public:
1304 static const int kStartOffset = start_offset;
1305
1306 static inline void IterateBody(HeapObject* obj,
1307 int object_size,
1308 ObjectVisitor* v);
1309
1310 template<typename StaticVisitor>
1311 static inline void IterateBody(HeapObject* obj, int object_size) {
1312 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1313 SLOT_ADDR(obj, object_size));
1314 }
1315};
1316
1317#undef SLOT_ADDR
1318
1319
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320// The HeapNumber class describes heap allocated numbers that cannot be
1321// represented in a Smi (small integer)
1322class HeapNumber: public HeapObject {
1323 public:
1324 // [value]: number value.
1325 inline double value();
1326 inline void set_value(double value);
1327
1328 // Casting.
1329 static inline HeapNumber* cast(Object* obj);
1330
1331 // Dispatched behavior.
1332 Object* HeapNumberToBoolean();
whesse@chromium.org023421e2010-12-21 12:19:12 +00001333 inline void HeapNumberPrint() {
1334 HeapNumberPrint(stdout);
1335 }
1336 void HeapNumberPrint(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337 void HeapNumberPrint(StringStream* accumulator);
1338#ifdef DEBUG
1339 void HeapNumberVerify();
1340#endif
1341
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001342 inline int get_exponent();
1343 inline int get_sign();
1344
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001345 // Layout description.
ager@chromium.org236ad962008-09-25 09:45:57 +00001346 static const int kValueOffset = HeapObject::kHeaderSize;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001347 // IEEE doubles are two 32 bit words. The first is just mantissa, the second
1348 // is a mixture of sign, exponent and mantissa. Our current platforms are all
1349 // little endian apart from non-EABI arm which is little endian with big
1350 // endian floating point word ordering!
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001351 static const int kMantissaOffset = kValueOffset;
1352 static const int kExponentOffset = kValueOffset + 4;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001353
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354 static const int kSize = kValueOffset + kDoubleSize;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001355 static const uint32_t kSignMask = 0x80000000u;
1356 static const uint32_t kExponentMask = 0x7ff00000u;
1357 static const uint32_t kMantissaMask = 0xfffffu;
ager@chromium.orgac091b72010-05-05 07:34:42 +00001358 static const int kMantissaBits = 52;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +00001359 static const int kExponentBits = 11;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001360 static const int kExponentBias = 1023;
1361 static const int kExponentShift = 20;
1362 static const int kMantissaBitsInTopWord = 20;
1363 static const int kNonMantissaBitsInTopWord = 12;
1364
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365 private:
1366 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1367};
1368
1369
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001370// JSReceiver includes types on which properties can be defined, i.e.,
1371// JSObject and JSProxy.
1372class JSReceiver: public HeapObject {
1373 public:
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001374 enum DeleteMode {
1375 NORMAL_DELETION,
1376 STRICT_DELETION,
1377 FORCE_DELETION
1378 };
1379
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001380 // Casting.
1381 static inline JSReceiver* cast(Object* obj);
1382
1383 // Can cause GC.
1384 MUST_USE_RESULT MaybeObject* SetProperty(String* key,
1385 Object* value,
1386 PropertyAttributes attributes,
1387 StrictModeFlag strict_mode);
1388 MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
1389 String* key,
1390 Object* value,
1391 PropertyAttributes attributes,
1392 StrictModeFlag strict_mode);
1393
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001394 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
1395
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001396 // Returns the class name ([[Class]] property in the specification).
1397 String* class_name();
1398
1399 // Returns the constructor name (the name (possibly, inferred name) of the
1400 // function that was used to instantiate the object).
1401 String* constructor_name();
1402
1403 inline PropertyAttributes GetPropertyAttribute(String* name);
1404 PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
1405 String* name);
1406 PropertyAttributes GetLocalPropertyAttribute(String* name);
1407
1408 // Can cause a GC.
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001409 inline bool HasProperty(String* name);
1410 inline bool HasLocalProperty(String* name);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001411
1412 // Return the object's prototype (might be Heap::null_value()).
1413 inline Object* GetPrototype();
1414
1415 // Set the object's prototype (only JSReceiver and null are allowed).
1416 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
1417 bool skip_hidden_prototypes);
1418
1419 // Lookup a property. If found, the result is valid and has
1420 // detailed information.
1421 void LocalLookup(String* name, LookupResult* result);
1422 void Lookup(String* name, LookupResult* result);
1423
1424 private:
1425 PropertyAttributes GetPropertyAttribute(JSReceiver* receiver,
1426 LookupResult* result,
1427 String* name,
1428 bool continue_search);
1429
1430 DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
1431};
1432
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433// The JSObject describes real heap allocated JavaScript objects with
1434// properties.
1435// Note that the map of JSObject changes during execution to enable inline
1436// caching.
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001437class JSObject: public JSReceiver {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001438 public:
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001439 enum ElementsKind {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001440 // The "fast" kind for tagged values. Must be first to make it possible
1441 // to efficiently check maps if they have fast elements.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001442 FAST_ELEMENTS,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001443
1444 // The "fast" kind for unwrapped, non-tagged double values.
1445 FAST_DOUBLE_ELEMENTS,
1446
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001447 // The "slow" kind.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001448 DICTIONARY_ELEMENTS,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001449 NON_STRICT_ARGUMENTS_ELEMENTS,
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001450 // The "fast" kind for external arrays
ager@chromium.org3811b432009-10-28 14:53:37 +00001451 EXTERNAL_BYTE_ELEMENTS,
1452 EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
1453 EXTERNAL_SHORT_ELEMENTS,
1454 EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
1455 EXTERNAL_INT_ELEMENTS,
1456 EXTERNAL_UNSIGNED_INT_ELEMENTS,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001457 EXTERNAL_FLOAT_ELEMENTS,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001458 EXTERNAL_DOUBLE_ELEMENTS,
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001459 EXTERNAL_PIXEL_ELEMENTS,
1460
1461 // Derived constants from ElementsKind
1462 FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_BYTE_ELEMENTS,
1463 LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
1464 FIRST_ELEMENTS_KIND = FAST_ELEMENTS,
1465 LAST_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001466 };
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001467
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001468 static const int kElementsKindCount =
1469 LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
1470
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001471 // [properties]: Backing storage for properties.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001472 // properties is a FixedArray in the fast case and a Dictionary in the
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001473 // slow case.
1474 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001475 inline void initialize_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476 inline bool HasFastProperties();
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001477 inline StringDictionary* property_dictionary(); // Gets slow properties.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001478
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001479 // [elements]: The elements (properties with names that are integers).
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001480 //
1481 // Elements can be in two general modes: fast and slow. Each mode
1482 // corrensponds to a set of object representations of elements that
1483 // have something in common.
1484 //
1485 // In the fast mode elements is a FixedArray and so each element can
1486 // be quickly accessed. This fact is used in the generated code. The
whesse@chromium.org7b260152011-06-20 15:33:18 +00001487 // elements array can have one of three maps in this mode:
1488 // fixed_array_map, non_strict_arguments_elements_map or
1489 // fixed_cow_array_map (for copy-on-write arrays). In the latter case
1490 // the elements array may be shared by a few objects and so before
1491 // writing to any element the array must be copied. Use
1492 // EnsureWritableFastElements in this case.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001493 //
whesse@chromium.org7b260152011-06-20 15:33:18 +00001494 // In the slow mode the elements is either a NumberDictionary, an
1495 // ExternalArray, or a FixedArray parameter map for a (non-strict)
1496 // arguments object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001497 DECL_ACCESSORS(elements, FixedArrayBase)
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001498 inline void initialize_elements();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001499 MUST_USE_RESULT inline MaybeObject* ResetElements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001500 inline ElementsKind GetElementsKind();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00001501 inline ElementsAccessor* GetElementsAccessor();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001502 inline bool HasFastElements();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001503 inline bool HasFastDoubleElements();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001504 inline bool HasDictionaryElements();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001505 inline bool HasExternalPixelElements();
ager@chromium.org3811b432009-10-28 14:53:37 +00001506 inline bool HasExternalArrayElements();
1507 inline bool HasExternalByteElements();
1508 inline bool HasExternalUnsignedByteElements();
1509 inline bool HasExternalShortElements();
1510 inline bool HasExternalUnsignedShortElements();
1511 inline bool HasExternalIntElements();
1512 inline bool HasExternalUnsignedIntElements();
1513 inline bool HasExternalFloatElements();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001514 inline bool HasExternalDoubleElements();
whesse@chromium.org7b260152011-06-20 15:33:18 +00001515 bool HasFastArgumentsElements();
1516 bool HasDictionaryArgumentsElements();
ager@chromium.org5c838252010-02-19 08:53:10 +00001517 inline bool AllowsSetElementsLength();
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001518 inline NumberDictionary* element_dictionary(); // Gets slow elements.
whesse@chromium.org7b260152011-06-20 15:33:18 +00001519
1520 // Requires: HasFastElements().
lrn@chromium.org303ada72010-10-27 09:33:13 +00001521 MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001522
ager@chromium.org5ec48922009-05-05 07:25:34 +00001523 // Collects elements starting at index 0.
1524 // Undefined values are placed after non-undefined values.
1525 // Returns the number of non-undefined values.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001526 MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
ager@chromium.org5ec48922009-05-05 07:25:34 +00001527 // As PrepareElementsForSort, but only on objects where elements is
1528 // a dictionary, and it will stay a dictionary.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001529 MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
ager@chromium.org5ec48922009-05-05 07:25:34 +00001530
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001531 MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001532 String* key,
1533 Object* value,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001534 PropertyAttributes attributes,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001535 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001536 MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
1537 LookupResult* result,
1538 String* name,
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001539 Object* value,
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001540 bool check_prototype,
1541 StrictModeFlag strict_mode);
1542 MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
1543 Object* structure,
1544 String* name,
1545 Object* value,
1546 JSObject* holder,
1547 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001548 MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSFunction* setter,
1549 Object* value);
1550 MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
1551 String* name,
1552 Object* value,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001553 PropertyAttributes attributes,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001554 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001555 MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
1556 String* name,
1557 Object* value,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001558 PropertyAttributes attributes,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001559 StrictModeFlag strict_mode);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001560 MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
lrn@chromium.org303ada72010-10-27 09:33:13 +00001561 String* key,
1562 Object* value,
1563 PropertyAttributes attributes);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001564
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001565 // Retrieve a value in a normalized object given a lookup result.
1566 // Handles the special representation of JS global objects.
1567 Object* GetNormalizedProperty(LookupResult* result);
1568
1569 // Sets the property value in a normalized object given a lookup result.
1570 // Handles the special representation of JS global objects.
1571 Object* SetNormalizedProperty(LookupResult* result, Object* value);
1572
1573 // Sets the property value in a normalized object given (key, value, details).
1574 // Handles the special representation of JS global objects.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001575 MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
1576 Object* value,
1577 PropertyDetails details);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001578
1579 // Deletes the named property in a normalized object.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001580 MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
1581 DeleteMode mode);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001582
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583 // Retrieve interceptors.
1584 InterceptorInfo* GetNamedInterceptor();
1585 InterceptorInfo* GetIndexedInterceptor();
1586
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001587 // Used from JSReceiver.
1588 PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
1589 String* name,
1590 bool continue_search);
1591 PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
1592 String* name,
1593 bool continue_search);
1594 PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
1595 Object* receiver,
1596 LookupResult* result,
1597 String* name,
1598 bool continue_search);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599
lrn@chromium.org303ada72010-10-27 09:33:13 +00001600 MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
1601 bool is_getter,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001602 Object* fun,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001603 PropertyAttributes attributes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001604 Object* LookupAccessor(String* name, bool is_getter);
1605
lrn@chromium.org303ada72010-10-27 09:33:13 +00001606 MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00001607
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001608 // Used from Object::GetProperty().
lrn@chromium.org303ada72010-10-27 09:33:13 +00001609 MaybeObject* GetPropertyWithFailedAccessCheck(
1610 Object* receiver,
1611 LookupResult* result,
1612 String* name,
1613 PropertyAttributes* attributes);
1614 MaybeObject* GetPropertyWithInterceptor(
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001615 JSReceiver* receiver,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001616 String* name,
1617 PropertyAttributes* attributes);
1618 MaybeObject* GetPropertyPostInterceptor(
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001619 JSReceiver* receiver,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001620 String* name,
1621 PropertyAttributes* attributes);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001622 MaybeObject* GetLocalPropertyPostInterceptor(JSReceiver* receiver,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001623 String* name,
1624 PropertyAttributes* attributes);
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001625
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +00001626 // Returns true if this is an instance of an api function and has
1627 // been modified since it was created. May give false positives.
1628 bool IsDirty();
1629
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001630 // If the receiver is a JSGlobalProxy this method will return its prototype,
1631 // otherwise the result is the receiver itself.
1632 inline Object* BypassGlobalProxy();
1633
1634 // Accessors for hidden properties object.
1635 //
1636 // Hidden properties are not local properties of the object itself.
1637 // Instead they are stored on an auxiliary JSObject stored as a local
1638 // property with a special name Heap::hidden_symbol(). But if the
1639 // receiver is a JSGlobalProxy then the auxiliary object is a property
1640 // of its prototype.
1641 //
1642 // Has/Get/SetHiddenPropertiesObject methods don't allow the holder to be
1643 // a JSGlobalProxy. Use BypassGlobalProxy method above to get to the real
1644 // holder.
1645 //
1646 // These accessors do not touch interceptors or accessors.
1647 inline bool HasHiddenPropertiesObject();
1648 inline Object* GetHiddenPropertiesObject();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001649 MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject(
1650 Object* hidden_obj);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001651
vegorov@chromium.org7943d462011-08-01 11:41:52 +00001652 // Indicates whether the hidden properties object should be created.
1653 enum HiddenPropertiesFlag { ALLOW_CREATION, OMIT_CREATION };
1654
1655 // Retrieves the hidden properties object.
1656 //
1657 // The undefined value might be returned in case no hidden properties object
1658 // is present and creation was omitted.
1659 inline bool HasHiddenProperties();
1660 MUST_USE_RESULT MaybeObject* GetHiddenProperties(HiddenPropertiesFlag flag);
1661
1662 // Retrieves a permanent object identity hash code.
1663 //
1664 // The identity hash is stored as a hidden property. The undefined value might
1665 // be returned in case no hidden properties object is present and creation was
1666 // omitted.
1667 MUST_USE_RESULT MaybeObject* GetIdentityHash(HiddenPropertiesFlag flag);
1668
lrn@chromium.org303ada72010-10-27 09:33:13 +00001669 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
1670 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001671
1672 // Tests for the fast common case for property enumeration.
1673 bool IsSimpleEnum();
1674
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001675 // Do we want to keep the elements in fast case when increasing the
1676 // capacity?
1677 bool ShouldConvertToSlowElements(int new_capacity);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001678 // Returns true if the backing storage for the slow-case elements of
1679 // this object takes up nearly as much space as a fast-case backing
1680 // storage would. In that case the JSObject should have fast
1681 // elements.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001682 bool ShouldConvertToFastElements();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001683 // Returns true if the elements of JSObject contains only values that can be
1684 // represented in a FixedDoubleArray.
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001685 bool CanConvertToFastDoubleElements();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001686
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001687 // Tells whether the index'th element is present.
1688 inline bool HasElement(uint32_t index);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001689 bool HasElementWithReceiver(JSReceiver* receiver, uint32_t index);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001690
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001691 // Computes the new capacity when expanding the elements of a JSObject.
1692 static int NewElementsCapacity(int old_capacity) {
1693 // (old_capacity + 50%) + 16
1694 return old_capacity + (old_capacity >> 1) + 16;
1695 }
1696
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001697 // Tells whether the index'th element is present and how it is stored.
1698 enum LocalElementType {
1699 // There is no element with given index.
1700 UNDEFINED_ELEMENT,
1701
1702 // Element with given index is handled by interceptor.
1703 INTERCEPTED_ELEMENT,
1704
1705 // Element with given index is character in string.
1706 STRING_CHARACTER_ELEMENT,
1707
1708 // Element with given index is stored in fast backing store.
1709 FAST_ELEMENT,
1710
1711 // Element with given index is stored in slow backing store.
1712 DICTIONARY_ELEMENT
1713 };
1714
1715 LocalElementType HasLocalElement(uint32_t index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001716
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001717 bool HasElementWithInterceptor(JSReceiver* receiver, uint32_t index);
1718 bool HasElementPostInterceptor(JSReceiver* receiver, uint32_t index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001719
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001720 MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
1721 Object* value,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001722 StrictModeFlag strict_mode,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001723 bool check_prototype);
1724 MUST_USE_RESULT MaybeObject* SetDictionaryElement(uint32_t index,
1725 Object* value,
1726 StrictModeFlag strict_mode,
1727 bool check_prototype);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001728
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001729 MUST_USE_RESULT MaybeObject* SetFastDoubleElement(
1730 uint32_t index,
1731 Object* value,
1732 StrictModeFlag strict_mode,
1733 bool check_prototype = true);
1734
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001735 // Set the index'th array element.
1736 // A Failure object is returned if GC is needed.
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001737 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1738 Object* value,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001739 StrictModeFlag strict_mode,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001740 bool check_prototype);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001741
1742 // Returns the index'th element.
1743 // The undefined object if index is out of bounds.
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001744 MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745
whesse@chromium.org7b260152011-06-20 15:33:18 +00001746 // Replace the elements' backing store with fast elements of the given
1747 // capacity. Update the length for JSArrays. Returns the new backing
1748 // store.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001749 MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity,
1750 int length);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001751 MUST_USE_RESULT MaybeObject* SetFastDoubleElementsCapacityAndLength(
1752 int capacity,
1753 int length);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001754 MUST_USE_RESULT MaybeObject* SetSlowElements(Object* length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001755
1756 // Lookup interceptors are used for handling properties controlled by host
1757 // objects.
1758 inline bool HasNamedInterceptor();
1759 inline bool HasIndexedInterceptor();
1760
1761 // Support functions for v8 api (needed for correct interceptor behavior).
1762 bool HasRealNamedProperty(String* key);
1763 bool HasRealElementProperty(uint32_t index);
1764 bool HasRealNamedCallbackProperty(String* key);
1765
1766 // Initializes the array to a certain length
lrn@chromium.org303ada72010-10-27 09:33:13 +00001767 MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001768
1769 // Get the header size for a JSObject. Used to compute the index of
1770 // internal fields as well as the number of internal fields.
1771 inline int GetHeaderSize();
1772
1773 inline int GetInternalFieldCount();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001774 inline int GetInternalFieldOffset(int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001775 inline Object* GetInternalField(int index);
1776 inline void SetInternalField(int index, Object* value);
1777
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001778 // Lookup a property. If found, the result is valid and has
1779 // detailed information.
1780 void LocalLookup(String* name, LookupResult* result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001781
1782 // The following lookup functions skip interceptors.
1783 void LocalLookupRealNamedProperty(String* name, LookupResult* result);
1784 void LookupRealNamedProperty(String* name, LookupResult* result);
1785 void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
1786 void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001787 MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001788 uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
ager@chromium.org870a0b62008-11-04 11:43:05 +00001789 void LookupCallback(String* name, LookupResult* result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001790
1791 // Returns the number of properties on this object filtering out properties
1792 // with the specified attributes (ignoring interceptors).
1793 int NumberOfLocalProperties(PropertyAttributes filter);
1794 // Returns the number of enumerable properties (ignoring interceptors).
1795 int NumberOfEnumProperties();
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001796 // Fill in details for properties into storage starting at the specified
1797 // index.
1798 void GetLocalPropertyNames(FixedArray* storage, int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001799
1800 // Returns the number of properties on this object filtering out properties
1801 // with the specified attributes (ignoring interceptors).
1802 int NumberOfLocalElements(PropertyAttributes filter);
1803 // Returns the number of enumerable elements (ignoring interceptors).
1804 int NumberOfEnumElements();
1805 // Returns the number of elements on this object filtering out elements
1806 // with the specified attributes (ignoring interceptors).
1807 int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
1808 // Count and fill in the enumerable elements into storage.
1809 // (storage->length() == NumberOfEnumElements()).
1810 // If storage is NULL, will count the elements without adding
1811 // them to any storage.
1812 // Returns the number of enumerable elements.
1813 int GetEnumElementKeys(FixedArray* storage);
1814
1815 // Add a property to a fast-case object using a map transition to
1816 // new_map.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001817 MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
1818 String* name,
1819 Object* value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001820
1821 // Add a constant function property to a fast-case object.
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001822 // This leaves a CONSTANT_TRANSITION in the old map, and
1823 // if it is called on a second object with this map, a
1824 // normal property is added instead, with a map transition.
1825 // This avoids the creation of many maps with the same constant
1826 // function, all orphaned.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001827 MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
1828 String* name,
1829 JSFunction* function,
1830 PropertyAttributes attributes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001831
lrn@chromium.org303ada72010-10-27 09:33:13 +00001832 MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
1833 String* name,
1834 Object* value,
1835 PropertyAttributes attributes);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001836
1837 // Converts a descriptor of any other type to a real field,
1838 // backed by the properties array. Descriptors of visible
1839 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1840 // Converts the descriptor on the original object's map to a
1841 // map transition, and the the new field is on the object's new map.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001842 MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
ager@chromium.org7c537e22008-10-16 08:43:32 +00001843 String* name,
1844 Object* new_value,
1845 PropertyAttributes attributes);
1846
1847 // Converts a descriptor of any other type to a real field,
1848 // backed by the properties array. Descriptors of visible
1849 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001850 MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
1851 String* name,
1852 Object* new_value,
1853 PropertyAttributes attributes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001854
1855 // Add a property to a fast-case object.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001856 MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
1857 Object* value,
1858 PropertyAttributes attributes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001859
1860 // Add a property to a slow-case object.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001861 MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
1862 Object* value,
1863 PropertyAttributes attributes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001864
1865 // Add a property to an object.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001866 MUST_USE_RESULT MaybeObject* AddProperty(String* name,
1867 Object* value,
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001868 PropertyAttributes attributes,
1869 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001870
1871 // Convert the object to use the canonical dictionary
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001872 // representation. If the object is expected to have additional properties
1873 // added this number can be indicated to have the backing store allocated to
1874 // an initial capacity for holding these properties.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001875 MUST_USE_RESULT MaybeObject* NormalizeProperties(
1876 PropertyNormalizationMode mode,
1877 int expected_additional_properties);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001878
1879 // Convert and update the elements backing store to be a NumberDictionary
1880 // dictionary. Returns the backing after conversion.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001881 MUST_USE_RESULT MaybeObject* NormalizeElements();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001882
lrn@chromium.org303ada72010-10-27 09:33:13 +00001883 MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
ricow@chromium.org65fae842010-08-25 15:26:24 +00001884
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001885 // Transform slow named properties to fast variants.
1886 // Returns failure if allocation failed.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001887 MUST_USE_RESULT MaybeObject* TransformToFastProperties(
1888 int unused_property_fields);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889
ager@chromium.org7c537e22008-10-16 08:43:32 +00001890 // Access fast-case object properties at index.
1891 inline Object* FastPropertyAt(int index);
1892 inline Object* FastPropertyAtPut(int index, Object* value);
1893
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001894 // Access to in object properties.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001895 inline int GetInObjectPropertyOffset(int index);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001896 inline Object* InObjectPropertyAt(int index);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001897 inline Object* InObjectPropertyAtPut(int index,
1898 Object* value,
1899 WriteBarrierMode mode
1900 = UPDATE_WRITE_BARRIER);
ager@chromium.org7c537e22008-10-16 08:43:32 +00001901
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001902 // initializes the body after properties slot, properties slot is
1903 // initialized by set_properties
1904 // Note: this call does not update write barrier, it is caller's
1905 // reponsibility to ensure that *v* can be collected without WB here.
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001906 inline void InitializeBody(int object_size, Object* value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001907
1908 // Check whether this object references another object
1909 bool ReferencesObject(Object* obj);
1910
1911 // Casting.
1912 static inline JSObject* cast(Object* obj);
1913
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001914 // Disalow further properties to be added to the object.
lrn@chromium.org303ada72010-10-27 09:33:13 +00001915 MUST_USE_RESULT MaybeObject* PreventExtensions();
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001916
1917
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001918 // Dispatched behavior.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001919 void JSObjectShortPrint(StringStream* accumulator);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001920#ifdef OBJECT_PRINT
1921 inline void JSObjectPrint() {
1922 JSObjectPrint(stdout);
1923 }
1924 void JSObjectPrint(FILE* out);
1925#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001926#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001927 void JSObjectVerify();
whesse@chromium.org023421e2010-12-21 12:19:12 +00001928#endif
1929#ifdef OBJECT_PRINT
1930 inline void PrintProperties() {
1931 PrintProperties(stdout);
1932 }
1933 void PrintProperties(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001934
whesse@chromium.org023421e2010-12-21 12:19:12 +00001935 inline void PrintElements() {
1936 PrintElements(stdout);
1937 }
1938 void PrintElements(FILE* out);
1939#endif
1940
1941#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942 // Structure for collecting spill information about JSObjects.
1943 class SpillInformation {
1944 public:
1945 void Clear();
1946 void Print();
1947 int number_of_objects_;
1948 int number_of_objects_with_fast_properties_;
1949 int number_of_objects_with_fast_elements_;
1950 int number_of_fast_used_fields_;
1951 int number_of_fast_unused_fields_;
1952 int number_of_slow_used_properties_;
1953 int number_of_slow_unused_properties_;
1954 int number_of_fast_used_elements_;
1955 int number_of_fast_unused_elements_;
1956 int number_of_slow_used_elements_;
1957 int number_of_slow_unused_elements_;
1958 };
1959
1960 void IncrementSpillStatistics(SpillInformation* info);
1961#endif
1962 Object* SlowReverseLookup(Object* value);
1963
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001964 // Maximal number of fast properties for the JSObject. Used to
1965 // restrict the number of map transitions to avoid an explosion in
1966 // the number of maps for objects used as dictionaries.
1967 inline int MaxFastProperties();
1968
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001969 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
1970 // Also maximal value of JSArray's length property.
1971 static const uint32_t kMaxElementCount = 0xffffffffu;
1972
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001973 // Constants for heuristics controlling conversion of fast elements
1974 // to slow elements.
1975
1976 // Maximal gap that can be introduced by adding an element beyond
1977 // the current elements length.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001978 static const uint32_t kMaxGap = 1024;
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001979
1980 // Maximal length of fast elements array that won't be checked for
1981 // being dense enough on expansion.
1982 static const int kMaxUncheckedFastElementsLength = 5000;
1983
1984 // Same as above but for old arrays. This limit is more strict. We
1985 // don't want to be wasteful with long lived objects.
1986 static const int kMaxUncheckedOldFastElementsLength = 500;
1987
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001988 static const int kInitialMaxFastElementArray = 100000;
whesse@chromium.org023421e2010-12-21 12:19:12 +00001989 static const int kMaxFastProperties = 12;
ager@chromium.org7c537e22008-10-16 08:43:32 +00001990 static const int kMaxInstanceSize = 255 * kPointerSize;
1991 // When extending the backing storage for property values, we increase
1992 // its size by more than the 1 entry necessary, so sequentially adding fields
1993 // to the same object requires fewer allocations and copies.
1994 static const int kFieldsAdded = 3;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001995
1996 // Layout description.
ager@chromium.org236ad962008-09-25 09:45:57 +00001997 static const int kPropertiesOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001998 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
1999 static const int kHeaderSize = kElementsOffset + kPointerSize;
2000
ager@chromium.org18ad94b2009-09-02 08:22:29 +00002001 STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
2002
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002003 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
2004 public:
2005 static inline int SizeOf(Map* map, HeapObject* object);
2006 };
2007
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002008 private:
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002009 friend class DictionaryElementsAccessor;
2010
lrn@chromium.org303ada72010-10-27 09:33:13 +00002011 MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
2012 Object* structure,
2013 uint32_t index,
2014 Object* holder);
2015 MaybeObject* SetElementWithCallback(Object* structure,
2016 uint32_t index,
2017 Object* value,
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00002018 JSObject* holder,
2019 StrictModeFlag strict_mode);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002020 MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
2021 uint32_t index,
2022 Object* value,
2023 StrictModeFlag strict_mode,
2024 bool check_prototype);
lrn@chromium.org5d00b602011-01-05 09:51:43 +00002025 MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
2026 uint32_t index,
2027 Object* value,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002028 StrictModeFlag strict_mode,
lrn@chromium.org5d00b602011-01-05 09:51:43 +00002029 bool check_prototype);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002030
lrn@chromium.org303ada72010-10-27 09:33:13 +00002031 MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
2032 DeleteMode mode);
2033 MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002034
lrn@chromium.org303ada72010-10-27 09:33:13 +00002035 MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002036
whesse@chromium.org7b260152011-06-20 15:33:18 +00002037 MUST_USE_RESULT MaybeObject* DeleteFastElement(uint32_t index);
2038 MUST_USE_RESULT MaybeObject* DeleteDictionaryElement(uint32_t index,
2039 DeleteMode mode);
2040
2041 bool ReferencesObjectFromElements(FixedArray* elements,
2042 ElementsKind kind,
2043 Object* object);
2044 bool HasElementInElements(FixedArray* elements,
2045 ElementsKind kind,
2046 uint32_t index);
2047
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002048 // Returns true if most of the elements backing storage is used.
2049 bool HasDenseElements();
2050
ricow@chromium.org2c99e282011-07-28 09:15:17 +00002051 // Gets the current elements capacity and the number of used elements.
2052 void GetElementsCapacityAndUsage(int* capacity, int* used);
2053
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002054 bool CanSetCallback(String* name);
lrn@chromium.org303ada72010-10-27 09:33:13 +00002055 MUST_USE_RESULT MaybeObject* SetElementCallback(
2056 uint32_t index,
2057 Object* structure,
2058 PropertyAttributes attributes);
2059 MUST_USE_RESULT MaybeObject* SetPropertyCallback(
2060 String* name,
2061 Object* structure,
2062 PropertyAttributes attributes);
2063 MUST_USE_RESULT MaybeObject* DefineGetterSetter(
2064 String* name,
2065 PropertyAttributes attributes);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002066
2067 void LookupInDescriptor(String* name, LookupResult* result);
2068
2069 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
2070};
2071
2072
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002073// Common superclass for FixedArrays that allow implementations to share
2074// common accessors and some code paths.
2075class FixedArrayBase: public HeapObject {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002076 public:
2077 // [length]: length of the array.
2078 inline int length();
2079 inline void set_length(int value);
2080
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002081 inline static FixedArrayBase* cast(Object* object);
2082
2083 // Layout description.
2084 // Length is smi tagged when it is stored.
2085 static const int kLengthOffset = HeapObject::kHeaderSize;
2086 static const int kHeaderSize = kLengthOffset + kPointerSize;
2087};
2088
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002089
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002090class FixedDoubleArray;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002091
2092// FixedArray describes fixed-sized arrays with element type Object*.
2093class FixedArray: public FixedArrayBase {
2094 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002095 // Setter and getter for elements.
2096 inline Object* get(int index);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002097 // Setter that uses write barrier.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002098 inline void set(int index, Object* value);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002099 inline bool is_the_hole(int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002100
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002101 // Setter that doesn't need write barrier).
2102 inline void set(int index, Smi* value);
2103 // Setter with explicit barrier mode.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002104 inline void set(int index, Object* value, WriteBarrierMode mode);
2105
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002106 // Setters for frequently used oddballs located in old space.
2107 inline void set_undefined(int index);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002108 // TODO(isolates): duplicate.
2109 inline void set_undefined(Heap* heap, int index);
ager@chromium.org236ad962008-09-25 09:45:57 +00002110 inline void set_null(int index);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002111 // TODO(isolates): duplicate.
2112 inline void set_null(Heap* heap, int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002113 inline void set_the_hole(int index);
2114
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002115 // Setters with less debug checks for the GC to use.
2116 inline void set_unchecked(int index, Smi* value);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002117 inline void set_null_unchecked(Heap* heap, int index);
2118 inline void set_unchecked(Heap* heap, int index, Object* value,
2119 WriteBarrierMode mode);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00002120
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002121 // Gives access to raw memory which stores the array's data.
2122 inline Object** data_start();
2123
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002124 // Copy operations.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002125 MUST_USE_RESULT inline MaybeObject* Copy();
2126 MUST_USE_RESULT MaybeObject* CopySize(int new_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002127
2128 // Add the elements of a JSArray to this FixedArray.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002129 MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002130
2131 // Compute the union of this and other.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002132 MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002133
2134 // Copy a sub array from the receiver to dest.
2135 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
2136
2137 // Garbage collection support.
2138 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
2139
ager@chromium.org3e875802009-06-29 08:26:34 +00002140 // Code Generation support.
2141 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2142
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002143 // Casting.
2144 static inline FixedArray* cast(Object* obj);
2145
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00002146 // Maximal allowed size, in bytes, of a single FixedArray.
2147 // Prevents overflowing size computations, as well as extreme memory
2148 // consumption.
2149 static const int kMaxSize = 512 * MB;
2150 // Maximally allowed length of a FixedArray.
2151 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002152
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002153 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00002154#ifdef OBJECT_PRINT
2155 inline void FixedArrayPrint() {
2156 FixedArrayPrint(stdout);
2157 }
2158 void FixedArrayPrint(FILE* out);
2159#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002160#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002161 void FixedArrayVerify();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002162 // Checks if two FixedArrays have identical contents.
2163 bool IsEqualTo(FixedArray* other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002164#endif
2165
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002166 // Swap two elements in a pair of arrays. If this array and the
2167 // numbers array are the same object, the elements are only swapped
2168 // once.
2169 void SwapPairs(FixedArray* numbers, int i, int j);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002170
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002171 // Sort prefix of this array and the numbers array as pairs wrt. the
2172 // numbers. If the numbers array and the this array are the same
2173 // object, the prefix of this array is sorted.
2174 void SortPairs(FixedArray* numbers, uint32_t len);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002175
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002176 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
2177 public:
2178 static inline int SizeOf(Map* map, HeapObject* object) {
2179 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
2180 }
2181 };
2182
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002183 protected:
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002184 // Set operation on FixedArray without using write barriers. Can
2185 // only be used for storing old space objects or smis.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002186 static inline void fast_set(FixedArray* array, int index, Object* value);
2187
2188 private:
2189 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
2190};
2191
2192
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002193// FixedDoubleArray describes fixed-sized arrays with element type double.
2194class FixedDoubleArray: public FixedArrayBase {
2195 public:
2196 inline void Initialize(FixedArray* from);
2197 inline void Initialize(FixedDoubleArray* from);
2198 inline void Initialize(NumberDictionary* from);
2199
2200 // Setter and getter for elements.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002201 inline double get_scalar(int index);
2202 inline MaybeObject* get(int index);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002203 inline void set(int index, double value);
2204 inline void set_the_hole(int index);
2205
2206 // Checking for the hole.
2207 inline bool is_the_hole(int index);
2208
2209 // Garbage collection support.
2210 inline static int SizeFor(int length) {
2211 return kHeaderSize + length * kDoubleSize;
2212 }
2213
rossberg@chromium.org717967f2011-07-20 13:44:42 +00002214 // Code Generation support.
2215 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2216
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00002217 inline static bool is_the_hole_nan(double value);
2218 inline static double hole_nan_as_double();
2219 inline static double canonical_not_the_hole_nan_as_double();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002220
2221 // Casting.
2222 static inline FixedDoubleArray* cast(Object* obj);
2223
2224 // Maximal allowed size, in bytes, of a single FixedDoubleArray.
2225 // Prevents overflowing size computations, as well as extreme memory
2226 // consumption.
2227 static const int kMaxSize = 512 * MB;
2228 // Maximally allowed length of a FixedArray.
2229 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
2230
2231 // Dispatched behavior.
2232#ifdef OBJECT_PRINT
2233 inline void FixedDoubleArrayPrint() {
2234 FixedDoubleArrayPrint(stdout);
2235 }
2236 void FixedDoubleArrayPrint(FILE* out);
2237#endif
2238
2239#ifdef DEBUG
2240 void FixedDoubleArrayVerify();
2241#endif
2242
2243 private:
2244 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
2245};
2246
2247
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002248// DescriptorArrays are fixed arrays used to hold instance descriptors.
2249// The format of the these objects is:
danno@chromium.org40cb8782011-05-25 07:58:50 +00002250// TODO(1399): It should be possible to make room for bit_field3 in the map
2251// without overloading the instance descriptors field in the map
2252// (and storing it in the DescriptorArray when the map has one).
2253// [0]: storage for bit_field3 for Map owning this object (Smi)
2254// [1]: point to a fixed array with (value, detail) pairs.
2255// [2]: next enumeration index (Smi), or pointer to small fixed array:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002256// [0]: next enumeration index (Smi)
2257// [1]: pointer to fixed array with enum cache
danno@chromium.org40cb8782011-05-25 07:58:50 +00002258// [3]: first key
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259// [length() - 1]: last key
2260//
2261class DescriptorArray: public FixedArray {
2262 public:
danno@chromium.org40cb8782011-05-25 07:58:50 +00002263 // Returns true for both shared empty_descriptor_array and for smis, which the
2264 // map uses to encode additional bit fields when the descriptor array is not
2265 // yet used.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002266 inline bool IsEmpty();
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00002267
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002268 // Returns the number of descriptors in the array.
2269 int number_of_descriptors() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002270 ASSERT(length() > kFirstIndex || IsEmpty());
2271 int len = length();
2272 return len <= kFirstIndex ? 0 : len - kFirstIndex;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002273 }
2274
2275 int NextEnumerationIndex() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002276 if (IsEmpty()) return PropertyDetails::kInitialIndex;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002277 Object* obj = get(kEnumerationIndexIndex);
2278 if (obj->IsSmi()) {
2279 return Smi::cast(obj)->value();
2280 } else {
2281 Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
2282 return Smi::cast(index)->value();
2283 }
2284 }
2285
2286 // Set next enumeration index and flush any enum cache.
2287 void SetNextEnumerationIndex(int value) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002288 if (!IsEmpty()) {
2289 fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
2290 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002291 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002292 bool HasEnumCache() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002293 return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002294 }
2295
2296 Object* GetEnumCache() {
2297 ASSERT(HasEnumCache());
2298 FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
2299 return bridge->get(kEnumCacheBridgeCacheIndex);
2300 }
2301
danno@chromium.org40cb8782011-05-25 07:58:50 +00002302 // TODO(1399): It should be possible to make room for bit_field3 in the map
2303 // without overloading the instance descriptors field in the map
2304 // (and storing it in the DescriptorArray when the map has one).
2305 inline int bit_field3_storage();
2306 inline void set_bit_field3_storage(int value);
2307
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002308 // Initialize or change the enum cache,
2309 // using the supplied storage for the small "bridge".
2310 void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
2311
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002312 // Accessors for fetching instance descriptor at descriptor number.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002313 inline String* GetKey(int descriptor_number);
2314 inline Object* GetValue(int descriptor_number);
2315 inline Smi* GetDetails(int descriptor_number);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002316 inline PropertyType GetType(int descriptor_number);
2317 inline int GetFieldIndex(int descriptor_number);
2318 inline JSFunction* GetConstantFunction(int descriptor_number);
2319 inline Object* GetCallbacksObject(int descriptor_number);
2320 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
2321 inline bool IsProperty(int descriptor_number);
2322 inline bool IsTransition(int descriptor_number);
2323 inline bool IsNullDescriptor(int descriptor_number);
2324 inline bool IsDontEnum(int descriptor_number);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002325
2326 // Accessor for complete descriptor.
2327 inline void Get(int descriptor_number, Descriptor* desc);
2328 inline void Set(int descriptor_number, Descriptor* desc);
2329
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00002330 // Transfer complete descriptor from another descriptor array to
2331 // this one.
2332 inline void CopyFrom(int index, DescriptorArray* src, int src_index);
2333
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002334 // Copy the descriptor array, insert a new descriptor and optionally
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002335 // remove map transitions. If the descriptor is already present, it is
2336 // replaced. If a replaced descriptor is a real property (not a transition
2337 // or null), its enumeration index is kept as is.
2338 // If adding a real property, map transitions must be removed. If adding
2339 // a transition, they must not be removed. All null descriptors are removed.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002340 MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
2341 TransitionFlag transition_flag);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002342
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002343 // Remove all transitions. Return a copy of the array with all transitions
2344 // removed, or a Failure object if the new array could not be allocated.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002345 MUST_USE_RESULT MaybeObject* RemoveTransitions();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002346
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002347 // Sort the instance descriptors by the hash codes of their keys.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00002348 // Does not check for duplicates.
2349 void SortUnchecked();
2350
2351 // Sort the instance descriptors by the hash codes of their keys.
2352 // Checks the result for duplicates.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002353 void Sort();
2354
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002355 // Search the instance descriptors for given name.
2356 inline int Search(String* name);
2357
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00002358 // As the above, but uses DescriptorLookupCache and updates it when
2359 // necessary.
2360 inline int SearchWithCache(String* name);
2361
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002362 // Tells whether the name is present int the array.
2363 bool Contains(String* name) { return kNotFound != Search(name); }
2364
2365 // Perform a binary search in the instance descriptors represented
2366 // by this fixed array. low and high are descriptor indices. If there
2367 // are three instance descriptors in this array it should be called
2368 // with low=0 and high=2.
2369 int BinarySearch(String* name, int low, int high);
2370
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002371 // Perform a linear search in the instance descriptors represented
ager@chromium.org32912102009-01-16 10:38:43 +00002372 // by this fixed array. len is the number of descriptor indices that are
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00002373 // valid. Does not require the descriptors to be sorted.
2374 int LinearSearch(String* name, int len);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002375
2376 // Allocates a DescriptorArray, but returns the singleton
2377 // empty descriptor array object if number_of_descriptors is 0.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002378 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002379
2380 // Casting.
2381 static inline DescriptorArray* cast(Object* obj);
2382
2383 // Constant for denoting key was not found.
2384 static const int kNotFound = -1;
2385
danno@chromium.org40cb8782011-05-25 07:58:50 +00002386 static const int kBitField3StorageIndex = 0;
2387 static const int kContentArrayIndex = 1;
2388 static const int kEnumerationIndexIndex = 2;
2389 static const int kFirstIndex = 3;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002390
2391 // The length of the "bridge" to the enum cache.
2392 static const int kEnumCacheBridgeLength = 2;
2393 static const int kEnumCacheBridgeEnumIndex = 0;
2394 static const int kEnumCacheBridgeCacheIndex = 1;
2395
2396 // Layout description.
danno@chromium.org40cb8782011-05-25 07:58:50 +00002397 static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
2398 static const int kContentArrayOffset = kBitField3StorageOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002399 static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
2400 static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
2401
2402 // Layout description for the bridge array.
2403 static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
2404 static const int kEnumCacheBridgeCacheOffset =
2405 kEnumCacheBridgeEnumOffset + kPointerSize;
2406
whesse@chromium.org023421e2010-12-21 12:19:12 +00002407#ifdef OBJECT_PRINT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002408 // Print all the descriptors.
whesse@chromium.org023421e2010-12-21 12:19:12 +00002409 inline void PrintDescriptors() {
2410 PrintDescriptors(stdout);
2411 }
2412 void PrintDescriptors(FILE* out);
2413#endif
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00002414
whesse@chromium.org023421e2010-12-21 12:19:12 +00002415#ifdef DEBUG
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00002416 // Is the descriptor array sorted and without duplicates?
2417 bool IsSortedNoDuplicates();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002418
2419 // Are two DescriptorArrays equal?
2420 bool IsEqualTo(DescriptorArray* other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002421#endif
2422
2423 // The maximum number of descriptors we want in a descriptor array (should
2424 // fit in a page).
2425 static const int kMaxNumberOfDescriptors = 1024 + 512;
2426
2427 private:
2428 // Conversion from descriptor number to array indices.
2429 static int ToKeyIndex(int descriptor_number) {
2430 return descriptor_number+kFirstIndex;
2431 }
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00002432
2433 static int ToDetailsIndex(int descriptor_number) {
2434 return (descriptor_number << 1) + 1;
2435 }
2436
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002437 static int ToValueIndex(int descriptor_number) {
2438 return descriptor_number << 1;
2439 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002440
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002441 bool is_null_descriptor(int descriptor_number) {
2442 return PropertyDetails(GetDetails(descriptor_number)).type() ==
2443 NULL_DESCRIPTOR;
2444 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002445 // Swap operation on FixedArray without using write barriers.
2446 static inline void fast_swap(FixedArray* array, int first, int second);
2447
2448 // Swap descriptor first and second.
2449 inline void Swap(int first, int second);
2450
2451 FixedArray* GetContentArray() {
2452 return FixedArray::cast(get(kContentArrayIndex));
2453 }
2454 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
2455};
2456
2457
2458// HashTable is a subclass of FixedArray that implements a hash table
2459// that uses open addressing and quadratic probing.
2460//
2461// In order for the quadratic probing to work, elements that have not
2462// yet been used and elements that have been deleted are
2463// distinguished. Probing continues when deleted elements are
2464// encountered and stops when unused elements are encountered.
2465//
2466// - Elements with key == undefined have not been used yet.
2467// - Elements with key == null have been deleted.
2468//
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002469// The hash table class is parameterized with a Shape and a Key.
2470// Shape must be a class with the following interface:
2471// class ExampleShape {
2472// public:
2473// // Tells whether key matches other.
2474// static bool IsMatch(Key key, Object* other);
2475// // Returns the hash value for key.
2476// static uint32_t Hash(Key key);
2477// // Returns the hash value for object.
2478// static uint32_t HashForObject(Key key, Object* object);
2479// // Convert key to an object.
2480// static inline Object* AsObject(Key key);
2481// // The prefix size indicates number of elements in the beginning
2482// // of the backing storage.
2483// static const int kPrefixSize = ..;
2484// // The Element size indicates number of elements per entry.
2485// static const int kEntrySize = ..;
2486// };
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002487// The prefix size indicates an amount of memory in the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002488// beginning of the backing storage that can be used for non-element
2489// information by subclasses.
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002490
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002491template<typename Shape, typename Key>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002492class HashTable: public FixedArray {
2493 public:
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002494 // Returns the number of elements in the hash table.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002495 int NumberOfElements() {
2496 return Smi::cast(get(kNumberOfElementsIndex))->value();
2497 }
2498
kasperl@chromium.orgedf0cd12010-01-05 13:29:12 +00002499 // Returns the number of deleted elements in the hash table.
2500 int NumberOfDeletedElements() {
2501 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
2502 }
2503
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002504 // Returns the capacity of the hash table.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002505 int Capacity() {
2506 return Smi::cast(get(kCapacityIndex))->value();
2507 }
2508
2509 // ElementAdded should be called whenever an element is added to a
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002510 // hash table.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002511 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
2512
2513 // ElementRemoved should be called whenever an element is removed from
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002514 // a hash table.
kasperl@chromium.orgedf0cd12010-01-05 13:29:12 +00002515 void ElementRemoved() {
2516 SetNumberOfElements(NumberOfElements() - 1);
2517 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
2518 }
2519 void ElementsRemoved(int n) {
2520 SetNumberOfElements(NumberOfElements() - n);
2521 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
2522 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002523
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002524 // Returns a new HashTable object. Might return Failure.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002525 MUST_USE_RESULT static MaybeObject* Allocate(
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00002526 int at_least_space_for,
2527 PretenureFlag pretenure = NOT_TENURED);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002528
ricow@chromium.org2c99e282011-07-28 09:15:17 +00002529 // Computes the required capacity for a table holding the given
2530 // number of elements. May be more than HashTable::kMaxCapacity.
2531 static int ComputeCapacity(int at_least_space_for);
2532
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002533 // Returns the key at entry.
2534 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
2535
ager@chromium.org32912102009-01-16 10:38:43 +00002536 // Tells whether k is a real key. Null and undefined are not allowed
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002537 // as keys and can be used to indicate missing or deleted elements.
2538 bool IsKey(Object* k) {
2539 return !k->IsNull() && !k->IsUndefined();
2540 }
2541
2542 // Garbage collection support.
2543 void IteratePrefix(ObjectVisitor* visitor);
2544 void IterateElements(ObjectVisitor* visitor);
2545
2546 // Casting.
2547 static inline HashTable* cast(Object* obj);
2548
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002549 // Compute the probe offset (quadratic probing).
2550 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
2551 return (n + n * n) >> 1;
2552 }
2553
2554 static const int kNumberOfElementsIndex = 0;
kasperl@chromium.orgedf0cd12010-01-05 13:29:12 +00002555 static const int kNumberOfDeletedElementsIndex = 1;
2556 static const int kCapacityIndex = 2;
2557 static const int kPrefixStartIndex = 3;
2558 static const int kElementsStartIndex =
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002559 kPrefixStartIndex + Shape::kPrefixSize;
kasperl@chromium.orgedf0cd12010-01-05 13:29:12 +00002560 static const int kEntrySize = Shape::kEntrySize;
2561 static const int kElementsStartOffset =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002562 kHeaderSize + kElementsStartIndex * kPointerSize;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002563 static const int kCapacityOffset =
2564 kHeaderSize + kCapacityIndex * kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002565
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00002566 // Constant used for denoting a absent entry.
2567 static const int kNotFound = -1;
2568
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00002569 // Maximal capacity of HashTable. Based on maximal length of underlying
2570 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
2571 // cannot overflow.
2572 static const int kMaxCapacity =
2573 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
2574
ricow@chromium.org4980dff2010-07-19 08:33:45 +00002575 // Find entry for key otherwise return kNotFound.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002576 inline int FindEntry(Key key);
2577 int FindEntry(Isolate* isolate, Key key);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002578
2579 protected:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002580 // Find the entry at which to insert element with the given key that
2581 // has the given hash value.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002582 uint32_t FindInsertionEntry(uint32_t hash);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002583
2584 // Returns the index for an entry (of the key)
2585 static inline int EntryToIndex(int entry) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002586 return (entry * kEntrySize) + kElementsStartIndex;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002587 }
2588
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002589 // Update the number of elements in the hash table.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002590 void SetNumberOfElements(int nof) {
2591 fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
2592 }
2593
kasperl@chromium.orgedf0cd12010-01-05 13:29:12 +00002594 // Update the number of deleted elements in the hash table.
2595 void SetNumberOfDeletedElements(int nod) {
2596 fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
2597 }
2598
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002599 // Sets the capacity of the hash table.
2600 void SetCapacity(int capacity) {
2601 // To scale a computed hash code to fit within the hash table, we
2602 // use bit-wise AND with a mask, so the capacity must be positive
2603 // and non-zero.
2604 ASSERT(capacity > 0);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00002605 ASSERT(capacity <= kMaxCapacity);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002606 fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
2607 }
2608
2609
2610 // Returns probe entry.
2611 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
2612 ASSERT(IsPowerOf2(size));
2613 return (hash + GetProbeOffset(number)) & (size - 1);
2614 }
2615
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00002616 static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
2617 return hash & (size - 1);
2618 }
2619
2620 static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
2621 return (last + number) & (size - 1);
2622 }
2623
ager@chromium.org04921a82011-06-27 13:21:41 +00002624 // Rehashes this hash-table into the new table.
2625 MUST_USE_RESULT MaybeObject* Rehash(HashTable* new_table, Key key);
2626
2627 // Attempt to shrink hash table after removal of key.
2628 MUST_USE_RESULT MaybeObject* Shrink(Key key);
2629
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002630 // Ensure enough space for n additional elements.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002631 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002632};
2633
2634
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002635
2636// HashTableKey is an abstract superclass for virtual key behavior.
2637class HashTableKey {
2638 public:
2639 // Returns whether the other object matches this key.
2640 virtual bool IsMatch(Object* other) = 0;
2641 // Returns the hash value for this key.
2642 virtual uint32_t Hash() = 0;
2643 // Returns the hash value for object.
2644 virtual uint32_t HashForObject(Object* key) = 0;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002645 // Returns the key object for storing into the hash table.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002646 // If allocations fails a failure object is returned.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002647 MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002648 // Required.
2649 virtual ~HashTableKey() {}
2650};
2651
2652class SymbolTableShape {
2653 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002654 static inline bool IsMatch(HashTableKey* key, Object* value) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002655 return key->IsMatch(value);
2656 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002657 static inline uint32_t Hash(HashTableKey* key) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002658 return key->Hash();
2659 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002660 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002661 return key->HashForObject(object);
2662 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002663 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002664 return key->AsObject();
2665 }
2666
2667 static const int kPrefixSize = 0;
2668 static const int kEntrySize = 1;
2669};
2670
danno@chromium.org40cb8782011-05-25 07:58:50 +00002671class SeqAsciiString;
2672
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002673// SymbolTable.
2674//
2675// No special elements in the prefix and the element size is 1
2676// because only the symbol itself (the key) needs to be stored.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002677class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002678 public:
2679 // Find symbol in the symbol table. If it is not there yet, it is
2680 // added. The return value is the symbol table which might have
2681 // been enlarged. If the return value is not a failure, the symbol
2682 // pointer *s is set to the symbol found.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002683 MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002684 MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
2685 Object** s);
danno@chromium.org40cb8782011-05-25 07:58:50 +00002686 MUST_USE_RESULT MaybeObject* LookupSubStringAsciiSymbol(
2687 Handle<SeqAsciiString> str,
2688 int from,
2689 int length,
2690 Object** s);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002691 MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
2692 Object** s);
lrn@chromium.org303ada72010-10-27 09:33:13 +00002693 MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002694
ager@chromium.org7c537e22008-10-16 08:43:32 +00002695 // Looks up a symbol that is equal to the given string and returns
2696 // true if it is found, assigning the symbol to the given output
2697 // parameter.
2698 bool LookupSymbolIfExists(String* str, String** symbol);
ager@chromium.org6141cbe2009-11-20 12:14:52 +00002699 bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
ager@chromium.org7c537e22008-10-16 08:43:32 +00002700
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002701 // Casting.
2702 static inline SymbolTable* cast(Object* obj);
2703
2704 private:
lrn@chromium.org303ada72010-10-27 09:33:13 +00002705 MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002706
2707 DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
2708};
2709
2710
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002711class MapCacheShape {
2712 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002713 static inline bool IsMatch(HashTableKey* key, Object* value) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002714 return key->IsMatch(value);
2715 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002716 static inline uint32_t Hash(HashTableKey* key) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002717 return key->Hash();
2718 }
2719
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002720 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002721 return key->HashForObject(object);
2722 }
2723
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002724 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002725 return key->AsObject();
2726 }
2727
2728 static const int kPrefixSize = 0;
2729 static const int kEntrySize = 2;
2730};
2731
2732
ager@chromium.org236ad962008-09-25 09:45:57 +00002733// MapCache.
2734//
2735// Maps keys that are a fixed array of symbols to a map.
2736// Used for canonicalize maps for object literals.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002737class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
ager@chromium.org236ad962008-09-25 09:45:57 +00002738 public:
2739 // Find cached value for a string key, otherwise return null.
2740 Object* Lookup(FixedArray* key);
lrn@chromium.org303ada72010-10-27 09:33:13 +00002741 MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
ager@chromium.org236ad962008-09-25 09:45:57 +00002742 static inline MapCache* cast(Object* obj);
2743
2744 private:
2745 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
2746};
2747
2748
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002749template <typename Shape, typename Key>
2750class Dictionary: public HashTable<Shape, Key> {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002751 public:
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002752 static inline Dictionary<Shape, Key>* cast(Object* obj) {
2753 return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
2754 }
2755
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002756 // Returns the value at entry.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00002757 Object* ValueAt(int entry) {
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002758 return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00002759 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002760
2761 // Set the value for entry.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002762 // Returns false if the put wasn't performed due to property being read only.
2763 // Returns true on successful put.
2764 bool ValueAtPut(int entry, Object* value) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +00002765 // Check that this value can actually be written.
2766 PropertyDetails details = DetailsAt(entry);
2767 // If a value has not been initilized we allow writing to it even if
2768 // it is read only (a declared const that has not been initialized).
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002769 if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
2770 return false;
2771 }
2772 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
2773 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002774 }
2775
2776 // Returns the property details for the property at entry.
2777 PropertyDetails DetailsAt(int entry) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002778 ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002779 return PropertyDetails(
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002780 Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002781 }
2782
2783 // Set the details for entry.
2784 void DetailsAtPut(int entry, PropertyDetails value) {
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002785 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002786 }
2787
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002788 // Sorting support
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002789 void CopyValuesTo(FixedArray* elements);
2790
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002791 // Delete a property from the dictionary.
ager@chromium.orge2902be2009-06-08 12:21:35 +00002792 Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002793
ager@chromium.org04921a82011-06-27 13:21:41 +00002794 // Attempt to shrink the dictionary after deletion of key.
2795 MUST_USE_RESULT MaybeObject* Shrink(Key key);
2796
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002797 // Returns the number of elements in the dictionary filtering out properties
2798 // with the specified attributes.
2799 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
2800
2801 // Returns the number of enumerable elements in the dictionary.
2802 int NumberOfEnumElements();
2803
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002804 enum SortMode { UNSORTED, SORTED };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002805 // Copies keys to preallocated fixed array.
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002806 void CopyKeysTo(FixedArray* storage,
2807 PropertyAttributes filter,
2808 SortMode sort_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002809 // Fill in details for properties into storage.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002810 void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002811
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002812 // Accessors for next enumeration index.
2813 void SetNextEnumerationIndex(int index) {
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00002814 this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002815 }
2816
2817 int NextEnumerationIndex() {
2818 return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
2819 }
2820
2821 // Returns a new array for dictionary usage. Might return Failure.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002822 MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002823
2824 // Ensure enough space for n additional elements.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002825 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002826
whesse@chromium.org023421e2010-12-21 12:19:12 +00002827#ifdef OBJECT_PRINT
2828 inline void Print() {
2829 Print(stdout);
2830 }
2831 void Print(FILE* out);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002832#endif
2833 // Returns the key (slow).
2834 Object* SlowReverseLookup(Object* value);
2835
2836 // Sets the entry to (key, value) pair.
2837 inline void SetEntry(int entry,
2838 Object* key,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00002839 Object* value);
2840 inline void SetEntry(int entry,
2841 Object* key,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002842 Object* value,
2843 PropertyDetails details);
2844
lrn@chromium.org303ada72010-10-27 09:33:13 +00002845 MUST_USE_RESULT MaybeObject* Add(Key key,
2846 Object* value,
2847 PropertyDetails details);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002848
2849 protected:
2850 // Generic at put operation.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002851 MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002852
2853 // Add entry to dictionary.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002854 MUST_USE_RESULT MaybeObject* AddEntry(Key key,
2855 Object* value,
2856 PropertyDetails details,
2857 uint32_t hash);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002858
2859 // Generate new enumeration indices to avoid enumeration index overflow.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002860 MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002861 static const int kMaxNumberKeyIndex =
2862 HashTable<Shape, Key>::kPrefixStartIndex;
2863 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
2864};
2865
2866
2867class StringDictionaryShape {
2868 public:
2869 static inline bool IsMatch(String* key, Object* other);
2870 static inline uint32_t Hash(String* key);
2871 static inline uint32_t HashForObject(String* key, Object* object);
lrn@chromium.org303ada72010-10-27 09:33:13 +00002872 MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002873 static const int kPrefixSize = 2;
2874 static const int kEntrySize = 3;
2875 static const bool kIsEnumerable = true;
2876};
2877
2878
2879class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
2880 public:
2881 static inline StringDictionary* cast(Object* obj) {
2882 ASSERT(obj->IsDictionary());
2883 return reinterpret_cast<StringDictionary*>(obj);
2884 }
2885
2886 // Copies enumerable keys to preallocated fixed array.
2887 void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
2888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002889 // For transforming properties of a JSObject.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002890 MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
2891 JSObject* obj,
2892 int unused_property_fields);
ricow@chromium.org4980dff2010-07-19 08:33:45 +00002893
2894 // Find entry for key otherwise return kNotFound. Optimzed version of
2895 // HashTable::FindEntry.
2896 int FindEntry(String* key);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002897};
2898
2899
2900class NumberDictionaryShape {
2901 public:
2902 static inline bool IsMatch(uint32_t key, Object* other);
2903 static inline uint32_t Hash(uint32_t key);
2904 static inline uint32_t HashForObject(uint32_t key, Object* object);
lrn@chromium.org303ada72010-10-27 09:33:13 +00002905 MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002906 static const int kPrefixSize = 2;
2907 static const int kEntrySize = 3;
2908 static const bool kIsEnumerable = false;
2909};
2910
2911
2912class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
2913 public:
2914 static NumberDictionary* cast(Object* obj) {
2915 ASSERT(obj->IsDictionary());
2916 return reinterpret_cast<NumberDictionary*>(obj);
2917 }
2918
2919 // Type specific at put (default NONE attributes is used when adding).
lrn@chromium.org303ada72010-10-27 09:33:13 +00002920 MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
2921 MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
2922 Object* value,
2923 PropertyDetails details);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002924
2925 // Set an existing entry or add a new one if needed.
lrn@chromium.org303ada72010-10-27 09:33:13 +00002926 MUST_USE_RESULT MaybeObject* Set(uint32_t key,
2927 Object* value,
2928 PropertyDetails details);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002929
2930 void UpdateMaxNumberKey(uint32_t key);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002931
2932 // If slow elements are required we will never go back to fast-case
2933 // for the elements kept in this dictionary. We require slow
2934 // elements if an element has been added at an index larger than
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002935 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
2936 // when defining a getter or setter with a number key.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002937 inline bool requires_slow_elements();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002938 inline void set_requires_slow_elements();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002939
2940 // Get the value of the max number key that has been added to this
2941 // dictionary. max_number_key can only be called if
2942 // requires_slow_elements returns false.
2943 inline uint32_t max_number_key();
2944
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00002945 // Remove all entries were key is a number and (from <= key && key < to).
2946 void RemoveNumberEntries(uint32_t from, uint32_t to);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002947
2948 // Bit masks.
2949 static const int kRequiresSlowElementsMask = 1;
2950 static const int kRequiresSlowElementsTagSize = 1;
2951 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002952};
2953
2954
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002955class ObjectHashTableShape {
2956 public:
2957 static inline bool IsMatch(JSObject* key, Object* other);
2958 static inline uint32_t Hash(JSObject* key);
2959 static inline uint32_t HashForObject(JSObject* key, Object* object);
2960 MUST_USE_RESULT static inline MaybeObject* AsObject(JSObject* key);
2961 static const int kPrefixSize = 0;
2962 static const int kEntrySize = 2;
2963};
2964
2965
2966// ObjectHashTable maps keys that are JavaScript objects to object values by
2967// using the identity hash of the key for hashing purposes.
2968class ObjectHashTable: public HashTable<ObjectHashTableShape, JSObject*> {
2969 public:
2970 static inline ObjectHashTable* cast(Object* obj) {
2971 ASSERT(obj->IsHashTable());
2972 return reinterpret_cast<ObjectHashTable*>(obj);
2973 }
2974
2975 // Looks up the value associated with the given key. The undefined value is
2976 // returned in case the key is not present.
2977 Object* Lookup(JSObject* key);
2978
2979 // Adds (or overwrites) the value associated with the given key. Mapping a
2980 // key to the undefined value causes removal of the whole entry.
2981 MUST_USE_RESULT MaybeObject* Put(JSObject* key, Object* value);
2982
2983 private:
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002984 friend class MarkCompactCollector;
2985
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002986 void AddEntry(int entry, JSObject* key, Object* value);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002987 void RemoveEntry(int entry, Heap* heap);
2988 inline void RemoveEntry(int entry);
2989
2990 // Returns the index to the value of an entry.
2991 static inline int EntryToValueIndex(int entry) {
2992 return EntryToIndex(entry) + 1;
2993 }
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002994};
2995
2996
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002997// JSFunctionResultCache caches results of some JSFunction invocation.
2998// It is a fixed array with fixed structure:
2999// [0]: factory function
3000// [1]: finger index
3001// [2]: current cache size
3002// [3]: dummy field.
3003// The rest of array are key/value pairs.
3004class JSFunctionResultCache: public FixedArray {
3005 public:
3006 static const int kFactoryIndex = 0;
3007 static const int kFingerIndex = kFactoryIndex + 1;
3008 static const int kCacheSizeIndex = kFingerIndex + 1;
3009 static const int kDummyIndex = kCacheSizeIndex + 1;
3010 static const int kEntriesIndex = kDummyIndex + 1;
antonm@chromium.org397e23c2010-04-21 12:00:05 +00003011
3012 static const int kEntrySize = 2; // key + value
ager@chromium.orgac091b72010-05-05 07:34:42 +00003013
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00003014 static const int kFactoryOffset = kHeaderSize;
3015 static const int kFingerOffset = kFactoryOffset + kPointerSize;
3016 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
3017
ager@chromium.orgac091b72010-05-05 07:34:42 +00003018 inline void MakeZeroSize();
3019 inline void Clear();
3020
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003021 inline int size();
3022 inline void set_size(int size);
3023 inline int finger_index();
3024 inline void set_finger_index(int finger_index);
3025
ager@chromium.orgac091b72010-05-05 07:34:42 +00003026 // Casting
3027 static inline JSFunctionResultCache* cast(Object* obj);
3028
3029#ifdef DEBUG
3030 void JSFunctionResultCacheVerify();
3031#endif
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00003032};
3033
3034
ricow@chromium.org65fae842010-08-25 15:26:24 +00003035// The cache for maps used by normalized (dictionary mode) objects.
3036// Such maps do not have property descriptors, so a typical program
3037// needs very limited number of distinct normalized maps.
3038class NormalizedMapCache: public FixedArray {
3039 public:
3040 static const int kEntries = 64;
3041
lrn@chromium.org303ada72010-10-27 09:33:13 +00003042 MUST_USE_RESULT MaybeObject* Get(JSObject* object,
3043 PropertyNormalizationMode mode);
ricow@chromium.org65fae842010-08-25 15:26:24 +00003044
ricow@chromium.org65fae842010-08-25 15:26:24 +00003045 void Clear();
3046
3047 // Casting
3048 static inline NormalizedMapCache* cast(Object* obj);
3049
3050#ifdef DEBUG
3051 void NormalizedMapCacheVerify();
3052#endif
ricow@chromium.org65fae842010-08-25 15:26:24 +00003053};
3054
3055
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003056// ByteArray represents fixed sized byte arrays. Used by the outside world,
3057// such as PCRE, and also by the memory allocator and garbage collector to
3058// fill in free blocks in the heap.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00003059class ByteArray: public FixedArrayBase {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003060 public:
3061 // Setter and getter.
3062 inline byte get(int index);
3063 inline void set(int index, byte value);
3064
3065 // Treat contents as an int array.
3066 inline int get_int(int index);
3067
3068 static int SizeFor(int length) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003069 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003070 }
3071 // We use byte arrays for free blocks in the heap. Given a desired size in
3072 // bytes that is a multiple of the word size and big enough to hold a byte
3073 // array, this function returns the number of elements a byte array should
3074 // have.
3075 static int LengthFor(int size_in_bytes) {
3076 ASSERT(IsAligned(size_in_bytes, kPointerSize));
3077 ASSERT(size_in_bytes >= kHeaderSize);
3078 return size_in_bytes - kHeaderSize;
3079 }
3080
3081 // Returns data start address.
3082 inline Address GetDataStartAddress();
3083
3084 // Returns a pointer to the ByteArray object for a given data start address.
3085 static inline ByteArray* FromDataStartAddress(Address address);
3086
3087 // Casting.
3088 static inline ByteArray* cast(Object* obj);
3089
3090 // Dispatched behavior.
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003091 inline int ByteArraySize() {
3092 return SizeFor(this->length());
3093 }
whesse@chromium.org023421e2010-12-21 12:19:12 +00003094#ifdef OBJECT_PRINT
3095 inline void ByteArrayPrint() {
3096 ByteArrayPrint(stdout);
3097 }
3098 void ByteArrayPrint(FILE* out);
3099#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003100#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003101 void ByteArrayVerify();
3102#endif
3103
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003104 // Layout description.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003105 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00003106
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00003107 // Maximal memory consumption for a single ByteArray.
3108 static const int kMaxSize = 512 * MB;
3109 // Maximal length of a single ByteArray.
3110 static const int kMaxLength = kMaxSize - kHeaderSize;
3111
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003112 private:
3113 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
3114};
3115
3116
ager@chromium.org3811b432009-10-28 14:53:37 +00003117// An ExternalArray represents a fixed-size array of primitive values
3118// which live outside the JavaScript heap. Its subclasses are used to
3119// implement the CanvasArray types being defined in the WebGL
3120// specification. As of this writing the first public draft is not yet
3121// available, but Khronos members can access the draft at:
3122// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
3123//
3124// The semantics of these arrays differ from CanvasPixelArray.
3125// Out-of-range values passed to the setter are converted via a C
3126// cast, not clamping. Out-of-range indices cause exceptions to be
3127// raised rather than being silently ignored.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00003128class ExternalArray: public FixedArrayBase {
ager@chromium.org3811b432009-10-28 14:53:37 +00003129 public:
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003130
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003131 inline bool is_the_hole(int index) { return false; }
3132
ager@chromium.org3811b432009-10-28 14:53:37 +00003133 // [external_pointer]: The pointer to the external memory area backing this
3134 // external array.
3135 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
3136
3137 // Casting.
3138 static inline ExternalArray* cast(Object* obj);
3139
3140 // Maximal acceptable length for an external array.
3141 static const int kMaxLength = 0x3fffffff;
3142
3143 // ExternalArray headers are not quadword aligned.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003144 static const int kExternalPointerOffset =
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00003145 POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize);
ager@chromium.org3811b432009-10-28 14:53:37 +00003146 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00003147 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
ager@chromium.org3811b432009-10-28 14:53:37 +00003148
3149 private:
3150 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
3151};
3152
3153
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003154// A ExternalPixelArray represents a fixed-size byte array with special
3155// semantics used for implementing the CanvasPixelArray object. Please see the
3156// specification at:
3157
3158// http://www.whatwg.org/specs/web-apps/current-work/
3159// multipage/the-canvas-element.html#canvaspixelarray
3160// In particular, write access clamps the value written to 0 or 255 if the
3161// value written is outside this range.
3162class ExternalPixelArray: public ExternalArray {
3163 public:
3164 inline uint8_t* external_pixel_pointer();
3165
3166 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003167 inline uint8_t get_scalar(int index);
3168 inline MaybeObject* get(int index);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003169 inline void set(int index, uint8_t value);
3170
3171 // This accessor applies the correct conversion from Smi, HeapNumber and
3172 // undefined and clamps the converted value between 0 and 255.
3173 Object* SetValue(uint32_t index, Object* value);
3174
3175 // Casting.
3176 static inline ExternalPixelArray* cast(Object* obj);
3177
3178#ifdef OBJECT_PRINT
3179 inline void ExternalPixelArrayPrint() {
3180 ExternalPixelArrayPrint(stdout);
3181 }
3182 void ExternalPixelArrayPrint(FILE* out);
3183#endif
3184#ifdef DEBUG
3185 void ExternalPixelArrayVerify();
3186#endif // DEBUG
3187
3188 private:
3189 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
3190};
3191
3192
ager@chromium.org3811b432009-10-28 14:53:37 +00003193class ExternalByteArray: public ExternalArray {
3194 public:
3195 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003196 inline int8_t get_scalar(int index);
3197 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003198 inline void set(int index, int8_t value);
3199
3200 // This accessor applies the correct conversion from Smi, HeapNumber
3201 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003202 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003203
3204 // Casting.
3205 static inline ExternalByteArray* cast(Object* obj);
3206
whesse@chromium.org023421e2010-12-21 12:19:12 +00003207#ifdef OBJECT_PRINT
3208 inline void ExternalByteArrayPrint() {
3209 ExternalByteArrayPrint(stdout);
3210 }
3211 void ExternalByteArrayPrint(FILE* out);
3212#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003213#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003214 void ExternalByteArrayVerify();
3215#endif // DEBUG
3216
3217 private:
3218 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
3219};
3220
3221
3222class ExternalUnsignedByteArray: public ExternalArray {
3223 public:
3224 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003225 inline uint8_t get_scalar(int index);
3226 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003227 inline void set(int index, uint8_t value);
3228
3229 // This accessor applies the correct conversion from Smi, HeapNumber
3230 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003231 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003232
3233 // Casting.
3234 static inline ExternalUnsignedByteArray* cast(Object* obj);
3235
whesse@chromium.org023421e2010-12-21 12:19:12 +00003236#ifdef OBJECT_PRINT
3237 inline void ExternalUnsignedByteArrayPrint() {
3238 ExternalUnsignedByteArrayPrint(stdout);
3239 }
3240 void ExternalUnsignedByteArrayPrint(FILE* out);
3241#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003242#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003243 void ExternalUnsignedByteArrayVerify();
3244#endif // DEBUG
3245
3246 private:
3247 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
3248};
3249
3250
3251class ExternalShortArray: public ExternalArray {
3252 public:
3253 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003254 inline int16_t get_scalar(int index);
3255 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003256 inline void set(int index, int16_t value);
3257
3258 // This accessor applies the correct conversion from Smi, HeapNumber
3259 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003260 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003261
3262 // Casting.
3263 static inline ExternalShortArray* cast(Object* obj);
3264
whesse@chromium.org023421e2010-12-21 12:19:12 +00003265#ifdef OBJECT_PRINT
3266 inline void ExternalShortArrayPrint() {
3267 ExternalShortArrayPrint(stdout);
3268 }
3269 void ExternalShortArrayPrint(FILE* out);
3270#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003271#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003272 void ExternalShortArrayVerify();
3273#endif // DEBUG
3274
3275 private:
3276 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
3277};
3278
3279
3280class ExternalUnsignedShortArray: public ExternalArray {
3281 public:
3282 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003283 inline uint16_t get_scalar(int index);
3284 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003285 inline void set(int index, uint16_t value);
3286
3287 // This accessor applies the correct conversion from Smi, HeapNumber
3288 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003289 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003290
3291 // Casting.
3292 static inline ExternalUnsignedShortArray* cast(Object* obj);
3293
whesse@chromium.org023421e2010-12-21 12:19:12 +00003294#ifdef OBJECT_PRINT
3295 inline void ExternalUnsignedShortArrayPrint() {
3296 ExternalUnsignedShortArrayPrint(stdout);
3297 }
3298 void ExternalUnsignedShortArrayPrint(FILE* out);
3299#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003300#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003301 void ExternalUnsignedShortArrayVerify();
3302#endif // DEBUG
3303
3304 private:
3305 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
3306};
3307
3308
3309class ExternalIntArray: public ExternalArray {
3310 public:
3311 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003312 inline int32_t get_scalar(int index);
3313 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003314 inline void set(int index, int32_t value);
3315
3316 // This accessor applies the correct conversion from Smi, HeapNumber
3317 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003318 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003319
3320 // Casting.
3321 static inline ExternalIntArray* cast(Object* obj);
3322
whesse@chromium.org023421e2010-12-21 12:19:12 +00003323#ifdef OBJECT_PRINT
3324 inline void ExternalIntArrayPrint() {
3325 ExternalIntArrayPrint(stdout);
3326 }
3327 void ExternalIntArrayPrint(FILE* out);
3328#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003329#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003330 void ExternalIntArrayVerify();
3331#endif // DEBUG
3332
3333 private:
3334 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
3335};
3336
3337
3338class ExternalUnsignedIntArray: public ExternalArray {
3339 public:
3340 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003341 inline uint32_t get_scalar(int index);
3342 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003343 inline void set(int index, uint32_t value);
3344
3345 // This accessor applies the correct conversion from Smi, HeapNumber
3346 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003347 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003348
3349 // Casting.
3350 static inline ExternalUnsignedIntArray* cast(Object* obj);
3351
whesse@chromium.org023421e2010-12-21 12:19:12 +00003352#ifdef OBJECT_PRINT
3353 inline void ExternalUnsignedIntArrayPrint() {
3354 ExternalUnsignedIntArrayPrint(stdout);
3355 }
3356 void ExternalUnsignedIntArrayPrint(FILE* out);
3357#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003358#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003359 void ExternalUnsignedIntArrayVerify();
3360#endif // DEBUG
3361
3362 private:
3363 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
3364};
3365
3366
3367class ExternalFloatArray: public ExternalArray {
3368 public:
3369 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003370 inline float get_scalar(int index);
3371 inline MaybeObject* get(int index);
ager@chromium.org3811b432009-10-28 14:53:37 +00003372 inline void set(int index, float value);
3373
3374 // This accessor applies the correct conversion from Smi, HeapNumber
3375 // and undefined.
lrn@chromium.org303ada72010-10-27 09:33:13 +00003376 MaybeObject* SetValue(uint32_t index, Object* value);
ager@chromium.org3811b432009-10-28 14:53:37 +00003377
3378 // Casting.
3379 static inline ExternalFloatArray* cast(Object* obj);
3380
whesse@chromium.org023421e2010-12-21 12:19:12 +00003381#ifdef OBJECT_PRINT
3382 inline void ExternalFloatArrayPrint() {
3383 ExternalFloatArrayPrint(stdout);
3384 }
3385 void ExternalFloatArrayPrint(FILE* out);
3386#endif
ager@chromium.org3811b432009-10-28 14:53:37 +00003387#ifdef DEBUG
ager@chromium.org3811b432009-10-28 14:53:37 +00003388 void ExternalFloatArrayVerify();
3389#endif // DEBUG
3390
3391 private:
3392 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
3393};
3394
3395
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00003396class ExternalDoubleArray: public ExternalArray {
3397 public:
3398 // Setter and getter.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00003399 inline double get_scalar(int index);
3400 inline MaybeObject* get(int index);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00003401 inline void set(int index, double value);
3402
3403 // This accessor applies the correct conversion from Smi, HeapNumber
3404 // and undefined.
3405 MaybeObject* SetValue(uint32_t index, Object* value);
3406
3407 // Casting.
3408 static inline ExternalDoubleArray* cast(Object* obj);
3409
3410#ifdef OBJECT_PRINT
3411 inline void ExternalDoubleArrayPrint() {
3412 ExternalDoubleArrayPrint(stdout);
3413 }
3414 void ExternalDoubleArrayPrint(FILE* out);
3415#endif // OBJECT_PRINT
3416#ifdef DEBUG
3417 void ExternalDoubleArrayVerify();
3418#endif // DEBUG
3419
3420 private:
3421 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalDoubleArray);
3422};
3423
3424
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003425// DeoptimizationInputData is a fixed array used to hold the deoptimization
3426// data for code generated by the Hydrogen/Lithium compiler. It also
3427// contains information about functions that were inlined. If N different
3428// functions were inlined then first N elements of the literal array will
3429// contain these functions.
3430//
3431// It can be empty.
3432class DeoptimizationInputData: public FixedArray {
3433 public:
3434 // Layout description. Indices in the array.
3435 static const int kTranslationByteArrayIndex = 0;
3436 static const int kInlinedFunctionCountIndex = 1;
3437 static const int kLiteralArrayIndex = 2;
3438 static const int kOsrAstIdIndex = 3;
3439 static const int kOsrPcOffsetIndex = 4;
3440 static const int kFirstDeoptEntryIndex = 5;
3441
3442 // Offsets of deopt entry elements relative to the start of the entry.
3443 static const int kAstIdOffset = 0;
3444 static const int kTranslationIndexOffset = 1;
3445 static const int kArgumentsStackHeightOffset = 2;
3446 static const int kDeoptEntrySize = 3;
3447
3448 // Simple element accessors.
3449#define DEFINE_ELEMENT_ACCESSORS(name, type) \
3450 type* name() { \
3451 return type::cast(get(k##name##Index)); \
3452 } \
3453 void Set##name(type* value) { \
3454 set(k##name##Index, value); \
3455 }
3456
3457 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
3458 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
3459 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
3460 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
3461 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
3462
3463 // Unchecked accessor to be used during GC.
3464 FixedArray* UncheckedLiteralArray() {
3465 return reinterpret_cast<FixedArray*>(get(kLiteralArrayIndex));
3466 }
3467
3468#undef DEFINE_ELEMENT_ACCESSORS
3469
3470 // Accessors for elements of the ith deoptimization entry.
3471#define DEFINE_ENTRY_ACCESSORS(name, type) \
3472 type* name(int i) { \
3473 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
3474 } \
3475 void Set##name(int i, type* value) { \
3476 set(IndexForEntry(i) + k##name##Offset, value); \
3477 }
3478
3479 DEFINE_ENTRY_ACCESSORS(AstId, Smi)
3480 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
3481 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
3482
3483#undef DEFINE_ENTRY_ACCESSORS
3484
3485 int DeoptCount() {
3486 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
3487 }
3488
3489 // Allocates a DeoptimizationInputData.
3490 MUST_USE_RESULT static MaybeObject* Allocate(int deopt_entry_count,
3491 PretenureFlag pretenure);
3492
3493 // Casting.
3494 static inline DeoptimizationInputData* cast(Object* obj);
3495
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003496#ifdef ENABLE_DISASSEMBLER
whesse@chromium.org023421e2010-12-21 12:19:12 +00003497 void DeoptimizationInputDataPrint(FILE* out);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003498#endif
3499
3500 private:
3501 static int IndexForEntry(int i) {
3502 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
3503 }
3504
3505 static int LengthFor(int entry_count) {
3506 return IndexForEntry(entry_count);
3507 }
3508};
3509
3510
3511// DeoptimizationOutputData is a fixed array used to hold the deoptimization
3512// data for code generated by the full compiler.
3513// The format of the these objects is
3514// [i * 2]: Ast ID for ith deoptimization.
3515// [i * 2 + 1]: PC and state of ith deoptimization
3516class DeoptimizationOutputData: public FixedArray {
3517 public:
3518 int DeoptPoints() { return length() / 2; }
3519 Smi* AstId(int index) { return Smi::cast(get(index * 2)); }
3520 void SetAstId(int index, Smi* id) { set(index * 2, id); }
3521 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
3522 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
3523
3524 static int LengthOfFixedArray(int deopt_points) {
3525 return deopt_points * 2;
3526 }
3527
3528 // Allocates a DeoptimizationOutputData.
3529 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_deopt_points,
3530 PretenureFlag pretenure);
3531
3532 // Casting.
3533 static inline DeoptimizationOutputData* cast(Object* obj);
3534
whesse@chromium.org7b260152011-06-20 15:33:18 +00003535#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
whesse@chromium.org023421e2010-12-21 12:19:12 +00003536 void DeoptimizationOutputDataPrint(FILE* out);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003537#endif
3538};
3539
3540
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003541class SafepointEntry;
3542
3543
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003544// Code describes objects with on-the-fly generated machine code.
3545class Code: public HeapObject {
3546 public:
3547 // Opaque data type for encapsulating code flags like kind, inline
3548 // cache state, and arguments count.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00003549 // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
3550 // enumeration type has correct value range (see Issue 830 for more details).
3551 enum Flags {
3552 FLAGS_MIN_VALUE = kMinInt,
3553 FLAGS_MAX_VALUE = kMaxInt
3554 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003555
3556 enum Kind {
3557 FUNCTION,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003558 OPTIMIZED_FUNCTION,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003559 STUB,
3560 BUILTIN,
3561 LOAD_IC,
3562 KEYED_LOAD_IC,
3563 CALL_IC,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003564 KEYED_CALL_IC,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003565 STORE_IC,
3566 KEYED_STORE_IC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00003567 UNARY_OP_IC,
3568 BINARY_OP_IC,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003569 COMPARE_IC,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003570 TO_BOOLEAN_IC,
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003571 // No more than 16 kinds. The value currently encoded in four bits in
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003572 // Flags.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003573
3574 // Pseudo-kinds.
ager@chromium.orga74f0da2008-12-03 16:05:52 +00003575 REGEXP = BUILTIN,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003576 FIRST_IC_KIND = LOAD_IC,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003577 LAST_IC_KIND = TO_BOOLEAN_IC
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003578 };
3579
3580 enum {
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +00003581 NUMBER_OF_KINDS = LAST_IC_KIND + 1
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003582 };
3583
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003584 typedef int ExtraICState;
3585
3586 static const ExtraICState kNoExtraICState = 0;
3587
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00003588#ifdef ENABLE_DISASSEMBLER
3589 // Printing
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003590 static const char* Kind2String(Kind kind);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003591 static const char* ICState2String(InlineCacheState state);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00003592 static const char* PropertyType2String(PropertyType type);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003593 static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
whesse@chromium.org023421e2010-12-21 12:19:12 +00003594 inline void Disassemble(const char* name) {
3595 Disassemble(name, stdout);
3596 }
3597 void Disassemble(const char* name, FILE* out);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00003598#endif // ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003599
3600 // [instruction_size]: Size of the native instructions
3601 inline int instruction_size();
3602 inline void set_instruction_size(int value);
3603
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003604 // [relocation_info]: Code relocation information
3605 DECL_ACCESSORS(relocation_info, ByteArray)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003606 void InvalidateRelocation();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003607
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003608 // [deoptimization_data]: Array containing data for deopt.
3609 DECL_ACCESSORS(deoptimization_data, FixedArray)
3610
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00003611 // [code_flushing_candidate]: Field only used during garbage
3612 // collection to hold code flushing candidates. The contents of this
3613 // field does not have to be traced during garbage collection since
3614 // it is only used by the garbage collector itself.
3615 DECL_ACCESSORS(next_code_flushing_candidate, Object)
3616
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003617 // Unchecked accessors to be used during GC.
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003618 inline ByteArray* unchecked_relocation_info();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003619 inline FixedArray* unchecked_deoptimization_data();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003620
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003621 inline int relocation_size();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003622
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003623 // [flags]: Various code flags.
3624 inline Flags flags();
3625 inline void set_flags(Flags flags);
3626
3627 // [flags]: Access to specific code flags.
3628 inline Kind kind();
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003629 inline InlineCacheState ic_state(); // Only valid for IC stubs.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003630 inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00003631 inline InLoopFlag ic_in_loop(); // Only valid for IC stubs.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003632 inline PropertyType type(); // Only valid for monomorphic IC stubs.
3633 inline int arguments_count(); // Only valid for call IC stubs.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003634
3635 // Testers for IC stub kinds.
3636 inline bool is_inline_cache_stub();
3637 inline bool is_load_stub() { return kind() == LOAD_IC; }
3638 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
3639 inline bool is_store_stub() { return kind() == STORE_IC; }
3640 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
3641 inline bool is_call_stub() { return kind() == CALL_IC; }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00003642 inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003643 inline bool is_unary_op_stub() { return kind() == UNARY_OP_IC; }
3644 inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003645 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003646 inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003647
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003648 // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00003649 inline int major_key();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003650 inline void set_major_key(int value);
3651
3652 // [optimizable]: For FUNCTION kind, tells if it is optimizable.
3653 inline bool optimizable();
3654 inline void set_optimizable(bool value);
3655
3656 // [has_deoptimization_support]: For FUNCTION kind, tells if it has
3657 // deoptimization support.
3658 inline bool has_deoptimization_support();
3659 inline void set_has_deoptimization_support(bool value);
3660
3661 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
3662 // how long the function has been marked for OSR and therefore which
3663 // level of loop nesting we are willing to do on-stack replacement
3664 // for.
3665 inline void set_allow_osr_at_loop_nesting_level(int level);
3666 inline int allow_osr_at_loop_nesting_level();
3667
3668 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
3669 // reserved in the code prologue.
3670 inline unsigned stack_slots();
3671 inline void set_stack_slots(unsigned slots);
3672
3673 // [safepoint_table_start]: For kind OPTIMIZED_CODE, the offset in
3674 // the instruction stream where the safepoint table starts.
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003675 inline unsigned safepoint_table_offset();
3676 inline void set_safepoint_table_offset(unsigned offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003677
3678 // [stack_check_table_start]: For kind FUNCTION, the offset in the
3679 // instruction stream where the stack check table starts.
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003680 inline unsigned stack_check_table_offset();
3681 inline void set_stack_check_table_offset(unsigned offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003682
3683 // [check type]: For kind CALL_IC, tells how to check if the
3684 // receiver is valid for the given call.
3685 inline CheckType check_type();
3686 inline void set_check_type(CheckType value);
3687
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003688 // [type-recording unary op type]: For kind UNARY_OP_IC.
danno@chromium.org40cb8782011-05-25 07:58:50 +00003689 inline byte unary_op_type();
3690 inline void set_unary_op_type(byte value);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00003691
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003692 // [type-recording binary op type]: For kind BINARY_OP_IC.
danno@chromium.org40cb8782011-05-25 07:58:50 +00003693 inline byte binary_op_type();
3694 inline void set_binary_op_type(byte value);
3695 inline byte binary_op_result_type();
3696 inline void set_binary_op_result_type(byte value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003697
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003698 // [compare state]: For kind COMPARE_IC, tells what state the stub is in.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003699 inline byte compare_state();
3700 inline void set_compare_state(byte value);
3701
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003702 // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
3703 inline byte to_boolean_state();
3704 inline void set_to_boolean_state(byte value);
3705
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003706 // Get the safepoint entry for the given pc.
3707 SafepointEntry GetSafepointEntry(Address pc);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003708
3709 // Mark this code object as not having a stack check table. Assumes kind
3710 // is FUNCTION.
3711 void SetNoStackCheckTable();
3712
3713 // Find the first map in an IC stub.
3714 Map* FindFirstMap();
kasper.lund7276f142008-07-30 08:49:36 +00003715
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003716 // Flags operations.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003717 static inline Flags ComputeFlags(
3718 Kind kind,
3719 InLoopFlag in_loop = NOT_IN_LOOP,
3720 InlineCacheState ic_state = UNINITIALIZED,
3721 ExtraICState extra_ic_state = kNoExtraICState,
3722 PropertyType type = NORMAL,
3723 int argc = -1,
3724 InlineCacheHolderFlag holder = OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003725
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003726 static inline Flags ComputeMonomorphicFlags(
3727 Kind kind,
3728 PropertyType type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003729 ExtraICState extra_ic_state = kNoExtraICState,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00003730 InlineCacheHolderFlag holder = OWN_MAP,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003731 InLoopFlag in_loop = NOT_IN_LOOP,
3732 int argc = -1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003733
3734 static inline Kind ExtractKindFromFlags(Flags flags);
kasper.lund7276f142008-07-30 08:49:36 +00003735 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00003736 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003737 static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003738 static inline PropertyType ExtractTypeFromFlags(Flags flags);
3739 static inline int ExtractArgumentsCountFromFlags(Flags flags);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00003740 static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003741 static inline Flags RemoveTypeFromFlags(Flags flags);
3742
ager@chromium.org8bb60582008-12-11 12:02:20 +00003743 // Convert a target address into a code object.
3744 static inline Code* GetCodeFromTargetAddress(Address address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003745
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003746 // Convert an entry address into an object.
3747 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
3748
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003749 // Returns the address of the first instruction.
3750 inline byte* instruction_start();
3751
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003752 // Returns the address right after the last instruction.
3753 inline byte* instruction_end();
3754
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003755 // Returns the size of the instructions, padding, and relocation information.
3756 inline int body_size();
3757
3758 // Returns the address of the first relocation info (read backwards!).
3759 inline byte* relocation_start();
3760
3761 // Code entry point.
3762 inline byte* entry();
3763
3764 // Returns true if pc is inside this object's instructions.
3765 inline bool contains(byte* pc);
3766
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003767 // Relocate the code by delta bytes. Called to signal that this code
3768 // object has been moved by delta bytes.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003769 void Relocate(intptr_t delta);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003770
3771 // Migrate code described by desc.
3772 void CopyFrom(const CodeDesc& desc);
3773
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00003774 // Returns the object size for a given body (used for allocation).
3775 static int SizeFor(int body_size) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003776 ASSERT_SIZE_TAG_ALIGNED(body_size);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00003777 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003778 }
3779
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003780 // Calculate the size of the code object to report for log events. This takes
3781 // the layout of the code object into account.
3782 int ExecutableSize() {
3783 // Check that the assumptions about the layout of the code object holds.
ager@chromium.orga1645e22009-09-09 19:27:10 +00003784 ASSERT_EQ(static_cast<int>(instruction_start() - address()),
3785 Code::kHeaderSize);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00003786 return instruction_size() + Code::kHeaderSize;
3787 }
3788
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003789 // Locating source position.
3790 int SourcePosition(Address pc);
3791 int SourceStatementPosition(Address pc);
3792
3793 // Casting.
3794 static inline Code* cast(Object* obj);
3795
3796 // Dispatched behavior.
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00003797 int CodeSize() { return SizeFor(body_size()); }
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00003798 inline void CodeIterateBody(ObjectVisitor* v);
3799
3800 template<typename StaticVisitor>
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003801 inline void CodeIterateBody(Heap* heap);
whesse@chromium.org023421e2010-12-21 12:19:12 +00003802#ifdef OBJECT_PRINT
3803 inline void CodePrint() {
3804 CodePrint(stdout);
3805 }
3806 void CodePrint(FILE* out);
3807#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003808#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003809 void CodeVerify();
3810#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003811
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00003812 // Returns the isolate/heap this code object belongs to.
3813 inline Isolate* isolate();
3814 inline Heap* heap();
3815
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003816 // Max loop nesting marker used to postpose OSR. We don't take loop
3817 // nesting that is deeper than 5 levels into account.
3818 static const int kMaxLoopNestingMarker = 6;
3819
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003820 // Layout description.
ager@chromium.org236ad962008-09-25 09:45:57 +00003821 static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00003822 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003823 static const int kDeoptimizationDataOffset =
3824 kRelocationInfoOffset + kPointerSize;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00003825 static const int kNextCodeFlushingCandidateOffset =
3826 kDeoptimizationDataOffset + kPointerSize;
3827 static const int kFlagsOffset =
3828 kNextCodeFlushingCandidateOffset + kPointerSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003829
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00003830 static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003831 static const int kKindSpecificFlagsSize = 2 * kIntSize;
3832
3833 static const int kHeaderPaddingStart = kKindSpecificFlagsOffset +
3834 kKindSpecificFlagsSize;
3835
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003836 // Add padding to align the instruction start following right after
kasperl@chromium.org061ef742009-02-27 12:16:20 +00003837 // the Code object header.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003838 static const int kHeaderSize =
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003839 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
kasper.lund7276f142008-07-30 08:49:36 +00003840
3841 // Byte offsets within kKindSpecificFlagsOffset.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003842 static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset;
3843 static const int kOptimizableOffset = kKindSpecificFlagsOffset;
3844 static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
3845 static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
3846
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00003847 static const int kUnaryOpTypeOffset = kStubMajorKeyOffset + 1;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003848 static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
ricow@chromium.org9fa09672011-07-25 11:05:35 +00003849 static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
3850 static const int kToBooleanTypeOffset = kStubMajorKeyOffset + 1;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003851 static const int kHasDeoptimizationSupportOffset = kOptimizableOffset + 1;
3852
3853 static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;
3854 static const int kAllowOSRAtLoopNestingLevelOffset =
3855 kHasDeoptimizationSupportOffset + 1;
3856
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003857 static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
3858 static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003859
3860 // Flags layout.
kasper.lund7276f142008-07-30 08:49:36 +00003861 static const int kFlagsICStateShift = 0;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003862 static const int kFlagsICInLoopShift = 3;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +00003863 static const int kFlagsTypeShift = 4;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003864 static const int kFlagsKindShift = 8;
3865 static const int kFlagsICHolderShift = 12;
3866 static const int kFlagsExtraICStateShift = 13;
3867 static const int kFlagsArgumentsCountShift = 15;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003868
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003869 static const int kFlagsICStateMask = 0x00000007; // 00000000111
3870 static const int kFlagsICInLoopMask = 0x00000008; // 00000001000
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00003871 static const int kFlagsTypeMask = 0x000000F0; // 00001110000
3872 static const int kFlagsKindMask = 0x00000F00; // 11110000000
3873 static const int kFlagsCacheInPrototypeMapMask = 0x00001000;
3874 static const int kFlagsExtraICStateMask = 0x00006000;
3875 static const int kFlagsArgumentsCountMask = 0xFFFF8000;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00003876
3877 static const int kFlagsNotUsedInLookup =
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00003878 (kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003879
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003880 private:
3881 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
3882};
3883
3884
3885// All heap objects have a Map that describes their structure.
3886// A Map contains information about:
3887// - Size information about the object
3888// - How to iterate over an object (for garbage collection)
3889class Map: public HeapObject {
3890 public:
ager@chromium.org32912102009-01-16 10:38:43 +00003891 // Instance size.
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00003892 // Size in bytes or kVariableSizeSentinel if instances do not have
3893 // a fixed size.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003894 inline int instance_size();
3895 inline void set_instance_size(int value);
3896
ager@chromium.org7c537e22008-10-16 08:43:32 +00003897 // Count of properties allocated in the object.
3898 inline int inobject_properties();
3899 inline void set_inobject_properties(int value);
3900
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00003901 // Count of property fields pre-allocated in the object when first allocated.
3902 inline int pre_allocated_property_fields();
3903 inline void set_pre_allocated_property_fields(int value);
3904
ager@chromium.org32912102009-01-16 10:38:43 +00003905 // Instance type.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003906 inline InstanceType instance_type();
3907 inline void set_instance_type(InstanceType value);
3908
ager@chromium.org32912102009-01-16 10:38:43 +00003909 // Tells how many unused property fields are available in the
3910 // instance (only used for JSObject in fast mode).
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003911 inline int unused_property_fields();
3912 inline void set_unused_property_fields(int value);
3913
ager@chromium.org32912102009-01-16 10:38:43 +00003914 // Bit field.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003915 inline byte bit_field();
3916 inline void set_bit_field(byte value);
3917
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00003918 // Bit field 2.
3919 inline byte bit_field2();
3920 inline void set_bit_field2(byte value);
3921
danno@chromium.org40cb8782011-05-25 07:58:50 +00003922 // Bit field 3.
3923 // TODO(1399): It should be possible to make room for bit_field3 in the map
3924 // without overloading the instance descriptors field (and storing it in the
3925 // DescriptorArray when the map has one).
3926 inline int bit_field3();
3927 inline void set_bit_field3(int value);
3928
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003929 // Tells whether the object in the prototype property will be used
3930 // for instances created from this function. If the prototype
3931 // property is set to a value that is not a JSObject, the prototype
3932 // property will not be used to create instances of the function.
3933 // See ECMA-262, 13.2.2.
3934 inline void set_non_instance_prototype(bool value);
3935 inline bool has_non_instance_prototype();
3936
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00003937 // Tells whether function has special prototype property. If not, prototype
3938 // property will not be created when accessed (will return undefined),
3939 // and construction from this function will not be allowed.
3940 inline void set_function_with_prototype(bool value);
3941 inline bool function_with_prototype();
3942
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003943 // Tells whether the instance with this map should be ignored by the
3944 // __proto__ accessor.
3945 inline void set_is_hidden_prototype() {
3946 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
3947 }
3948
3949 inline bool is_hidden_prototype() {
3950 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
3951 }
3952
ager@chromium.orgeadaf222009-06-16 09:43:10 +00003953 // Records and queries whether the instance has a named interceptor.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003954 inline void set_has_named_interceptor() {
3955 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
3956 }
3957
3958 inline bool has_named_interceptor() {
3959 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
3960 }
3961
ager@chromium.orgeadaf222009-06-16 09:43:10 +00003962 // Records and queries whether the instance has an indexed interceptor.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003963 inline void set_has_indexed_interceptor() {
3964 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
3965 }
3966
3967 inline bool has_indexed_interceptor() {
3968 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
3969 }
3970
3971 // Tells whether the instance is undetectable.
3972 // An undetectable object is a special class of JSObject: 'typeof' operator
3973 // returns undefined, ToBoolean returns false. Otherwise it behaves like
3974 // a normal JS object. It is useful for implementing undetectable
3975 // document.all in Firefox & Safari.
3976 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
3977 inline void set_is_undetectable() {
3978 set_bit_field(bit_field() | (1 << kIsUndetectable));
3979 }
3980
3981 inline bool is_undetectable() {
3982 return ((1 << kIsUndetectable) & bit_field()) != 0;
3983 }
3984
3985 // Tells whether the instance has a call-as-function handler.
3986 inline void set_has_instance_call_handler() {
3987 set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
3988 }
3989
3990 inline bool has_instance_call_handler() {
3991 return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
3992 }
3993
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00003994 inline void set_is_extensible(bool value);
3995 inline bool is_extensible();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00003996
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00003997 inline void set_elements_kind(JSObject::ElementsKind elements_kind) {
3998 ASSERT(elements_kind < JSObject::kElementsKindCount);
3999 ASSERT(JSObject::kElementsKindCount <= (1 << kElementsKindBitCount));
4000 set_bit_field2((bit_field2() & ~kElementsKindMask) |
4001 (elements_kind << kElementsKindShift));
4002 ASSERT(this->elements_kind() == elements_kind);
4003 }
4004
4005 inline JSObject::ElementsKind elements_kind() {
4006 return static_cast<JSObject::ElementsKind>(
4007 (bit_field2() & kElementsKindMask) >> kElementsKindShift);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00004008 }
4009
whesse@chromium.org7b260152011-06-20 15:33:18 +00004010 // Tells whether the instance has fast elements.
4011 // Equivalent to instance->GetElementsKind() == FAST_ELEMENTS.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004012 inline bool has_fast_elements() {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00004013 return elements_kind() == JSObject::FAST_ELEMENTS;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004014 }
4015
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004016 inline bool has_fast_double_elements() {
4017 return elements_kind() == JSObject::FAST_DOUBLE_ELEMENTS;
4018 }
4019
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004020 inline bool has_external_array_elements() {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00004021 JSObject::ElementsKind kind(elements_kind());
4022 return kind >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
4023 kind <= JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004024 }
4025
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004026 inline bool has_dictionary_elements() {
4027 return elements_kind() == JSObject::DICTIONARY_ELEMENTS;
4028 }
4029
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004030 // Tells whether the map is attached to SharedFunctionInfo
4031 // (for inobject slack tracking).
4032 inline void set_attached_to_shared_function_info(bool value);
4033
4034 inline bool attached_to_shared_function_info();
4035
4036 // Tells whether the map is shared between objects that may have different
4037 // behavior. If true, the map should never be modified, instead a clone
4038 // should be created and modified.
4039 inline void set_is_shared(bool value);
4040
4041 inline bool is_shared();
4042
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004043 // Tells whether the instance needs security checks when accessing its
4044 // properties.
ager@chromium.org870a0b62008-11-04 11:43:05 +00004045 inline void set_is_access_check_needed(bool access_check_needed);
4046 inline bool is_access_check_needed();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004047
4048 // [prototype]: implicit prototype object.
4049 DECL_ACCESSORS(prototype, Object)
4050
4051 // [constructor]: points back to the function responsible for this map.
4052 DECL_ACCESSORS(constructor, Object)
4053
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004054 inline JSFunction* unchecked_constructor();
4055
danno@chromium.org40cb8782011-05-25 07:58:50 +00004056 // Should only be called by the code that initializes map to set initial valid
4057 // value of the instance descriptor member.
4058 inline void init_instance_descriptors();
4059
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004060 // [instance descriptors]: describes the object.
4061 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
4062
danno@chromium.org40cb8782011-05-25 07:58:50 +00004063 // Sets the instance descriptor array for the map to be an empty descriptor
4064 // array.
4065 inline void clear_instance_descriptors();
4066
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004067 // [stub cache]: contains stubs compiled for this map.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004068 DECL_ACCESSORS(code_cache, Object)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004069
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00004070 // [prototype transitions]: cache of prototype transitions.
4071 // Prototype transition is a transition that happens
4072 // when we change object's prototype to a new one.
4073 // Cache format:
4074 // 0: finger - index of the first free cell in the cache
4075 // 1 + 2 * i: prototype
4076 // 2 + 2 * i: target map
4077 DECL_ACCESSORS(prototype_transitions, FixedArray)
4078 inline FixedArray* unchecked_prototype_transitions();
4079
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00004080 static const int kProtoTransitionHeaderSize = 1;
4081 static const int kProtoTransitionNumberOfEntriesOffset = 0;
4082 static const int kProtoTransitionElementsPerEntry = 2;
4083 static const int kProtoTransitionPrototypeOffset = 0;
4084 static const int kProtoTransitionMapOffset = 1;
4085
4086 inline int NumberOfProtoTransitions() {
4087 FixedArray* cache = unchecked_prototype_transitions();
4088 if (cache->length() == 0) return 0;
4089 return
4090 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
4091 }
4092
4093 inline void SetNumberOfProtoTransitions(int value) {
4094 FixedArray* cache = unchecked_prototype_transitions();
4095 ASSERT(cache->length() != 0);
4096 cache->set_unchecked(kProtoTransitionNumberOfEntriesOffset,
4097 Smi::FromInt(value));
4098 }
4099
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004100 // Lookup in the map's instance descriptors and fill out the result
4101 // with the given holder if the name is found. The holder may be
4102 // NULL when this function is used from the compiler.
4103 void LookupInDescriptors(JSObject* holder,
4104 String* name,
4105 LookupResult* result);
4106
lrn@chromium.org303ada72010-10-27 09:33:13 +00004107 MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004108
lrn@chromium.org303ada72010-10-27 09:33:13 +00004109 MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
4110 NormalizedMapSharingMode sharing);
ricow@chromium.org65fae842010-08-25 15:26:24 +00004111
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004112 // Returns a copy of the map, with all transitions dropped from the
4113 // instance descriptors.
lrn@chromium.org303ada72010-10-27 09:33:13 +00004114 MUST_USE_RESULT MaybeObject* CopyDropTransitions();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004115
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004116 // Returns this map if it already has elements that are fast, otherwise
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00004117 // returns a copy of the map, with all transitions dropped from the
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004118 // descriptors and the ElementsKind set to FAST_ELEMENTS.
lrn@chromium.org303ada72010-10-27 09:33:13 +00004119 MUST_USE_RESULT inline MaybeObject* GetFastElementsMap();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00004120
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004121 // Returns this map if it already has fast elements that are doubles,
4122 // otherwise returns a copy of the map, with all transitions dropped from the
4123 // descriptors and the ElementsKind set to FAST_DOUBLE_ELEMENTS.
4124 MUST_USE_RESULT inline MaybeObject* GetFastDoubleElementsMap();
4125
4126 // Returns this map if already has dictionary elements, otherwise returns a
4127 // copy of the map, with all transitions dropped from the descriptors and the
4128 // ElementsKind set to DICTIONARY_ELEMENTS.
lrn@chromium.org303ada72010-10-27 09:33:13 +00004129 MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00004130
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00004131 // Returns a new map with all transitions dropped from the descriptors and the
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004132 // ElementsKind set to one of the value corresponding to array_type.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00004133 MUST_USE_RESULT MaybeObject* GetExternalArrayElementsMap(
4134 ExternalArrayType array_type,
4135 bool safe_to_add_transition);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004136
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004137 // Returns the property index for name (only valid for FAST MODE).
4138 int PropertyIndexFor(String* name);
4139
4140 // Returns the next free property index (only valid for FAST MODE).
4141 int NextFreePropertyIndex();
4142
4143 // Returns the number of properties described in instance_descriptors.
4144 int NumberOfDescribedProperties();
4145
4146 // Casting.
4147 static inline Map* cast(Object* obj);
4148
4149 // Locate an accessor in the instance descriptor.
4150 AccessorDescriptor* FindAccessor(String* name);
4151
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004152 // Code cache operations.
4153
4154 // Clears the code cache.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004155 inline void ClearCodeCache(Heap* heap);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004156
4157 // Update code cache.
lrn@chromium.org303ada72010-10-27 09:33:13 +00004158 MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004159
4160 // Returns the found code or undefined if absent.
4161 Object* FindInCodeCache(String* name, Code::Flags flags);
4162
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004163 // Returns the non-negative index of the code object if it is in the
4164 // cache and -1 otherwise.
sgjesse@chromium.org99a37fa2010-03-11 09:23:46 +00004165 int IndexInCodeCache(Object* name, Code* code);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004166
4167 // Removes a code object from the code cache at the given index.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004168 void RemoveFromCodeCache(String* name, Code* code, int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004169
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00004170 // For every transition in this map, makes the transition's
4171 // target's prototype pointer point back to this map.
4172 // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
4173 void CreateBackPointers();
4174
4175 // Set all map transitions from this map to dead maps to null.
4176 // Also, restore the original prototype on the targets of these
4177 // transitions, so that we do not process this map again while
4178 // following back pointers.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004179 void ClearNonLiveTransitions(Heap* heap, Object* real_prototype);
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00004180
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00004181 // Computes a hash value for this map, to be used in HashTables and such.
4182 int Hash();
4183
4184 // Compares this map to another to see if they describe equivalent objects.
4185 // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if
4186 // it had exactly zero inobject properties.
4187 // The "shared" flags of both this map and |other| are ignored.
4188 bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode);
4189
4190 // Returns true if this map and |other| describe equivalent objects.
4191 // The "shared" flags of both this map and |other| are ignored.
4192 bool EquivalentTo(Map* other) {
4193 return EquivalentToForNormalization(other, KEEP_INOBJECT_PROPERTIES);
4194 }
4195
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004196 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00004197#ifdef OBJECT_PRINT
4198 inline void MapPrint() {
4199 MapPrint(stdout);
4200 }
4201 void MapPrint(FILE* out);
4202#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004203#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004204 void MapVerify();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004205 void SharedMapVerify();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004206#endif
4207
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004208 inline int visitor_id();
4209 inline void set_visitor_id(int visitor_id);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00004210
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004211 // Returns the isolate/heap this map belongs to.
4212 inline Isolate* isolate();
4213 inline Heap* heap();
4214
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004215 typedef void (*TraverseCallback)(Map* map, void* data);
4216
4217 void TraverseTransitionTree(TraverseCallback callback, void* data);
4218
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00004219 static const int kMaxCachedPrototypeTransitions = 256;
4220
4221 Object* GetPrototypeTransition(Object* prototype);
4222
4223 MaybeObject* PutPrototypeTransition(Object* prototype, Map* map);
4224
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004225 static const int kMaxPreAllocatedPropertyFields = 255;
4226
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004227 // Layout description.
ager@chromium.org7c537e22008-10-16 08:43:32 +00004228 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
4229 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004230 static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
4231 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
danno@chromium.org40cb8782011-05-25 07:58:50 +00004232 // Storage for instance descriptors is overloaded to also contain additional
4233 // map flags when unused (bit_field3). When the map has instance descriptors,
4234 // the flags are transferred to the instance descriptor array and accessed
4235 // through an extra indirection.
4236 // TODO(1399): It should be possible to make room for bit_field3 in the map
4237 // without overloading the instance descriptors field, but the map is
4238 // currently perfectly aligned to 32 bytes and extending it at all would
4239 // double its size. After the increment GC work lands, this size restriction
4240 // could be loosened and bit_field3 moved directly back in the map.
4241 static const int kInstanceDescriptorsOrBitField3Offset =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004242 kConstructorOffset + kPointerSize;
danno@chromium.org40cb8782011-05-25 07:58:50 +00004243 static const int kCodeCacheOffset =
4244 kInstanceDescriptorsOrBitField3Offset + kPointerSize;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00004245 static const int kPrototypeTransitionsOffset =
4246 kCodeCacheOffset + kPointerSize;
4247 static const int kPadStart = kPrototypeTransitionsOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004248 static const int kSize = MAP_POINTER_ALIGN(kPadStart);
4249
4250 // Layout of pointer fields. Heap iteration code relies on them
4251 // being continiously allocated.
4252 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
4253 static const int kPointerFieldsEndOffset =
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00004254 Map::kPrototypeTransitionsOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004255
ager@chromium.org7c537e22008-10-16 08:43:32 +00004256 // Byte offsets within kInstanceSizesOffset.
4257 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
ager@chromium.orga1645e22009-09-09 19:27:10 +00004258 static const int kInObjectPropertiesByte = 1;
4259 static const int kInObjectPropertiesOffset =
4260 kInstanceSizesOffset + kInObjectPropertiesByte;
4261 static const int kPreAllocatedPropertyFieldsByte = 2;
4262 static const int kPreAllocatedPropertyFieldsOffset =
4263 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00004264 static const int kVisitorIdByte = 3;
4265 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
ager@chromium.org7c537e22008-10-16 08:43:32 +00004266
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004267 // Byte offsets within kInstanceAttributesOffset attributes.
ager@chromium.org7c537e22008-10-16 08:43:32 +00004268 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
4269 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
4270 static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00004271 static const int kBitField2Offset = kInstanceAttributesOffset + 3;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004272
ager@chromium.org18ad94b2009-09-02 08:22:29 +00004273 STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
4274
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004275 // Bit positions for bit field.
mads.s.ager31e71382008-08-13 09:32:07 +00004276 static const int kUnused = 0; // To be used for marking recently used maps.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004277 static const int kHasNonInstancePrototype = 1;
4278 static const int kIsHiddenPrototype = 2;
4279 static const int kHasNamedInterceptor = 3;
4280 static const int kHasIndexedInterceptor = 4;
4281 static const int kIsUndetectable = 5;
4282 static const int kHasInstanceCallHandler = 6;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00004283 static const int kIsAccessCheckNeeded = 7;
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00004284
ager@chromium.orge2902be2009-06-08 12:21:35 +00004285 // Bit positions for bit field 2
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00004286 static const int kIsExtensible = 0;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00004287 static const int kFunctionWithPrototype = 1;
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00004288 static const int kStringWrapperSafeForDefaultValueOf = 2;
4289 static const int kAttachedToSharedFunctionInfo = 3;
4290 // No bits can be used after kElementsKindFirstBit, they are all reserved for
4291 // storing ElementKind. for anything other than storing the ElementKind.
4292 static const int kElementsKindShift = 4;
4293 static const int kElementsKindBitCount = 4;
4294
4295 // Derived values from bit field 2
4296 static const int kElementsKindMask = (-1 << kElementsKindShift) &
4297 ((1 << (kElementsKindShift + kElementsKindBitCount)) - 1);
4298 static const int8_t kMaximumBitField2FastElementValue = static_cast<int8_t>(
4299 (JSObject::FAST_ELEMENTS + 1) << Map::kElementsKindShift) - 1;
danno@chromium.org40cb8782011-05-25 07:58:50 +00004300
4301 // Bit positions for bit field 3
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00004302 static const int kIsShared = 0;
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00004303
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004304 // Layout of the default cache. It holds alternating name and code objects.
4305 static const int kCodeCacheEntrySize = 2;
4306 static const int kCodeCacheEntryNameOffset = 0;
4307 static const int kCodeCacheEntryCodeOffset = 1;
4308
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004309 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
4310 kPointerFieldsEndOffset,
4311 kSize> BodyDescriptor;
4312
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004313 private:
4314 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
4315};
4316
4317
4318// An abstract superclass, a marker class really, for simple structure classes.
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00004319// It doesn't carry much functionality but allows struct classes to be
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004320// identified in the type system.
4321class Struct: public HeapObject {
4322 public:
4323 inline void InitializeBody(int object_size);
4324 static inline Struct* cast(Object* that);
4325};
4326
4327
mads.s.ager31e71382008-08-13 09:32:07 +00004328// Script describes a script which has been added to the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004329class Script: public Struct {
4330 public:
ager@chromium.orge2902be2009-06-08 12:21:35 +00004331 // Script types.
4332 enum Type {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00004333 TYPE_NATIVE = 0,
4334 TYPE_EXTENSION = 1,
4335 TYPE_NORMAL = 2
ager@chromium.orge2902be2009-06-08 12:21:35 +00004336 };
4337
4338 // Script compilation types.
4339 enum CompilationType {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00004340 COMPILATION_TYPE_HOST = 0,
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00004341 COMPILATION_TYPE_EVAL = 1
ager@chromium.orge2902be2009-06-08 12:21:35 +00004342 };
4343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004344 // [source]: the script source.
4345 DECL_ACCESSORS(source, Object)
4346
4347 // [name]: the script name.
4348 DECL_ACCESSORS(name, Object)
4349
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00004350 // [id]: the script id.
4351 DECL_ACCESSORS(id, Object)
4352
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004353 // [line_offset]: script line offset in resource from where it was extracted.
4354 DECL_ACCESSORS(line_offset, Smi)
4355
4356 // [column_offset]: script column offset in resource from where it was
4357 // extracted.
4358 DECL_ACCESSORS(column_offset, Smi)
4359
ager@chromium.org65dad4b2009-04-23 08:48:43 +00004360 // [data]: additional data associated with this script.
4361 DECL_ACCESSORS(data, Object)
4362
ager@chromium.org9085a012009-05-11 19:22:57 +00004363 // [context_data]: context data for the context this script was compiled in.
4364 DECL_ACCESSORS(context_data, Object)
4365
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004366 // [wrapper]: the wrapper cache.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00004367 DECL_ACCESSORS(wrapper, Foreign)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004368
4369 // [type]: the script type.
4370 DECL_ACCESSORS(type, Smi)
4371
ager@chromium.orge2902be2009-06-08 12:21:35 +00004372 // [compilation]: how the the script was compiled.
4373 DECL_ACCESSORS(compilation_type, Smi)
4374
ager@chromium.orgc4c92722009-11-18 14:12:51 +00004375 // [line_ends]: FixedArray of line ends positions.
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00004376 DECL_ACCESSORS(line_ends, Object)
iposva@chromium.org245aa852009-02-10 00:49:54 +00004377
sgjesse@chromium.org98180592009-12-02 08:17:28 +00004378 // [eval_from_shared]: for eval scripts the shared funcion info for the
4379 // function from which eval was called.
4380 DECL_ACCESSORS(eval_from_shared, Object)
ager@chromium.orge2902be2009-06-08 12:21:35 +00004381
4382 // [eval_from_instructions_offset]: the instruction offset in the code for the
4383 // function from which eval was called where eval was called.
4384 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
4385
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004386 static inline Script* cast(Object* obj);
4387
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00004388 // If script source is an external string, check that the underlying
4389 // resource is accessible. Otherwise, always return true.
4390 inline bool HasValidSource();
4391
whesse@chromium.org023421e2010-12-21 12:19:12 +00004392#ifdef OBJECT_PRINT
4393 inline void ScriptPrint() {
4394 ScriptPrint(stdout);
4395 }
4396 void ScriptPrint(FILE* out);
4397#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004398#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004399 void ScriptVerify();
4400#endif
4401
ager@chromium.org236ad962008-09-25 09:45:57 +00004402 static const int kSourceOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004403 static const int kNameOffset = kSourceOffset + kPointerSize;
4404 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
4405 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
ager@chromium.org65dad4b2009-04-23 08:48:43 +00004406 static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
ager@chromium.org9085a012009-05-11 19:22:57 +00004407 static const int kContextOffset = kDataOffset + kPointerSize;
4408 static const int kWrapperOffset = kContextOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004409 static const int kTypeOffset = kWrapperOffset + kPointerSize;
ager@chromium.orge2902be2009-06-08 12:21:35 +00004410 static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +00004411 static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
4412 static const int kIdOffset = kLineEndsOffset + kPointerSize;
sgjesse@chromium.org98180592009-12-02 08:17:28 +00004413 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
ager@chromium.orge2902be2009-06-08 12:21:35 +00004414 static const int kEvalFrominstructionsOffsetOffset =
sgjesse@chromium.org98180592009-12-02 08:17:28 +00004415 kEvalFromSharedOffset + kPointerSize;
ager@chromium.orge2902be2009-06-08 12:21:35 +00004416 static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004417
4418 private:
4419 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
4420};
4421
4422
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004423// List of builtin functions we want to identify to improve code
4424// generation.
4425//
4426// Each entry has a name of a global object property holding an object
4427// optionally followed by ".prototype", a name of a builtin function
4428// on the object (the one the id is set for), and a label.
4429//
4430// Installation of ids for the selected builtin functions is handled
4431// by the bootstrapper.
4432//
4433// NOTE: Order is important: math functions should be at the end of
4434// the list and MathFloor should be the first math function.
4435#define FUNCTIONS_WITH_ID_LIST(V) \
4436 V(Array.prototype, push, ArrayPush) \
4437 V(Array.prototype, pop, ArrayPop) \
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00004438 V(Function.prototype, apply, FunctionApply) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004439 V(String.prototype, charCodeAt, StringCharCodeAt) \
4440 V(String.prototype, charAt, StringCharAt) \
4441 V(String, fromCharCode, StringFromCharCode) \
4442 V(Math, floor, MathFloor) \
4443 V(Math, round, MathRound) \
4444 V(Math, ceil, MathCeil) \
4445 V(Math, abs, MathAbs) \
4446 V(Math, log, MathLog) \
4447 V(Math, sin, MathSin) \
4448 V(Math, cos, MathCos) \
4449 V(Math, tan, MathTan) \
4450 V(Math, asin, MathASin) \
4451 V(Math, acos, MathACos) \
4452 V(Math, atan, MathATan) \
4453 V(Math, exp, MathExp) \
4454 V(Math, sqrt, MathSqrt) \
4455 V(Math, pow, MathPow)
4456
4457
4458enum BuiltinFunctionId {
4459#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
4460 k##name,
4461 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
4462#undef DECLARE_FUNCTION_ID
4463 // Fake id for a special case of Math.pow. Note, it continues the
4464 // list of math functions.
4465 kMathPowHalf,
4466 kFirstMathFunctionId = kMathFloor
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004467};
4468
4469
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004470// SharedFunctionInfo describes the JSFunction information that can be
4471// shared by multiple instances of the function.
4472class SharedFunctionInfo: public HeapObject {
4473 public:
4474 // [name]: Function name.
4475 DECL_ACCESSORS(name, Object)
4476
4477 // [code]: Function code.
4478 DECL_ACCESSORS(code, Code)
4479
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00004480 // [scope_info]: Scope info.
ager@chromium.orgb5737492010-07-15 09:29:43 +00004481 DECL_ACCESSORS(scope_info, SerializedScopeInfo)
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00004482
ager@chromium.org5aa501c2009-06-23 07:57:28 +00004483 // [construct stub]: Code stub for constructing instances of this function.
4484 DECL_ACCESSORS(construct_stub, Code)
4485
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004486 inline Code* unchecked_code();
4487
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004488 // Returns if this function has been compiled to native code yet.
4489 inline bool is_compiled();
4490
4491 // [length]: The function length - usually the number of declared parameters.
4492 // Use up to 2^30 parameters.
4493 inline int length();
4494 inline void set_length(int value);
4495
4496 // [formal parameter count]: The declared number of parameters.
4497 inline int formal_parameter_count();
4498 inline void set_formal_parameter_count(int value);
4499
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004500 // Set the formal parameter count so the function code will be
4501 // called without using argument adaptor frames.
4502 inline void DontAdaptArguments();
4503
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004504 // [expected_nof_properties]: Expected number of properties for the function.
4505 inline int expected_nof_properties();
4506 inline void set_expected_nof_properties(int value);
4507
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004508 // Inobject slack tracking is the way to reclaim unused inobject space.
4509 //
4510 // The instance size is initially determined by adding some slack to
4511 // expected_nof_properties (to allow for a few extra properties added
4512 // after the constructor). There is no guarantee that the extra space
4513 // will not be wasted.
4514 //
4515 // Here is the algorithm to reclaim the unused inobject space:
4516 // - Detect the first constructor call for this SharedFunctionInfo.
4517 // When it happens enter the "in progress" state: remember the
4518 // constructor's initial_map and install a special construct stub that
4519 // counts constructor calls.
4520 // - While the tracking is in progress create objects filled with
4521 // one_pointer_filler_map instead of undefined_value. This way they can be
4522 // resized quickly and safely.
4523 // - Once enough (kGenerousAllocationCount) objects have been created
4524 // compute the 'slack' (traverse the map transition tree starting from the
4525 // initial_map and find the lowest value of unused_property_fields).
4526 // - Traverse the transition tree again and decrease the instance size
4527 // of every map. Existing objects will resize automatically (they are
4528 // filled with one_pointer_filler_map). All further allocations will
4529 // use the adjusted instance size.
4530 // - Decrease expected_nof_properties so that an allocations made from
4531 // another context will use the adjusted instance size too.
4532 // - Exit "in progress" state by clearing the reference to the initial_map
4533 // and setting the regular construct stub (generic or inline).
4534 //
4535 // The above is the main event sequence. Some special cases are possible
4536 // while the tracking is in progress:
4537 //
4538 // - GC occurs.
4539 // Check if the initial_map is referenced by any live objects (except this
4540 // SharedFunctionInfo). If it is, continue tracking as usual.
4541 // If it is not, clear the reference and reset the tracking state. The
4542 // tracking will be initiated again on the next constructor call.
4543 //
4544 // - The constructor is called from another context.
4545 // Immediately complete the tracking, perform all the necessary changes
4546 // to maps. This is necessary because there is no efficient way to track
4547 // multiple initial_maps.
4548 // Proceed to create an object in the current context (with the adjusted
4549 // size).
4550 //
4551 // - A different constructor function sharing the same SharedFunctionInfo is
4552 // called in the same context. This could be another closure in the same
4553 // context, or the first function could have been disposed.
4554 // This is handled the same way as the previous case.
4555 //
4556 // Important: inobject slack tracking is not attempted during the snapshot
4557 // creation.
4558
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +00004559 static const int kGenerousAllocationCount = 8;
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004560
4561 // [construction_count]: Counter for constructor calls made during
4562 // the tracking phase.
4563 inline int construction_count();
4564 inline void set_construction_count(int value);
4565
4566 // [initial_map]: initial map of the first function called as a constructor.
4567 // Saved for the duration of the tracking phase.
4568 // This is a weak link (GC resets it to undefined_value if no other live
4569 // object reference this map).
4570 DECL_ACCESSORS(initial_map, Object)
4571
4572 // True if the initial_map is not undefined and the countdown stub is
4573 // installed.
4574 inline bool IsInobjectSlackTrackingInProgress();
4575
4576 // Starts the tracking.
4577 // Stores the initial map and installs the countdown stub.
4578 // IsInobjectSlackTrackingInProgress is normally true after this call,
4579 // except when tracking have not been started (e.g. the map has no unused
4580 // properties or the snapshot is being built).
4581 void StartInobjectSlackTracking(Map* map);
4582
4583 // Completes the tracking.
4584 // IsInobjectSlackTrackingInProgress is false after this call.
4585 void CompleteInobjectSlackTracking();
4586
4587 // Clears the initial_map before the GC marking phase to ensure the reference
4588 // is weak. IsInobjectSlackTrackingInProgress is false after this call.
4589 void DetachInitialMap();
4590
4591 // Restores the link to the initial map after the GC marking phase.
4592 // IsInobjectSlackTrackingInProgress is true after this call.
4593 void AttachInitialMap(Map* map);
4594
4595 // False if there are definitely no live objects created from this function.
4596 // True if live objects _may_ exist (existence not guaranteed).
4597 // May go back from true to false after GC.
whesse@chromium.org7b260152011-06-20 15:33:18 +00004598 DECL_BOOLEAN_ACCESSORS(live_objects_may_exist)
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004599
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004600 // [instance class name]: class name for instances.
4601 DECL_ACCESSORS(instance_class_name, Object)
4602
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00004603 // [function data]: This field holds some additional data for function.
4604 // Currently it either has FunctionTemplateInfo to make benefit the API
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004605 // or Smi identifying a builtin function.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004606 // In the long run we don't want all functions to have this field but
4607 // we can fix that when we have a better model for storing hidden data
4608 // on objects.
4609 DECL_ACCESSORS(function_data, Object)
4610
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00004611 inline bool IsApiFunction();
4612 inline FunctionTemplateInfo* get_api_func_data();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004613 inline bool HasBuiltinFunctionId();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004614 inline BuiltinFunctionId builtin_function_id();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00004615
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004616 // [script info]: Script from which the function originates.
4617 DECL_ACCESSORS(script, Object)
4618
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00004619 // [num_literals]: Number of literals used by this function.
4620 inline int num_literals();
4621 inline void set_num_literals(int value);
4622
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004623 // [start_position_and_type]: Field used to store both the source code
4624 // position, whether or not the function is a function expression,
4625 // and whether or not the function is a toplevel function. The two
4626 // least significants bit indicates whether the function is an
4627 // expression and the rest contains the source code position.
4628 inline int start_position_and_type();
4629 inline void set_start_position_and_type(int value);
4630
4631 // [debug info]: Debug information.
4632 DECL_ACCESSORS(debug_info, Object)
4633
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +00004634 // [inferred name]: Name inferred from variable or property
4635 // assignment of this function. Used to facilitate debugging and
4636 // profiling of JavaScript code written in OO style, where almost
4637 // all functions are anonymous but are assigned to object
4638 // properties.
4639 DECL_ACCESSORS(inferred_name, String)
4640
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00004641 // The function's name if it is non-empty, otherwise the inferred name.
4642 String* DebugName();
4643
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004644 // Position of the 'function' token in the script source.
4645 inline int function_token_position();
4646 inline void set_function_token_position(int function_token_position);
4647
4648 // Position of this function in the script source.
4649 inline int start_position();
4650 inline void set_start_position(int start_position);
4651
4652 // End position of this function in the script source.
4653 inline int end_position();
4654 inline void set_end_position(int end_position);
4655
4656 // Is this function a function expression in the source code.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00004657 DECL_BOOLEAN_ACCESSORS(is_expression)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004658
ager@chromium.orga1645e22009-09-09 19:27:10 +00004659 // Is this function a top-level function (scripts, evals).
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00004660 DECL_BOOLEAN_ACCESSORS(is_toplevel)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004661
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004662 // Bit field containing various information collected by the compiler to
4663 // drive optimization.
4664 inline int compiler_hints();
4665 inline void set_compiler_hints(int value);
4666
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004667 // A counter used to determine when to stress the deoptimizer with a
4668 // deopt.
4669 inline Smi* deopt_counter();
4670 inline void set_deopt_counter(Smi* counter);
4671
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004672 // Add information on assignments of the form this.x = ...;
4673 void SetThisPropertyAssignmentsInfo(
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004674 bool has_only_simple_this_property_assignments,
4675 FixedArray* this_property_assignments);
4676
ager@chromium.org18ad94b2009-09-02 08:22:29 +00004677 // Clear information on assignments of the form this.x = ...;
4678 void ClearThisPropertyAssignmentsInfo();
4679
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004680 // Indicate that this function only consists of assignments of the form
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004681 // this.x = y; where y is either a constant or refers to an argument.
4682 inline bool has_only_simple_this_property_assignments();
4683
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00004684 // Indicates if this function can be lazy compiled.
4685 // This is used to determine if we can safely flush code from a function
4686 // when doing GC if we expect that the function will no longer be used.
whesse@chromium.org7b260152011-06-20 15:33:18 +00004687 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00004688
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004689 // Indicates how many full GCs this function has survived with assigned
4690 // code object. Used to determine when it is relatively safe to flush
4691 // this code object and replace it with lazy compilation stub.
4692 // Age is reset when GC notices that the code object is referenced
4693 // from the stack or compilation cache.
4694 inline int code_age();
4695 inline void set_code_age(int age);
4696
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004697 // Indicates whether optimizations have been disabled for this
4698 // shared function info. If a function is repeatedly optimized or if
4699 // we cannot optimize the function we disable optimization to avoid
4700 // spending time attempting to optimize it again.
whesse@chromium.org7b260152011-06-20 15:33:18 +00004701 DECL_BOOLEAN_ACCESSORS(optimization_disabled)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004702
ricow@chromium.org83aa5492011-02-07 12:42:56 +00004703 // Indicates whether the function is a strict mode function.
whesse@chromium.org7b260152011-06-20 15:33:18 +00004704 DECL_BOOLEAN_ACCESSORS(strict_mode)
4705
4706 // False if the function definitely does not allocate an arguments object.
4707 DECL_BOOLEAN_ACCESSORS(uses_arguments)
4708
4709 // True if the function has any duplicated parameter names.
4710 DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters)
ricow@chromium.org83aa5492011-02-07 12:42:56 +00004711
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004712 // Indicates whether the function is a native function.
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004713 // These needs special threatment in .call and .apply since
4714 // null passed as the receiver should not be translated to the
4715 // global object.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00004716 DECL_BOOLEAN_ACCESSORS(native)
4717
4718 // Indicates that the function was created by the Function function.
4719 // Though it's anonymous, toString should treat it as if it had the name
4720 // "anonymous". We don't set the name itself so that the system does not
4721 // see a binding for it.
4722 DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004723
whesse@chromium.org7b260152011-06-20 15:33:18 +00004724 // Indicates whether the function is a bound function created using
4725 // the bind function.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00004726 DECL_BOOLEAN_ACCESSORS(bound)
4727
4728 // Indicates that the function is anonymous (the name field can be set
4729 // through the API, which does not change this flag).
4730 DECL_BOOLEAN_ACCESSORS(is_anonymous)
whesse@chromium.org7b260152011-06-20 15:33:18 +00004731
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004732 // Indicates whether or not the code in the shared function support
4733 // deoptimization.
4734 inline bool has_deoptimization_support();
4735
4736 // Enable deoptimization support through recompiled code.
4737 void EnableDeoptimizationSupport(Code* recompiled);
4738
ager@chromium.orgea91cc52011-05-23 06:06:11 +00004739 // Disable (further) attempted optimization of all functions sharing this
4740 // shared function info. The function is the one we actually tried to
4741 // optimize.
4742 void DisableOptimization(JSFunction* function);
4743
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004744 // Lookup the bailout ID and ASSERT that it exists in the non-optimized
4745 // code, returns whether it asserted (i.e., always true if assertions are
4746 // disabled).
4747 bool VerifyBailoutId(int id);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004748
ager@chromium.org5c838252010-02-19 08:53:10 +00004749 // Check whether a inlined constructor can be generated with the given
4750 // prototype.
4751 bool CanGenerateInlineConstructor(Object* prototype);
4752
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00004753 // Prevents further attempts to generate inline constructors.
4754 // To be called if generation failed for any reason.
4755 void ForbidInlineConstructor();
4756
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004757 // For functions which only contains this property assignments this provides
4758 // access to the names for the properties assigned.
4759 DECL_ACCESSORS(this_property_assignments, Object)
4760 inline int this_property_assignments_count();
4761 inline void set_this_property_assignments_count(int value);
4762 String* GetThisPropertyAssignmentName(int index);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00004763 bool IsThisPropertyAssignmentArgument(int index);
4764 int GetThisPropertyAssignmentArgument(int index);
4765 Object* GetThisPropertyAssignmentConstant(int index);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004766
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004767 // [source code]: Source code for the function.
4768 bool HasSourceCode();
4769 Object* GetSourceCode();
4770
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004771 inline int opt_count();
4772 inline void set_opt_count(int opt_count);
4773
4774 // Source size of this function.
4775 int SourceSize();
4776
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004777 // Calculate the instance size.
4778 int CalculateInstanceSize();
4779
4780 // Calculate the number of in-object properties.
4781 int CalculateInObjectProperties();
4782
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004783 // Dispatched behavior.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004784 // Set max_length to -1 for unlimited length.
4785 void SourceCodePrint(StringStream* accumulator, int max_length);
whesse@chromium.org023421e2010-12-21 12:19:12 +00004786#ifdef OBJECT_PRINT
4787 inline void SharedFunctionInfoPrint() {
4788 SharedFunctionInfoPrint(stdout);
4789 }
4790 void SharedFunctionInfoPrint(FILE* out);
4791#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004792#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004793 void SharedFunctionInfoVerify();
4794#endif
4795
4796 // Casting.
4797 static inline SharedFunctionInfo* cast(Object* obj);
4798
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004799 // Constants.
4800 static const int kDontAdaptArgumentsSentinel = -1;
4801
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004802 // Layout description.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004803 // Pointer fields.
ager@chromium.org236ad962008-09-25 09:45:57 +00004804 static const int kNameOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004805 static const int kCodeOffset = kNameOffset + kPointerSize;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00004806 static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
4807 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004808 static const int kInstanceClassNameOffset =
4809 kConstructStubOffset + kPointerSize;
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00004810 static const int kFunctionDataOffset =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004811 kInstanceClassNameOffset + kPointerSize;
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00004812 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004813 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
4814 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004815 static const int kInitialMapOffset =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004816 kInferredNameOffset + kPointerSize;
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004817 static const int kThisPropertyAssignmentsOffset =
4818 kInitialMapOffset + kPointerSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004819 static const int kDeoptCounterOffset =
4820 kThisPropertyAssignmentsOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004821#if V8_HOST_ARCH_32_BIT
4822 // Smi fields.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004823 static const int kLengthOffset =
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004824 kDeoptCounterOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004825 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
4826 static const int kExpectedNofPropertiesOffset =
4827 kFormalParameterCountOffset + kPointerSize;
4828 static const int kNumLiteralsOffset =
4829 kExpectedNofPropertiesOffset + kPointerSize;
4830 static const int kStartPositionAndTypeOffset =
4831 kNumLiteralsOffset + kPointerSize;
4832 static const int kEndPositionOffset =
4833 kStartPositionAndTypeOffset + kPointerSize;
4834 static const int kFunctionTokenPositionOffset =
4835 kEndPositionOffset + kPointerSize;
4836 static const int kCompilerHintsOffset =
4837 kFunctionTokenPositionOffset + kPointerSize;
4838 static const int kThisPropertyAssignmentsCountOffset =
4839 kCompilerHintsOffset + kPointerSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004840 static const int kOptCountOffset =
4841 kThisPropertyAssignmentsCountOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004842 // Total size.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004843 static const int kSize = kOptCountOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004844#else
4845 // The only reason to use smi fields instead of int fields
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004846 // is to allow iteration without maps decoding during
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004847 // garbage collections.
4848 // To avoid wasting space on 64-bit architectures we use
4849 // the following trick: we group integer fields into pairs
4850 // First integer in each pair is shifted left by 1.
4851 // By doing this we guarantee that LSB of each kPointerSize aligned
4852 // word is not set and thus this word cannot be treated as pointer
4853 // to HeapObject during old space traversal.
4854 static const int kLengthOffset =
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004855 kDeoptCounterOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004856 static const int kFormalParameterCountOffset =
4857 kLengthOffset + kIntSize;
4858
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004859 static const int kExpectedNofPropertiesOffset =
4860 kFormalParameterCountOffset + kIntSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004861 static const int kNumLiteralsOffset =
4862 kExpectedNofPropertiesOffset + kIntSize;
4863
4864 static const int kEndPositionOffset =
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00004865 kNumLiteralsOffset + kIntSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004866 static const int kStartPositionAndTypeOffset =
4867 kEndPositionOffset + kIntSize;
4868
4869 static const int kFunctionTokenPositionOffset =
4870 kStartPositionAndTypeOffset + kIntSize;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004871 static const int kCompilerHintsOffset =
kasperl@chromium.org71affb52009-05-26 05:44:31 +00004872 kFunctionTokenPositionOffset + kIntSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004873
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004874 static const int kThisPropertyAssignmentsCountOffset =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004875 kCompilerHintsOffset + kIntSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004876 static const int kOptCountOffset =
4877 kThisPropertyAssignmentsCountOffset + kIntSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004878
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004879 // Total size.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004880 static const int kSize = kOptCountOffset + kIntSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00004881
4882#endif
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004883
4884 // The construction counter for inobject slack tracking is stored in the
4885 // most significant byte of compiler_hints which is otherwise unused.
4886 // Its offset depends on the endian-ness of the architecture.
4887#if __BYTE_ORDER == __LITTLE_ENDIAN
4888 static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
4889#elif __BYTE_ORDER == __BIG_ENDIAN
4890 static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
4891#else
4892#error Unknown byte ordering
4893#endif
4894
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00004895 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004896
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00004897 typedef FixedBodyDescriptor<kNameOffset,
4898 kThisPropertyAssignmentsOffset + kPointerSize,
4899 kSize> BodyDescriptor;
4900
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004901 // Bit positions in start_position_and_type.
4902 // The source code start position is in the 30 most significant bits of
4903 // the start_position_and_type field.
4904 static const int kIsExpressionBit = 0;
4905 static const int kIsTopLevelBit = 1;
4906 static const int kStartPositionShift = 2;
4907 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
mads.s.ager31e71382008-08-13 09:32:07 +00004908
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004909 // Bit positions in compiler_hints.
whesse@chromium.org7b260152011-06-20 15:33:18 +00004910 static const int kCodeAgeSize = 3;
4911 static const int kCodeAgeMask = (1 << kCodeAgeSize) - 1;
whesse@chromium.org7b260152011-06-20 15:33:18 +00004912
4913 enum CompilerHints {
4914 kHasOnlySimpleThisPropertyAssignments,
4915 kAllowLazyCompilation,
4916 kLiveObjectsMayExist,
4917 kCodeAgeShift,
4918 kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
4919 kStrictModeFunction,
4920 kUsesArguments,
4921 kHasDuplicateParameters,
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00004922 kNative,
4923 kBoundFunction,
4924 kIsAnonymous,
4925 kNameShouldPrintAsAnonymous,
4926 kCompilerHintsCount // Pseudo entry
whesse@chromium.org7b260152011-06-20 15:33:18 +00004927 };
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00004928
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004929 private:
4930#if V8_HOST_ARCH_32_BIT
4931 // On 32 bit platforms, compiler hints is a smi.
4932 static const int kCompilerHintsSmiTagSize = kSmiTagSize;
4933 static const int kCompilerHintsSize = kPointerSize;
4934#else
4935 // On 64 bit platforms, compiler hints is not a smi, see comment above.
4936 static const int kCompilerHintsSmiTagSize = 0;
4937 static const int kCompilerHintsSize = kIntSize;
4938#endif
4939
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00004940 STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <=
4941 SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte);
4942
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004943 public:
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004944 // Constants for optimizing codegen for strict mode function and
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004945 // native tests.
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004946 // Allows to use byte-widgh instructions.
4947 static const int kStrictModeBitWithinByte =
4948 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
4949
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004950 static const int kNativeBitWithinByte =
4951 (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004952
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004953#if __BYTE_ORDER == __LITTLE_ENDIAN
4954 static const int kStrictModeByteOffset = kCompilerHintsOffset +
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004955 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004956 static const int kNativeByteOffset = kCompilerHintsOffset +
4957 (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004958#elif __BYTE_ORDER == __BIG_ENDIAN
4959 static const int kStrictModeByteOffset = kCompilerHintsOffset +
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004960 (kCompilerHintsSize - 1) -
4961 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004962 static const int kNativeByteOffset = kCompilerHintsOffset +
ricow@chromium.org6fe7a8e2011-05-13 07:57:29 +00004963 (kCompilerHintsSize - 1) -
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00004964 ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004965#else
4966#error Unknown byte ordering
4967#endif
4968
4969 private:
mads.s.ager31e71382008-08-13 09:32:07 +00004970 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004971};
4972
4973
4974// JSFunction describes JavaScript functions.
4975class JSFunction: public JSObject {
4976 public:
4977 // [prototype_or_initial_map]:
4978 DECL_ACCESSORS(prototype_or_initial_map, Object)
4979
4980 // [shared_function_info]: The information about the function that
4981 // can be shared by instances.
4982 DECL_ACCESSORS(shared, SharedFunctionInfo)
4983
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004984 inline SharedFunctionInfo* unchecked_shared();
4985
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004986 // [context]: The context for this function.
4987 inline Context* context();
4988 inline Object* unchecked_context();
4989 inline void set_context(Object* context);
4990
4991 // [code]: The generated code object for this function. Executed
4992 // when the function is invoked, e.g. foo() or new foo(). See
4993 // [[Call]] and [[Construct]] description in ECMA-262, section
4994 // 8.6.2, page 27.
4995 inline Code* code();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004996 inline void set_code(Code* code);
4997 inline void ReplaceCode(Code* code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004998
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00004999 inline Code* unchecked_code();
5000
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00005001 // Tells whether this function is builtin.
5002 inline bool IsBuiltin();
5003
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005004 // Tells whether or not the function needs arguments adaption.
5005 inline bool NeedsArgumentsAdaption();
5006
5007 // Tells whether or not this function has been optimized.
5008 inline bool IsOptimized();
5009
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +00005010 // Tells whether or not this function can be optimized.
5011 inline bool IsOptimizable();
5012
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005013 // Mark this function for lazy recompilation. The function will be
5014 // recompiled the next time it is executed.
5015 void MarkForLazyRecompilation();
5016
5017 // Tells whether or not the function is already marked for lazy
5018 // recompilation.
5019 inline bool IsMarkedForLazyRecompilation();
5020
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005021 // Check whether or not this function is inlineable.
5022 bool IsInlineable();
5023
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005024 // [literals]: Fixed array holding the materialized literals.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005025 //
5026 // If the function contains object, regexp or array literals, the
5027 // literals array prefix contains the object, regexp, and array
5028 // function to be used when creating these literals. This is
5029 // necessary so that we do not dynamically lookup the object, regexp
5030 // or array functions. Performing a dynamic lookup, we might end up
5031 // using the functions from a new context that we should not have
5032 // access to.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005033 DECL_ACCESSORS(literals, FixedArray)
5034
5035 // The initial map for an object created by this constructor.
5036 inline Map* initial_map();
5037 inline void set_initial_map(Map* value);
5038 inline bool has_initial_map();
5039
5040 // Get and set the prototype property on a JSFunction. If the
5041 // function has an initial map the prototype is set on the initial
5042 // map. Otherwise, the prototype is put in the initial map field
5043 // until an initial map is needed.
5044 inline bool has_prototype();
5045 inline bool has_instance_prototype();
5046 inline Object* prototype();
5047 inline Object* instance_prototype();
5048 Object* SetInstancePrototype(Object* value);
lrn@chromium.org303ada72010-10-27 09:33:13 +00005049 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005050
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00005051 // After prototype is removed, it will not be created when accessed, and
5052 // [[Construct]] from this function will not be allowed.
5053 Object* RemovePrototype();
5054 inline bool should_have_prototype();
5055
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005056 // Accessor for this function's initial map's [[class]]
5057 // property. This is primarily used by ECMA native functions. This
5058 // method sets the class_name field of this function's initial map
5059 // to a given value. It creates an initial map if this function does
5060 // not have one. Note that this method does not copy the initial map
5061 // if it has one already, but simply replaces it with the new value.
5062 // Instances created afterwards will have a map whose [[class]] is
5063 // set to 'value', but there is no guarantees on instances created
5064 // before.
5065 Object* SetInstanceClassName(String* name);
5066
5067 // Returns if this function has been compiled to native code yet.
5068 inline bool is_compiled();
5069
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005070 // [next_function_link]: Field for linking functions. This list is treated as
5071 // a weak list by the GC.
5072 DECL_ACCESSORS(next_function_link, Object)
5073
5074 // Prints the name of the function using PrintF.
whesse@chromium.org023421e2010-12-21 12:19:12 +00005075 inline void PrintName() {
5076 PrintName(stdout);
5077 }
5078 void PrintName(FILE* out);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005079
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005080 // Casting.
5081 static inline JSFunction* cast(Object* obj);
5082
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00005083 // Iterates the objects, including code objects indirectly referenced
5084 // through pointers to the first instruction in the code object.
5085 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
5086
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005087 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00005088#ifdef OBJECT_PRINT
5089 inline void JSFunctionPrint() {
5090 JSFunctionPrint(stdout);
5091 }
5092 void JSFunctionPrint(FILE* out);
5093#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005094#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005095 void JSFunctionVerify();
5096#endif
5097
5098 // Returns the number of allocated literals.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005099 inline int NumberOfLiterals();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005100
ager@chromium.org236ad962008-09-25 09:45:57 +00005101 // Retrieve the global context from a function's literal array.
5102 static Context* GlobalContextFromLiterals(FixedArray* literals);
5103
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005104 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
5105 // kSize) is weak and has special handling during garbage collection.
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00005106 static const int kCodeEntryOffset = JSObject::kHeaderSize;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00005107 static const int kPrototypeOrInitialMapOffset =
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00005108 kCodeEntryOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005109 static const int kSharedFunctionInfoOffset =
5110 kPrototypeOrInitialMapOffset + kPointerSize;
5111 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
5112 static const int kLiteralsOffset = kContextOffset + kPointerSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005113 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
5114 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
5115 static const int kSize = kNextFunctionLinkOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005116
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005117 // Layout of the literals array.
ager@chromium.org236ad962008-09-25 09:45:57 +00005118 static const int kLiteralsPrefixSize = 1;
5119 static const int kLiteralGlobalContextIndex = 0;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00005120
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005121 private:
5122 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
5123};
5124
5125
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005126// JSGlobalProxy's prototype must be a JSGlobalObject or null,
5127// and the prototype is hidden. JSGlobalProxy always delegates
5128// property accesses to its prototype if the prototype is not null.
5129//
5130// A JSGlobalProxy can be reinitialized which will preserve its identity.
5131//
5132// Accessing a JSGlobalProxy requires security check.
5133
5134class JSGlobalProxy : public JSObject {
5135 public:
ager@chromium.orgea91cc52011-05-23 06:06:11 +00005136 // [context]: the owner global context of this global proxy object.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005137 // It is null value if this object is not used by any context.
5138 DECL_ACCESSORS(context, Object)
5139
5140 // Casting.
5141 static inline JSGlobalProxy* cast(Object* obj);
5142
5143 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00005144#ifdef OBJECT_PRINT
5145 inline void JSGlobalProxyPrint() {
5146 JSGlobalProxyPrint(stdout);
5147 }
5148 void JSGlobalProxyPrint(FILE* out);
5149#endif
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005150#ifdef DEBUG
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005151 void JSGlobalProxyVerify();
5152#endif
5153
5154 // Layout description.
5155 static const int kContextOffset = JSObject::kHeaderSize;
5156 static const int kSize = kContextOffset + kPointerSize;
5157
5158 private:
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005159 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
5160};
5161
5162
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005163// Forward declaration.
5164class JSBuiltinsObject;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005165class JSGlobalPropertyCell;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005166
5167// Common super class for JavaScript global objects and the special
5168// builtins global objects.
5169class GlobalObject: public JSObject {
5170 public:
5171 // [builtins]: the object holding the runtime routines written in JS.
5172 DECL_ACCESSORS(builtins, JSBuiltinsObject)
5173
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00005174 // [global context]: the global context corresponding to this global object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005175 DECL_ACCESSORS(global_context, Context)
5176
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005177 // [global receiver]: the global receiver object of the context
5178 DECL_ACCESSORS(global_receiver, JSObject)
5179
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00005180 // Retrieve the property cell used to store a property.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005181 JSGlobalPropertyCell* GetPropertyCell(LookupResult* result);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00005182
lrn@chromium.org303ada72010-10-27 09:33:13 +00005183 // This is like GetProperty, but is used when you know the lookup won't fail
5184 // by throwing an exception. This is for the debug and builtins global
5185 // objects, where it is known which properties can be expected to be present
5186 // on the object.
5187 Object* GetPropertyNoExceptionThrown(String* key) {
5188 Object* answer = GetProperty(key)->ToObjectUnchecked();
5189 return answer;
5190 }
5191
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00005192 // Ensure that the global object has a cell for the given property name.
lrn@chromium.org303ada72010-10-27 09:33:13 +00005193 MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00005194
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005195 // Casting.
5196 static inline GlobalObject* cast(Object* obj);
5197
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005198 // Layout description.
5199 static const int kBuiltinsOffset = JSObject::kHeaderSize;
5200 static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005201 static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
5202 static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005203
5204 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005205 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
mads.s.ager31e71382008-08-13 09:32:07 +00005206
5207 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005208};
5209
5210
5211// JavaScript global object.
5212class JSGlobalObject: public GlobalObject {
5213 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005214 // Casting.
5215 static inline JSGlobalObject* cast(Object* obj);
5216
5217 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00005218#ifdef OBJECT_PRINT
5219 inline void JSGlobalObjectPrint() {
5220 JSGlobalObjectPrint(stdout);
5221 }
5222 void JSGlobalObjectPrint(FILE* out);
5223#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005224#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005225 void JSGlobalObjectVerify();
5226#endif
5227
5228 // Layout description.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005229 static const int kSize = GlobalObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005230
5231 private:
5232 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
5233};
5234
5235
5236// Builtins global object which holds the runtime routines written in
5237// JavaScript.
5238class JSBuiltinsObject: public GlobalObject {
5239 public:
5240 // Accessors for the runtime routines written in JavaScript.
5241 inline Object* javascript_builtin(Builtins::JavaScript id);
5242 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
5243
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00005244 // Accessors for code of the runtime routines written in JavaScript.
5245 inline Code* javascript_builtin_code(Builtins::JavaScript id);
5246 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
5247
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005248 // Casting.
5249 static inline JSBuiltinsObject* cast(Object* obj);
5250
5251 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00005252#ifdef OBJECT_PRINT
5253 inline void JSBuiltinsObjectPrint() {
5254 JSBuiltinsObjectPrint(stdout);
5255 }
5256 void JSBuiltinsObjectPrint(FILE* out);
5257#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005258#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005259 void JSBuiltinsObjectVerify();
5260#endif
5261
5262 // Layout description. The size of the builtins object includes
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00005263 // room for two pointers per runtime routine written in javascript
5264 // (function and code object).
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005265 static const int kJSBuiltinsCount = Builtins::id_count;
5266 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00005267 static const int kJSBuiltinsCodeOffset =
5268 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005269 static const int kSize =
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00005270 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
5271
5272 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
5273 return kJSBuiltinsOffset + id * kPointerSize;
5274 }
5275
5276 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
5277 return kJSBuiltinsCodeOffset + id * kPointerSize;
5278 }
5279
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005280 private:
5281 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
5282};
5283
5284
5285// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
5286class JSValue: public JSObject {
5287 public:
5288 // [value]: the object being wrapped.
5289 DECL_ACCESSORS(value, Object)
5290
5291 // Casting.
5292 static inline JSValue* cast(Object* obj);
5293
5294 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00005295#ifdef OBJECT_PRINT
5296 inline void JSValuePrint() {
5297 JSValuePrint(stdout);
5298 }
5299 void JSValuePrint(FILE* out);
5300#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005301#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005302 void JSValueVerify();
5303#endif
5304
5305 // Layout description.
5306 static const int kValueOffset = JSObject::kHeaderSize;
5307 static const int kSize = kValueOffset + kPointerSize;
5308
5309 private:
5310 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
5311};
5312
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00005313
5314// Representation of message objects used for error reporting through
5315// the API. The messages are formatted in JavaScript so this object is
5316// a real JavaScript object. The information used for formatting the
5317// error messages are not directly accessible from JavaScript to
5318// prevent leaking information to user code called during error
5319// formatting.
5320class JSMessageObject: public JSObject {
5321 public:
5322 // [type]: the type of error message.
5323 DECL_ACCESSORS(type, String)
5324
5325 // [arguments]: the arguments for formatting the error message.
5326 DECL_ACCESSORS(arguments, JSArray)
5327
5328 // [script]: the script from which the error message originated.
5329 DECL_ACCESSORS(script, Object)
5330
5331 // [stack_trace]: the stack trace for this error message.
5332 DECL_ACCESSORS(stack_trace, Object)
5333
5334 // [stack_frames]: an array of stack frames for this error object.
5335 DECL_ACCESSORS(stack_frames, Object)
5336
5337 // [start_position]: the start position in the script for the error message.
5338 inline int start_position();
5339 inline void set_start_position(int value);
5340
5341 // [end_position]: the end position in the script for the error message.
5342 inline int end_position();
5343 inline void set_end_position(int value);
5344
5345 // Casting.
5346 static inline JSMessageObject* cast(Object* obj);
5347
5348 // Dispatched behavior.
5349#ifdef OBJECT_PRINT
5350 inline void JSMessageObjectPrint() {
5351 JSMessageObjectPrint(stdout);
5352 }
5353 void JSMessageObjectPrint(FILE* out);
5354#endif
5355#ifdef DEBUG
5356 void JSMessageObjectVerify();
5357#endif
5358
5359 // Layout description.
5360 static const int kTypeOffset = JSObject::kHeaderSize;
5361 static const int kArgumentsOffset = kTypeOffset + kPointerSize;
5362 static const int kScriptOffset = kArgumentsOffset + kPointerSize;
5363 static const int kStackTraceOffset = kScriptOffset + kPointerSize;
5364 static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
5365 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
5366 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
5367 static const int kSize = kEndPositionOffset + kPointerSize;
5368
5369 typedef FixedBodyDescriptor<HeapObject::kMapOffset,
5370 kStackFramesOffset + kPointerSize,
5371 kSize> BodyDescriptor;
5372};
5373
5374
ager@chromium.org236ad962008-09-25 09:45:57 +00005375// Regular expressions
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005376// The regular expression holds a single reference to a FixedArray in
5377// the kDataOffset field.
5378// The FixedArray contains the following data:
5379// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
5380// - reference to the original source string
5381// - reference to the original flag string
5382// If it is an atom regexp
5383// - a reference to a literal string to search for
5384// If it is an irregexp regexp:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005385// - a reference to code for ASCII inputs (bytecode or compiled), or a smi
5386// used for tracking the last usage (used for code flushing).
5387// - a reference to code for UC16 inputs (bytecode or compiled), or a smi
5388// used for tracking the last usage (used for code flushing)..
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005389// - max number of registers used by irregexp implementations.
5390// - number of capture registers (output values) of the regexp.
ager@chromium.org236ad962008-09-25 09:45:57 +00005391class JSRegExp: public JSObject {
5392 public:
ager@chromium.orga74f0da2008-12-03 16:05:52 +00005393 // Meaning of Type:
5394 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
ager@chromium.orga74f0da2008-12-03 16:05:52 +00005395 // ATOM: A simple string to match against using an indexOf operation.
5396 // IRREGEXP: Compiled with Irregexp.
5397 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
ager@chromium.org381abbb2009-02-25 13:23:22 +00005398 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005399 enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
ager@chromium.org236ad962008-09-25 09:45:57 +00005400
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005401 class Flags {
5402 public:
5403 explicit Flags(uint32_t value) : value_(value) { }
5404 bool is_global() { return (value_ & GLOBAL) != 0; }
5405 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
5406 bool is_multiline() { return (value_ & MULTILINE) != 0; }
5407 uint32_t value() { return value_; }
5408 private:
5409 uint32_t value_;
5410 };
ager@chromium.org236ad962008-09-25 09:45:57 +00005411
ager@chromium.org236ad962008-09-25 09:45:57 +00005412 DECL_ACCESSORS(data, Object)
5413
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005414 inline Type TypeTag();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00005415 inline int CaptureCount();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00005416 inline Flags GetFlags();
5417 inline String* Pattern();
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005418 inline Object* DataAt(int index);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005419 // Set implementation data after the object has been prepared.
5420 inline void SetDataAt(int index, Object* value);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005421
5422 // Used during GC when flushing code or setting age.
5423 inline Object* DataAtUnchecked(int index);
5424 inline void SetDataAtUnchecked(int index, Object* value, Heap* heap);
5425 inline Type TypeTagUnchecked();
5426
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00005427 static int code_index(bool is_ascii) {
5428 if (is_ascii) {
5429 return kIrregexpASCIICodeIndex;
5430 } else {
5431 return kIrregexpUC16CodeIndex;
5432 }
5433 }
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005434
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005435 static int saved_code_index(bool is_ascii) {
5436 if (is_ascii) {
5437 return kIrregexpASCIICodeSavedIndex;
5438 } else {
5439 return kIrregexpUC16CodeSavedIndex;
5440 }
5441 }
5442
ager@chromium.org236ad962008-09-25 09:45:57 +00005443 static inline JSRegExp* cast(Object* obj);
5444
5445 // Dispatched behavior.
5446#ifdef DEBUG
ager@chromium.org236ad962008-09-25 09:45:57 +00005447 void JSRegExpVerify();
5448#endif
5449
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005450 static const int kDataOffset = JSObject::kHeaderSize;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00005451 static const int kSize = kDataOffset + kPointerSize;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005452
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005453 // Indices in the data array.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005454 static const int kTagIndex = 0;
5455 static const int kSourceIndex = kTagIndex + 1;
5456 static const int kFlagsIndex = kSourceIndex + 1;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005457 static const int kDataIndex = kFlagsIndex + 1;
5458 // The data fields are used in different ways depending on the
5459 // value of the tag.
5460 // Atom regexps (literal strings).
5461 static const int kAtomPatternIndex = kDataIndex;
5462
5463 static const int kAtomDataSize = kAtomPatternIndex + 1;
5464
ager@chromium.orga1645e22009-09-09 19:27:10 +00005465 // Irregexp compiled code or bytecode for ASCII. If compilation
5466 // fails, this fields hold an exception object that should be
5467 // thrown if the regexp is used again.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005468 static const int kIrregexpASCIICodeIndex = kDataIndex;
ager@chromium.orga1645e22009-09-09 19:27:10 +00005469 // Irregexp compiled code or bytecode for UC16. If compilation
5470 // fails, this fields hold an exception object that should be
5471 // thrown if the regexp is used again.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005472 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005473
5474 // Saved instance of Irregexp compiled code or bytecode for ASCII that
5475 // is a potential candidate for flushing.
5476 static const int kIrregexpASCIICodeSavedIndex = kDataIndex + 2;
5477 // Saved instance of Irregexp compiled code or bytecode for UC16 that is
5478 // a potential candidate for flushing.
5479 static const int kIrregexpUC16CodeSavedIndex = kDataIndex + 3;
5480
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005481 // Maximal number of registers used by either ASCII or UC16.
5482 // Only used to check that there is enough stack space
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005483 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005484 // Number of captures in the compiled regexp.
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005485 static const int kIrregexpCaptureCountIndex = kDataIndex + 5;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00005486
5487 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00005488
5489 // Offsets directly into the data fixed array.
5490 static const int kDataTagOffset =
5491 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
5492 static const int kDataAsciiCodeOffset =
5493 FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00005494 static const int kDataUC16CodeOffset =
5495 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00005496 static const int kIrregexpCaptureCountOffset =
5497 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
lrn@chromium.org25156de2010-04-06 13:10:27 +00005498
5499 // In-object fields.
5500 static const int kSourceFieldIndex = 0;
5501 static const int kGlobalFieldIndex = 1;
5502 static const int kIgnoreCaseFieldIndex = 2;
5503 static const int kMultilineFieldIndex = 3;
5504 static const int kLastIndexFieldIndex = 4;
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +00005505 static const int kInObjectFieldCount = 5;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005506
5507 // The uninitialized value for a regexp code object.
5508 static const int kUninitializedValue = -1;
5509
5510 // The compilation error value for the regexp code object. The real error
5511 // object is in the saved code field.
5512 static const int kCompilationErrorValue = -2;
5513
5514 // When we store the sweep generation at which we moved the code from the
5515 // code index to the saved code index we mask it of to be in the [0:255]
5516 // range.
5517 static const int kCodeAgeMask = 0xff;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005518};
5519
5520
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00005521class CompilationCacheShape {
5522 public:
5523 static inline bool IsMatch(HashTableKey* key, Object* value) {
5524 return key->IsMatch(value);
5525 }
5526
5527 static inline uint32_t Hash(HashTableKey* key) {
5528 return key->Hash();
5529 }
5530
5531 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5532 return key->HashForObject(object);
5533 }
5534
lrn@chromium.org303ada72010-10-27 09:33:13 +00005535 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00005536 return key->AsObject();
5537 }
5538
5539 static const int kPrefixSize = 0;
5540 static const int kEntrySize = 2;
5541};
5542
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00005543
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00005544class CompilationCacheTable: public HashTable<CompilationCacheShape,
5545 HashTableKey*> {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005546 public:
5547 // Find cached value for a string key, otherwise return null.
5548 Object* Lookup(String* src);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005549 Object* LookupEval(String* src, Context* context, StrictModeFlag strict_mode);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005550 Object* LookupRegExp(String* source, JSRegExp::Flags flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00005551 MaybeObject* Put(String* src, Object* value);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005552 MaybeObject* PutEval(String* src,
5553 Context* context,
5554 SharedFunctionInfo* value);
lrn@chromium.org303ada72010-10-27 09:33:13 +00005555 MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005556
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005557 // Remove given value from cache.
5558 void Remove(Object* value);
5559
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005560 static inline CompilationCacheTable* cast(Object* obj);
5561
5562 private:
5563 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
ager@chromium.org236ad962008-09-25 09:45:57 +00005564};
5565
5566
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005567class CodeCache: public Struct {
5568 public:
5569 DECL_ACCESSORS(default_cache, FixedArray)
5570 DECL_ACCESSORS(normal_type_cache, Object)
5571
5572 // Add the code object to the cache.
lrn@chromium.org303ada72010-10-27 09:33:13 +00005573 MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005574
5575 // Lookup code object in the cache. Returns code object if found and undefined
5576 // if not.
5577 Object* Lookup(String* name, Code::Flags flags);
5578
5579 // Get the internal index of a code object in the cache. Returns -1 if the
5580 // code object is not in that cache. This index can be used to later call
5581 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
5582 // RemoveByIndex.
sgjesse@chromium.org99a37fa2010-03-11 09:23:46 +00005583 int GetIndex(Object* name, Code* code);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005584
5585 // Remove an object from the cache with the provided internal index.
sgjesse@chromium.org99a37fa2010-03-11 09:23:46 +00005586 void RemoveByIndex(Object* name, Code* code, int index);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005587
5588 static inline CodeCache* cast(Object* obj);
5589
whesse@chromium.org023421e2010-12-21 12:19:12 +00005590#ifdef OBJECT_PRINT
5591 inline void CodeCachePrint() {
5592 CodeCachePrint(stdout);
5593 }
5594 void CodeCachePrint(FILE* out);
5595#endif
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005596#ifdef DEBUG
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005597 void CodeCacheVerify();
5598#endif
5599
5600 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
5601 static const int kNormalTypeCacheOffset =
5602 kDefaultCacheOffset + kPointerSize;
5603 static const int kSize = kNormalTypeCacheOffset + kPointerSize;
5604
5605 private:
lrn@chromium.org303ada72010-10-27 09:33:13 +00005606 MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
5607 MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005608 Object* LookupDefaultCache(String* name, Code::Flags flags);
5609 Object* LookupNormalTypeCache(String* name, Code::Flags flags);
5610
5611 // Code cache layout of the default cache. Elements are alternating name and
5612 // code objects for non normal load/store/call IC's.
5613 static const int kCodeCacheEntrySize = 2;
5614 static const int kCodeCacheEntryNameOffset = 0;
5615 static const int kCodeCacheEntryCodeOffset = 1;
5616
5617 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
5618};
5619
5620
5621class CodeCacheHashTableShape {
5622 public:
5623 static inline bool IsMatch(HashTableKey* key, Object* value) {
5624 return key->IsMatch(value);
5625 }
5626
5627 static inline uint32_t Hash(HashTableKey* key) {
5628 return key->Hash();
5629 }
5630
5631 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5632 return key->HashForObject(object);
5633 }
5634
lrn@chromium.org303ada72010-10-27 09:33:13 +00005635 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005636 return key->AsObject();
5637 }
5638
5639 static const int kPrefixSize = 0;
5640 static const int kEntrySize = 2;
5641};
5642
5643
5644class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
5645 HashTableKey*> {
5646 public:
5647 Object* Lookup(String* name, Code::Flags flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00005648 MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005649
5650 int GetIndex(String* name, Code::Flags flags);
5651 void RemoveByIndex(int index);
5652
5653 static inline CodeCacheHashTable* cast(Object* obj);
5654
5655 // Initial size of the fixed array backing the hash table.
5656 static const int kInitialSize = 64;
5657
5658 private:
5659 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
5660};
5661
5662
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00005663class PolymorphicCodeCache: public Struct {
5664 public:
5665 DECL_ACCESSORS(cache, Object)
5666
5667 MUST_USE_RESULT MaybeObject* Update(MapList* maps,
5668 Code::Flags flags,
5669 Code* code);
5670 Object* Lookup(MapList* maps, Code::Flags flags);
5671
5672 static inline PolymorphicCodeCache* cast(Object* obj);
5673
5674#ifdef OBJECT_PRINT
5675 inline void PolymorphicCodeCachePrint() {
5676 PolymorphicCodeCachePrint(stdout);
5677 }
5678 void PolymorphicCodeCachePrint(FILE* out);
5679#endif
5680#ifdef DEBUG
5681 void PolymorphicCodeCacheVerify();
5682#endif
5683
5684 static const int kCacheOffset = HeapObject::kHeaderSize;
5685 static const int kSize = kCacheOffset + kPointerSize;
5686
5687 private:
5688 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache);
5689};
5690
5691
5692class PolymorphicCodeCacheHashTable
5693 : public HashTable<CodeCacheHashTableShape, HashTableKey*> {
5694 public:
5695 Object* Lookup(MapList* maps, int code_kind);
5696 MUST_USE_RESULT MaybeObject* Put(MapList* maps, int code_kind, Code* code);
5697
5698 static inline PolymorphicCodeCacheHashTable* cast(Object* obj);
5699
5700 static const int kInitialSize = 64;
5701 private:
5702 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable);
5703};
5704
5705
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005706enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
5707enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
5708
5709
ager@chromium.org7c537e22008-10-16 08:43:32 +00005710class StringHasher {
5711 public:
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00005712 explicit inline StringHasher(int length);
ager@chromium.org7c537e22008-10-16 08:43:32 +00005713
5714 // Returns true if the hash of this string can be computed without
5715 // looking at the contents.
5716 inline bool has_trivial_hash();
5717
5718 // Add a character to the hash and update the array index calculation.
5719 inline void AddCharacter(uc32 c);
5720
5721 // Adds a character to the hash but does not update the array index
5722 // calculation. This can only be called when it has been verified
5723 // that the input is not an array index.
5724 inline void AddCharacterNoIndex(uc32 c);
5725
5726 // Returns the value to store in the hash field of a string with
5727 // the given length and contents.
5728 uint32_t GetHashField();
5729
5730 // Returns true if the characters seen so far make up a legal array
5731 // index.
5732 bool is_array_index() { return is_array_index_; }
5733
5734 bool is_valid() { return is_valid_; }
5735
5736 void invalidate() { is_valid_ = false; }
5737
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00005738 // Calculated hash value for a string consisting of 1 to
5739 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
5740 // value is represented decimal value.
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00005741 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00005742
ager@chromium.org7c537e22008-10-16 08:43:32 +00005743 private:
ager@chromium.org7c537e22008-10-16 08:43:32 +00005744 uint32_t array_index() {
5745 ASSERT(is_array_index());
5746 return array_index_;
5747 }
5748
5749 inline uint32_t GetHash();
5750
5751 int length_;
5752 uint32_t raw_running_hash_;
5753 uint32_t array_index_;
5754 bool is_array_index_;
5755 bool is_first_char_;
5756 bool is_valid_;
ager@chromium.org6141cbe2009-11-20 12:14:52 +00005757 friend class TwoCharHashTableKey;
ager@chromium.org7c537e22008-10-16 08:43:32 +00005758};
5759
5760
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00005761// Calculates string hash.
5762template <typename schar>
5763inline uint32_t HashSequentialString(const schar* chars, int length);
5764
5765
ager@chromium.org870a0b62008-11-04 11:43:05 +00005766// The characteristics of a string are stored in its map. Retrieving these
5767// few bits of information is moderately expensive, involving two memory
5768// loads where the second is dependent on the first. To improve efficiency
5769// the shape of the string is given its own class so that it can be retrieved
5770// once and used for several string operations. A StringShape is small enough
5771// to be passed by value and is immutable, but be aware that flattening a
ager@chromium.orgc3e50d82008-11-05 11:53:10 +00005772// string can potentially alter its shape. Also be aware that a GC caused by
5773// something else can alter the shape of a string due to ConsString
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00005774// shortcutting. Keeping these restrictions in mind has proven to be error-
5775// prone and so we no longer put StringShapes in variables unless there is a
5776// concrete performance benefit at that particular point in the code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00005777class StringShape BASE_EMBEDDED {
5778 public:
5779 inline explicit StringShape(String* s);
5780 inline explicit StringShape(Map* s);
5781 inline explicit StringShape(InstanceType t);
ager@chromium.org870a0b62008-11-04 11:43:05 +00005782 inline bool IsSequential();
5783 inline bool IsExternal();
5784 inline bool IsCons();
ager@chromium.org870a0b62008-11-04 11:43:05 +00005785 inline bool IsExternalAscii();
5786 inline bool IsExternalTwoByte();
5787 inline bool IsSequentialAscii();
5788 inline bool IsSequentialTwoByte();
5789 inline bool IsSymbol();
5790 inline StringRepresentationTag representation_tag();
5791 inline uint32_t full_representation_tag();
5792 inline uint32_t size_tag();
5793#ifdef DEBUG
5794 inline uint32_t type() { return type_; }
5795 inline void invalidate() { valid_ = false; }
5796 inline bool valid() { return valid_; }
5797#else
5798 inline void invalidate() { }
5799#endif
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00005800
ager@chromium.org870a0b62008-11-04 11:43:05 +00005801 private:
5802 uint32_t type_;
5803#ifdef DEBUG
5804 inline void set_valid() { valid_ = true; }
5805 bool valid_;
5806#else
5807 inline void set_valid() { }
5808#endif
5809};
5810
5811
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005812// The String abstract class captures JavaScript string values:
5813//
5814// Ecma-262:
5815// 4.3.16 String Value
5816// A string value is a member of the type String and is a finite
5817// ordered sequence of zero or more 16-bit unsigned integer values.
5818//
5819// All string values have a length field.
5820class String: public HeapObject {
5821 public:
5822 // Get and set the length of the string.
5823 inline int length();
5824 inline void set_length(int value);
5825
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005826 // Get and set the hash field of the string.
5827 inline uint32_t hash_field();
5828 inline void set_hash_field(uint32_t value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005829
ager@chromium.org5ec48922009-05-05 07:25:34 +00005830 inline bool IsAsciiRepresentation();
5831 inline bool IsTwoByteRepresentation();
5832
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +00005833 // Returns whether this string has ascii chars, i.e. all of them can
5834 // be ascii encoded. This might be the case even if the string is
5835 // two-byte. Such strings may appear when the embedder prefers
5836 // two-byte external representations even for ascii data.
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +00005837 //
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +00005838 // NOTE: this should be considered only a hint. False negatives are
5839 // possible.
5840 inline bool HasOnlyAsciiChars();
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +00005841
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005842 // Get and set individual two byte chars in the string.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00005843 inline void Set(int index, uint16_t value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005844 // Get individual two byte char in the string. Repeated calls
5845 // to this method are not efficient unless the string is flat.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00005846 inline uint16_t Get(int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005847
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00005848 // Try to flatten the string. Checks first inline to see if it is
5849 // necessary. Does nothing if the string is not a cons string.
5850 // Flattening allocates a sequential string with the same data as
5851 // the given string and mutates the cons string to a degenerate
5852 // form, where the first component is the new sequential string and
5853 // the second component is the empty string. If allocation fails,
5854 // this function returns a failure. If flattening succeeds, this
5855 // function returns the sequential string that is now the first
5856 // component of the cons string.
5857 //
5858 // Degenerate cons strings are handled specially by the garbage
5859 // collector (see IsShortcutCandidate).
5860 //
5861 // Use FlattenString from Handles.cc to flatten even in case an
5862 // allocation failure happens.
lrn@chromium.org303ada72010-10-27 09:33:13 +00005863 inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005864
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00005865 // Convenience function. Has exactly the same behavior as
5866 // TryFlatten(), except in the case of failure returns the original
5867 // string.
5868 inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
5869
ager@chromium.org7c537e22008-10-16 08:43:32 +00005870 Vector<const char> ToAsciiVector();
5871 Vector<const uc16> ToUC16Vector();
5872
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005873 // Mark the string as an undetectable object. It only applies to
5874 // ascii and two byte string types.
5875 bool MarkAsUndetectable();
5876
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005877 // Return a substring.
lrn@chromium.org303ada72010-10-27 09:33:13 +00005878 MUST_USE_RESULT MaybeObject* SubString(int from,
5879 int to,
5880 PretenureFlag pretenure = NOT_TENURED);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005881
5882 // String equality operations.
5883 inline bool Equals(String* other);
5884 bool IsEqualTo(Vector<const char> str);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005885 bool IsAsciiEqualTo(Vector<const char> str);
5886 bool IsTwoByteEqualTo(Vector<const uc16> str);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005887
5888 // Return a UTF8 representation of the string. The string is null
5889 // terminated but may optionally contain nulls. Length is returned
5890 // in length_output if length_output is not a null pointer The string
5891 // should be nearly flat, otherwise the performance of this method may
5892 // be very slow (quadratic in the length). Setting robustness_flag to
5893 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
5894 // handles unexpected data without causing assert failures and it does not
5895 // do any heap allocations. This is useful when printing stack traces.
5896 SmartPointer<char> ToCString(AllowNullsFlag allow_nulls,
5897 RobustnessFlag robustness_flag,
5898 int offset,
5899 int length,
5900 int* length_output = 0);
5901 SmartPointer<char> ToCString(
5902 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
5903 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
5904 int* length_output = 0);
5905
ager@chromium.org9258b6b2008-09-11 09:11:10 +00005906 int Utf8Length();
5907
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005908 // Return a 16 bit Unicode representation of the string.
5909 // The string should be nearly flat, otherwise the performance of
5910 // of this method may be very bad. Setting robustness_flag to
5911 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
5912 // handles unexpected data without causing assert failures and it does not
5913 // do any heap allocations. This is useful when printing stack traces.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00005914 SmartPointer<uc16> ToWideCString(
5915 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005916
5917 // Tells whether the hash code has been computed.
5918 inline bool HasHashCode();
5919
5920 // Returns a hash value used for the property table
5921 inline uint32_t Hash();
5922
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005923 static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
5924 int length);
ager@chromium.org7c537e22008-10-16 08:43:32 +00005925
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005926 static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
5927 uint32_t* index,
5928 int length);
5929
ager@chromium.org6f10e412009-02-13 10:11:16 +00005930 // Externalization.
5931 bool MakeExternal(v8::String::ExternalStringResource* resource);
5932 bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
5933
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005934 // Conversion.
5935 inline bool AsArrayIndex(uint32_t* index);
5936
5937 // Casting.
5938 static inline String* cast(Object* obj);
5939
5940 void PrintOn(FILE* out);
5941
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005942 // For use during stack traces. Performs rudimentary sanity check.
5943 bool LooksValid();
5944
5945 // Dispatched behavior.
5946 void StringShortPrint(StringStream* accumulator);
whesse@chromium.org023421e2010-12-21 12:19:12 +00005947#ifdef OBJECT_PRINT
5948 inline void StringPrint() {
5949 StringPrint(stdout);
5950 }
5951 void StringPrint(FILE* out);
vegorov@chromium.org7943d462011-08-01 11:41:52 +00005952
5953 char* ToAsciiArray();
whesse@chromium.org023421e2010-12-21 12:19:12 +00005954#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005955#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005956 void StringVerify();
5957#endif
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00005958 inline bool IsFlat();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005959
5960 // Layout description.
ager@chromium.org236ad962008-09-25 09:45:57 +00005961 static const int kLengthOffset = HeapObject::kHeaderSize;
ager@chromium.orgac091b72010-05-05 07:34:42 +00005962 static const int kHashFieldOffset = kLengthOffset + kPointerSize;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00005963 static const int kSize = kHashFieldOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005964
ager@chromium.org3811b432009-10-28 14:53:37 +00005965 // Maximum number of characters to consider when trying to convert a string
5966 // value into an array index.
ager@chromium.org7c537e22008-10-16 08:43:32 +00005967 static const int kMaxArrayIndexSize = 10;
5968
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005969 // Max ascii char code.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005970 static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
ager@chromium.org381abbb2009-02-25 13:23:22 +00005971 static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
ager@chromium.org8bb60582008-12-11 12:02:20 +00005972 static const int kMaxUC16CharCode = 0xffff;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005973
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005974 // Minimum length for a cons string.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005975 static const int kMinNonFlatLength = 13;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005976
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00005977 // Mask constant for checking if a string has a computed hash code
5978 // and if it is an array index. The least significant bit indicates
5979 // whether a hash code has been computed. If the hash code has been
5980 // computed the 2nd bit tells whether the string can be used as an
5981 // array index.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00005982 static const int kHashNotComputedMask = 1;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00005983 static const int kIsNotArrayIndexMask = 1 << 1;
5984 static const int kNofHashBitFields = 2;
ager@chromium.org7c537e22008-10-16 08:43:32 +00005985
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005986 // Shift constant retrieving hash code from hash field.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00005987 static const int kHashShift = kNofHashBitFields;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005988
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005989 // Array index strings this short can keep their index in the hash
5990 // field.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00005991 static const int kMaxCachedArrayIndexLength = 7;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005992
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005993 // For strings which are array indexes the hash value has the string length
5994 // mixed into the hash, mainly to avoid a hash value of zero which would be
5995 // the case for the string '0'. 24 bits are used for the array index value.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00005996 static const int kArrayIndexValueBits = 24;
5997 static const int kArrayIndexLengthBits =
5998 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
5999
6000 STATIC_CHECK((kArrayIndexLengthBits > 0));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006001 STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00006002
6003 static const int kArrayIndexHashLengthShift =
6004 kArrayIndexValueBits + kNofHashBitFields;
6005
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006006 static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00006007
ricow@chromium.org30ce4112010-05-31 10:38:25 +00006008 static const int kArrayIndexValueMask =
6009 ((1 << kArrayIndexValueBits) - 1) << kHashShift;
ager@chromium.org3811b432009-10-28 14:53:37 +00006010
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00006011 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
6012 // could use a mask to test if the length of string is less than or equal to
6013 // kMaxCachedArrayIndexLength.
6014 STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
6015
6016 static const int kContainsCachedArrayIndexMask =
6017 (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
6018 kIsNotArrayIndexMask;
6019
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006020 // Value of empty hash field indicating that the hash is not computed.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00006021 static const int kEmptyHashField =
6022 kIsNotArrayIndexMask | kHashNotComputedMask;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00006023
6024 // Value of hash field containing computed hash equal to zero.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00006025 static const int kZeroHash = kIsNotArrayIndexMask;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006026
6027 // Maximal string length.
6028 static const int kMaxLength = (1 << (32 - 2)) - 1;
6029
6030 // Max length for computing hash. For strings longer than this limit the
6031 // string length is used as the hash value.
6032 static const int kMaxHashCalcLength = 16383;
ager@chromium.org7c537e22008-10-16 08:43:32 +00006033
kasper.lund7276f142008-07-30 08:49:36 +00006034 // Limit for truncation in short printing.
6035 static const int kMaxShortPrintLength = 1024;
6036
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006037 // Support for regular expressions.
6038 const uc16* GetTwoByteData();
6039 const uc16* GetTwoByteData(unsigned start);
6040
6041 // Support for StringInputBuffer
6042 static const unibrow::byte* ReadBlock(String* input,
6043 unibrow::byte* util_buffer,
6044 unsigned capacity,
6045 unsigned* remaining,
6046 unsigned* offset);
6047 static const unibrow::byte* ReadBlock(String** input,
6048 unibrow::byte* util_buffer,
6049 unsigned capacity,
6050 unsigned* remaining,
6051 unsigned* offset);
6052
6053 // Helper function for flattening strings.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00006054 template <typename sinkchar>
6055 static void WriteToFlat(String* source,
6056 sinkchar* sink,
6057 int from,
6058 int to);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006059
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00006060 static inline bool IsAscii(const char* chars, int length) {
6061 const char* limit = chars + length;
6062#ifdef V8_HOST_CAN_READ_UNALIGNED
6063 ASSERT(kMaxAsciiCharCode == 0x7F);
6064 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
6065 while (chars <= limit - sizeof(uintptr_t)) {
6066 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
6067 return false;
6068 }
6069 chars += sizeof(uintptr_t);
6070 }
6071#endif
6072 while (chars < limit) {
6073 if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
6074 ++chars;
6075 }
6076 return true;
6077 }
6078
6079 static inline bool IsAscii(const uc16* chars, int length) {
6080 const uc16* limit = chars + length;
6081 while (chars < limit) {
6082 if (*chars > kMaxAsciiCharCodeU) return false;
6083 ++chars;
6084 }
6085 return true;
6086 }
6087
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006088 protected:
6089 class ReadBlockBuffer {
6090 public:
6091 ReadBlockBuffer(unibrow::byte* util_buffer_,
6092 unsigned cursor_,
6093 unsigned capacity_,
6094 unsigned remaining_) :
6095 util_buffer(util_buffer_),
6096 cursor(cursor_),
6097 capacity(capacity_),
6098 remaining(remaining_) {
6099 }
6100 unibrow::byte* util_buffer;
6101 unsigned cursor;
6102 unsigned capacity;
6103 unsigned remaining;
6104 };
6105
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006106 static inline const unibrow::byte* ReadBlock(String* input,
6107 ReadBlockBuffer* buffer,
6108 unsigned* offset,
6109 unsigned max_chars);
6110 static void ReadBlockIntoBuffer(String* input,
6111 ReadBlockBuffer* buffer,
6112 unsigned* offset_ptr,
6113 unsigned max_chars);
6114
6115 private:
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00006116 // Try to flatten the top level ConsString that is hiding behind this
6117 // string. This is a no-op unless the string is a ConsString. Flatten
6118 // mutates the ConsString and might return a failure.
lrn@chromium.org303ada72010-10-27 09:33:13 +00006119 MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00006120
ricow@chromium.org30ce4112010-05-31 10:38:25 +00006121 static inline bool IsHashFieldComputed(uint32_t field);
6122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006123 // Slow case of String::Equals. This implementation works on any strings
6124 // but it is most efficient on strings that are almost flat.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00006125 bool SlowEquals(String* other);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006126
6127 // Slow case of AsArrayIndex.
6128 bool SlowAsArrayIndex(uint32_t* index);
6129
6130 // Compute and set the hash code.
6131 uint32_t ComputeAndSetHash();
6132
6133 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
6134};
6135
6136
6137// The SeqString abstract class captures sequential string values.
6138class SeqString: public String {
6139 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006140 // Casting.
6141 static inline SeqString* cast(Object* obj);
6142
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006143 private:
6144 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
6145};
6146
6147
6148// The AsciiString class captures sequential ascii string objects.
6149// Each character in the AsciiString is an ascii character.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006150class SeqAsciiString: public SeqString {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006151 public:
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00006152 static const bool kHasAsciiEncoding = true;
6153
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006154 // Dispatched behavior.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006155 inline uint16_t SeqAsciiStringGet(int index);
6156 inline void SeqAsciiStringSet(int index, uint16_t value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006157
6158 // Get the address of the characters in this string.
6159 inline Address GetCharsAddress();
6160
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00006161 inline char* GetChars();
6162
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006163 // Casting
ager@chromium.org7c537e22008-10-16 08:43:32 +00006164 static inline SeqAsciiString* cast(Object* obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006165
6166 // Garbage collection support. This method is called by the
6167 // garbage collector to compute the actual size of an AsciiString
6168 // instance.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00006169 inline int SeqAsciiStringSize(InstanceType instance_type);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006170
6171 // Computes the size for an AsciiString instance of a given length.
6172 static int SizeFor(int length) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00006173 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006174 }
6175
6176 // Layout description.
6177 static const int kHeaderSize = String::kSize;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00006178 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006179
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00006180 // Maximal memory usage for a single sequential ASCII string.
6181 static const int kMaxSize = 512 * MB;
6182 // Maximal length of a single sequential ASCII string.
6183 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
6184 static const int kMaxLength = (kMaxSize - kHeaderSize);
6185
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006186 // Support for StringInputBuffer.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006187 inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6188 unsigned* offset,
6189 unsigned chars);
6190 inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
6191 unsigned* offset,
6192 unsigned chars);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006193
6194 private:
ager@chromium.org7c537e22008-10-16 08:43:32 +00006195 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006196};
6197
6198
6199// The TwoByteString class captures sequential unicode string objects.
6200// Each character in the TwoByteString is a two-byte uint16_t.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006201class SeqTwoByteString: public SeqString {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006202 public:
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00006203 static const bool kHasAsciiEncoding = false;
6204
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006205 // Dispatched behavior.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006206 inline uint16_t SeqTwoByteStringGet(int index);
6207 inline void SeqTwoByteStringSet(int index, uint16_t value);
6208
6209 // Get the address of the characters in this string.
6210 inline Address GetCharsAddress();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006211
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00006212 inline uc16* GetChars();
6213
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006214 // For regexp code.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006215 const uint16_t* SeqTwoByteStringGetData(unsigned start);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006216
6217 // Casting
ager@chromium.org7c537e22008-10-16 08:43:32 +00006218 static inline SeqTwoByteString* cast(Object* obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006219
6220 // Garbage collection support. This method is called by the
6221 // garbage collector to compute the actual size of a TwoByteString
6222 // instance.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00006223 inline int SeqTwoByteStringSize(InstanceType instance_type);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006224
6225 // Computes the size for a TwoByteString instance of a given length.
6226 static int SizeFor(int length) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00006227 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006228 }
6229
6230 // Layout description.
6231 static const int kHeaderSize = String::kSize;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00006232 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006233
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00006234 // Maximal memory usage for a single sequential two-byte string.
6235 static const int kMaxSize = 512 * MB;
6236 // Maximal length of a single sequential two-byte string.
6237 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
6238 static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
6239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006240 // Support for StringInputBuffer.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006241 inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6242 unsigned* offset_ptr,
6243 unsigned chars);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006244
6245 private:
ager@chromium.org7c537e22008-10-16 08:43:32 +00006246 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006247};
6248
6249
6250// The ConsString class describes string values built by using the
6251// addition operator on strings. A ConsString is a pair where the
6252// first and second components are pointers to other string values.
6253// One or both components of a ConsString can be pointers to other
6254// ConsStrings, creating a binary tree of ConsStrings where the leaves
6255// are non-ConsString string values. The string value represented by
6256// a ConsString can be obtained by concatenating the leaf string
6257// values in a left-to-right depth-first traversal of the tree.
6258class ConsString: public String {
6259 public:
ager@chromium.org870a0b62008-11-04 11:43:05 +00006260 // First string of the cons cell.
6261 inline String* first();
6262 // Doesn't check that the result is a string, even in debug mode. This is
6263 // useful during GC where the mark bits confuse the checks.
6264 inline Object* unchecked_first();
6265 inline void set_first(String* first,
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00006266 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006267
ager@chromium.org870a0b62008-11-04 11:43:05 +00006268 // Second string of the cons cell.
6269 inline String* second();
6270 // Doesn't check that the result is a string, even in debug mode. This is
6271 // useful during GC where the mark bits confuse the checks.
6272 inline Object* unchecked_second();
6273 inline void set_second(String* second,
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00006274 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006275
6276 // Dispatched behavior.
6277 uint16_t ConsStringGet(int index);
6278
6279 // Casting.
6280 static inline ConsString* cast(Object* obj);
6281
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006282 // Layout description.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00006283 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006284 static const int kSecondOffset = kFirstOffset + kPointerSize;
6285 static const int kSize = kSecondOffset + kPointerSize;
6286
6287 // Support for StringInputBuffer.
6288 inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
6289 unsigned* offset_ptr,
6290 unsigned chars);
6291 inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6292 unsigned* offset_ptr,
6293 unsigned chars);
6294
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00006295 // Minimum length for a cons string.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006296 static const int kMinLength = 13;
6297
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006298 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
6299 BodyDescriptor;
6300
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006301 private:
6302 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
6303};
6304
6305
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006306// The ExternalString class describes string values that are backed by
6307// a string resource that lies outside the V8 heap. ExternalStrings
6308// consist of the length field common to all strings, a pointer to the
6309// external resource. It is important to ensure (externally) that the
6310// resource is not deallocated while the ExternalString is live in the
6311// V8 heap.
6312//
6313// The API expects that all ExternalStrings are created through the
6314// API. Therefore, ExternalStrings should not be used internally.
6315class ExternalString: public String {
6316 public:
6317 // Casting
6318 static inline ExternalString* cast(Object* obj);
6319
6320 // Layout description.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00006321 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006322 static const int kSize = kResourceOffset + kPointerSize;
6323
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006324 STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
6325
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006326 private:
6327 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
6328};
6329
6330
6331// The ExternalAsciiString class is an external string backed by an
6332// ASCII string.
6333class ExternalAsciiString: public ExternalString {
6334 public:
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00006335 static const bool kHasAsciiEncoding = true;
6336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006337 typedef v8::String::ExternalAsciiStringResource Resource;
6338
6339 // The underlying resource.
6340 inline Resource* resource();
6341 inline void set_resource(Resource* buffer);
6342
6343 // Dispatched behavior.
6344 uint16_t ExternalAsciiStringGet(int index);
6345
6346 // Casting.
6347 static inline ExternalAsciiString* cast(Object* obj);
6348
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006349 // Garbage collection support.
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006350 inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
6351
6352 template<typename StaticVisitor>
6353 inline void ExternalAsciiStringIterateBody();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006354
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006355 // Support for StringInputBuffer.
6356 const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
6357 unsigned* offset,
6358 unsigned chars);
6359 inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6360 unsigned* offset,
6361 unsigned chars);
6362
6363 private:
6364 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
6365};
6366
6367
6368// The ExternalTwoByteString class is an external string backed by a UTF-16
6369// encoded string.
6370class ExternalTwoByteString: public ExternalString {
6371 public:
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00006372 static const bool kHasAsciiEncoding = false;
6373
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006374 typedef v8::String::ExternalStringResource Resource;
6375
6376 // The underlying string resource.
6377 inline Resource* resource();
6378 inline void set_resource(Resource* buffer);
6379
6380 // Dispatched behavior.
6381 uint16_t ExternalTwoByteStringGet(int index);
6382
6383 // For regexp code.
6384 const uint16_t* ExternalTwoByteStringGetData(unsigned start);
6385
6386 // Casting.
6387 static inline ExternalTwoByteString* cast(Object* obj);
6388
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006389 // Garbage collection support.
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006390 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
6391
6392 template<typename StaticVisitor>
6393 inline void ExternalTwoByteStringIterateBody();
6394
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006395
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006396 // Support for StringInputBuffer.
6397 void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6398 unsigned* offset_ptr,
6399 unsigned chars);
6400
6401 private:
6402 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
6403};
6404
6405
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006406// Utility superclass for stack-allocated objects that must be updated
6407// on gc. It provides two ways for the gc to update instances, either
6408// iterating or updating after gc.
6409class Relocatable BASE_EMBEDDED {
6410 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006411 explicit inline Relocatable(Isolate* isolate);
6412 inline virtual ~Relocatable();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006413 virtual void IterateInstance(ObjectVisitor* v) { }
6414 virtual void PostGarbageCollection() { }
6415
6416 static void PostGarbageCollectionProcessing();
6417 static int ArchiveSpacePerThread();
lrn@chromium.org1c092762011-05-09 09:42:16 +00006418 static char* ArchiveState(Isolate* isolate, char* to);
6419 static char* RestoreState(Isolate* isolate, char* from);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006420 static void Iterate(ObjectVisitor* v);
6421 static void Iterate(ObjectVisitor* v, Relocatable* top);
6422 static char* Iterate(ObjectVisitor* v, char* t);
6423 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006424 Isolate* isolate_;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006425 Relocatable* prev_;
6426};
6427
6428
ager@chromium.orga74f0da2008-12-03 16:05:52 +00006429// A flat string reader provides random access to the contents of a
6430// string independent of the character width of the string. The handle
6431// must be valid as long as the reader is being used.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006432class FlatStringReader : public Relocatable {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00006433 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006434 FlatStringReader(Isolate* isolate, Handle<String> str);
6435 FlatStringReader(Isolate* isolate, Vector<const char> input);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006436 void PostGarbageCollection();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00006437 inline uc32 Get(int index);
6438 int length() { return length_; }
ager@chromium.orga74f0da2008-12-03 16:05:52 +00006439 private:
6440 String** str_;
6441 bool is_ascii_;
6442 int length_;
6443 const void* start_;
ager@chromium.orga74f0da2008-12-03 16:05:52 +00006444};
6445
6446
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006447// Note that StringInputBuffers are not valid across a GC! To fix this
6448// it would have to store a String Handle instead of a String* and
6449// AsciiStringReadBlock would have to be modified to use memcpy.
6450//
6451// StringInputBuffer is able to traverse any string regardless of how
6452// deeply nested a sequence of ConsStrings it is made of. However,
6453// performance will be better if deep strings are flattened before they
6454// are traversed. Since flattening requires memory allocation this is
6455// not always desirable, however (esp. in debugging situations).
6456class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
6457 public:
6458 virtual void Seek(unsigned pos);
6459 inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00006460 explicit inline StringInputBuffer(String* backing):
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006461 unibrow::InputBuffer<String, String*, 1024>(backing) {}
6462};
6463
6464
6465class SafeStringInputBuffer
6466 : public unibrow::InputBuffer<String, String**, 256> {
6467 public:
6468 virtual void Seek(unsigned pos);
6469 inline SafeStringInputBuffer()
6470 : unibrow::InputBuffer<String, String**, 256>() {}
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00006471 explicit inline SafeStringInputBuffer(String** backing)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006472 : unibrow::InputBuffer<String, String**, 256>(backing) {}
6473};
6474
6475
ager@chromium.org7c537e22008-10-16 08:43:32 +00006476template <typename T>
6477class VectorIterator {
6478 public:
6479 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
6480 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
6481 T GetNext() { return data_[index_++]; }
6482 bool has_more() { return index_ < data_.length(); }
6483 private:
6484 Vector<const T> data_;
6485 int index_;
6486};
6487
6488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006489// The Oddball describes objects null, undefined, true, and false.
6490class Oddball: public HeapObject {
6491 public:
6492 // [to_string]: Cached to_string computed at startup.
6493 DECL_ACCESSORS(to_string, String)
6494
6495 // [to_number]: Cached to_number computed at startup.
6496 DECL_ACCESSORS(to_number, Object)
6497
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006498 inline byte kind();
6499 inline void set_kind(byte kind);
6500
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006501 // Casting.
6502 static inline Oddball* cast(Object* obj);
6503
6504 // Dispatched behavior.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006505#ifdef DEBUG
6506 void OddballVerify();
6507#endif
6508
6509 // Initialize the fields.
lrn@chromium.org303ada72010-10-27 09:33:13 +00006510 MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006511 Object* to_number,
6512 byte kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006513
6514 // Layout description.
ager@chromium.org236ad962008-09-25 09:45:57 +00006515 static const int kToStringOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006516 static const int kToNumberOffset = kToStringOffset + kPointerSize;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006517 static const int kKindOffset = kToNumberOffset + kPointerSize;
6518 static const int kSize = kKindOffset + kPointerSize;
6519
6520 static const byte kFalse = 0;
6521 static const byte kTrue = 1;
6522 static const byte kNotBooleanMask = ~1;
6523 static const byte kTheHole = 2;
6524 static const byte kNull = 3;
6525 static const byte kArgumentMarker = 4;
6526 static const byte kUndefined = 5;
6527 static const byte kOther = 6;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006528
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006529 typedef FixedBodyDescriptor<kToStringOffset,
6530 kToNumberOffset + kPointerSize,
6531 kSize> BodyDescriptor;
6532
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006533 private:
6534 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
6535};
6536
6537
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00006538class JSGlobalPropertyCell: public HeapObject {
6539 public:
6540 // [value]: value of the global property.
6541 DECL_ACCESSORS(value, Object)
6542
6543 // Casting.
6544 static inline JSGlobalPropertyCell* cast(Object* obj);
6545
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00006546#ifdef DEBUG
6547 void JSGlobalPropertyCellVerify();
whesse@chromium.org023421e2010-12-21 12:19:12 +00006548#endif
6549#ifdef OBJECT_PRINT
6550 inline void JSGlobalPropertyCellPrint() {
6551 JSGlobalPropertyCellPrint(stdout);
6552 }
6553 void JSGlobalPropertyCellPrint(FILE* out);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00006554#endif
6555
6556 // Layout description.
6557 static const int kValueOffset = HeapObject::kHeaderSize;
6558 static const int kSize = kValueOffset + kPointerSize;
6559
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006560 typedef FixedBodyDescriptor<kValueOffset,
6561 kValueOffset + kPointerSize,
6562 kSize> BodyDescriptor;
6563
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00006564 // Returns the isolate/heap this cell object belongs to.
6565 inline Isolate* isolate();
6566 inline Heap* heap();
6567
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00006568 private:
6569 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
6570};
6571
6572
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006573// The JSProxy describes EcmaScript Harmony proxies
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00006574class JSProxy: public JSReceiver {
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006575 public:
6576 // [handler]: The handler property.
6577 DECL_ACCESSORS(handler, Object)
6578
rossberg@chromium.org717967f2011-07-20 13:44:42 +00006579 // [padding]: The padding slot (unused, see below).
6580 DECL_ACCESSORS(padding, Object)
6581
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006582 // Casting.
6583 static inline JSProxy* cast(Object* obj);
6584
rossberg@chromium.org717967f2011-07-20 13:44:42 +00006585 bool HasPropertyWithHandler(String* name);
6586
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00006587 MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00006588 String* name,
6589 Object* value,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00006590 PropertyAttributes attributes,
6591 StrictModeFlag strict_mode);
6592
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00006593 MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
6594 String* name,
6595 DeleteMode mode);
6596
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00006597 MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
6598 JSReceiver* receiver,
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00006599 String* name,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00006600 bool* has_exception);
6601
rossberg@chromium.org717967f2011-07-20 13:44:42 +00006602 // Turn this into an (empty) JSObject.
6603 void Fix();
6604
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006605 // Dispatched behavior.
6606#ifdef OBJECT_PRINT
6607 inline void JSProxyPrint() {
6608 JSProxyPrint(stdout);
6609 }
6610 void JSProxyPrint(FILE* out);
6611#endif
6612#ifdef DEBUG
6613 void JSProxyVerify();
6614#endif
6615
rossberg@chromium.org717967f2011-07-20 13:44:42 +00006616 // Layout description. We add padding so that a proxy has the same
6617 // size as a virgin JSObject. This is essential for becoming a JSObject
6618 // upon freeze.
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006619 static const int kHandlerOffset = HeapObject::kHeaderSize;
rossberg@chromium.org717967f2011-07-20 13:44:42 +00006620 static const int kPaddingOffset = kHandlerOffset + kPointerSize;
6621 static const int kSize = kPaddingOffset + kPointerSize;
6622
6623 STATIC_CHECK(kSize == JSObject::kHeaderSize);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006624
6625 typedef FixedBodyDescriptor<kHandlerOffset,
6626 kHandlerOffset + kPointerSize,
6627 kSize> BodyDescriptor;
6628
6629 private:
6630 DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy);
6631};
6632
6633
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00006634// TODO(rossberg): Only a stub for now.
6635class JSFunctionProxy: public JSProxy {
6636 public:
6637 // Casting.
6638 static inline JSFunctionProxy* cast(Object* obj);
6639
6640 private:
6641 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy);
6642};
6643
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00006644
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00006645// The JSWeakMap describes EcmaScript Harmony weak maps
6646class JSWeakMap: public JSObject {
6647 public:
6648 // [table]: the backing hash table mapping keys to values.
6649 DECL_ACCESSORS(table, ObjectHashTable)
6650
6651 // [next]: linked list of encountered weak maps during GC.
6652 DECL_ACCESSORS(next, Object)
6653
6654 // Unchecked accessors to be used during GC.
6655 inline ObjectHashTable* unchecked_table();
6656
6657 // Casting.
6658 static inline JSWeakMap* cast(Object* obj);
6659
6660#ifdef OBJECT_PRINT
6661 inline void JSWeakMapPrint() {
6662 JSWeakMapPrint(stdout);
6663 }
6664 void JSWeakMapPrint(FILE* out);
6665#endif
6666#ifdef DEBUG
6667 void JSWeakMapVerify();
6668#endif
6669
6670 static const int kTableOffset = JSObject::kHeaderSize;
6671 static const int kNextOffset = kTableOffset + kPointerSize;
6672 static const int kSize = kNextOffset + kPointerSize;
6673
6674 private:
6675 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
6676};
6677
6678
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006679// Foreign describes objects pointing from JavaScript to C structures.
ager@chromium.org9258b6b2008-09-11 09:11:10 +00006680// Since they cannot contain references to JS HeapObjects they can be
6681// placed in old_data_space.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006682class Foreign: public HeapObject {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006683 public:
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006684 // [address]: field containing the address.
6685 inline Address address();
6686 inline void set_address(Address value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006687
6688 // Casting.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006689 static inline Foreign* cast(Object* obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006690
6691 // Dispatched behavior.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006692 inline void ForeignIterateBody(ObjectVisitor* v);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006693
6694 template<typename StaticVisitor>
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006695 inline void ForeignIterateBody();
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00006696
whesse@chromium.org023421e2010-12-21 12:19:12 +00006697#ifdef OBJECT_PRINT
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006698 inline void ForeignPrint() {
6699 ForeignPrint(stdout);
whesse@chromium.org023421e2010-12-21 12:19:12 +00006700 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006701 void ForeignPrint(FILE* out);
whesse@chromium.org023421e2010-12-21 12:19:12 +00006702#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006703#ifdef DEBUG
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006704 void ForeignVerify();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006705#endif
6706
6707 // Layout description.
6708
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006709 static const int kAddressOffset = HeapObject::kHeaderSize;
6710 static const int kSize = kAddressOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006711
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006712 STATIC_CHECK(kAddressOffset == Internals::kForeignAddressOffset);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006713
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006714 private:
ager@chromium.orgea91cc52011-05-23 06:06:11 +00006715 DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006716};
6717
6718
6719// The JSArray describes JavaScript Arrays
6720// Such an array can be in one of two modes:
6721// - fast, backing storage is a FixedArray and length <= elements.length();
6722// Please note: push and pop can be used to grow and shrink the array.
6723// - slow, backing storage is a HashTable with numbers as keys.
6724class JSArray: public JSObject {
6725 public:
6726 // [length]: The length property.
6727 DECL_ACCESSORS(length, Object)
6728
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006729 // Overload the length setter to skip write barrier when the length
6730 // is set to a smi. This matches the set function on FixedArray.
6731 inline void set_length(Smi* length);
6732
lrn@chromium.org303ada72010-10-27 09:33:13 +00006733 MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
6734 Object* value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006735
6736 // Initialize the array with the given capacity. The function may
6737 // fail due to out-of-memory situations, but only if the requested
6738 // capacity is non-zero.
lrn@chromium.org303ada72010-10-27 09:33:13 +00006739 MUST_USE_RESULT MaybeObject* Initialize(int capacity);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006740
6741 // Set the content of the array to the content of storage.
ager@chromium.org7c537e22008-10-16 08:43:32 +00006742 inline void SetContent(FixedArray* storage);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006743
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006744 // Casting.
6745 static inline JSArray* cast(Object* obj);
6746
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00006747 // Uses handles. Ensures that the fixed array backing the JSArray has at
6748 // least the stated size.
ager@chromium.org5aa501c2009-06-23 07:57:28 +00006749 inline void EnsureSize(int minimum_size_of_backing_fixed_array);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00006750
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006751 // Dispatched behavior.
whesse@chromium.org023421e2010-12-21 12:19:12 +00006752#ifdef OBJECT_PRINT
6753 inline void JSArrayPrint() {
6754 JSArrayPrint(stdout);
6755 }
6756 void JSArrayPrint(FILE* out);
6757#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006758#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006759 void JSArrayVerify();
6760#endif
6761
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00006762 // Number of element slots to pre-allocate for an empty array.
6763 static const int kPreallocatedArrayElements = 4;
6764
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006765 // Layout description.
6766 static const int kLengthOffset = JSObject::kHeaderSize;
6767 static const int kSize = kLengthOffset + kPointerSize;
6768
6769 private:
ager@chromium.org5aa501c2009-06-23 07:57:28 +00006770 // Expand the fixed array backing of a fast-case JSArray to at least
6771 // the requested size.
6772 void Expand(int minimum_size_of_backing_fixed_array);
6773
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006774 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
6775};
6776
6777
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +00006778// JSRegExpResult is just a JSArray with a specific initial map.
6779// This initial map adds in-object properties for "index" and "input"
6780// properties, as assigned by RegExp.prototype.exec, which allows
6781// faster creation of RegExp exec results.
6782// This class just holds constants used when creating the result.
6783// After creation the result must be treated as a JSArray in all regards.
6784class JSRegExpResult: public JSArray {
6785 public:
6786 // Offsets of object fields.
6787 static const int kIndexOffset = JSArray::kSize;
6788 static const int kInputOffset = kIndexOffset + kPointerSize;
6789 static const int kSize = kInputOffset + kPointerSize;
6790 // Indices of in-object properties.
6791 static const int kIndexIndex = 0;
6792 static const int kInputIndex = 1;
6793 private:
6794 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
6795};
6796
6797
ager@chromium.org32912102009-01-16 10:38:43 +00006798// An accessor must have a getter, but can have no setter.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006799//
6800// When setting a property, V8 searches accessors in prototypes.
6801// If an accessor was found and it does not have a setter,
6802// the request is ignored.
6803//
ager@chromium.orgeadaf222009-06-16 09:43:10 +00006804// If the accessor in the prototype has the READ_ONLY property attribute, then
6805// a new value is added to the local object when the property is set.
6806// This shadows the accessor in the prototype.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006807class AccessorInfo: public Struct {
6808 public:
6809 DECL_ACCESSORS(getter, Object)
6810 DECL_ACCESSORS(setter, Object)
6811 DECL_ACCESSORS(data, Object)
6812 DECL_ACCESSORS(name, Object)
6813 DECL_ACCESSORS(flag, Smi)
6814
6815 inline bool all_can_read();
6816 inline void set_all_can_read(bool value);
6817
6818 inline bool all_can_write();
6819 inline void set_all_can_write(bool value);
6820
ager@chromium.org870a0b62008-11-04 11:43:05 +00006821 inline bool prohibits_overwriting();
6822 inline void set_prohibits_overwriting(bool value);
6823
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006824 inline PropertyAttributes property_attributes();
6825 inline void set_property_attributes(PropertyAttributes attributes);
6826
6827 static inline AccessorInfo* cast(Object* obj);
6828
whesse@chromium.org023421e2010-12-21 12:19:12 +00006829#ifdef OBJECT_PRINT
6830 inline void AccessorInfoPrint() {
6831 AccessorInfoPrint(stdout);
6832 }
6833 void AccessorInfoPrint(FILE* out);
6834#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006835#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006836 void AccessorInfoVerify();
6837#endif
6838
ager@chromium.org236ad962008-09-25 09:45:57 +00006839 static const int kGetterOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006840 static const int kSetterOffset = kGetterOffset + kPointerSize;
6841 static const int kDataOffset = kSetterOffset + kPointerSize;
6842 static const int kNameOffset = kDataOffset + kPointerSize;
6843 static const int kFlagOffset = kNameOffset + kPointerSize;
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00006844 static const int kSize = kFlagOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006845
6846 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006847 // Bit positions in flag.
ager@chromium.org870a0b62008-11-04 11:43:05 +00006848 static const int kAllCanReadBit = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006849 static const int kAllCanWriteBit = 1;
ager@chromium.org870a0b62008-11-04 11:43:05 +00006850 static const int kProhibitsOverwritingBit = 2;
6851 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
mads.s.ager31e71382008-08-13 09:32:07 +00006852
6853 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006854};
6855
6856
6857class AccessCheckInfo: public Struct {
6858 public:
6859 DECL_ACCESSORS(named_callback, Object)
6860 DECL_ACCESSORS(indexed_callback, Object)
6861 DECL_ACCESSORS(data, Object)
6862
6863 static inline AccessCheckInfo* cast(Object* obj);
6864
whesse@chromium.org023421e2010-12-21 12:19:12 +00006865#ifdef OBJECT_PRINT
6866 inline void AccessCheckInfoPrint() {
6867 AccessCheckInfoPrint(stdout);
6868 }
6869 void AccessCheckInfoPrint(FILE* out);
6870#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006871#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006872 void AccessCheckInfoVerify();
6873#endif
6874
ager@chromium.org236ad962008-09-25 09:45:57 +00006875 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006876 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
6877 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
6878 static const int kSize = kDataOffset + kPointerSize;
6879
6880 private:
6881 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
6882};
6883
6884
6885class InterceptorInfo: public Struct {
6886 public:
6887 DECL_ACCESSORS(getter, Object)
6888 DECL_ACCESSORS(setter, Object)
6889 DECL_ACCESSORS(query, Object)
6890 DECL_ACCESSORS(deleter, Object)
6891 DECL_ACCESSORS(enumerator, Object)
6892 DECL_ACCESSORS(data, Object)
6893
6894 static inline InterceptorInfo* cast(Object* obj);
6895
whesse@chromium.org023421e2010-12-21 12:19:12 +00006896#ifdef OBJECT_PRINT
6897 inline void InterceptorInfoPrint() {
6898 InterceptorInfoPrint(stdout);
6899 }
6900 void InterceptorInfoPrint(FILE* out);
6901#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006902#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006903 void InterceptorInfoVerify();
6904#endif
6905
ager@chromium.org236ad962008-09-25 09:45:57 +00006906 static const int kGetterOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006907 static const int kSetterOffset = kGetterOffset + kPointerSize;
6908 static const int kQueryOffset = kSetterOffset + kPointerSize;
6909 static const int kDeleterOffset = kQueryOffset + kPointerSize;
6910 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
6911 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
6912 static const int kSize = kDataOffset + kPointerSize;
6913
6914 private:
6915 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
6916};
6917
6918
6919class CallHandlerInfo: public Struct {
6920 public:
6921 DECL_ACCESSORS(callback, Object)
6922 DECL_ACCESSORS(data, Object)
6923
6924 static inline CallHandlerInfo* cast(Object* obj);
6925
whesse@chromium.org023421e2010-12-21 12:19:12 +00006926#ifdef OBJECT_PRINT
6927 inline void CallHandlerInfoPrint() {
6928 CallHandlerInfoPrint(stdout);
6929 }
6930 void CallHandlerInfoPrint(FILE* out);
6931#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006932#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006933 void CallHandlerInfoVerify();
6934#endif
6935
ager@chromium.org236ad962008-09-25 09:45:57 +00006936 static const int kCallbackOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006937 static const int kDataOffset = kCallbackOffset + kPointerSize;
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00006938 static const int kSize = kDataOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006939
6940 private:
6941 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
6942};
6943
6944
6945class TemplateInfo: public Struct {
6946 public:
6947 DECL_ACCESSORS(tag, Object)
6948 DECL_ACCESSORS(property_list, Object)
6949
6950#ifdef DEBUG
6951 void TemplateInfoVerify();
6952#endif
6953
ager@chromium.org236ad962008-09-25 09:45:57 +00006954 static const int kTagOffset = HeapObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006955 static const int kPropertyListOffset = kTagOffset + kPointerSize;
6956 static const int kHeaderSize = kPropertyListOffset + kPointerSize;
6957 protected:
6958 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
6959 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
6960};
6961
6962
6963class FunctionTemplateInfo: public TemplateInfo {
6964 public:
6965 DECL_ACCESSORS(serial_number, Object)
6966 DECL_ACCESSORS(call_code, Object)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006967 DECL_ACCESSORS(property_accessors, Object)
6968 DECL_ACCESSORS(prototype_template, Object)
6969 DECL_ACCESSORS(parent_template, Object)
6970 DECL_ACCESSORS(named_property_handler, Object)
6971 DECL_ACCESSORS(indexed_property_handler, Object)
6972 DECL_ACCESSORS(instance_template, Object)
6973 DECL_ACCESSORS(class_name, Object)
6974 DECL_ACCESSORS(signature, Object)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006975 DECL_ACCESSORS(instance_call_handler, Object)
6976 DECL_ACCESSORS(access_check_info, Object)
6977 DECL_ACCESSORS(flag, Smi)
6978
6979 // Following properties use flag bits.
6980 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
6981 DECL_BOOLEAN_ACCESSORS(undetectable)
6982 // If the bit is set, object instances created by this function
6983 // requires access check.
6984 DECL_BOOLEAN_ACCESSORS(needs_access_check)
ricow@chromium.org2c99e282011-07-28 09:15:17 +00006985 DECL_BOOLEAN_ACCESSORS(read_only_prototype)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006986
6987 static inline FunctionTemplateInfo* cast(Object* obj);
6988
whesse@chromium.org023421e2010-12-21 12:19:12 +00006989#ifdef OBJECT_PRINT
6990 inline void FunctionTemplateInfoPrint() {
6991 FunctionTemplateInfoPrint(stdout);
6992 }
6993 void FunctionTemplateInfoPrint(FILE* out);
6994#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006995#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00006996 void FunctionTemplateInfoVerify();
6997#endif
6998
6999 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
7000 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
kasper.lund212ac232008-07-16 07:07:30 +00007001 static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007002 static const int kPrototypeTemplateOffset =
7003 kPropertyAccessorsOffset + kPointerSize;
7004 static const int kParentTemplateOffset =
7005 kPrototypeTemplateOffset + kPointerSize;
7006 static const int kNamedPropertyHandlerOffset =
7007 kParentTemplateOffset + kPointerSize;
7008 static const int kIndexedPropertyHandlerOffset =
7009 kNamedPropertyHandlerOffset + kPointerSize;
7010 static const int kInstanceTemplateOffset =
7011 kIndexedPropertyHandlerOffset + kPointerSize;
7012 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
7013 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
v8.team.kasperl727e9952008-09-02 14:56:44 +00007014 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007015 static const int kAccessCheckInfoOffset =
7016 kInstanceCallHandlerOffset + kPointerSize;
7017 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
ricow@chromium.org2c99e282011-07-28 09:15:17 +00007018 static const int kSize = kFlagOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007019
7020 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007021 // Bit position in the flag, from least significant bit position.
7022 static const int kHiddenPrototypeBit = 0;
7023 static const int kUndetectableBit = 1;
7024 static const int kNeedsAccessCheckBit = 2;
ricow@chromium.org2c99e282011-07-28 09:15:17 +00007025 static const int kReadOnlyPrototypeBit = 3;
mads.s.ager31e71382008-08-13 09:32:07 +00007026
7027 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007028};
7029
7030
7031class ObjectTemplateInfo: public TemplateInfo {
7032 public:
7033 DECL_ACCESSORS(constructor, Object)
kasper.lund212ac232008-07-16 07:07:30 +00007034 DECL_ACCESSORS(internal_field_count, Object)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007035
7036 static inline ObjectTemplateInfo* cast(Object* obj);
7037
whesse@chromium.org023421e2010-12-21 12:19:12 +00007038#ifdef OBJECT_PRINT
7039 inline void ObjectTemplateInfoPrint() {
7040 ObjectTemplateInfoPrint(stdout);
7041 }
7042 void ObjectTemplateInfoPrint(FILE* out);
7043#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007044#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007045 void ObjectTemplateInfoVerify();
7046#endif
7047
7048 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
kasper.lund212ac232008-07-16 07:07:30 +00007049 static const int kInternalFieldCountOffset =
7050 kConstructorOffset + kPointerSize;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00007051 static const int kSize = kInternalFieldCountOffset + kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007052};
7053
7054
7055class SignatureInfo: public Struct {
7056 public:
7057 DECL_ACCESSORS(receiver, Object)
7058 DECL_ACCESSORS(args, Object)
7059
7060 static inline SignatureInfo* cast(Object* obj);
7061
whesse@chromium.org023421e2010-12-21 12:19:12 +00007062#ifdef OBJECT_PRINT
7063 inline void SignatureInfoPrint() {
7064 SignatureInfoPrint(stdout);
7065 }
7066 void SignatureInfoPrint(FILE* out);
7067#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007068#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007069 void SignatureInfoVerify();
7070#endif
7071
ager@chromium.org236ad962008-09-25 09:45:57 +00007072 static const int kReceiverOffset = Struct::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007073 static const int kArgsOffset = kReceiverOffset + kPointerSize;
7074 static const int kSize = kArgsOffset + kPointerSize;
7075
7076 private:
7077 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
7078};
7079
7080
7081class TypeSwitchInfo: public Struct {
7082 public:
7083 DECL_ACCESSORS(types, Object)
7084
7085 static inline TypeSwitchInfo* cast(Object* obj);
7086
whesse@chromium.org023421e2010-12-21 12:19:12 +00007087#ifdef OBJECT_PRINT
7088 inline void TypeSwitchInfoPrint() {
7089 TypeSwitchInfoPrint(stdout);
7090 }
7091 void TypeSwitchInfoPrint(FILE* out);
7092#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007093#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007094 void TypeSwitchInfoVerify();
7095#endif
7096
ager@chromium.org236ad962008-09-25 09:45:57 +00007097 static const int kTypesOffset = Struct::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007098 static const int kSize = kTypesOffset + kPointerSize;
7099};
7100
7101
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007102#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.org32912102009-01-16 10:38:43 +00007103// The DebugInfo class holds additional information for a function being
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007104// debugged.
7105class DebugInfo: public Struct {
7106 public:
ager@chromium.org32912102009-01-16 10:38:43 +00007107 // The shared function info for the source being debugged.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007108 DECL_ACCESSORS(shared, SharedFunctionInfo)
7109 // Code object for the original code.
7110 DECL_ACCESSORS(original_code, Code)
7111 // Code object for the patched code. This code object is the code object
7112 // currently active for the function.
7113 DECL_ACCESSORS(code, Code)
7114 // Fixed array holding status information for each active break point.
7115 DECL_ACCESSORS(break_points, FixedArray)
7116
7117 // Check if there is a break point at a code position.
7118 bool HasBreakPoint(int code_position);
7119 // Get the break point info object for a code position.
7120 Object* GetBreakPointInfo(int code_position);
7121 // Clear a break point.
7122 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
7123 int code_position,
7124 Handle<Object> break_point_object);
7125 // Set a break point.
7126 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
7127 int source_position, int statement_position,
7128 Handle<Object> break_point_object);
7129 // Get the break point objects for a code position.
7130 Object* GetBreakPointObjects(int code_position);
7131 // Find the break point info holding this break point object.
7132 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
7133 Handle<Object> break_point_object);
7134 // Get the number of break points for this function.
7135 int GetBreakPointCount();
7136
7137 static inline DebugInfo* cast(Object* obj);
7138
whesse@chromium.org023421e2010-12-21 12:19:12 +00007139#ifdef OBJECT_PRINT
7140 inline void DebugInfoPrint() {
7141 DebugInfoPrint(stdout);
7142 }
7143 void DebugInfoPrint(FILE* out);
7144#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007145#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007146 void DebugInfoVerify();
7147#endif
7148
ager@chromium.org236ad962008-09-25 09:45:57 +00007149 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007150 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
7151 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
7152 static const int kActiveBreakPointsCountIndex =
7153 kPatchedCodeIndex + kPointerSize;
7154 static const int kBreakPointsStateIndex =
7155 kActiveBreakPointsCountIndex + kPointerSize;
7156 static const int kSize = kBreakPointsStateIndex + kPointerSize;
7157
7158 private:
7159 static const int kNoBreakPointInfo = -1;
7160
7161 // Lookup the index in the break_points array for a code position.
7162 int GetBreakPointInfoIndex(int code_position);
7163
7164 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
7165};
7166
7167
7168// The BreakPointInfo class holds information for break points set in a
7169// function. The DebugInfo object holds a BreakPointInfo object for each code
7170// position with one or more break points.
7171class BreakPointInfo: public Struct {
7172 public:
7173 // The position in the code for the break point.
7174 DECL_ACCESSORS(code_position, Smi)
7175 // The position in the source for the break position.
7176 DECL_ACCESSORS(source_position, Smi)
7177 // The position in the source for the last statement before this break
7178 // position.
7179 DECL_ACCESSORS(statement_position, Smi)
7180 // List of related JavaScript break points.
7181 DECL_ACCESSORS(break_point_objects, Object)
7182
7183 // Removes a break point.
7184 static void ClearBreakPoint(Handle<BreakPointInfo> info,
7185 Handle<Object> break_point_object);
7186 // Set a break point.
7187 static void SetBreakPoint(Handle<BreakPointInfo> info,
7188 Handle<Object> break_point_object);
7189 // Check if break point info has this break point object.
7190 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
7191 Handle<Object> break_point_object);
7192 // Get the number of break points for this code position.
7193 int GetBreakPointCount();
7194
7195 static inline BreakPointInfo* cast(Object* obj);
7196
whesse@chromium.org023421e2010-12-21 12:19:12 +00007197#ifdef OBJECT_PRINT
7198 inline void BreakPointInfoPrint() {
7199 BreakPointInfoPrint(stdout);
7200 }
7201 void BreakPointInfoPrint(FILE* out);
7202#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007203#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007204 void BreakPointInfoVerify();
7205#endif
7206
ager@chromium.org236ad962008-09-25 09:45:57 +00007207 static const int kCodePositionIndex = Struct::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007208 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
7209 static const int kStatementPositionIndex =
7210 kSourcePositionIndex + kPointerSize;
7211 static const int kBreakPointObjectsIndex =
7212 kStatementPositionIndex + kPointerSize;
7213 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
7214
7215 private:
7216 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
7217};
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007218#endif // ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007219
7220
7221#undef DECL_BOOLEAN_ACCESSORS
7222#undef DECL_ACCESSORS
7223
7224
7225// Abstract base class for visiting, and optionally modifying, the
7226// pointers contained in Objects. Used in GC and serialization/deserialization.
7227class ObjectVisitor BASE_EMBEDDED {
7228 public:
7229 virtual ~ObjectVisitor() {}
7230
7231 // Visits a contiguous arrays of pointers in the half-open range
7232 // [start, end). Any or all of the values may be modified on return.
7233 virtual void VisitPointers(Object** start, Object** end) = 0;
7234
7235 // To allow lazy clearing of inline caches the visitor has
7236 // a rich interface for iterating over Code objects..
7237
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007238 // Visits a code target in the instruction stream.
7239 virtual void VisitCodeTarget(RelocInfo* rinfo);
7240
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00007241 // Visits a code entry in a JS function.
7242 virtual void VisitCodeEntry(Address entry_address);
7243
kasperl@chromium.orga5551262010-12-07 12:49:48 +00007244 // Visits a global property cell reference in the instruction stream.
7245 virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
7246
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007247 // Visits a runtime entry in the instruction stream.
7248 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
7249
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007250 // Visits the resource of an ASCII or two-byte string.
7251 virtual void VisitExternalAsciiString(
7252 v8::String::ExternalAsciiStringResource** resource) {}
7253 virtual void VisitExternalTwoByteString(
7254 v8::String::ExternalStringResource** resource) {}
7255
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007256 // Visits a debug call target in the instruction stream.
7257 virtual void VisitDebugTarget(RelocInfo* rinfo);
7258
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007259 // Handy shorthand for visiting a single pointer.
7260 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
7261
7262 // Visits a contiguous arrays of external references (references to the C++
7263 // heap) in the half-open range [start, end). Any or all of the values
7264 // may be modified on return.
7265 virtual void VisitExternalReferences(Address* start, Address* end) {}
7266
7267 inline void VisitExternalReference(Address* p) {
7268 VisitExternalReferences(p, p + 1);
7269 }
7270
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00007271 // Visits a handle that has an embedder-assigned class ID.
7272 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
7273
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007274#ifdef DEBUG
7275 // Intended for serialization/deserialization checking: insert, or
7276 // check for the presence of, a tag at this position in the stream.
7277 virtual void Synchronize(const char* tag) {}
ager@chromium.org3811b432009-10-28 14:53:37 +00007278#else
7279 inline void Synchronize(const char* tag) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007280#endif
7281};
7282
7283
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00007284class StructBodyDescriptor : public
7285 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
7286 public:
7287 static inline int SizeOf(Map* map, HeapObject* object) {
7288 return map->instance_size();
7289 }
7290};
7291
7292
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00007293// BooleanBit is a helper class for setting and getting a bit in an
7294// integer or Smi.
7295class BooleanBit : public AllStatic {
7296 public:
7297 static inline bool get(Smi* smi, int bit_position) {
7298 return get(smi->value(), bit_position);
7299 }
7300
7301 static inline bool get(int value, int bit_position) {
7302 return (value & (1 << bit_position)) != 0;
7303 }
7304
7305 static inline Smi* set(Smi* smi, int bit_position, bool v) {
7306 return Smi::FromInt(set(smi->value(), bit_position, v));
7307 }
7308
7309 static inline int set(int value, int bit_position, bool v) {
7310 if (v) {
7311 value |= (1 << bit_position);
7312 } else {
7313 value &= ~(1 << bit_position);
7314 }
7315 return value;
7316 }
7317};
7318
7319} } // namespace v8::internal
7320
7321#endif // V8_OBJECTS_H_