blob: 03445e8745568dbad527d35d262d390b8ba14e41 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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
31#include "builtins.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "smart-pointer.h"
33#include "unicode-inl.h"
Steve Block3ce2e202009-11-05 08:53:23 +000034#if V8_TARGET_ARCH_ARM
35#include "arm/constants-arm.h"
Andrei Popescu31002712010-02-23 13:46:05 +000036#elif V8_TARGET_ARCH_MIPS
37#include "mips/constants-mips.h"
Steve Block3ce2e202009-11-05 08:53:23 +000038#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000039
40//
Kristian Monsen50ef84f2010-07-29 15:18:00 +010041// Most object types in the V8 JavaScript are described in this file.
Steve Blocka7e24c12009-10-30 11:49:00 +000042//
43// Inheritance hierarchy:
John Reck59135872010-11-02 12:39:01 -070044// - MaybeObject (an object or a failure)
45// - Failure (immediate for marking failed operation)
Steve Blocka7e24c12009-10-30 11:49:00 +000046// - Object
47// - Smi (immediate small integer)
Steve Blocka7e24c12009-10-30 11:49:00 +000048// - HeapObject (superclass for everything allocated in the heap)
49// - JSObject
50// - JSArray
51// - JSRegExp
52// - JSFunction
53// - GlobalObject
54// - JSGlobalObject
55// - JSBuiltinsObject
56// - JSGlobalProxy
Steve Block1e0659c2011-05-24 12:43:12 +010057// - JSValue
58// - JSMessageObject
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010059// - ByteArray
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010060// - ExternalArray
Steve Block44f0eee2011-05-26 01:26:41 +010061// - ExternalPixelArray
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010062// - ExternalByteArray
63// - ExternalUnsignedByteArray
64// - ExternalShortArray
65// - ExternalUnsignedShortArray
66// - ExternalIntArray
67// - ExternalUnsignedIntArray
68// - ExternalFloatArray
69// - FixedArray
70// - DescriptorArray
71// - HashTable
72// - Dictionary
73// - SymbolTable
74// - CompilationCacheTable
75// - CodeCacheHashTable
76// - MapCache
77// - Context
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010078// - JSFunctionResultCache
Kristian Monsen50ef84f2010-07-29 15:18:00 +010079// - SerializedScopeInfo
Steve Blocka7e24c12009-10-30 11:49:00 +000080// - String
81// - SeqString
82// - SeqAsciiString
83// - SeqTwoByteString
84// - ConsString
Steve Blocka7e24c12009-10-30 11:49:00 +000085// - ExternalString
86// - ExternalAsciiString
87// - ExternalTwoByteString
88// - HeapNumber
89// - Code
90// - Map
91// - Oddball
92// - Proxy
93// - SharedFunctionInfo
94// - Struct
95// - AccessorInfo
96// - AccessCheckInfo
97// - InterceptorInfo
98// - CallHandlerInfo
99// - TemplateInfo
100// - FunctionTemplateInfo
101// - ObjectTemplateInfo
102// - Script
103// - SignatureInfo
104// - TypeSwitchInfo
105// - DebugInfo
106// - BreakPointInfo
Steve Block6ded16b2010-05-10 14:33:55 +0100107// - CodeCache
Steve Blocka7e24c12009-10-30 11:49:00 +0000108//
109// Formats of Object*:
110// Smi: [31 bit signed int] 0
111// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
112// Failure: [30 bit signed int] 11
113
114// Ecma-262 3rd 8.6.1
115enum PropertyAttributes {
116 NONE = v8::None,
117 READ_ONLY = v8::ReadOnly,
118 DONT_ENUM = v8::DontEnum,
119 DONT_DELETE = v8::DontDelete,
120 ABSENT = 16 // Used in runtime to indicate a property is absent.
121 // ABSENT can never be stored in or returned from a descriptor's attributes
122 // bitfield. It is only used as a return value meaning the attributes of
123 // a non-existent property.
124};
125
126namespace v8 {
127namespace internal {
128
129
130// PropertyDetails captures type and attributes for a property.
131// They are used both in property dictionaries and instance descriptors.
132class PropertyDetails BASE_EMBEDDED {
133 public:
134
135 PropertyDetails(PropertyAttributes attributes,
136 PropertyType type,
137 int index = 0) {
Steve Block44f0eee2011-05-26 01:26:41 +0100138 ASSERT(type != EXTERNAL_ARRAY_TRANSITION);
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 ASSERT(TypeField::is_valid(type));
140 ASSERT(AttributesField::is_valid(attributes));
Steve Block44f0eee2011-05-26 01:26:41 +0100141 ASSERT(StorageField::is_valid(index));
Steve Blocka7e24c12009-10-30 11:49:00 +0000142
143 value_ = TypeField::encode(type)
144 | AttributesField::encode(attributes)
Steve Block44f0eee2011-05-26 01:26:41 +0100145 | StorageField::encode(index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000146
147 ASSERT(type == this->type());
148 ASSERT(attributes == this->attributes());
149 ASSERT(index == this->index());
150 }
151
Steve Block44f0eee2011-05-26 01:26:41 +0100152 PropertyDetails(PropertyAttributes attributes,
153 PropertyType type,
154 ExternalArrayType array_type) {
155 ASSERT(type == EXTERNAL_ARRAY_TRANSITION);
156 ASSERT(TypeField::is_valid(type));
157 ASSERT(AttributesField::is_valid(attributes));
158 ASSERT(StorageField::is_valid(static_cast<int>(array_type)));
159
160 value_ = TypeField::encode(type)
161 | AttributesField::encode(attributes)
162 | StorageField::encode(static_cast<int>(array_type));
163
164 ASSERT(type == this->type());
165 ASSERT(attributes == this->attributes());
166 ASSERT(array_type == this->array_type());
167 }
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 // Conversion for storing details as Object*.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100170 explicit inline PropertyDetails(Smi* smi);
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 inline Smi* AsSmi();
172
173 PropertyType type() { return TypeField::decode(value_); }
174
175 bool IsTransition() {
176 PropertyType t = type();
177 ASSERT(t != INTERCEPTOR);
Steve Block44f0eee2011-05-26 01:26:41 +0100178 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
179 t == EXTERNAL_ARRAY_TRANSITION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 }
181
182 bool IsProperty() {
183 return type() < FIRST_PHANTOM_PROPERTY_TYPE;
184 }
185
186 PropertyAttributes attributes() { return AttributesField::decode(value_); }
187
Steve Block44f0eee2011-05-26 01:26:41 +0100188 int index() { return StorageField::decode(value_); }
189
190 ExternalArrayType array_type() {
191 ASSERT(type() == EXTERNAL_ARRAY_TRANSITION);
192 return static_cast<ExternalArrayType>(StorageField::decode(value_));
193 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
195 inline PropertyDetails AsDeleted();
196
Steve Block44f0eee2011-05-26 01:26:41 +0100197 static bool IsValidIndex(int index) {
198 return StorageField::is_valid(index);
199 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000200
201 bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
202 bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; }
203 bool IsDontEnum() { return (attributes() & DONT_ENUM) != 0; }
204 bool IsDeleted() { return DeletedField::decode(value_) != 0;}
205
206 // Bit fields in value_ (type, shift, size). Must be public so the
207 // constants can be embedded in generated code.
Steve Block44f0eee2011-05-26 01:26:41 +0100208 class TypeField: public BitField<PropertyType, 0, 4> {};
209 class AttributesField: public BitField<PropertyAttributes, 4, 3> {};
210 class DeletedField: public BitField<uint32_t, 7, 1> {};
211 class StorageField: public BitField<uint32_t, 8, 32-8> {};
Steve Blocka7e24c12009-10-30 11:49:00 +0000212
213 static const int kInitialIndex = 1;
214 private:
215 uint32_t value_;
216};
217
218
219// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
220enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
221
222
223// PropertyNormalizationMode is used to specify whether to keep
224// inobject properties when normalizing properties of a JSObject.
225enum PropertyNormalizationMode {
226 CLEAR_INOBJECT_PROPERTIES,
227 KEEP_INOBJECT_PROPERTIES
228};
229
230
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100231// NormalizedMapSharingMode is used to specify whether a map may be shared
232// by different objects with normalized properties.
233enum NormalizedMapSharingMode {
234 UNIQUE_NORMALIZED_MAP,
235 SHARED_NORMALIZED_MAP
236};
237
238
Steve Block791712a2010-08-27 10:21:07 +0100239// Instance size sentinel for objects of variable size.
240static const int kVariableSizeSentinel = 0;
241
242
Steve Blocka7e24c12009-10-30 11:49:00 +0000243// All Maps have a field instance_type containing a InstanceType.
244// It describes the type of the instances.
245//
246// As an example, a JavaScript object is a heap object and its map
247// instance_type is JS_OBJECT_TYPE.
248//
249// The names of the string instance types are intended to systematically
Leon Clarkee46be812010-01-19 14:06:41 +0000250// mirror their encoding in the instance_type field of the map. The default
251// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
252// encoding is mentioned explicitly in the name. Likewise, the default
253// representation is considered sequential. It is not mentioned in the
254// name. The other representations (eg, CONS, EXTERNAL) are explicitly
255// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
256// symbol) or a STRING_TYPE (if it is not a symbol).
Steve Blocka7e24c12009-10-30 11:49:00 +0000257//
258// NOTE: The following things are some that depend on the string types having
259// instance_types that are less than those of all other types:
260// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
261// Object::IsString.
262//
263// NOTE: Everything following JS_VALUE_TYPE is considered a
264// JSObject for GC purposes. The first four entries here have typeof
265// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
Steve Blockd0582a62009-12-15 09:54:21 +0000266#define INSTANCE_TYPE_LIST_ALL(V) \
267 V(SYMBOL_TYPE) \
268 V(ASCII_SYMBOL_TYPE) \
269 V(CONS_SYMBOL_TYPE) \
270 V(CONS_ASCII_SYMBOL_TYPE) \
271 V(EXTERNAL_SYMBOL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100272 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000273 V(EXTERNAL_ASCII_SYMBOL_TYPE) \
274 V(STRING_TYPE) \
275 V(ASCII_STRING_TYPE) \
276 V(CONS_STRING_TYPE) \
277 V(CONS_ASCII_STRING_TYPE) \
278 V(EXTERNAL_STRING_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100279 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000280 V(EXTERNAL_ASCII_STRING_TYPE) \
281 V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
282 \
283 V(MAP_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000284 V(CODE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000285 V(ODDBALL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100286 V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
Leon Clarkee46be812010-01-19 14:06:41 +0000287 \
288 V(HEAP_NUMBER_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000289 V(PROXY_TYPE) \
290 V(BYTE_ARRAY_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000291 /* Note: the order of these external array */ \
292 /* types is relied upon in */ \
293 /* Object::IsExternalArray(). */ \
294 V(EXTERNAL_BYTE_ARRAY_TYPE) \
295 V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
296 V(EXTERNAL_SHORT_ARRAY_TYPE) \
297 V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
298 V(EXTERNAL_INT_ARRAY_TYPE) \
299 V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
300 V(EXTERNAL_FLOAT_ARRAY_TYPE) \
Steve Block44f0eee2011-05-26 01:26:41 +0100301 V(EXTERNAL_PIXEL_ARRAY_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000302 V(FILLER_TYPE) \
303 \
304 V(ACCESSOR_INFO_TYPE) \
305 V(ACCESS_CHECK_INFO_TYPE) \
306 V(INTERCEPTOR_INFO_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000307 V(CALL_HANDLER_INFO_TYPE) \
308 V(FUNCTION_TEMPLATE_INFO_TYPE) \
309 V(OBJECT_TEMPLATE_INFO_TYPE) \
310 V(SIGNATURE_INFO_TYPE) \
311 V(TYPE_SWITCH_INFO_TYPE) \
312 V(SCRIPT_TYPE) \
Steve Block6ded16b2010-05-10 14:33:55 +0100313 V(CODE_CACHE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000314 \
Iain Merrick75681382010-08-19 15:07:18 +0100315 V(FIXED_ARRAY_TYPE) \
316 V(SHARED_FUNCTION_INFO_TYPE) \
317 \
Steve Block1e0659c2011-05-24 12:43:12 +0100318 V(JS_MESSAGE_OBJECT_TYPE) \
319 \
Steve Blockd0582a62009-12-15 09:54:21 +0000320 V(JS_VALUE_TYPE) \
321 V(JS_OBJECT_TYPE) \
322 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
323 V(JS_GLOBAL_OBJECT_TYPE) \
324 V(JS_BUILTINS_OBJECT_TYPE) \
325 V(JS_GLOBAL_PROXY_TYPE) \
326 V(JS_ARRAY_TYPE) \
327 V(JS_REGEXP_TYPE) \
328 \
329 V(JS_FUNCTION_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000330
331#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000332#define INSTANCE_TYPE_LIST_DEBUGGER(V) \
333 V(DEBUG_INFO_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000334 V(BREAK_POINT_INFO_TYPE)
335#else
336#define INSTANCE_TYPE_LIST_DEBUGGER(V)
337#endif
338
Steve Blockd0582a62009-12-15 09:54:21 +0000339#define INSTANCE_TYPE_LIST(V) \
340 INSTANCE_TYPE_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 INSTANCE_TYPE_LIST_DEBUGGER(V)
342
343
344// Since string types are not consecutive, this macro is used to
345// iterate over them.
346#define STRING_TYPE_LIST(V) \
Steve Blockd0582a62009-12-15 09:54:21 +0000347 V(SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100348 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000349 symbol, \
350 Symbol) \
351 V(ASCII_SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100352 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000353 ascii_symbol, \
354 AsciiSymbol) \
355 V(CONS_SYMBOL_TYPE, \
356 ConsString::kSize, \
357 cons_symbol, \
358 ConsSymbol) \
359 V(CONS_ASCII_SYMBOL_TYPE, \
360 ConsString::kSize, \
361 cons_ascii_symbol, \
362 ConsAsciiSymbol) \
363 V(EXTERNAL_SYMBOL_TYPE, \
364 ExternalTwoByteString::kSize, \
365 external_symbol, \
366 ExternalSymbol) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100367 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
368 ExternalTwoByteString::kSize, \
369 external_symbol_with_ascii_data, \
370 ExternalSymbolWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000371 V(EXTERNAL_ASCII_SYMBOL_TYPE, \
372 ExternalAsciiString::kSize, \
373 external_ascii_symbol, \
374 ExternalAsciiSymbol) \
375 V(STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100376 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000377 string, \
378 String) \
379 V(ASCII_STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100380 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000381 ascii_string, \
382 AsciiString) \
383 V(CONS_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000385 cons_string, \
386 ConsString) \
387 V(CONS_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000389 cons_ascii_string, \
390 ConsAsciiString) \
391 V(EXTERNAL_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 ExternalTwoByteString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000393 external_string, \
394 ExternalString) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100395 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
396 ExternalTwoByteString::kSize, \
397 external_string_with_ascii_data, \
398 ExternalStringWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000399 V(EXTERNAL_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 ExternalAsciiString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000401 external_ascii_string, \
Steve Block791712a2010-08-27 10:21:07 +0100402 ExternalAsciiString)
Steve Blocka7e24c12009-10-30 11:49:00 +0000403
404// A struct is a simple object a set of object-valued fields. Including an
405// object type in this causes the compiler to generate most of the boilerplate
406// code for the class including allocation and garbage collection routines,
407// casts and predicates. All you need to define is the class, methods and
408// object verification routines. Easy, no?
409//
410// Note that for subtle reasons related to the ordering or numerical values of
411// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
412// manually.
Steve Blockd0582a62009-12-15 09:54:21 +0000413#define STRUCT_LIST_ALL(V) \
414 V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
415 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
416 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
417 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
418 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
419 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
420 V(SIGNATURE_INFO, SignatureInfo, signature_info) \
421 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
Steve Block6ded16b2010-05-10 14:33:55 +0100422 V(SCRIPT, Script, script) \
423 V(CODE_CACHE, CodeCache, code_cache)
Steve Blocka7e24c12009-10-30 11:49:00 +0000424
425#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000426#define STRUCT_LIST_DEBUGGER(V) \
427 V(DEBUG_INFO, DebugInfo, debug_info) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
429#else
430#define STRUCT_LIST_DEBUGGER(V)
431#endif
432
Steve Blockd0582a62009-12-15 09:54:21 +0000433#define STRUCT_LIST(V) \
434 STRUCT_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 STRUCT_LIST_DEBUGGER(V)
436
437// We use the full 8 bits of the instance_type field to encode heap object
438// instance types. The high-order bit (bit 7) is set if the object is not a
439// string, and cleared if it is a string.
440const uint32_t kIsNotStringMask = 0x80;
441const uint32_t kStringTag = 0x0;
442const uint32_t kNotStringTag = 0x80;
443
Leon Clarkee46be812010-01-19 14:06:41 +0000444// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
445// There are not enough types that the non-string types (with bit 7 set) can
446// have bit 6 set too.
447const uint32_t kIsSymbolMask = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000448const uint32_t kNotSymbolTag = 0x0;
Leon Clarkee46be812010-01-19 14:06:41 +0000449const uint32_t kSymbolTag = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000450
Steve Blocka7e24c12009-10-30 11:49:00 +0000451// If bit 7 is clear then bit 2 indicates whether the string consists of
452// two-byte characters or one-byte characters.
453const uint32_t kStringEncodingMask = 0x4;
454const uint32_t kTwoByteStringTag = 0x0;
455const uint32_t kAsciiStringTag = 0x4;
456
457// If bit 7 is clear, the low-order 2 bits indicate the representation
458// of the string.
459const uint32_t kStringRepresentationMask = 0x03;
460enum StringRepresentationTag {
461 kSeqStringTag = 0x0,
462 kConsStringTag = 0x1,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100463 kExternalStringTag = 0x2
Steve Blocka7e24c12009-10-30 11:49:00 +0000464};
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100465const uint32_t kIsConsStringMask = 0x1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000466
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100467// If bit 7 is clear, then bit 3 indicates whether this two-byte
468// string actually contains ascii data.
469const uint32_t kAsciiDataHintMask = 0x08;
470const uint32_t kAsciiDataHintTag = 0x08;
471
Steve Blocka7e24c12009-10-30 11:49:00 +0000472
473// A ConsString with an empty string as the right side is a candidate
474// for being shortcut by the garbage collector unless it is a
475// symbol. It's not common to have non-flat symbols, so we do not
476// shortcut them thereby avoiding turning symbols into strings. See
477// heap.cc and mark-compact.cc.
478const uint32_t kShortcutTypeMask =
479 kIsNotStringMask |
480 kIsSymbolMask |
481 kStringRepresentationMask;
482const uint32_t kShortcutTypeTag = kConsStringTag;
483
484
485enum InstanceType {
Leon Clarkee46be812010-01-19 14:06:41 +0000486 // String types.
Steve Block1e0659c2011-05-24 12:43:12 +0100487 // FIRST_STRING_TYPE
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100488 SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000489 ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100490 CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000491 CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100492 EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
493 EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
494 kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000495 EXTERNAL_ASCII_SYMBOL_TYPE =
496 kAsciiStringTag | kSymbolTag | kExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100497 STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000498 ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100499 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000500 CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100501 EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
502 EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
503 kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
Steve Block1e0659c2011-05-24 12:43:12 +0100504 // LAST_STRING_TYPE
Steve Blockd0582a62009-12-15 09:54:21 +0000505 EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
506 PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000507
Leon Clarkee46be812010-01-19 14:06:41 +0000508 // Objects allocated in their own spaces (never in new space).
509 MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 CODE_TYPE,
511 ODDBALL_TYPE,
512 JS_GLOBAL_PROPERTY_CELL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000513
514 // "Data", objects that cannot contain non-map-word pointers to heap
515 // objects.
516 HEAP_NUMBER_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000517 PROXY_TYPE,
518 BYTE_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000519 EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
Steve Block3ce2e202009-11-05 08:53:23 +0000520 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
521 EXTERNAL_SHORT_ARRAY_TYPE,
522 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
523 EXTERNAL_INT_ARRAY_TYPE,
524 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100525 EXTERNAL_FLOAT_ARRAY_TYPE,
526 EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
Leon Clarkee46be812010-01-19 14:06:41 +0000527 FILLER_TYPE, // LAST_DATA_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000528
Leon Clarkee46be812010-01-19 14:06:41 +0000529 // Structs.
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 ACCESSOR_INFO_TYPE,
531 ACCESS_CHECK_INFO_TYPE,
532 INTERCEPTOR_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 CALL_HANDLER_INFO_TYPE,
534 FUNCTION_TEMPLATE_INFO_TYPE,
535 OBJECT_TEMPLATE_INFO_TYPE,
536 SIGNATURE_INFO_TYPE,
537 TYPE_SWITCH_INFO_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000538 SCRIPT_TYPE,
Steve Block6ded16b2010-05-10 14:33:55 +0100539 CODE_CACHE_TYPE,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100540 // The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
541 // is defined. However as include/v8.h contain some of the instance type
542 // constants always having them avoids them getting different numbers
543 // depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 DEBUG_INFO_TYPE,
545 BREAK_POINT_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000546
Leon Clarkee46be812010-01-19 14:06:41 +0000547 FIXED_ARRAY_TYPE,
548 SHARED_FUNCTION_INFO_TYPE,
549
Steve Block1e0659c2011-05-24 12:43:12 +0100550 JS_MESSAGE_OBJECT_TYPE,
551
Leon Clarkee46be812010-01-19 14:06:41 +0000552 JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 JS_OBJECT_TYPE,
554 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
555 JS_GLOBAL_OBJECT_TYPE,
556 JS_BUILTINS_OBJECT_TYPE,
557 JS_GLOBAL_PROXY_TYPE,
558 JS_ARRAY_TYPE,
Steve Block1e0659c2011-05-24 12:43:12 +0100559
560 JS_REGEXP_TYPE, // LAST_JS_OBJECT_TYPE, FIRST_FUNCTION_CLASS_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000561
562 JS_FUNCTION_TYPE,
563
564 // Pseudo-types
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 FIRST_TYPE = 0x0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000566 LAST_TYPE = JS_FUNCTION_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000567 INVALID_TYPE = FIRST_TYPE - 1,
568 FIRST_NONSTRING_TYPE = MAP_TYPE,
Steve Block1e0659c2011-05-24 12:43:12 +0100569 FIRST_STRING_TYPE = FIRST_TYPE,
570 LAST_STRING_TYPE = FIRST_NONSTRING_TYPE - 1,
Leon Clarkee46be812010-01-19 14:06:41 +0000571 // Boundaries for testing for an external array.
572 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100573 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000574 // Boundary for promotion to old data space/old pointer space.
575 LAST_DATA_TYPE = FILLER_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000576 // Boundaries for testing the type is a JavaScript "object". Note that
577 // function objects are not counted as objects, even though they are
578 // implemented as such; only values whose typeof is "object" are included.
579 FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
Steve Block1e0659c2011-05-24 12:43:12 +0100580 LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE,
581 // RegExp objects have [[Class]] "function" because they are callable.
582 // All types from this type and above are objects with [[Class]] "function".
583 FIRST_FUNCTION_CLASS_TYPE = JS_REGEXP_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000584};
585
Steve Block44f0eee2011-05-26 01:26:41 +0100586static const int kExternalArrayTypeCount = LAST_EXTERNAL_ARRAY_TYPE -
587 FIRST_EXTERNAL_ARRAY_TYPE + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000588
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100589STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
590STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
591STATIC_CHECK(PROXY_TYPE == Internals::kProxyType);
592
593
Steve Blocka7e24c12009-10-30 11:49:00 +0000594enum CompareResult {
595 LESS = -1,
596 EQUAL = 0,
597 GREATER = 1,
598
599 NOT_EQUAL = GREATER
600};
601
602
603#define DECL_BOOLEAN_ACCESSORS(name) \
604 inline bool name(); \
605 inline void set_##name(bool value); \
606
607
608#define DECL_ACCESSORS(name, type) \
609 inline type* name(); \
610 inline void set_##name(type* value, \
611 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
612
613
614class StringStream;
615class ObjectVisitor;
616
617struct ValueInfo : public Malloced {
618 ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
619 InstanceType type;
620 Object* ptr;
621 const char* str;
622 double number;
623};
624
625
626// A template-ized version of the IsXXX functions.
627template <class C> static inline bool Is(Object* obj);
628
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629
John Reck59135872010-11-02 12:39:01 -0700630class MaybeObject BASE_EMBEDDED {
631 public:
632 inline bool IsFailure();
633 inline bool IsRetryAfterGC();
634 inline bool IsOutOfMemory();
635 inline bool IsException();
636 INLINE(bool IsTheHole());
637 inline bool ToObject(Object** obj) {
638 if (IsFailure()) return false;
639 *obj = reinterpret_cast<Object*>(this);
640 return true;
641 }
642 inline Object* ToObjectUnchecked() {
643 ASSERT(!IsFailure());
644 return reinterpret_cast<Object*>(this);
645 }
646 inline Object* ToObjectChecked() {
647 CHECK(!IsFailure());
648 return reinterpret_cast<Object*>(this);
649 }
650
Ben Murdochb0fe1622011-05-05 13:52:32 +0100651#ifdef OBJECT_PRINT
John Reck59135872010-11-02 12:39:01 -0700652 // Prints this object with details.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100653 inline void Print() {
654 Print(stdout);
655 };
656 inline void PrintLn() {
657 PrintLn(stdout);
658 }
659 void Print(FILE* out);
660 void PrintLn(FILE* out);
661#endif
662#ifdef DEBUG
John Reck59135872010-11-02 12:39:01 -0700663 // Verifies the object.
664 void Verify();
665#endif
666};
Steve Blocka7e24c12009-10-30 11:49:00 +0000667
Ben Murdochb8e0da22011-05-16 14:20:40 +0100668
669#define OBJECT_TYPE_LIST(V) \
670 V(Smi) \
671 V(HeapObject) \
672 V(Number) \
673
674#define HEAP_OBJECT_TYPE_LIST(V) \
675 V(HeapNumber) \
676 V(String) \
677 V(Symbol) \
678 V(SeqString) \
679 V(ExternalString) \
680 V(ConsString) \
681 V(ExternalTwoByteString) \
682 V(ExternalAsciiString) \
683 V(SeqTwoByteString) \
684 V(SeqAsciiString) \
685 \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100686 V(ExternalArray) \
687 V(ExternalByteArray) \
688 V(ExternalUnsignedByteArray) \
689 V(ExternalShortArray) \
690 V(ExternalUnsignedShortArray) \
691 V(ExternalIntArray) \
692 V(ExternalUnsignedIntArray) \
693 V(ExternalFloatArray) \
Steve Block44f0eee2011-05-26 01:26:41 +0100694 V(ExternalPixelArray) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100695 V(ByteArray) \
696 V(JSObject) \
697 V(JSContextExtensionObject) \
698 V(Map) \
699 V(DescriptorArray) \
700 V(DeoptimizationInputData) \
701 V(DeoptimizationOutputData) \
702 V(FixedArray) \
703 V(Context) \
704 V(CatchContext) \
705 V(GlobalContext) \
706 V(JSFunction) \
707 V(Code) \
708 V(Oddball) \
709 V(SharedFunctionInfo) \
710 V(JSValue) \
Steve Block1e0659c2011-05-24 12:43:12 +0100711 V(JSMessageObject) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100712 V(StringWrapper) \
713 V(Proxy) \
714 V(Boolean) \
715 V(JSArray) \
716 V(JSRegExp) \
717 V(HashTable) \
718 V(Dictionary) \
719 V(SymbolTable) \
720 V(JSFunctionResultCache) \
721 V(NormalizedMapCache) \
722 V(CompilationCacheTable) \
723 V(CodeCacheHashTable) \
724 V(MapCache) \
725 V(Primitive) \
726 V(GlobalObject) \
727 V(JSGlobalObject) \
728 V(JSBuiltinsObject) \
729 V(JSGlobalProxy) \
730 V(UndetectableObject) \
731 V(AccessCheckNeeded) \
732 V(JSGlobalPropertyCell) \
733
Steve Blocka7e24c12009-10-30 11:49:00 +0000734// Object is the abstract superclass for all classes in the
735// object hierarchy.
736// Object does not use any virtual functions to avoid the
737// allocation of the C++ vtable.
738// Since Smi and Failure are subclasses of Object no
739// data members can be present in Object.
John Reck59135872010-11-02 12:39:01 -0700740class Object : public MaybeObject {
Steve Blocka7e24c12009-10-30 11:49:00 +0000741 public:
742 // Type testing.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100743#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
744 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
745 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
746#undef IS_TYPE_FUNCTION_DECL
Steve Blocka7e24c12009-10-30 11:49:00 +0000747
748 // Returns true if this object is an instance of the specified
749 // function template.
750 inline bool IsInstanceOf(FunctionTemplateInfo* type);
751
752 inline bool IsStruct();
753#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
754 STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
755#undef DECLARE_STRUCT_PREDICATE
756
757 // Oddball testing.
758 INLINE(bool IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 INLINE(bool IsNull());
Steve Block44f0eee2011-05-26 01:26:41 +0100760 INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
Steve Blocka7e24c12009-10-30 11:49:00 +0000761 INLINE(bool IsTrue());
762 INLINE(bool IsFalse());
Ben Murdoch086aeea2011-05-13 15:57:08 +0100763 inline bool IsArgumentsMarker();
Steve Blocka7e24c12009-10-30 11:49:00 +0000764
765 // Extract the number.
766 inline double Number();
767
768 inline bool HasSpecificClassOf(String* name);
769
John Reck59135872010-11-02 12:39:01 -0700770 MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9.
771 Object* ToBoolean(); // ECMA-262 9.2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000772
773 // Convert to a JSObject if needed.
774 // global_context is used when creating wrapper object.
John Reck59135872010-11-02 12:39:01 -0700775 MUST_USE_RESULT MaybeObject* ToObject(Context* global_context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000776
777 // Converts this to a Smi if possible.
778 // Failure is returned otherwise.
John Reck59135872010-11-02 12:39:01 -0700779 MUST_USE_RESULT inline MaybeObject* ToSmi();
Steve Blocka7e24c12009-10-30 11:49:00 +0000780
781 void Lookup(String* name, LookupResult* result);
782
783 // Property access.
John Reck59135872010-11-02 12:39:01 -0700784 MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
785 MUST_USE_RESULT inline MaybeObject* GetProperty(
786 String* key,
787 PropertyAttributes* attributes);
788 MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
789 Object* receiver,
790 String* key,
791 PropertyAttributes* attributes);
792 MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
793 LookupResult* result,
794 String* key,
795 PropertyAttributes* attributes);
796 MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
797 Object* structure,
798 String* name,
799 Object* holder);
800 MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
801 JSFunction* getter);
Steve Blocka7e24c12009-10-30 11:49:00 +0000802
John Reck59135872010-11-02 12:39:01 -0700803 inline MaybeObject* GetElement(uint32_t index);
804 // For use when we know that no exception can be thrown.
805 inline Object* GetElementNoExceptionThrown(uint32_t index);
806 MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000807
808 // Return the object's prototype (might be Heap::null_value()).
809 Object* GetPrototype();
810
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100811 // Tries to convert an object to an array index. Returns true and sets
812 // the output parameter if it succeeds.
813 inline bool ToArrayIndex(uint32_t* index);
814
Steve Blocka7e24c12009-10-30 11:49:00 +0000815 // Returns true if this is a JSValue containing a string and the index is
816 // < the length of the string. Used to implement [] on strings.
817 inline bool IsStringObjectWithCharacterAt(uint32_t index);
818
819#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000820 // Verify a pointer is a valid object pointer.
821 static void VerifyPointer(Object* p);
822#endif
823
824 // Prints this object without details.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100825 inline void ShortPrint() {
826 ShortPrint(stdout);
827 }
828 void ShortPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000829
830 // Prints this object without details to a message accumulator.
831 void ShortPrint(StringStream* accumulator);
832
833 // Casting: This cast is only needed to satisfy macros in objects-inl.h.
834 static Object* cast(Object* value) { return value; }
835
836 // Layout description.
837 static const int kHeaderSize = 0; // Object does not take up any space.
838
839 private:
840 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
841};
842
843
844// Smi represents integer Numbers that can be stored in 31 bits.
845// Smis are immediate which means they are NOT allocated in the heap.
Steve Blocka7e24c12009-10-30 11:49:00 +0000846// The this pointer has the following format: [31 bit signed int] 0
Steve Block3ce2e202009-11-05 08:53:23 +0000847// For long smis it has the following format:
848// [32 bit signed int] [31 bits zero padding] 0
849// Smi stands for small integer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000850class Smi: public Object {
851 public:
852 // Returns the integer value.
853 inline int value();
854
855 // Convert a value to a Smi object.
856 static inline Smi* FromInt(int value);
857
858 static inline Smi* FromIntptr(intptr_t value);
859
860 // Returns whether value can be represented in a Smi.
861 static inline bool IsValid(intptr_t value);
862
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 // Casting.
864 static inline Smi* cast(Object* object);
865
866 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100867 inline void SmiPrint() {
868 SmiPrint(stdout);
869 }
870 void SmiPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871 void SmiPrint(StringStream* accumulator);
872#ifdef DEBUG
873 void SmiVerify();
874#endif
875
Steve Block3ce2e202009-11-05 08:53:23 +0000876 static const int kMinValue = (-1 << (kSmiValueSize - 1));
877 static const int kMaxValue = -(kMinValue + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000878
879 private:
880 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
881};
882
883
884// Failure is used for reporting out of memory situations and
885// propagating exceptions through the runtime system. Failure objects
886// are transient and cannot occur as part of the object graph.
887//
888// Failures are a single word, encoded as follows:
889// +-------------------------+---+--+--+
Ben Murdochf87a2032010-10-22 12:50:53 +0100890// |.........unused..........|sss|tt|11|
Steve Blocka7e24c12009-10-30 11:49:00 +0000891// +-------------------------+---+--+--+
Steve Block3ce2e202009-11-05 08:53:23 +0000892// 7 6 4 32 10
893//
Steve Blocka7e24c12009-10-30 11:49:00 +0000894//
895// The low two bits, 0-1, are the failure tag, 11. The next two bits,
896// 2-3, are a failure type tag 'tt' with possible values:
897// 00 RETRY_AFTER_GC
898// 01 EXCEPTION
899// 10 INTERNAL_ERROR
900// 11 OUT_OF_MEMORY_EXCEPTION
901//
902// The next three bits, 4-6, are an allocation space tag 'sss'. The
903// allocation space tag is 000 for all failure types except
904// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
905// allocation spaces (the encoding is found in globals.h).
Steve Blocka7e24c12009-10-30 11:49:00 +0000906
907// Failure type tag info.
908const int kFailureTypeTagSize = 2;
909const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
910
John Reck59135872010-11-02 12:39:01 -0700911class Failure: public MaybeObject {
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 public:
913 // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
914 enum Type {
915 RETRY_AFTER_GC = 0,
916 EXCEPTION = 1, // Returning this marker tells the real exception
Steve Block44f0eee2011-05-26 01:26:41 +0100917 // is in Isolate::pending_exception.
Steve Blocka7e24c12009-10-30 11:49:00 +0000918 INTERNAL_ERROR = 2,
919 OUT_OF_MEMORY_EXCEPTION = 3
920 };
921
922 inline Type type() const;
923
924 // Returns the space that needs to be collected for RetryAfterGC failures.
925 inline AllocationSpace allocation_space() const;
926
Steve Blocka7e24c12009-10-30 11:49:00 +0000927 inline bool IsInternalError() const;
928 inline bool IsOutOfMemoryException() const;
929
Ben Murdochf87a2032010-10-22 12:50:53 +0100930 static inline Failure* RetryAfterGC(AllocationSpace space);
931 static inline Failure* RetryAfterGC(); // NEW_SPACE
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 static inline Failure* Exception();
933 static inline Failure* InternalError();
934 static inline Failure* OutOfMemoryException();
935 // Casting.
John Reck59135872010-11-02 12:39:01 -0700936 static inline Failure* cast(MaybeObject* object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000937
938 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100939 inline void FailurePrint() {
940 FailurePrint(stdout);
941 }
942 void FailurePrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 void FailurePrint(StringStream* accumulator);
944#ifdef DEBUG
945 void FailureVerify();
946#endif
947
948 private:
Steve Block3ce2e202009-11-05 08:53:23 +0000949 inline intptr_t value() const;
950 static inline Failure* Construct(Type type, intptr_t value = 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000951
952 DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
953};
954
955
956// Heap objects typically have a map pointer in their first word. However,
957// during GC other data (eg, mark bits, forwarding addresses) is sometimes
958// encoded in the first word. The class MapWord is an abstraction of the
959// value in a heap object's first word.
960class MapWord BASE_EMBEDDED {
961 public:
962 // Normal state: the map word contains a map pointer.
963
964 // Create a map word from a map pointer.
965 static inline MapWord FromMap(Map* map);
966
967 // View this map word as a map pointer.
968 inline Map* ToMap();
969
970
971 // Scavenge collection: the map word of live objects in the from space
972 // contains a forwarding address (a heap object pointer in the to space).
973
974 // True if this map word is a forwarding address for a scavenge
975 // collection. Only valid during a scavenge collection (specifically,
976 // when all map words are heap object pointers, ie. not during a full GC).
977 inline bool IsForwardingAddress();
978
979 // Create a map word from a forwarding address.
980 static inline MapWord FromForwardingAddress(HeapObject* object);
981
982 // View this map word as a forwarding address.
983 inline HeapObject* ToForwardingAddress();
984
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 // Marking phase of full collection: the map word of live objects is
986 // marked, and may be marked as overflowed (eg, the object is live, its
987 // children have not been visited, and it does not fit in the marking
988 // stack).
989
990 // True if this map word's mark bit is set.
991 inline bool IsMarked();
992
993 // Return this map word but with its mark bit set.
994 inline void SetMark();
995
996 // Return this map word but with its mark bit cleared.
997 inline void ClearMark();
998
999 // True if this map word's overflow bit is set.
1000 inline bool IsOverflowed();
1001
1002 // Return this map word but with its overflow bit set.
1003 inline void SetOverflow();
1004
1005 // Return this map word but with its overflow bit cleared.
1006 inline void ClearOverflow();
1007
1008
1009 // Compacting phase of a full compacting collection: the map word of live
1010 // objects contains an encoding of the original map address along with the
1011 // forwarding address (represented as an offset from the first live object
1012 // in the same page as the (old) object address).
1013
1014 // Create a map word from a map address and a forwarding address offset.
1015 static inline MapWord EncodeAddress(Address map_address, int offset);
1016
1017 // Return the map address encoded in this map word.
1018 inline Address DecodeMapAddress(MapSpace* map_space);
1019
1020 // Return the forwarding offset encoded in this map word.
1021 inline int DecodeOffset();
1022
1023
1024 // During serialization: the map word is used to hold an encoded
1025 // address, and possibly a mark bit (set and cleared with SetMark
1026 // and ClearMark).
1027
1028 // Create a map word from an encoded address.
1029 static inline MapWord FromEncodedAddress(Address address);
1030
1031 inline Address ToEncodedAddress();
1032
1033 // Bits used by the marking phase of the garbage collector.
1034 //
1035 // The first word of a heap object is normally a map pointer. The last two
1036 // bits are tagged as '01' (kHeapObjectTag). We reuse the last two bits to
1037 // mark an object as live and/or overflowed:
1038 // last bit = 0, marked as alive
1039 // second bit = 1, overflowed
1040 // An object is only marked as overflowed when it is marked as live while
1041 // the marking stack is overflowed.
1042 static const int kMarkingBit = 0; // marking bit
1043 static const int kMarkingMask = (1 << kMarkingBit); // marking mask
1044 static const int kOverflowBit = 1; // overflow bit
1045 static const int kOverflowMask = (1 << kOverflowBit); // overflow mask
1046
Leon Clarkee46be812010-01-19 14:06:41 +00001047 // Forwarding pointers and map pointer encoding. On 32 bit all the bits are
1048 // used.
Steve Blocka7e24c12009-10-30 11:49:00 +00001049 // +-----------------+------------------+-----------------+
1050 // |forwarding offset|page offset of map|page index of map|
1051 // +-----------------+------------------+-----------------+
Leon Clarkee46be812010-01-19 14:06:41 +00001052 // ^ ^ ^
1053 // | | |
1054 // | | kMapPageIndexBits
1055 // | kMapPageOffsetBits
1056 // kForwardingOffsetBits
1057 static const int kMapPageOffsetBits = kPageSizeBits - kMapAlignmentBits;
1058 static const int kForwardingOffsetBits = kPageSizeBits - kObjectAlignmentBits;
1059#ifdef V8_HOST_ARCH_64_BIT
1060 static const int kMapPageIndexBits = 16;
1061#else
1062 // Use all the 32-bits to encode on a 32-bit platform.
1063 static const int kMapPageIndexBits =
1064 32 - (kMapPageOffsetBits + kForwardingOffsetBits);
1065#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001066
1067 static const int kMapPageIndexShift = 0;
1068 static const int kMapPageOffsetShift =
1069 kMapPageIndexShift + kMapPageIndexBits;
1070 static const int kForwardingOffsetShift =
1071 kMapPageOffsetShift + kMapPageOffsetBits;
1072
Leon Clarkee46be812010-01-19 14:06:41 +00001073 // Bit masks covering the different parts the encoding.
1074 static const uintptr_t kMapPageIndexMask =
Steve Blocka7e24c12009-10-30 11:49:00 +00001075 (1 << kMapPageOffsetShift) - 1;
Leon Clarkee46be812010-01-19 14:06:41 +00001076 static const uintptr_t kMapPageOffsetMask =
Steve Blocka7e24c12009-10-30 11:49:00 +00001077 ((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask;
Leon Clarkee46be812010-01-19 14:06:41 +00001078 static const uintptr_t kForwardingOffsetMask =
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 ~(kMapPageIndexMask | kMapPageOffsetMask);
1080
1081 private:
1082 // HeapObject calls the private constructor and directly reads the value.
1083 friend class HeapObject;
1084
1085 explicit MapWord(uintptr_t value) : value_(value) {}
1086
1087 uintptr_t value_;
1088};
1089
1090
1091// HeapObject is the superclass for all classes describing heap allocated
1092// objects.
1093class HeapObject: public Object {
1094 public:
1095 // [map]: Contains a map which contains the object's reflective
1096 // information.
1097 inline Map* map();
1098 inline void set_map(Map* value);
1099
1100 // During garbage collection, the map word of a heap object does not
1101 // necessarily contain a map pointer.
1102 inline MapWord map_word();
1103 inline void set_map_word(MapWord map_word);
1104
Steve Block44f0eee2011-05-26 01:26:41 +01001105 // The Heap the object was allocated in. Used also to access Isolate.
1106 // This method can not be used during GC, it ASSERTs this.
1107 inline Heap* GetHeap();
1108 // Convenience method to get current isolate. This method can be
1109 // accessed only when its result is the same as
1110 // Isolate::Current(), it ASSERTs this. See also comment for GetHeap.
1111 inline Isolate* GetIsolate();
1112
Steve Blocka7e24c12009-10-30 11:49:00 +00001113 // Converts an address to a HeapObject pointer.
1114 static inline HeapObject* FromAddress(Address address);
1115
1116 // Returns the address of this HeapObject.
1117 inline Address address();
1118
1119 // Iterates over pointers contained in the object (including the Map)
1120 void Iterate(ObjectVisitor* v);
1121
1122 // Iterates over all pointers contained in the object except the
1123 // first map pointer. The object type is given in the first
1124 // parameter. This function does not access the map pointer in the
1125 // object, and so is safe to call while the map pointer is modified.
1126 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
1127
Steve Blocka7e24c12009-10-30 11:49:00 +00001128 // Returns the heap object's size in bytes
1129 inline int Size();
1130
1131 // Given a heap object's map pointer, returns the heap size in bytes
1132 // Useful when the map pointer field is used for other purposes.
1133 // GC internal.
1134 inline int SizeFromMap(Map* map);
1135
1136 // Support for the marking heap objects during the marking phase of GC.
1137 // True if the object is marked live.
1138 inline bool IsMarked();
1139
1140 // Mutate this object's map pointer to indicate that the object is live.
1141 inline void SetMark();
1142
1143 // Mutate this object's map pointer to remove the indication that the
1144 // object is live (ie, partially restore the map pointer).
1145 inline void ClearMark();
1146
1147 // True if this object is marked as overflowed. Overflowed objects have
1148 // been reached and marked during marking of the heap, but their children
1149 // have not necessarily been marked and they have not been pushed on the
1150 // marking stack.
1151 inline bool IsOverflowed();
1152
1153 // Mutate this object's map pointer to indicate that the object is
1154 // overflowed.
1155 inline void SetOverflow();
1156
1157 // Mutate this object's map pointer to remove the indication that the
1158 // object is overflowed (ie, partially restore the map pointer).
1159 inline void ClearOverflow();
1160
1161 // Returns the field at offset in obj, as a read/write Object* reference.
1162 // Does no checking, and is safe to use during GC, while maps are invalid.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001163 // Does not invoke write barrier, so should only be assigned to
Steve Blocka7e24c12009-10-30 11:49:00 +00001164 // during marking GC.
1165 static inline Object** RawField(HeapObject* obj, int offset);
1166
1167 // Casting.
1168 static inline HeapObject* cast(Object* obj);
1169
Leon Clarke4515c472010-02-03 11:58:03 +00001170 // Return the write barrier mode for this. Callers of this function
1171 // must be able to present a reference to an AssertNoAllocation
1172 // object as a sign that they are not going to use this function
1173 // from code that allocates and thus invalidates the returned write
1174 // barrier mode.
1175 inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
Steve Blocka7e24c12009-10-30 11:49:00 +00001176
1177 // Dispatched behavior.
1178 void HeapObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001179#ifdef OBJECT_PRINT
1180 inline void HeapObjectPrint() {
1181 HeapObjectPrint(stdout);
1182 }
1183 void HeapObjectPrint(FILE* out);
1184#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001185#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001186 void HeapObjectVerify();
1187 inline void VerifyObjectField(int offset);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001188 inline void VerifySmiField(int offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001189#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001190
Ben Murdochb0fe1622011-05-05 13:52:32 +01001191#ifdef OBJECT_PRINT
1192 void PrintHeader(FILE* out, const char* id);
1193#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001194
Ben Murdochb0fe1622011-05-05 13:52:32 +01001195#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 // Verify a pointer is a valid HeapObject pointer that points to object
1197 // areas in the heap.
1198 static void VerifyHeapPointer(Object* p);
1199#endif
1200
1201 // Layout description.
1202 // First field in a heap object is map.
1203 static const int kMapOffset = Object::kHeaderSize;
1204 static const int kHeaderSize = kMapOffset + kPointerSize;
1205
1206 STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
1207
1208 protected:
1209 // helpers for calling an ObjectVisitor to iterate over pointers in the
1210 // half-open range [start, end) specified as integer offsets
1211 inline void IteratePointers(ObjectVisitor* v, int start, int end);
1212 // as above, for the single element at "offset"
1213 inline void IteratePointer(ObjectVisitor* v, int offset);
1214
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 private:
1216 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
1217};
1218
1219
Iain Merrick75681382010-08-19 15:07:18 +01001220#define SLOT_ADDR(obj, offset) \
1221 reinterpret_cast<Object**>((obj)->address() + offset)
1222
1223// This class describes a body of an object of a fixed size
1224// in which all pointer fields are located in the [start_offset, end_offset)
1225// interval.
1226template<int start_offset, int end_offset, int size>
1227class FixedBodyDescriptor {
1228 public:
1229 static const int kStartOffset = start_offset;
1230 static const int kEndOffset = end_offset;
1231 static const int kSize = size;
1232
1233 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
1234
1235 template<typename StaticVisitor>
1236 static inline void IterateBody(HeapObject* obj) {
1237 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1238 SLOT_ADDR(obj, end_offset));
1239 }
1240};
1241
1242
1243// This class describes a body of an object of a variable size
1244// in which all pointer fields are located in the [start_offset, object_size)
1245// interval.
1246template<int start_offset>
1247class FlexibleBodyDescriptor {
1248 public:
1249 static const int kStartOffset = start_offset;
1250
1251 static inline void IterateBody(HeapObject* obj,
1252 int object_size,
1253 ObjectVisitor* v);
1254
1255 template<typename StaticVisitor>
1256 static inline void IterateBody(HeapObject* obj, int object_size) {
1257 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1258 SLOT_ADDR(obj, object_size));
1259 }
1260};
1261
1262#undef SLOT_ADDR
1263
1264
Steve Blocka7e24c12009-10-30 11:49:00 +00001265// The HeapNumber class describes heap allocated numbers that cannot be
1266// represented in a Smi (small integer)
1267class HeapNumber: public HeapObject {
1268 public:
1269 // [value]: number value.
1270 inline double value();
1271 inline void set_value(double value);
1272
1273 // Casting.
1274 static inline HeapNumber* cast(Object* obj);
1275
1276 // Dispatched behavior.
1277 Object* HeapNumberToBoolean();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001278 inline void HeapNumberPrint() {
1279 HeapNumberPrint(stdout);
1280 }
1281 void HeapNumberPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001282 void HeapNumberPrint(StringStream* accumulator);
1283#ifdef DEBUG
1284 void HeapNumberVerify();
1285#endif
1286
Steve Block6ded16b2010-05-10 14:33:55 +01001287 inline int get_exponent();
1288 inline int get_sign();
1289
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 // Layout description.
1291 static const int kValueOffset = HeapObject::kHeaderSize;
1292 // IEEE doubles are two 32 bit words. The first is just mantissa, the second
1293 // is a mixture of sign, exponent and mantissa. Our current platforms are all
1294 // little endian apart from non-EABI arm which is little endian with big
1295 // endian floating point word ordering!
Steve Blocka7e24c12009-10-30 11:49:00 +00001296 static const int kMantissaOffset = kValueOffset;
1297 static const int kExponentOffset = kValueOffset + 4;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001298
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 static const int kSize = kValueOffset + kDoubleSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 static const uint32_t kSignMask = 0x80000000u;
1301 static const uint32_t kExponentMask = 0x7ff00000u;
1302 static const uint32_t kMantissaMask = 0xfffffu;
Steve Block6ded16b2010-05-10 14:33:55 +01001303 static const int kMantissaBits = 52;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001304 static const int kExponentBits = 11;
Steve Blocka7e24c12009-10-30 11:49:00 +00001305 static const int kExponentBias = 1023;
1306 static const int kExponentShift = 20;
1307 static const int kMantissaBitsInTopWord = 20;
1308 static const int kNonMantissaBitsInTopWord = 12;
1309
1310 private:
1311 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1312};
1313
1314
1315// The JSObject describes real heap allocated JavaScript objects with
1316// properties.
1317// Note that the map of JSObject changes during execution to enable inline
1318// caching.
1319class JSObject: public HeapObject {
1320 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001321 enum DeleteMode {
1322 NORMAL_DELETION,
1323 STRICT_DELETION,
1324 FORCE_DELETION
1325 };
1326
Steve Blocka7e24c12009-10-30 11:49:00 +00001327 enum ElementsKind {
Iain Merrick75681382010-08-19 15:07:18 +01001328 // The only "fast" kind.
Steve Blocka7e24c12009-10-30 11:49:00 +00001329 FAST_ELEMENTS,
Iain Merrick75681382010-08-19 15:07:18 +01001330 // All the kinds below are "slow".
Steve Blocka7e24c12009-10-30 11:49:00 +00001331 DICTIONARY_ELEMENTS,
Steve Block3ce2e202009-11-05 08:53:23 +00001332 EXTERNAL_BYTE_ELEMENTS,
1333 EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
1334 EXTERNAL_SHORT_ELEMENTS,
1335 EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
1336 EXTERNAL_INT_ELEMENTS,
1337 EXTERNAL_UNSIGNED_INT_ELEMENTS,
Steve Block44f0eee2011-05-26 01:26:41 +01001338 EXTERNAL_FLOAT_ELEMENTS,
1339 EXTERNAL_PIXEL_ELEMENTS
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 };
1341
1342 // [properties]: Backing storage for properties.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001343 // properties is a FixedArray in the fast case and a Dictionary in the
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 // slow case.
1345 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
1346 inline void initialize_properties();
1347 inline bool HasFastProperties();
1348 inline StringDictionary* property_dictionary(); // Gets slow properties.
1349
1350 // [elements]: The elements (properties with names that are integers).
Iain Merrick75681382010-08-19 15:07:18 +01001351 //
1352 // Elements can be in two general modes: fast and slow. Each mode
1353 // corrensponds to a set of object representations of elements that
1354 // have something in common.
1355 //
1356 // In the fast mode elements is a FixedArray and so each element can
1357 // be quickly accessed. This fact is used in the generated code. The
1358 // elements array can have one of the two maps in this mode:
1359 // fixed_array_map or fixed_cow_array_map (for copy-on-write
1360 // arrays). In the latter case the elements array may be shared by a
1361 // few objects and so before writing to any element the array must
1362 // be copied. Use EnsureWritableFastElements in this case.
1363 //
Steve Block44f0eee2011-05-26 01:26:41 +01001364 // In the slow mode elements is either a NumberDictionary or an ExternalArray.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001365 DECL_ACCESSORS(elements, HeapObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00001366 inline void initialize_elements();
John Reck59135872010-11-02 12:39:01 -07001367 MUST_USE_RESULT inline MaybeObject* ResetElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001368 inline ElementsKind GetElementsKind();
1369 inline bool HasFastElements();
1370 inline bool HasDictionaryElements();
Steve Block44f0eee2011-05-26 01:26:41 +01001371 inline bool HasExternalPixelElements();
Steve Block3ce2e202009-11-05 08:53:23 +00001372 inline bool HasExternalArrayElements();
1373 inline bool HasExternalByteElements();
1374 inline bool HasExternalUnsignedByteElements();
1375 inline bool HasExternalShortElements();
1376 inline bool HasExternalUnsignedShortElements();
1377 inline bool HasExternalIntElements();
1378 inline bool HasExternalUnsignedIntElements();
1379 inline bool HasExternalFloatElements();
Steve Block6ded16b2010-05-10 14:33:55 +01001380 inline bool AllowsSetElementsLength();
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 inline NumberDictionary* element_dictionary(); // Gets slow elements.
Iain Merrick75681382010-08-19 15:07:18 +01001382 // Requires: this->HasFastElements().
John Reck59135872010-11-02 12:39:01 -07001383 MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001384
1385 // Collects elements starting at index 0.
1386 // Undefined values are placed after non-undefined values.
1387 // Returns the number of non-undefined values.
John Reck59135872010-11-02 12:39:01 -07001388 MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001389 // As PrepareElementsForSort, but only on objects where elements is
1390 // a dictionary, and it will stay a dictionary.
John Reck59135872010-11-02 12:39:01 -07001391 MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001392
John Reck59135872010-11-02 12:39:01 -07001393 MUST_USE_RESULT MaybeObject* SetProperty(String* key,
1394 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001395 PropertyAttributes attributes,
1396 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001397 MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
1398 String* key,
1399 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001400 PropertyAttributes attributes,
1401 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001402 MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
1403 LookupResult* result,
1404 String* name,
Ben Murdoch086aeea2011-05-13 15:57:08 +01001405 Object* value,
1406 bool check_prototype);
John Reck59135872010-11-02 12:39:01 -07001407 MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(Object* structure,
1408 String* name,
1409 Object* value,
1410 JSObject* holder);
1411 MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSFunction* setter,
1412 Object* value);
1413 MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
1414 String* name,
1415 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001416 PropertyAttributes attributes,
1417 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001418 MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
1419 String* name,
1420 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001421 PropertyAttributes attributes,
1422 StrictModeFlag strict_mode);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001423 MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
John Reck59135872010-11-02 12:39:01 -07001424 String* key,
1425 Object* value,
1426 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001427
1428 // Retrieve a value in a normalized object given a lookup result.
1429 // Handles the special representation of JS global objects.
1430 Object* GetNormalizedProperty(LookupResult* result);
1431
1432 // Sets the property value in a normalized object given a lookup result.
1433 // Handles the special representation of JS global objects.
1434 Object* SetNormalizedProperty(LookupResult* result, Object* value);
1435
1436 // Sets the property value in a normalized object given (key, value, details).
1437 // Handles the special representation of JS global objects.
John Reck59135872010-11-02 12:39:01 -07001438 MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
1439 Object* value,
1440 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00001441
1442 // Deletes the named property in a normalized object.
John Reck59135872010-11-02 12:39:01 -07001443 MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
1444 DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001445
Steve Blocka7e24c12009-10-30 11:49:00 +00001446 // Returns the class name ([[Class]] property in the specification).
1447 String* class_name();
1448
1449 // Returns the constructor name (the name (possibly, inferred name) of the
1450 // function that was used to instantiate the object).
1451 String* constructor_name();
1452
1453 // Retrieve interceptors.
1454 InterceptorInfo* GetNamedInterceptor();
1455 InterceptorInfo* GetIndexedInterceptor();
1456
1457 inline PropertyAttributes GetPropertyAttribute(String* name);
1458 PropertyAttributes GetPropertyAttributeWithReceiver(JSObject* receiver,
1459 String* name);
1460 PropertyAttributes GetLocalPropertyAttribute(String* name);
1461
John Reck59135872010-11-02 12:39:01 -07001462 MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
1463 bool is_getter,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001464 Object* fun,
John Reck59135872010-11-02 12:39:01 -07001465 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 Object* LookupAccessor(String* name, bool is_getter);
1467
John Reck59135872010-11-02 12:39:01 -07001468 MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
Leon Clarkef7060e22010-06-03 12:02:55 +01001469
Steve Blocka7e24c12009-10-30 11:49:00 +00001470 // Used from Object::GetProperty().
John Reck59135872010-11-02 12:39:01 -07001471 MaybeObject* GetPropertyWithFailedAccessCheck(
1472 Object* receiver,
1473 LookupResult* result,
1474 String* name,
1475 PropertyAttributes* attributes);
1476 MaybeObject* GetPropertyWithInterceptor(
1477 JSObject* receiver,
1478 String* name,
1479 PropertyAttributes* attributes);
1480 MaybeObject* GetPropertyPostInterceptor(
1481 JSObject* receiver,
1482 String* name,
1483 PropertyAttributes* attributes);
1484 MaybeObject* GetLocalPropertyPostInterceptor(JSObject* receiver,
1485 String* name,
1486 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001487
1488 // Returns true if this is an instance of an api function and has
1489 // been modified since it was created. May give false positives.
1490 bool IsDirty();
1491
1492 bool HasProperty(String* name) {
1493 return GetPropertyAttribute(name) != ABSENT;
1494 }
1495
1496 // Can cause a GC if it hits an interceptor.
1497 bool HasLocalProperty(String* name) {
1498 return GetLocalPropertyAttribute(name) != ABSENT;
1499 }
1500
Steve Blockd0582a62009-12-15 09:54:21 +00001501 // If the receiver is a JSGlobalProxy this method will return its prototype,
1502 // otherwise the result is the receiver itself.
1503 inline Object* BypassGlobalProxy();
1504
1505 // Accessors for hidden properties object.
1506 //
1507 // Hidden properties are not local properties of the object itself.
1508 // Instead they are stored on an auxiliary JSObject stored as a local
1509 // property with a special name Heap::hidden_symbol(). But if the
1510 // receiver is a JSGlobalProxy then the auxiliary object is a property
1511 // of its prototype.
1512 //
1513 // Has/Get/SetHiddenPropertiesObject methods don't allow the holder to be
1514 // a JSGlobalProxy. Use BypassGlobalProxy method above to get to the real
1515 // holder.
1516 //
1517 // These accessors do not touch interceptors or accessors.
1518 inline bool HasHiddenPropertiesObject();
1519 inline Object* GetHiddenPropertiesObject();
John Reck59135872010-11-02 12:39:01 -07001520 MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject(
1521 Object* hidden_obj);
Steve Blockd0582a62009-12-15 09:54:21 +00001522
John Reck59135872010-11-02 12:39:01 -07001523 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
1524 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001525
1526 // Tests for the fast common case for property enumeration.
1527 bool IsSimpleEnum();
1528
1529 // Do we want to keep the elements in fast case when increasing the
1530 // capacity?
1531 bool ShouldConvertToSlowElements(int new_capacity);
1532 // Returns true if the backing storage for the slow-case elements of
1533 // this object takes up nearly as much space as a fast-case backing
1534 // storage would. In that case the JSObject should have fast
1535 // elements.
1536 bool ShouldConvertToFastElements();
1537
1538 // Return the object's prototype (might be Heap::null_value()).
1539 inline Object* GetPrototype();
1540
Andrei Popescu402d9372010-02-26 13:31:12 +00001541 // Set the object's prototype (only JSObject and null are allowed).
John Reck59135872010-11-02 12:39:01 -07001542 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
1543 bool skip_hidden_prototypes);
Andrei Popescu402d9372010-02-26 13:31:12 +00001544
Steve Blocka7e24c12009-10-30 11:49:00 +00001545 // Tells whether the index'th element is present.
1546 inline bool HasElement(uint32_t index);
1547 bool HasElementWithReceiver(JSObject* receiver, uint32_t index);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001548
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001549 // Computes the new capacity when expanding the elements of a JSObject.
1550 static int NewElementsCapacity(int old_capacity) {
1551 // (old_capacity + 50%) + 16
1552 return old_capacity + (old_capacity >> 1) + 16;
1553 }
1554
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001555 // Tells whether the index'th element is present and how it is stored.
1556 enum LocalElementType {
1557 // There is no element with given index.
1558 UNDEFINED_ELEMENT,
1559
1560 // Element with given index is handled by interceptor.
1561 INTERCEPTED_ELEMENT,
1562
1563 // Element with given index is character in string.
1564 STRING_CHARACTER_ELEMENT,
1565
1566 // Element with given index is stored in fast backing store.
1567 FAST_ELEMENT,
1568
1569 // Element with given index is stored in slow backing store.
1570 DICTIONARY_ELEMENT
1571 };
1572
1573 LocalElementType HasLocalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001574
1575 bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
1576 bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
1577
Steve Block9fac8402011-05-12 15:51:54 +01001578 MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
1579 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001580 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01001581 bool check_prototype = true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001582
1583 // Set the index'th array element.
1584 // A Failure object is returned if GC is needed.
Steve Block9fac8402011-05-12 15:51:54 +01001585 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1586 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001587 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01001588 bool check_prototype = true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001589
1590 // Returns the index'th element.
1591 // The undefined object if index is out of bounds.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001592 MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
1593 MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
1594
1595 // Get external element value at index if there is one and undefined
1596 // otherwise. Can return a failure if allocation of a heap number
1597 // failed.
1598 MaybeObject* GetExternalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001599
John Reck59135872010-11-02 12:39:01 -07001600 MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity,
1601 int length);
1602 MUST_USE_RESULT MaybeObject* SetSlowElements(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001603
1604 // Lookup interceptors are used for handling properties controlled by host
1605 // objects.
1606 inline bool HasNamedInterceptor();
1607 inline bool HasIndexedInterceptor();
1608
1609 // Support functions for v8 api (needed for correct interceptor behavior).
1610 bool HasRealNamedProperty(String* key);
1611 bool HasRealElementProperty(uint32_t index);
1612 bool HasRealNamedCallbackProperty(String* key);
1613
1614 // Initializes the array to a certain length
John Reck59135872010-11-02 12:39:01 -07001615 MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001616
1617 // Get the header size for a JSObject. Used to compute the index of
1618 // internal fields as well as the number of internal fields.
1619 inline int GetHeaderSize();
1620
1621 inline int GetInternalFieldCount();
Steve Block44f0eee2011-05-26 01:26:41 +01001622 inline int GetInternalFieldOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001623 inline Object* GetInternalField(int index);
1624 inline void SetInternalField(int index, Object* value);
1625
1626 // Lookup a property. If found, the result is valid and has
1627 // detailed information.
1628 void LocalLookup(String* name, LookupResult* result);
1629 void Lookup(String* name, LookupResult* result);
1630
1631 // The following lookup functions skip interceptors.
1632 void LocalLookupRealNamedProperty(String* name, LookupResult* result);
1633 void LookupRealNamedProperty(String* name, LookupResult* result);
1634 void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
1635 void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
Steve Block1e0659c2011-05-24 12:43:12 +01001636 MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
1637 uint32_t index, Object* value, bool* found);
Steve Blocka7e24c12009-10-30 11:49:00 +00001638 void LookupCallback(String* name, LookupResult* result);
1639
1640 // Returns the number of properties on this object filtering out properties
1641 // with the specified attributes (ignoring interceptors).
1642 int NumberOfLocalProperties(PropertyAttributes filter);
1643 // Returns the number of enumerable properties (ignoring interceptors).
1644 int NumberOfEnumProperties();
1645 // Fill in details for properties into storage starting at the specified
1646 // index.
1647 void GetLocalPropertyNames(FixedArray* storage, int index);
1648
1649 // Returns the number of properties on this object filtering out properties
1650 // with the specified attributes (ignoring interceptors).
1651 int NumberOfLocalElements(PropertyAttributes filter);
1652 // Returns the number of enumerable elements (ignoring interceptors).
1653 int NumberOfEnumElements();
1654 // Returns the number of elements on this object filtering out elements
1655 // with the specified attributes (ignoring interceptors).
1656 int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
1657 // Count and fill in the enumerable elements into storage.
1658 // (storage->length() == NumberOfEnumElements()).
1659 // If storage is NULL, will count the elements without adding
1660 // them to any storage.
1661 // Returns the number of enumerable elements.
1662 int GetEnumElementKeys(FixedArray* storage);
1663
1664 // Add a property to a fast-case object using a map transition to
1665 // new_map.
John Reck59135872010-11-02 12:39:01 -07001666 MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
1667 String* name,
1668 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001669
1670 // Add a constant function property to a fast-case object.
1671 // This leaves a CONSTANT_TRANSITION in the old map, and
1672 // if it is called on a second object with this map, a
1673 // normal property is added instead, with a map transition.
1674 // This avoids the creation of many maps with the same constant
1675 // function, all orphaned.
John Reck59135872010-11-02 12:39:01 -07001676 MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
1677 String* name,
1678 JSFunction* function,
1679 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001680
John Reck59135872010-11-02 12:39:01 -07001681 MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
1682 String* name,
1683 Object* value,
1684 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001685
1686 // Converts a descriptor of any other type to a real field,
1687 // backed by the properties array. Descriptors of visible
1688 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1689 // Converts the descriptor on the original object's map to a
1690 // map transition, and the the new field is on the object's new map.
John Reck59135872010-11-02 12:39:01 -07001691 MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
Steve Blocka7e24c12009-10-30 11:49:00 +00001692 String* name,
1693 Object* new_value,
1694 PropertyAttributes attributes);
1695
1696 // Converts a descriptor of any other type to a real field,
1697 // backed by the properties array. Descriptors of visible
1698 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
John Reck59135872010-11-02 12:39:01 -07001699 MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
1700 String* name,
1701 Object* new_value,
1702 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001703
1704 // Add a property to a fast-case object.
John Reck59135872010-11-02 12:39:01 -07001705 MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
1706 Object* value,
1707 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001708
1709 // Add a property to a slow-case object.
John Reck59135872010-11-02 12:39:01 -07001710 MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
1711 Object* value,
1712 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001713
1714 // Add a property to an object.
John Reck59135872010-11-02 12:39:01 -07001715 MUST_USE_RESULT MaybeObject* AddProperty(String* name,
1716 Object* value,
Steve Block44f0eee2011-05-26 01:26:41 +01001717 PropertyAttributes attributes,
1718 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001719
1720 // Convert the object to use the canonical dictionary
1721 // representation. If the object is expected to have additional properties
1722 // added this number can be indicated to have the backing store allocated to
1723 // an initial capacity for holding these properties.
John Reck59135872010-11-02 12:39:01 -07001724 MUST_USE_RESULT MaybeObject* NormalizeProperties(
1725 PropertyNormalizationMode mode,
1726 int expected_additional_properties);
1727 MUST_USE_RESULT MaybeObject* NormalizeElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001728
John Reck59135872010-11-02 12:39:01 -07001729 MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001730
Steve Blocka7e24c12009-10-30 11:49:00 +00001731 // Transform slow named properties to fast variants.
1732 // Returns failure if allocation failed.
John Reck59135872010-11-02 12:39:01 -07001733 MUST_USE_RESULT MaybeObject* TransformToFastProperties(
1734 int unused_property_fields);
Steve Blocka7e24c12009-10-30 11:49:00 +00001735
1736 // Access fast-case object properties at index.
1737 inline Object* FastPropertyAt(int index);
1738 inline Object* FastPropertyAtPut(int index, Object* value);
1739
1740 // Access to in object properties.
Steve Block44f0eee2011-05-26 01:26:41 +01001741 inline int GetInObjectPropertyOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001742 inline Object* InObjectPropertyAt(int index);
1743 inline Object* InObjectPropertyAtPut(int index,
1744 Object* value,
1745 WriteBarrierMode mode
1746 = UPDATE_WRITE_BARRIER);
1747
1748 // initializes the body after properties slot, properties slot is
1749 // initialized by set_properties
1750 // Note: this call does not update write barrier, it is caller's
1751 // reponsibility to ensure that *v* can be collected without WB here.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001752 inline void InitializeBody(int object_size, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001753
1754 // Check whether this object references another object
1755 bool ReferencesObject(Object* obj);
1756
1757 // Casting.
1758 static inline JSObject* cast(Object* obj);
1759
Steve Block8defd9f2010-07-08 12:39:36 +01001760 // Disalow further properties to be added to the object.
John Reck59135872010-11-02 12:39:01 -07001761 MUST_USE_RESULT MaybeObject* PreventExtensions();
Steve Block8defd9f2010-07-08 12:39:36 +01001762
1763
Steve Blocka7e24c12009-10-30 11:49:00 +00001764 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 void JSObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001766#ifdef OBJECT_PRINT
1767 inline void JSObjectPrint() {
1768 JSObjectPrint(stdout);
1769 }
1770 void JSObjectPrint(FILE* out);
1771#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001772#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001773 void JSObjectVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001774#endif
1775#ifdef OBJECT_PRINT
1776 inline void PrintProperties() {
1777 PrintProperties(stdout);
1778 }
1779 void PrintProperties(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001780
Ben Murdochb0fe1622011-05-05 13:52:32 +01001781 inline void PrintElements() {
1782 PrintElements(stdout);
1783 }
1784 void PrintElements(FILE* out);
1785#endif
1786
1787#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001788 // Structure for collecting spill information about JSObjects.
1789 class SpillInformation {
1790 public:
1791 void Clear();
1792 void Print();
1793 int number_of_objects_;
1794 int number_of_objects_with_fast_properties_;
1795 int number_of_objects_with_fast_elements_;
1796 int number_of_fast_used_fields_;
1797 int number_of_fast_unused_fields_;
1798 int number_of_slow_used_properties_;
1799 int number_of_slow_unused_properties_;
1800 int number_of_fast_used_elements_;
1801 int number_of_fast_unused_elements_;
1802 int number_of_slow_used_elements_;
1803 int number_of_slow_unused_elements_;
1804 };
1805
1806 void IncrementSpillStatistics(SpillInformation* info);
1807#endif
1808 Object* SlowReverseLookup(Object* value);
1809
Steve Block8defd9f2010-07-08 12:39:36 +01001810 // Maximal number of fast properties for the JSObject. Used to
1811 // restrict the number of map transitions to avoid an explosion in
1812 // the number of maps for objects used as dictionaries.
1813 inline int MaxFastProperties();
1814
Leon Clarkee46be812010-01-19 14:06:41 +00001815 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
1816 // Also maximal value of JSArray's length property.
1817 static const uint32_t kMaxElementCount = 0xffffffffu;
1818
Steve Blocka7e24c12009-10-30 11:49:00 +00001819 static const uint32_t kMaxGap = 1024;
1820 static const int kMaxFastElementsLength = 5000;
1821 static const int kInitialMaxFastElementArray = 100000;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001822 static const int kMaxFastProperties = 12;
Steve Blocka7e24c12009-10-30 11:49:00 +00001823 static const int kMaxInstanceSize = 255 * kPointerSize;
1824 // When extending the backing storage for property values, we increase
1825 // its size by more than the 1 entry necessary, so sequentially adding fields
1826 // to the same object requires fewer allocations and copies.
1827 static const int kFieldsAdded = 3;
1828
1829 // Layout description.
1830 static const int kPropertiesOffset = HeapObject::kHeaderSize;
1831 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
1832 static const int kHeaderSize = kElementsOffset + kPointerSize;
1833
1834 STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
1835
Iain Merrick75681382010-08-19 15:07:18 +01001836 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
1837 public:
1838 static inline int SizeOf(Map* map, HeapObject* object);
1839 };
1840
Steve Blocka7e24c12009-10-30 11:49:00 +00001841 private:
John Reck59135872010-11-02 12:39:01 -07001842 MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
1843 Object* structure,
1844 uint32_t index,
1845 Object* holder);
1846 MaybeObject* SetElementWithCallback(Object* structure,
1847 uint32_t index,
1848 Object* value,
1849 JSObject* holder);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001850 MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
1851 uint32_t index,
1852 Object* value,
1853 StrictModeFlag strict_mode,
1854 bool check_prototype);
Steve Block9fac8402011-05-12 15:51:54 +01001855 MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
1856 uint32_t index,
1857 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001858 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01001859 bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00001860
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001861 MaybeObject* GetElementPostInterceptor(Object* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001862
John Reck59135872010-11-02 12:39:01 -07001863 MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
1864 DeleteMode mode);
1865 MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001866
John Reck59135872010-11-02 12:39:01 -07001867 MUST_USE_RESULT MaybeObject* DeleteElementPostInterceptor(uint32_t index,
1868 DeleteMode mode);
1869 MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001870
1871 PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
1872 String* name,
1873 bool continue_search);
1874 PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
1875 String* name,
1876 bool continue_search);
1877 PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
1878 Object* receiver,
1879 LookupResult* result,
1880 String* name,
1881 bool continue_search);
1882 PropertyAttributes GetPropertyAttribute(JSObject* receiver,
1883 LookupResult* result,
1884 String* name,
1885 bool continue_search);
1886
1887 // Returns true if most of the elements backing storage is used.
1888 bool HasDenseElements();
1889
Leon Clarkef7060e22010-06-03 12:02:55 +01001890 bool CanSetCallback(String* name);
John Reck59135872010-11-02 12:39:01 -07001891 MUST_USE_RESULT MaybeObject* SetElementCallback(
1892 uint32_t index,
1893 Object* structure,
1894 PropertyAttributes attributes);
1895 MUST_USE_RESULT MaybeObject* SetPropertyCallback(
1896 String* name,
1897 Object* structure,
1898 PropertyAttributes attributes);
1899 MUST_USE_RESULT MaybeObject* DefineGetterSetter(
1900 String* name,
1901 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001902
1903 void LookupInDescriptor(String* name, LookupResult* result);
1904
1905 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
1906};
1907
1908
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001909// FixedArray describes fixed-sized arrays with element type Object*.
1910class FixedArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001911 public:
1912 // [length]: length of the array.
1913 inline int length();
1914 inline void set_length(int value);
1915
Steve Blocka7e24c12009-10-30 11:49:00 +00001916 // Setter and getter for elements.
1917 inline Object* get(int index);
1918 // Setter that uses write barrier.
1919 inline void set(int index, Object* value);
1920
1921 // Setter that doesn't need write barrier).
1922 inline void set(int index, Smi* value);
1923 // Setter with explicit barrier mode.
1924 inline void set(int index, Object* value, WriteBarrierMode mode);
1925
1926 // Setters for frequently used oddballs located in old space.
1927 inline void set_undefined(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01001928 // TODO(isolates): duplicate.
1929 inline void set_undefined(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001930 inline void set_null(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01001931 // TODO(isolates): duplicate.
1932 inline void set_null(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001933 inline void set_the_hole(int index);
1934
Iain Merrick75681382010-08-19 15:07:18 +01001935 // Setters with less debug checks for the GC to use.
1936 inline void set_unchecked(int index, Smi* value);
Steve Block44f0eee2011-05-26 01:26:41 +01001937 inline void set_null_unchecked(Heap* heap, int index);
1938 inline void set_unchecked(Heap* heap, int index, Object* value,
1939 WriteBarrierMode mode);
Iain Merrick75681382010-08-19 15:07:18 +01001940
Steve Block6ded16b2010-05-10 14:33:55 +01001941 // Gives access to raw memory which stores the array's data.
1942 inline Object** data_start();
1943
Steve Blocka7e24c12009-10-30 11:49:00 +00001944 // Copy operations.
John Reck59135872010-11-02 12:39:01 -07001945 MUST_USE_RESULT inline MaybeObject* Copy();
1946 MUST_USE_RESULT MaybeObject* CopySize(int new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001947
1948 // Add the elements of a JSArray to this FixedArray.
John Reck59135872010-11-02 12:39:01 -07001949 MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001950
1951 // Compute the union of this and other.
John Reck59135872010-11-02 12:39:01 -07001952 MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
Steve Blocka7e24c12009-10-30 11:49:00 +00001953
1954 // Copy a sub array from the receiver to dest.
1955 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
1956
1957 // Garbage collection support.
1958 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
1959
1960 // Code Generation support.
1961 static int OffsetOfElementAt(int index) { return SizeFor(index); }
1962
1963 // Casting.
1964 static inline FixedArray* cast(Object* obj);
1965
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001966 // Layout description.
1967 // Length is smi tagged when it is stored.
1968 static const int kLengthOffset = HeapObject::kHeaderSize;
1969 static const int kHeaderSize = kLengthOffset + kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00001970
1971 // Maximal allowed size, in bytes, of a single FixedArray.
1972 // Prevents overflowing size computations, as well as extreme memory
1973 // consumption.
1974 static const int kMaxSize = 512 * MB;
1975 // Maximally allowed length of a FixedArray.
1976 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001977
1978 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001979#ifdef OBJECT_PRINT
1980 inline void FixedArrayPrint() {
1981 FixedArrayPrint(stdout);
1982 }
1983 void FixedArrayPrint(FILE* out);
1984#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001985#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001986 void FixedArrayVerify();
1987 // Checks if two FixedArrays have identical contents.
1988 bool IsEqualTo(FixedArray* other);
1989#endif
1990
1991 // Swap two elements in a pair of arrays. If this array and the
1992 // numbers array are the same object, the elements are only swapped
1993 // once.
1994 void SwapPairs(FixedArray* numbers, int i, int j);
1995
1996 // Sort prefix of this array and the numbers array as pairs wrt. the
1997 // numbers. If the numbers array and the this array are the same
1998 // object, the prefix of this array is sorted.
1999 void SortPairs(FixedArray* numbers, uint32_t len);
2000
Iain Merrick75681382010-08-19 15:07:18 +01002001 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
2002 public:
2003 static inline int SizeOf(Map* map, HeapObject* object) {
2004 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
2005 }
2006 };
2007
Steve Blocka7e24c12009-10-30 11:49:00 +00002008 protected:
Leon Clarke4515c472010-02-03 11:58:03 +00002009 // Set operation on FixedArray without using write barriers. Can
2010 // only be used for storing old space objects or smis.
Steve Blocka7e24c12009-10-30 11:49:00 +00002011 static inline void fast_set(FixedArray* array, int index, Object* value);
2012
2013 private:
2014 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
2015};
2016
2017
2018// DescriptorArrays are fixed arrays used to hold instance descriptors.
2019// The format of the these objects is:
2020// [0]: point to a fixed array with (value, detail) pairs.
2021// [1]: next enumeration index (Smi), or pointer to small fixed array:
2022// [0]: next enumeration index (Smi)
2023// [1]: pointer to fixed array with enum cache
2024// [2]: first key
2025// [length() - 1]: last key
2026//
2027class DescriptorArray: public FixedArray {
2028 public:
2029 // Is this the singleton empty_descriptor_array?
2030 inline bool IsEmpty();
Leon Clarkee46be812010-01-19 14:06:41 +00002031
Steve Blocka7e24c12009-10-30 11:49:00 +00002032 // Returns the number of descriptors in the array.
2033 int number_of_descriptors() {
Steve Block44f0eee2011-05-26 01:26:41 +01002034 ASSERT(length() > kFirstIndex || IsEmpty());
2035 int len = length();
2036 return len <= kFirstIndex ? 0 : len - kFirstIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00002037 }
2038
2039 int NextEnumerationIndex() {
2040 if (IsEmpty()) return PropertyDetails::kInitialIndex;
2041 Object* obj = get(kEnumerationIndexIndex);
2042 if (obj->IsSmi()) {
2043 return Smi::cast(obj)->value();
2044 } else {
2045 Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
2046 return Smi::cast(index)->value();
2047 }
2048 }
2049
2050 // Set next enumeration index and flush any enum cache.
2051 void SetNextEnumerationIndex(int value) {
2052 if (!IsEmpty()) {
2053 fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
2054 }
2055 }
2056 bool HasEnumCache() {
2057 return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
2058 }
2059
2060 Object* GetEnumCache() {
2061 ASSERT(HasEnumCache());
2062 FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
2063 return bridge->get(kEnumCacheBridgeCacheIndex);
2064 }
2065
2066 // Initialize or change the enum cache,
2067 // using the supplied storage for the small "bridge".
2068 void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
2069
2070 // Accessors for fetching instance descriptor at descriptor number.
2071 inline String* GetKey(int descriptor_number);
2072 inline Object* GetValue(int descriptor_number);
2073 inline Smi* GetDetails(int descriptor_number);
2074 inline PropertyType GetType(int descriptor_number);
2075 inline int GetFieldIndex(int descriptor_number);
2076 inline JSFunction* GetConstantFunction(int descriptor_number);
2077 inline Object* GetCallbacksObject(int descriptor_number);
2078 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
2079 inline bool IsProperty(int descriptor_number);
2080 inline bool IsTransition(int descriptor_number);
2081 inline bool IsNullDescriptor(int descriptor_number);
2082 inline bool IsDontEnum(int descriptor_number);
2083
2084 // Accessor for complete descriptor.
2085 inline void Get(int descriptor_number, Descriptor* desc);
2086 inline void Set(int descriptor_number, Descriptor* desc);
2087
2088 // Transfer complete descriptor from another descriptor array to
2089 // this one.
2090 inline void CopyFrom(int index, DescriptorArray* src, int src_index);
2091
2092 // Copy the descriptor array, insert a new descriptor and optionally
2093 // remove map transitions. If the descriptor is already present, it is
2094 // replaced. If a replaced descriptor is a real property (not a transition
2095 // or null), its enumeration index is kept as is.
2096 // If adding a real property, map transitions must be removed. If adding
2097 // a transition, they must not be removed. All null descriptors are removed.
John Reck59135872010-11-02 12:39:01 -07002098 MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
2099 TransitionFlag transition_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +00002100
2101 // Remove all transitions. Return a copy of the array with all transitions
2102 // removed, or a Failure object if the new array could not be allocated.
John Reck59135872010-11-02 12:39:01 -07002103 MUST_USE_RESULT MaybeObject* RemoveTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002104
2105 // Sort the instance descriptors by the hash codes of their keys.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002106 // Does not check for duplicates.
2107 void SortUnchecked();
2108
2109 // Sort the instance descriptors by the hash codes of their keys.
2110 // Checks the result for duplicates.
Steve Blocka7e24c12009-10-30 11:49:00 +00002111 void Sort();
2112
2113 // Search the instance descriptors for given name.
2114 inline int Search(String* name);
2115
Iain Merrick75681382010-08-19 15:07:18 +01002116 // As the above, but uses DescriptorLookupCache and updates it when
2117 // necessary.
2118 inline int SearchWithCache(String* name);
2119
Steve Blocka7e24c12009-10-30 11:49:00 +00002120 // Tells whether the name is present int the array.
2121 bool Contains(String* name) { return kNotFound != Search(name); }
2122
2123 // Perform a binary search in the instance descriptors represented
2124 // by this fixed array. low and high are descriptor indices. If there
2125 // are three instance descriptors in this array it should be called
2126 // with low=0 and high=2.
2127 int BinarySearch(String* name, int low, int high);
2128
2129 // Perform a linear search in the instance descriptors represented
2130 // by this fixed array. len is the number of descriptor indices that are
2131 // valid. Does not require the descriptors to be sorted.
2132 int LinearSearch(String* name, int len);
2133
2134 // Allocates a DescriptorArray, but returns the singleton
2135 // empty descriptor array object if number_of_descriptors is 0.
John Reck59135872010-11-02 12:39:01 -07002136 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
Steve Blocka7e24c12009-10-30 11:49:00 +00002137
2138 // Casting.
2139 static inline DescriptorArray* cast(Object* obj);
2140
2141 // Constant for denoting key was not found.
2142 static const int kNotFound = -1;
2143
2144 static const int kContentArrayIndex = 0;
2145 static const int kEnumerationIndexIndex = 1;
2146 static const int kFirstIndex = 2;
2147
2148 // The length of the "bridge" to the enum cache.
2149 static const int kEnumCacheBridgeLength = 2;
2150 static const int kEnumCacheBridgeEnumIndex = 0;
2151 static const int kEnumCacheBridgeCacheIndex = 1;
2152
2153 // Layout description.
2154 static const int kContentArrayOffset = FixedArray::kHeaderSize;
2155 static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
2156 static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
2157
2158 // Layout description for the bridge array.
2159 static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
2160 static const int kEnumCacheBridgeCacheOffset =
2161 kEnumCacheBridgeEnumOffset + kPointerSize;
2162
Ben Murdochb0fe1622011-05-05 13:52:32 +01002163#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +00002164 // Print all the descriptors.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002165 inline void PrintDescriptors() {
2166 PrintDescriptors(stdout);
2167 }
2168 void PrintDescriptors(FILE* out);
2169#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002170
Ben Murdochb0fe1622011-05-05 13:52:32 +01002171#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002172 // Is the descriptor array sorted and without duplicates?
2173 bool IsSortedNoDuplicates();
2174
2175 // Are two DescriptorArrays equal?
2176 bool IsEqualTo(DescriptorArray* other);
2177#endif
2178
2179 // The maximum number of descriptors we want in a descriptor array (should
2180 // fit in a page).
2181 static const int kMaxNumberOfDescriptors = 1024 + 512;
2182
2183 private:
2184 // Conversion from descriptor number to array indices.
2185 static int ToKeyIndex(int descriptor_number) {
2186 return descriptor_number+kFirstIndex;
2187 }
Leon Clarkee46be812010-01-19 14:06:41 +00002188
2189 static int ToDetailsIndex(int descriptor_number) {
2190 return (descriptor_number << 1) + 1;
2191 }
2192
Steve Blocka7e24c12009-10-30 11:49:00 +00002193 static int ToValueIndex(int descriptor_number) {
2194 return descriptor_number << 1;
2195 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002196
2197 bool is_null_descriptor(int descriptor_number) {
2198 return PropertyDetails(GetDetails(descriptor_number)).type() ==
2199 NULL_DESCRIPTOR;
2200 }
2201 // Swap operation on FixedArray without using write barriers.
2202 static inline void fast_swap(FixedArray* array, int first, int second);
2203
2204 // Swap descriptor first and second.
2205 inline void Swap(int first, int second);
2206
2207 FixedArray* GetContentArray() {
2208 return FixedArray::cast(get(kContentArrayIndex));
2209 }
2210 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
2211};
2212
2213
2214// HashTable is a subclass of FixedArray that implements a hash table
2215// that uses open addressing and quadratic probing.
2216//
2217// In order for the quadratic probing to work, elements that have not
2218// yet been used and elements that have been deleted are
2219// distinguished. Probing continues when deleted elements are
2220// encountered and stops when unused elements are encountered.
2221//
2222// - Elements with key == undefined have not been used yet.
2223// - Elements with key == null have been deleted.
2224//
2225// The hash table class is parameterized with a Shape and a Key.
2226// Shape must be a class with the following interface:
2227// class ExampleShape {
2228// public:
2229// // Tells whether key matches other.
2230// static bool IsMatch(Key key, Object* other);
2231// // Returns the hash value for key.
2232// static uint32_t Hash(Key key);
2233// // Returns the hash value for object.
2234// static uint32_t HashForObject(Key key, Object* object);
2235// // Convert key to an object.
2236// static inline Object* AsObject(Key key);
2237// // The prefix size indicates number of elements in the beginning
2238// // of the backing storage.
2239// static const int kPrefixSize = ..;
2240// // The Element size indicates number of elements per entry.
2241// static const int kEntrySize = ..;
2242// };
Steve Block3ce2e202009-11-05 08:53:23 +00002243// The prefix size indicates an amount of memory in the
Steve Blocka7e24c12009-10-30 11:49:00 +00002244// beginning of the backing storage that can be used for non-element
2245// information by subclasses.
2246
2247template<typename Shape, typename Key>
2248class HashTable: public FixedArray {
2249 public:
Steve Block3ce2e202009-11-05 08:53:23 +00002250 // Returns the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002251 int NumberOfElements() {
2252 return Smi::cast(get(kNumberOfElementsIndex))->value();
2253 }
2254
Leon Clarkee46be812010-01-19 14:06:41 +00002255 // Returns the number of deleted elements in the hash table.
2256 int NumberOfDeletedElements() {
2257 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
2258 }
2259
Steve Block3ce2e202009-11-05 08:53:23 +00002260 // Returns the capacity of the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002261 int Capacity() {
2262 return Smi::cast(get(kCapacityIndex))->value();
2263 }
2264
2265 // ElementAdded should be called whenever an element is added to a
Steve Block3ce2e202009-11-05 08:53:23 +00002266 // hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002267 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
2268
2269 // ElementRemoved should be called whenever an element is removed from
Steve Block3ce2e202009-11-05 08:53:23 +00002270 // a hash table.
Leon Clarkee46be812010-01-19 14:06:41 +00002271 void ElementRemoved() {
2272 SetNumberOfElements(NumberOfElements() - 1);
2273 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
2274 }
2275 void ElementsRemoved(int n) {
2276 SetNumberOfElements(NumberOfElements() - n);
2277 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
2278 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002279
Steve Block3ce2e202009-11-05 08:53:23 +00002280 // Returns a new HashTable object. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002281 MUST_USE_RESULT static MaybeObject* Allocate(
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002282 int at_least_space_for,
2283 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002284
2285 // Returns the key at entry.
2286 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
2287
2288 // Tells whether k is a real key. Null and undefined are not allowed
2289 // as keys and can be used to indicate missing or deleted elements.
2290 bool IsKey(Object* k) {
2291 return !k->IsNull() && !k->IsUndefined();
2292 }
2293
2294 // Garbage collection support.
2295 void IteratePrefix(ObjectVisitor* visitor);
2296 void IterateElements(ObjectVisitor* visitor);
2297
2298 // Casting.
2299 static inline HashTable* cast(Object* obj);
2300
2301 // Compute the probe offset (quadratic probing).
2302 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
2303 return (n + n * n) >> 1;
2304 }
2305
2306 static const int kNumberOfElementsIndex = 0;
Leon Clarkee46be812010-01-19 14:06:41 +00002307 static const int kNumberOfDeletedElementsIndex = 1;
2308 static const int kCapacityIndex = 2;
2309 static const int kPrefixStartIndex = 3;
2310 static const int kElementsStartIndex =
Steve Blocka7e24c12009-10-30 11:49:00 +00002311 kPrefixStartIndex + Shape::kPrefixSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002312 static const int kEntrySize = Shape::kEntrySize;
2313 static const int kElementsStartOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00002314 kHeaderSize + kElementsStartIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01002315 static const int kCapacityOffset =
2316 kHeaderSize + kCapacityIndex * kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002317
2318 // Constant used for denoting a absent entry.
2319 static const int kNotFound = -1;
2320
Leon Clarkee46be812010-01-19 14:06:41 +00002321 // Maximal capacity of HashTable. Based on maximal length of underlying
2322 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
2323 // cannot overflow.
2324 static const int kMaxCapacity =
2325 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
2326
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002327 // Find entry for key otherwise return kNotFound.
Steve Block44f0eee2011-05-26 01:26:41 +01002328 inline int FindEntry(Key key);
2329 int FindEntry(Isolate* isolate, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002330
2331 protected:
2332
2333 // Find the entry at which to insert element with the given key that
2334 // has the given hash value.
2335 uint32_t FindInsertionEntry(uint32_t hash);
2336
2337 // Returns the index for an entry (of the key)
2338 static inline int EntryToIndex(int entry) {
2339 return (entry * kEntrySize) + kElementsStartIndex;
2340 }
2341
Steve Block3ce2e202009-11-05 08:53:23 +00002342 // Update the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002343 void SetNumberOfElements(int nof) {
2344 fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
2345 }
2346
Leon Clarkee46be812010-01-19 14:06:41 +00002347 // Update the number of deleted elements in the hash table.
2348 void SetNumberOfDeletedElements(int nod) {
2349 fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
2350 }
2351
Steve Blocka7e24c12009-10-30 11:49:00 +00002352 // Sets the capacity of the hash table.
2353 void SetCapacity(int capacity) {
2354 // To scale a computed hash code to fit within the hash table, we
2355 // use bit-wise AND with a mask, so the capacity must be positive
2356 // and non-zero.
2357 ASSERT(capacity > 0);
Leon Clarkee46be812010-01-19 14:06:41 +00002358 ASSERT(capacity <= kMaxCapacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00002359 fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
2360 }
2361
2362
2363 // Returns probe entry.
2364 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
2365 ASSERT(IsPowerOf2(size));
2366 return (hash + GetProbeOffset(number)) & (size - 1);
2367 }
2368
Leon Clarkee46be812010-01-19 14:06:41 +00002369 static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
2370 return hash & (size - 1);
2371 }
2372
2373 static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
2374 return (last + number) & (size - 1);
2375 }
2376
Steve Blocka7e24c12009-10-30 11:49:00 +00002377 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002378 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002379};
2380
2381
2382
2383// HashTableKey is an abstract superclass for virtual key behavior.
2384class HashTableKey {
2385 public:
2386 // Returns whether the other object matches this key.
2387 virtual bool IsMatch(Object* other) = 0;
2388 // Returns the hash value for this key.
2389 virtual uint32_t Hash() = 0;
2390 // Returns the hash value for object.
2391 virtual uint32_t HashForObject(Object* key) = 0;
Steve Block3ce2e202009-11-05 08:53:23 +00002392 // Returns the key object for storing into the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002393 // If allocations fails a failure object is returned.
John Reck59135872010-11-02 12:39:01 -07002394 MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002395 // Required.
2396 virtual ~HashTableKey() {}
2397};
2398
2399class SymbolTableShape {
2400 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002401 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002402 return key->IsMatch(value);
2403 }
Steve Block44f0eee2011-05-26 01:26:41 +01002404 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002405 return key->Hash();
2406 }
Steve Block44f0eee2011-05-26 01:26:41 +01002407 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002408 return key->HashForObject(object);
2409 }
Steve Block44f0eee2011-05-26 01:26:41 +01002410 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002411 return key->AsObject();
2412 }
2413
2414 static const int kPrefixSize = 0;
2415 static const int kEntrySize = 1;
2416};
2417
2418// SymbolTable.
2419//
2420// No special elements in the prefix and the element size is 1
2421// because only the symbol itself (the key) needs to be stored.
2422class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
2423 public:
2424 // Find symbol in the symbol table. If it is not there yet, it is
2425 // added. The return value is the symbol table which might have
2426 // been enlarged. If the return value is not a failure, the symbol
2427 // pointer *s is set to the symbol found.
John Reck59135872010-11-02 12:39:01 -07002428 MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
Steve Block9fac8402011-05-12 15:51:54 +01002429 MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
2430 Object** s);
2431 MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
2432 Object** s);
John Reck59135872010-11-02 12:39:01 -07002433 MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002434
2435 // Looks up a symbol that is equal to the given string and returns
2436 // true if it is found, assigning the symbol to the given output
2437 // parameter.
2438 bool LookupSymbolIfExists(String* str, String** symbol);
Steve Blockd0582a62009-12-15 09:54:21 +00002439 bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002440
2441 // Casting.
2442 static inline SymbolTable* cast(Object* obj);
2443
2444 private:
John Reck59135872010-11-02 12:39:01 -07002445 MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002446
2447 DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
2448};
2449
2450
2451class MapCacheShape {
2452 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002453 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002454 return key->IsMatch(value);
2455 }
Steve Block44f0eee2011-05-26 01:26:41 +01002456 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002457 return key->Hash();
2458 }
2459
Steve Block44f0eee2011-05-26 01:26:41 +01002460 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002461 return key->HashForObject(object);
2462 }
2463
Steve Block44f0eee2011-05-26 01:26:41 +01002464 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002465 return key->AsObject();
2466 }
2467
2468 static const int kPrefixSize = 0;
2469 static const int kEntrySize = 2;
2470};
2471
2472
2473// MapCache.
2474//
2475// Maps keys that are a fixed array of symbols to a map.
2476// Used for canonicalize maps for object literals.
2477class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
2478 public:
2479 // Find cached value for a string key, otherwise return null.
2480 Object* Lookup(FixedArray* key);
John Reck59135872010-11-02 12:39:01 -07002481 MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002482 static inline MapCache* cast(Object* obj);
2483
2484 private:
2485 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
2486};
2487
2488
2489template <typename Shape, typename Key>
2490class Dictionary: public HashTable<Shape, Key> {
2491 public:
2492
2493 static inline Dictionary<Shape, Key>* cast(Object* obj) {
2494 return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
2495 }
2496
2497 // Returns the value at entry.
2498 Object* ValueAt(int entry) {
Steve Block6ded16b2010-05-10 14:33:55 +01002499 return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002500 }
2501
2502 // Set the value for entry.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002503 // Returns false if the put wasn't performed due to property being read only.
2504 // Returns true on successful put.
2505 bool ValueAtPut(int entry, Object* value) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002506 // Check that this value can actually be written.
2507 PropertyDetails details = DetailsAt(entry);
2508 // If a value has not been initilized we allow writing to it even if
2509 // it is read only (a declared const that has not been initialized).
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002510 if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
2511 return false;
2512 }
2513 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
2514 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002515 }
2516
2517 // Returns the property details for the property at entry.
2518 PropertyDetails DetailsAt(int entry) {
2519 ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
2520 return PropertyDetails(
Steve Block6ded16b2010-05-10 14:33:55 +01002521 Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002522 }
2523
2524 // Set the details for entry.
2525 void DetailsAtPut(int entry, PropertyDetails value) {
Steve Block6ded16b2010-05-10 14:33:55 +01002526 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002527 }
2528
2529 // Sorting support
2530 void CopyValuesTo(FixedArray* elements);
2531
2532 // Delete a property from the dictionary.
2533 Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
2534
2535 // Returns the number of elements in the dictionary filtering out properties
2536 // with the specified attributes.
2537 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
2538
2539 // Returns the number of enumerable elements in the dictionary.
2540 int NumberOfEnumElements();
2541
2542 // Copies keys to preallocated fixed array.
2543 void CopyKeysTo(FixedArray* storage, PropertyAttributes filter);
2544 // Fill in details for properties into storage.
2545 void CopyKeysTo(FixedArray* storage);
2546
2547 // Accessors for next enumeration index.
2548 void SetNextEnumerationIndex(int index) {
Steve Block6ded16b2010-05-10 14:33:55 +01002549 this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00002550 }
2551
2552 int NextEnumerationIndex() {
2553 return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
2554 }
2555
2556 // Returns a new array for dictionary usage. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002557 MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
Steve Blocka7e24c12009-10-30 11:49:00 +00002558
2559 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002560 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002561
Ben Murdochb0fe1622011-05-05 13:52:32 +01002562#ifdef OBJECT_PRINT
2563 inline void Print() {
2564 Print(stdout);
2565 }
2566 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00002567#endif
2568 // Returns the key (slow).
2569 Object* SlowReverseLookup(Object* value);
2570
2571 // Sets the entry to (key, value) pair.
2572 inline void SetEntry(int entry,
2573 Object* key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002574 Object* value);
2575 inline void SetEntry(int entry,
2576 Object* key,
Steve Blocka7e24c12009-10-30 11:49:00 +00002577 Object* value,
2578 PropertyDetails details);
2579
John Reck59135872010-11-02 12:39:01 -07002580 MUST_USE_RESULT MaybeObject* Add(Key key,
2581 Object* value,
2582 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002583
2584 protected:
2585 // Generic at put operation.
John Reck59135872010-11-02 12:39:01 -07002586 MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002587
2588 // Add entry to dictionary.
John Reck59135872010-11-02 12:39:01 -07002589 MUST_USE_RESULT MaybeObject* AddEntry(Key key,
2590 Object* value,
2591 PropertyDetails details,
2592 uint32_t hash);
Steve Blocka7e24c12009-10-30 11:49:00 +00002593
2594 // Generate new enumeration indices to avoid enumeration index overflow.
John Reck59135872010-11-02 12:39:01 -07002595 MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
Steve Blocka7e24c12009-10-30 11:49:00 +00002596 static const int kMaxNumberKeyIndex =
2597 HashTable<Shape, Key>::kPrefixStartIndex;
2598 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
2599};
2600
2601
2602class StringDictionaryShape {
2603 public:
2604 static inline bool IsMatch(String* key, Object* other);
2605 static inline uint32_t Hash(String* key);
2606 static inline uint32_t HashForObject(String* key, Object* object);
John Reck59135872010-11-02 12:39:01 -07002607 MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002608 static const int kPrefixSize = 2;
2609 static const int kEntrySize = 3;
2610 static const bool kIsEnumerable = true;
2611};
2612
2613
2614class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
2615 public:
2616 static inline StringDictionary* cast(Object* obj) {
2617 ASSERT(obj->IsDictionary());
2618 return reinterpret_cast<StringDictionary*>(obj);
2619 }
2620
2621 // Copies enumerable keys to preallocated fixed array.
2622 void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
2623
2624 // For transforming properties of a JSObject.
John Reck59135872010-11-02 12:39:01 -07002625 MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
2626 JSObject* obj,
2627 int unused_property_fields);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002628
2629 // Find entry for key otherwise return kNotFound. Optimzed version of
2630 // HashTable::FindEntry.
2631 int FindEntry(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002632};
2633
2634
2635class NumberDictionaryShape {
2636 public:
2637 static inline bool IsMatch(uint32_t key, Object* other);
2638 static inline uint32_t Hash(uint32_t key);
2639 static inline uint32_t HashForObject(uint32_t key, Object* object);
John Reck59135872010-11-02 12:39:01 -07002640 MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002641 static const int kPrefixSize = 2;
2642 static const int kEntrySize = 3;
2643 static const bool kIsEnumerable = false;
2644};
2645
2646
2647class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
2648 public:
2649 static NumberDictionary* cast(Object* obj) {
2650 ASSERT(obj->IsDictionary());
2651 return reinterpret_cast<NumberDictionary*>(obj);
2652 }
2653
2654 // Type specific at put (default NONE attributes is used when adding).
John Reck59135872010-11-02 12:39:01 -07002655 MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
2656 MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
2657 Object* value,
2658 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002659
2660 // Set an existing entry or add a new one if needed.
John Reck59135872010-11-02 12:39:01 -07002661 MUST_USE_RESULT MaybeObject* Set(uint32_t key,
2662 Object* value,
2663 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002664
2665 void UpdateMaxNumberKey(uint32_t key);
2666
2667 // If slow elements are required we will never go back to fast-case
2668 // for the elements kept in this dictionary. We require slow
2669 // elements if an element has been added at an index larger than
2670 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
2671 // when defining a getter or setter with a number key.
2672 inline bool requires_slow_elements();
2673 inline void set_requires_slow_elements();
2674
2675 // Get the value of the max number key that has been added to this
2676 // dictionary. max_number_key can only be called if
2677 // requires_slow_elements returns false.
2678 inline uint32_t max_number_key();
2679
2680 // Remove all entries were key is a number and (from <= key && key < to).
2681 void RemoveNumberEntries(uint32_t from, uint32_t to);
2682
2683 // Bit masks.
2684 static const int kRequiresSlowElementsMask = 1;
2685 static const int kRequiresSlowElementsTagSize = 1;
2686 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
2687};
2688
2689
Steve Block6ded16b2010-05-10 14:33:55 +01002690// JSFunctionResultCache caches results of some JSFunction invocation.
2691// It is a fixed array with fixed structure:
2692// [0]: factory function
2693// [1]: finger index
2694// [2]: current cache size
2695// [3]: dummy field.
2696// The rest of array are key/value pairs.
2697class JSFunctionResultCache: public FixedArray {
2698 public:
2699 static const int kFactoryIndex = 0;
2700 static const int kFingerIndex = kFactoryIndex + 1;
2701 static const int kCacheSizeIndex = kFingerIndex + 1;
2702 static const int kDummyIndex = kCacheSizeIndex + 1;
2703 static const int kEntriesIndex = kDummyIndex + 1;
2704
2705 static const int kEntrySize = 2; // key + value
2706
Kristian Monsen25f61362010-05-21 11:50:48 +01002707 static const int kFactoryOffset = kHeaderSize;
2708 static const int kFingerOffset = kFactoryOffset + kPointerSize;
2709 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
2710
Steve Block6ded16b2010-05-10 14:33:55 +01002711 inline void MakeZeroSize();
2712 inline void Clear();
2713
Ben Murdochb8e0da22011-05-16 14:20:40 +01002714 inline int size();
2715 inline void set_size(int size);
2716 inline int finger_index();
2717 inline void set_finger_index(int finger_index);
2718
Steve Block6ded16b2010-05-10 14:33:55 +01002719 // Casting
2720 static inline JSFunctionResultCache* cast(Object* obj);
2721
2722#ifdef DEBUG
2723 void JSFunctionResultCacheVerify();
2724#endif
2725};
2726
2727
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002728// The cache for maps used by normalized (dictionary mode) objects.
2729// Such maps do not have property descriptors, so a typical program
2730// needs very limited number of distinct normalized maps.
2731class NormalizedMapCache: public FixedArray {
2732 public:
2733 static const int kEntries = 64;
2734
John Reck59135872010-11-02 12:39:01 -07002735 MUST_USE_RESULT MaybeObject* Get(JSObject* object,
2736 PropertyNormalizationMode mode);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002737
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002738 void Clear();
2739
2740 // Casting
2741 static inline NormalizedMapCache* cast(Object* obj);
2742
2743#ifdef DEBUG
2744 void NormalizedMapCacheVerify();
2745#endif
2746
2747 private:
2748 static int Hash(Map* fast);
2749
2750 static bool CheckHit(Map* slow, Map* fast, PropertyNormalizationMode mode);
2751};
2752
2753
Steve Blocka7e24c12009-10-30 11:49:00 +00002754// ByteArray represents fixed sized byte arrays. Used by the outside world,
2755// such as PCRE, and also by the memory allocator and garbage collector to
2756// fill in free blocks in the heap.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002757class ByteArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002758 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002759 // [length]: length of the array.
2760 inline int length();
2761 inline void set_length(int value);
2762
Steve Blocka7e24c12009-10-30 11:49:00 +00002763 // Setter and getter.
2764 inline byte get(int index);
2765 inline void set(int index, byte value);
2766
2767 // Treat contents as an int array.
2768 inline int get_int(int index);
2769
2770 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002771 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
Steve Blocka7e24c12009-10-30 11:49:00 +00002772 }
2773 // We use byte arrays for free blocks in the heap. Given a desired size in
2774 // bytes that is a multiple of the word size and big enough to hold a byte
2775 // array, this function returns the number of elements a byte array should
2776 // have.
2777 static int LengthFor(int size_in_bytes) {
2778 ASSERT(IsAligned(size_in_bytes, kPointerSize));
2779 ASSERT(size_in_bytes >= kHeaderSize);
2780 return size_in_bytes - kHeaderSize;
2781 }
2782
2783 // Returns data start address.
2784 inline Address GetDataStartAddress();
2785
2786 // Returns a pointer to the ByteArray object for a given data start address.
2787 static inline ByteArray* FromDataStartAddress(Address address);
2788
2789 // Casting.
2790 static inline ByteArray* cast(Object* obj);
2791
2792 // Dispatched behavior.
Iain Merrick75681382010-08-19 15:07:18 +01002793 inline int ByteArraySize() {
2794 return SizeFor(this->length());
2795 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002796#ifdef OBJECT_PRINT
2797 inline void ByteArrayPrint() {
2798 ByteArrayPrint(stdout);
2799 }
2800 void ByteArrayPrint(FILE* out);
2801#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002802#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002803 void ByteArrayVerify();
2804#endif
2805
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002806 // Layout description.
2807 // Length is smi tagged when it is stored.
2808 static const int kLengthOffset = HeapObject::kHeaderSize;
2809 static const int kHeaderSize = kLengthOffset + kPointerSize;
2810
2811 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002812
Leon Clarkee46be812010-01-19 14:06:41 +00002813 // Maximal memory consumption for a single ByteArray.
2814 static const int kMaxSize = 512 * MB;
2815 // Maximal length of a single ByteArray.
2816 static const int kMaxLength = kMaxSize - kHeaderSize;
2817
Steve Blocka7e24c12009-10-30 11:49:00 +00002818 private:
2819 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
2820};
2821
2822
Steve Block3ce2e202009-11-05 08:53:23 +00002823// An ExternalArray represents a fixed-size array of primitive values
2824// which live outside the JavaScript heap. Its subclasses are used to
2825// implement the CanvasArray types being defined in the WebGL
2826// specification. As of this writing the first public draft is not yet
2827// available, but Khronos members can access the draft at:
2828// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
2829//
2830// The semantics of these arrays differ from CanvasPixelArray.
2831// Out-of-range values passed to the setter are converted via a C
2832// cast, not clamping. Out-of-range indices cause exceptions to be
2833// raised rather than being silently ignored.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002834class ExternalArray: public HeapObject {
Steve Block3ce2e202009-11-05 08:53:23 +00002835 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002836 // [length]: length of the array.
2837 inline int length();
2838 inline void set_length(int value);
2839
Steve Block3ce2e202009-11-05 08:53:23 +00002840 // [external_pointer]: The pointer to the external memory area backing this
2841 // external array.
2842 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
2843
2844 // Casting.
2845 static inline ExternalArray* cast(Object* obj);
2846
2847 // Maximal acceptable length for an external array.
2848 static const int kMaxLength = 0x3fffffff;
2849
2850 // ExternalArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002851 static const int kLengthOffset = HeapObject::kHeaderSize;
2852 static const int kExternalPointerOffset =
2853 POINTER_SIZE_ALIGN(kLengthOffset + kIntSize);
Steve Block3ce2e202009-11-05 08:53:23 +00002854 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002855 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Block3ce2e202009-11-05 08:53:23 +00002856
2857 private:
2858 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
2859};
2860
2861
Steve Block44f0eee2011-05-26 01:26:41 +01002862// A ExternalPixelArray represents a fixed-size byte array with special
2863// semantics used for implementing the CanvasPixelArray object. Please see the
2864// specification at:
2865
2866// http://www.whatwg.org/specs/web-apps/current-work/
2867// multipage/the-canvas-element.html#canvaspixelarray
2868// In particular, write access clamps the value written to 0 or 255 if the
2869// value written is outside this range.
2870class ExternalPixelArray: public ExternalArray {
2871 public:
2872 inline uint8_t* external_pixel_pointer();
2873
2874 // Setter and getter.
2875 inline uint8_t get(int index);
2876 inline void set(int index, uint8_t value);
2877
2878 // This accessor applies the correct conversion from Smi, HeapNumber and
2879 // undefined and clamps the converted value between 0 and 255.
2880 Object* SetValue(uint32_t index, Object* value);
2881
2882 // Casting.
2883 static inline ExternalPixelArray* cast(Object* obj);
2884
2885#ifdef OBJECT_PRINT
2886 inline void ExternalPixelArrayPrint() {
2887 ExternalPixelArrayPrint(stdout);
2888 }
2889 void ExternalPixelArrayPrint(FILE* out);
2890#endif
2891#ifdef DEBUG
2892 void ExternalPixelArrayVerify();
2893#endif // DEBUG
2894
2895 private:
2896 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
2897};
2898
2899
Steve Block3ce2e202009-11-05 08:53:23 +00002900class ExternalByteArray: public ExternalArray {
2901 public:
2902 // Setter and getter.
2903 inline int8_t get(int index);
2904 inline void set(int index, int8_t value);
2905
2906 // This accessor applies the correct conversion from Smi, HeapNumber
2907 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002908 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002909
2910 // Casting.
2911 static inline ExternalByteArray* cast(Object* obj);
2912
Ben Murdochb0fe1622011-05-05 13:52:32 +01002913#ifdef OBJECT_PRINT
2914 inline void ExternalByteArrayPrint() {
2915 ExternalByteArrayPrint(stdout);
2916 }
2917 void ExternalByteArrayPrint(FILE* out);
2918#endif
Steve Block3ce2e202009-11-05 08:53:23 +00002919#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00002920 void ExternalByteArrayVerify();
2921#endif // DEBUG
2922
2923 private:
2924 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
2925};
2926
2927
2928class ExternalUnsignedByteArray: public ExternalArray {
2929 public:
2930 // Setter and getter.
2931 inline uint8_t get(int index);
2932 inline void set(int index, uint8_t value);
2933
2934 // This accessor applies the correct conversion from Smi, HeapNumber
2935 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002936 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002937
2938 // Casting.
2939 static inline ExternalUnsignedByteArray* cast(Object* obj);
2940
Ben Murdochb0fe1622011-05-05 13:52:32 +01002941#ifdef OBJECT_PRINT
2942 inline void ExternalUnsignedByteArrayPrint() {
2943 ExternalUnsignedByteArrayPrint(stdout);
2944 }
2945 void ExternalUnsignedByteArrayPrint(FILE* out);
2946#endif
Steve Block3ce2e202009-11-05 08:53:23 +00002947#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00002948 void ExternalUnsignedByteArrayVerify();
2949#endif // DEBUG
2950
2951 private:
2952 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
2953};
2954
2955
2956class ExternalShortArray: public ExternalArray {
2957 public:
2958 // Setter and getter.
2959 inline int16_t get(int index);
2960 inline void set(int index, int16_t value);
2961
2962 // This accessor applies the correct conversion from Smi, HeapNumber
2963 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002964 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002965
2966 // Casting.
2967 static inline ExternalShortArray* cast(Object* obj);
2968
Ben Murdochb0fe1622011-05-05 13:52:32 +01002969#ifdef OBJECT_PRINT
2970 inline void ExternalShortArrayPrint() {
2971 ExternalShortArrayPrint(stdout);
2972 }
2973 void ExternalShortArrayPrint(FILE* out);
2974#endif
Steve Block3ce2e202009-11-05 08:53:23 +00002975#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00002976 void ExternalShortArrayVerify();
2977#endif // DEBUG
2978
2979 private:
2980 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
2981};
2982
2983
2984class ExternalUnsignedShortArray: public ExternalArray {
2985 public:
2986 // Setter and getter.
2987 inline uint16_t get(int index);
2988 inline void set(int index, uint16_t value);
2989
2990 // This accessor applies the correct conversion from Smi, HeapNumber
2991 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002992 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002993
2994 // Casting.
2995 static inline ExternalUnsignedShortArray* cast(Object* obj);
2996
Ben Murdochb0fe1622011-05-05 13:52:32 +01002997#ifdef OBJECT_PRINT
2998 inline void ExternalUnsignedShortArrayPrint() {
2999 ExternalUnsignedShortArrayPrint(stdout);
3000 }
3001 void ExternalUnsignedShortArrayPrint(FILE* out);
3002#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003003#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003004 void ExternalUnsignedShortArrayVerify();
3005#endif // DEBUG
3006
3007 private:
3008 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
3009};
3010
3011
3012class ExternalIntArray: public ExternalArray {
3013 public:
3014 // Setter and getter.
3015 inline int32_t get(int index);
3016 inline void set(int index, int32_t value);
3017
3018 // This accessor applies the correct conversion from Smi, HeapNumber
3019 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003020 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003021
3022 // Casting.
3023 static inline ExternalIntArray* cast(Object* obj);
3024
Ben Murdochb0fe1622011-05-05 13:52:32 +01003025#ifdef OBJECT_PRINT
3026 inline void ExternalIntArrayPrint() {
3027 ExternalIntArrayPrint(stdout);
3028 }
3029 void ExternalIntArrayPrint(FILE* out);
3030#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003031#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003032 void ExternalIntArrayVerify();
3033#endif // DEBUG
3034
3035 private:
3036 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
3037};
3038
3039
3040class ExternalUnsignedIntArray: public ExternalArray {
3041 public:
3042 // Setter and getter.
3043 inline uint32_t get(int index);
3044 inline void set(int index, uint32_t value);
3045
3046 // This accessor applies the correct conversion from Smi, HeapNumber
3047 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003048 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003049
3050 // Casting.
3051 static inline ExternalUnsignedIntArray* cast(Object* obj);
3052
Ben Murdochb0fe1622011-05-05 13:52:32 +01003053#ifdef OBJECT_PRINT
3054 inline void ExternalUnsignedIntArrayPrint() {
3055 ExternalUnsignedIntArrayPrint(stdout);
3056 }
3057 void ExternalUnsignedIntArrayPrint(FILE* out);
3058#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003059#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003060 void ExternalUnsignedIntArrayVerify();
3061#endif // DEBUG
3062
3063 private:
3064 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
3065};
3066
3067
3068class ExternalFloatArray: public ExternalArray {
3069 public:
3070 // Setter and getter.
3071 inline float get(int index);
3072 inline void set(int index, float value);
3073
3074 // This accessor applies the correct conversion from Smi, HeapNumber
3075 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003076 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003077
3078 // Casting.
3079 static inline ExternalFloatArray* cast(Object* obj);
3080
Ben Murdochb0fe1622011-05-05 13:52:32 +01003081#ifdef OBJECT_PRINT
3082 inline void ExternalFloatArrayPrint() {
3083 ExternalFloatArrayPrint(stdout);
3084 }
3085 void ExternalFloatArrayPrint(FILE* out);
3086#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003087#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003088 void ExternalFloatArrayVerify();
3089#endif // DEBUG
3090
3091 private:
3092 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
3093};
3094
3095
Ben Murdochb0fe1622011-05-05 13:52:32 +01003096// DeoptimizationInputData is a fixed array used to hold the deoptimization
3097// data for code generated by the Hydrogen/Lithium compiler. It also
3098// contains information about functions that were inlined. If N different
3099// functions were inlined then first N elements of the literal array will
3100// contain these functions.
3101//
3102// It can be empty.
3103class DeoptimizationInputData: public FixedArray {
3104 public:
3105 // Layout description. Indices in the array.
3106 static const int kTranslationByteArrayIndex = 0;
3107 static const int kInlinedFunctionCountIndex = 1;
3108 static const int kLiteralArrayIndex = 2;
3109 static const int kOsrAstIdIndex = 3;
3110 static const int kOsrPcOffsetIndex = 4;
3111 static const int kFirstDeoptEntryIndex = 5;
3112
3113 // Offsets of deopt entry elements relative to the start of the entry.
3114 static const int kAstIdOffset = 0;
3115 static const int kTranslationIndexOffset = 1;
3116 static const int kArgumentsStackHeightOffset = 2;
3117 static const int kDeoptEntrySize = 3;
3118
3119 // Simple element accessors.
3120#define DEFINE_ELEMENT_ACCESSORS(name, type) \
3121 type* name() { \
3122 return type::cast(get(k##name##Index)); \
3123 } \
3124 void Set##name(type* value) { \
3125 set(k##name##Index, value); \
3126 }
3127
3128 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
3129 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
3130 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
3131 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
3132 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
3133
3134 // Unchecked accessor to be used during GC.
3135 FixedArray* UncheckedLiteralArray() {
3136 return reinterpret_cast<FixedArray*>(get(kLiteralArrayIndex));
3137 }
3138
3139#undef DEFINE_ELEMENT_ACCESSORS
3140
3141 // Accessors for elements of the ith deoptimization entry.
3142#define DEFINE_ENTRY_ACCESSORS(name, type) \
3143 type* name(int i) { \
3144 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
3145 } \
3146 void Set##name(int i, type* value) { \
3147 set(IndexForEntry(i) + k##name##Offset, value); \
3148 }
3149
3150 DEFINE_ENTRY_ACCESSORS(AstId, Smi)
3151 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
3152 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
3153
3154#undef DEFINE_ENTRY_ACCESSORS
3155
3156 int DeoptCount() {
3157 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
3158 }
3159
3160 // Allocates a DeoptimizationInputData.
3161 MUST_USE_RESULT static MaybeObject* Allocate(int deopt_entry_count,
3162 PretenureFlag pretenure);
3163
3164 // Casting.
3165 static inline DeoptimizationInputData* cast(Object* obj);
3166
3167#ifdef OBJECT_PRINT
3168 void DeoptimizationInputDataPrint(FILE* out);
3169#endif
3170
3171 private:
3172 static int IndexForEntry(int i) {
3173 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
3174 }
3175
3176 static int LengthFor(int entry_count) {
3177 return IndexForEntry(entry_count);
3178 }
3179};
3180
3181
3182// DeoptimizationOutputData is a fixed array used to hold the deoptimization
3183// data for code generated by the full compiler.
3184// The format of the these objects is
3185// [i * 2]: Ast ID for ith deoptimization.
3186// [i * 2 + 1]: PC and state of ith deoptimization
3187class DeoptimizationOutputData: public FixedArray {
3188 public:
3189 int DeoptPoints() { return length() / 2; }
3190 Smi* AstId(int index) { return Smi::cast(get(index * 2)); }
3191 void SetAstId(int index, Smi* id) { set(index * 2, id); }
3192 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
3193 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
3194
3195 static int LengthOfFixedArray(int deopt_points) {
3196 return deopt_points * 2;
3197 }
3198
3199 // Allocates a DeoptimizationOutputData.
3200 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_deopt_points,
3201 PretenureFlag pretenure);
3202
3203 // Casting.
3204 static inline DeoptimizationOutputData* cast(Object* obj);
3205
3206#ifdef OBJECT_PRINT
3207 void DeoptimizationOutputDataPrint(FILE* out);
3208#endif
3209};
3210
3211
Ben Murdochb8e0da22011-05-16 14:20:40 +01003212class SafepointEntry;
3213
3214
Steve Blocka7e24c12009-10-30 11:49:00 +00003215// Code describes objects with on-the-fly generated machine code.
3216class Code: public HeapObject {
3217 public:
3218 // Opaque data type for encapsulating code flags like kind, inline
3219 // cache state, and arguments count.
Iain Merrick75681382010-08-19 15:07:18 +01003220 // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
3221 // enumeration type has correct value range (see Issue 830 for more details).
3222 enum Flags {
3223 FLAGS_MIN_VALUE = kMinInt,
3224 FLAGS_MAX_VALUE = kMaxInt
3225 };
Steve Blocka7e24c12009-10-30 11:49:00 +00003226
3227 enum Kind {
3228 FUNCTION,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003229 OPTIMIZED_FUNCTION,
Steve Blocka7e24c12009-10-30 11:49:00 +00003230 STUB,
3231 BUILTIN,
3232 LOAD_IC,
3233 KEYED_LOAD_IC,
Steve Block44f0eee2011-05-26 01:26:41 +01003234 KEYED_EXTERNAL_ARRAY_LOAD_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00003235 CALL_IC,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003236 KEYED_CALL_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00003237 STORE_IC,
3238 KEYED_STORE_IC,
Steve Block44f0eee2011-05-26 01:26:41 +01003239 KEYED_EXTERNAL_ARRAY_STORE_IC,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003240 TYPE_RECORDING_BINARY_OP_IC,
3241 COMPARE_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01003242 // No more than 16 kinds. The value currently encoded in four bits in
Steve Blocka7e24c12009-10-30 11:49:00 +00003243 // Flags.
3244
3245 // Pseudo-kinds.
3246 REGEXP = BUILTIN,
3247 FIRST_IC_KIND = LOAD_IC,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003248 LAST_IC_KIND = COMPARE_IC
Steve Blocka7e24c12009-10-30 11:49:00 +00003249 };
3250
3251 enum {
Kristian Monsen50ef84f2010-07-29 15:18:00 +01003252 NUMBER_OF_KINDS = LAST_IC_KIND + 1
Steve Blocka7e24c12009-10-30 11:49:00 +00003253 };
3254
Ben Murdochb8e0da22011-05-16 14:20:40 +01003255 typedef int ExtraICState;
3256
3257 static const ExtraICState kNoExtraICState = 0;
3258
Steve Blocka7e24c12009-10-30 11:49:00 +00003259#ifdef ENABLE_DISASSEMBLER
3260 // Printing
3261 static const char* Kind2String(Kind kind);
3262 static const char* ICState2String(InlineCacheState state);
3263 static const char* PropertyType2String(PropertyType type);
Steve Block1e0659c2011-05-24 12:43:12 +01003264 static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003265 inline void Disassemble(const char* name) {
3266 Disassemble(name, stdout);
3267 }
3268 void Disassemble(const char* name, FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00003269#endif // ENABLE_DISASSEMBLER
3270
3271 // [instruction_size]: Size of the native instructions
3272 inline int instruction_size();
3273 inline void set_instruction_size(int value);
3274
Leon Clarkeac952652010-07-15 11:15:24 +01003275 // [relocation_info]: Code relocation information
3276 DECL_ACCESSORS(relocation_info, ByteArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003277 void InvalidateRelocation();
Leon Clarkeac952652010-07-15 11:15:24 +01003278
Ben Murdochb0fe1622011-05-05 13:52:32 +01003279 // [deoptimization_data]: Array containing data for deopt.
3280 DECL_ACCESSORS(deoptimization_data, FixedArray)
3281
3282 // Unchecked accessors to be used during GC.
Leon Clarkeac952652010-07-15 11:15:24 +01003283 inline ByteArray* unchecked_relocation_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003284 inline FixedArray* unchecked_deoptimization_data();
Leon Clarkeac952652010-07-15 11:15:24 +01003285
Steve Blocka7e24c12009-10-30 11:49:00 +00003286 inline int relocation_size();
Steve Blocka7e24c12009-10-30 11:49:00 +00003287
Steve Blocka7e24c12009-10-30 11:49:00 +00003288 // [flags]: Various code flags.
3289 inline Flags flags();
3290 inline void set_flags(Flags flags);
3291
3292 // [flags]: Access to specific code flags.
3293 inline Kind kind();
3294 inline InlineCacheState ic_state(); // Only valid for IC stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003295 inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
Steve Blocka7e24c12009-10-30 11:49:00 +00003296 inline InLoopFlag ic_in_loop(); // Only valid for IC stubs.
3297 inline PropertyType type(); // Only valid for monomorphic IC stubs.
3298 inline int arguments_count(); // Only valid for call IC stubs.
3299
3300 // Testers for IC stub kinds.
3301 inline bool is_inline_cache_stub();
3302 inline bool is_load_stub() { return kind() == LOAD_IC; }
3303 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
3304 inline bool is_store_stub() { return kind() == STORE_IC; }
3305 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
3306 inline bool is_call_stub() { return kind() == CALL_IC; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003307 inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003308 inline bool is_type_recording_binary_op_stub() {
3309 return kind() == TYPE_RECORDING_BINARY_OP_IC;
3310 }
3311 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
Steve Block44f0eee2011-05-26 01:26:41 +01003312 inline bool is_external_array_load_stub() {
3313 return kind() == KEYED_EXTERNAL_ARRAY_LOAD_IC;
3314 }
3315 inline bool is_external_array_store_stub() {
3316 return kind() == KEYED_EXTERNAL_ARRAY_STORE_IC;
3317 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003318
Steve Block6ded16b2010-05-10 14:33:55 +01003319 // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003320 inline int major_key();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003321 inline void set_major_key(int value);
3322
3323 // [optimizable]: For FUNCTION kind, tells if it is optimizable.
3324 inline bool optimizable();
3325 inline void set_optimizable(bool value);
3326
3327 // [has_deoptimization_support]: For FUNCTION kind, tells if it has
3328 // deoptimization support.
3329 inline bool has_deoptimization_support();
3330 inline void set_has_deoptimization_support(bool value);
3331
3332 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
3333 // how long the function has been marked for OSR and therefore which
3334 // level of loop nesting we are willing to do on-stack replacement
3335 // for.
3336 inline void set_allow_osr_at_loop_nesting_level(int level);
3337 inline int allow_osr_at_loop_nesting_level();
3338
3339 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
3340 // reserved in the code prologue.
3341 inline unsigned stack_slots();
3342 inline void set_stack_slots(unsigned slots);
3343
3344 // [safepoint_table_start]: For kind OPTIMIZED_CODE, the offset in
3345 // the instruction stream where the safepoint table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01003346 inline unsigned safepoint_table_offset();
3347 inline void set_safepoint_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003348
3349 // [stack_check_table_start]: For kind FUNCTION, the offset in the
3350 // instruction stream where the stack check table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01003351 inline unsigned stack_check_table_offset();
3352 inline void set_stack_check_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003353
3354 // [check type]: For kind CALL_IC, tells how to check if the
3355 // receiver is valid for the given call.
3356 inline CheckType check_type();
3357 inline void set_check_type(CheckType value);
3358
Steve Block44f0eee2011-05-26 01:26:41 +01003359 // [external array type]: For kind KEYED_EXTERNAL_ARRAY_LOAD_IC and
3360 // KEYED_EXTERNAL_ARRAY_STORE_IC, identifies the type of external
3361 // array that the code stub is specialized for.
3362 inline ExternalArrayType external_array_type();
3363 inline void set_external_array_type(ExternalArrayType value);
3364
Ben Murdochb0fe1622011-05-05 13:52:32 +01003365 // [type-recording binary op type]: For all TYPE_RECORDING_BINARY_OP_IC.
3366 inline byte type_recording_binary_op_type();
3367 inline void set_type_recording_binary_op_type(byte value);
3368 inline byte type_recording_binary_op_result_type();
3369 inline void set_type_recording_binary_op_result_type(byte value);
3370
3371 // [compare state]: For kind compare IC stubs, tells what state the
3372 // stub is in.
3373 inline byte compare_state();
3374 inline void set_compare_state(byte value);
3375
Ben Murdochb8e0da22011-05-16 14:20:40 +01003376 // Get the safepoint entry for the given pc.
3377 SafepointEntry GetSafepointEntry(Address pc);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003378
3379 // Mark this code object as not having a stack check table. Assumes kind
3380 // is FUNCTION.
3381 void SetNoStackCheckTable();
3382
3383 // Find the first map in an IC stub.
3384 Map* FindFirstMap();
Steve Blocka7e24c12009-10-30 11:49:00 +00003385
3386 // Flags operations.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003387 static inline Flags ComputeFlags(
3388 Kind kind,
3389 InLoopFlag in_loop = NOT_IN_LOOP,
3390 InlineCacheState ic_state = UNINITIALIZED,
3391 ExtraICState extra_ic_state = kNoExtraICState,
3392 PropertyType type = NORMAL,
3393 int argc = -1,
3394 InlineCacheHolderFlag holder = OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +00003395
3396 static inline Flags ComputeMonomorphicFlags(
3397 Kind kind,
3398 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003399 ExtraICState extra_ic_state = kNoExtraICState,
Steve Block8defd9f2010-07-08 12:39:36 +01003400 InlineCacheHolderFlag holder = OWN_MAP,
Steve Blocka7e24c12009-10-30 11:49:00 +00003401 InLoopFlag in_loop = NOT_IN_LOOP,
3402 int argc = -1);
3403
3404 static inline Kind ExtractKindFromFlags(Flags flags);
3405 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003406 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003407 static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
3408 static inline PropertyType ExtractTypeFromFlags(Flags flags);
3409 static inline int ExtractArgumentsCountFromFlags(Flags flags);
Steve Block8defd9f2010-07-08 12:39:36 +01003410 static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003411 static inline Flags RemoveTypeFromFlags(Flags flags);
3412
3413 // Convert a target address into a code object.
3414 static inline Code* GetCodeFromTargetAddress(Address address);
3415
Steve Block791712a2010-08-27 10:21:07 +01003416 // Convert an entry address into an object.
3417 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
3418
Steve Blocka7e24c12009-10-30 11:49:00 +00003419 // Returns the address of the first instruction.
3420 inline byte* instruction_start();
3421
Leon Clarkeac952652010-07-15 11:15:24 +01003422 // Returns the address right after the last instruction.
3423 inline byte* instruction_end();
3424
Steve Blocka7e24c12009-10-30 11:49:00 +00003425 // Returns the size of the instructions, padding, and relocation information.
3426 inline int body_size();
3427
3428 // Returns the address of the first relocation info (read backwards!).
3429 inline byte* relocation_start();
3430
3431 // Code entry point.
3432 inline byte* entry();
3433
3434 // Returns true if pc is inside this object's instructions.
3435 inline bool contains(byte* pc);
3436
Steve Blocka7e24c12009-10-30 11:49:00 +00003437 // Relocate the code by delta bytes. Called to signal that this code
3438 // object has been moved by delta bytes.
Steve Blockd0582a62009-12-15 09:54:21 +00003439 void Relocate(intptr_t delta);
Steve Blocka7e24c12009-10-30 11:49:00 +00003440
3441 // Migrate code described by desc.
3442 void CopyFrom(const CodeDesc& desc);
3443
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003444 // Returns the object size for a given body (used for allocation).
3445 static int SizeFor(int body_size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003446 ASSERT_SIZE_TAG_ALIGNED(body_size);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003447 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
Steve Blocka7e24c12009-10-30 11:49:00 +00003448 }
3449
3450 // Calculate the size of the code object to report for log events. This takes
3451 // the layout of the code object into account.
3452 int ExecutableSize() {
3453 // Check that the assumptions about the layout of the code object holds.
3454 ASSERT_EQ(static_cast<int>(instruction_start() - address()),
3455 Code::kHeaderSize);
3456 return instruction_size() + Code::kHeaderSize;
3457 }
3458
3459 // Locating source position.
3460 int SourcePosition(Address pc);
3461 int SourceStatementPosition(Address pc);
3462
3463 // Casting.
3464 static inline Code* cast(Object* obj);
3465
3466 // Dispatched behavior.
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003467 int CodeSize() { return SizeFor(body_size()); }
Iain Merrick75681382010-08-19 15:07:18 +01003468 inline void CodeIterateBody(ObjectVisitor* v);
3469
3470 template<typename StaticVisitor>
Steve Block44f0eee2011-05-26 01:26:41 +01003471 inline void CodeIterateBody(Heap* heap);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003472#ifdef OBJECT_PRINT
3473 inline void CodePrint() {
3474 CodePrint(stdout);
3475 }
3476 void CodePrint(FILE* out);
3477#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003478#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003479 void CodeVerify();
3480#endif
Ben Murdochb0fe1622011-05-05 13:52:32 +01003481
Ben Murdoch8b112d22011-06-08 16:22:53 +01003482 // Returns the isolate/heap this code object belongs to.
3483 inline Isolate* isolate();
3484 inline Heap* heap();
3485
Ben Murdochb0fe1622011-05-05 13:52:32 +01003486 // Max loop nesting marker used to postpose OSR. We don't take loop
3487 // nesting that is deeper than 5 levels into account.
3488 static const int kMaxLoopNestingMarker = 6;
3489
Steve Blocka7e24c12009-10-30 11:49:00 +00003490 // Layout description.
3491 static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
Leon Clarkeac952652010-07-15 11:15:24 +01003492 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003493 static const int kDeoptimizationDataOffset =
3494 kRelocationInfoOffset + kPointerSize;
3495 static const int kFlagsOffset = kDeoptimizationDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003496 static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003497
3498 static const int kKindSpecificFlagsSize = 2 * kIntSize;
3499
3500 static const int kHeaderPaddingStart = kKindSpecificFlagsOffset +
3501 kKindSpecificFlagsSize;
3502
Steve Blocka7e24c12009-10-30 11:49:00 +00003503 // Add padding to align the instruction start following right after
3504 // the Code object header.
3505 static const int kHeaderSize =
Ben Murdochb0fe1622011-05-05 13:52:32 +01003506 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00003507
3508 // Byte offsets within kKindSpecificFlagsOffset.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003509 static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset;
3510 static const int kOptimizableOffset = kKindSpecificFlagsOffset;
3511 static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
3512 static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
Steve Block44f0eee2011-05-26 01:26:41 +01003513 static const int kExternalArrayTypeOffset = kKindSpecificFlagsOffset;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003514
3515 static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
3516 static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
3517 static const int kHasDeoptimizationSupportOffset = kOptimizableOffset + 1;
3518
3519 static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;
3520 static const int kAllowOSRAtLoopNestingLevelOffset =
3521 kHasDeoptimizationSupportOffset + 1;
3522
Steve Block1e0659c2011-05-24 12:43:12 +01003523 static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
3524 static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003525
3526 // Flags layout.
3527 static const int kFlagsICStateShift = 0;
3528 static const int kFlagsICInLoopShift = 3;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01003529 static const int kFlagsTypeShift = 4;
Steve Block44f0eee2011-05-26 01:26:41 +01003530 static const int kFlagsKindShift = 8;
3531 static const int kFlagsICHolderShift = 12;
3532 static const int kFlagsExtraICStateShift = 13;
3533 static const int kFlagsArgumentsCountShift = 15;
Steve Blocka7e24c12009-10-30 11:49:00 +00003534
Steve Block6ded16b2010-05-10 14:33:55 +01003535 static const int kFlagsICStateMask = 0x00000007; // 00000000111
3536 static const int kFlagsICInLoopMask = 0x00000008; // 00000001000
Steve Block44f0eee2011-05-26 01:26:41 +01003537 static const int kFlagsTypeMask = 0x000000F0; // 00001110000
3538 static const int kFlagsKindMask = 0x00000F00; // 11110000000
3539 static const int kFlagsCacheInPrototypeMapMask = 0x00001000;
3540 static const int kFlagsExtraICStateMask = 0x00006000;
3541 static const int kFlagsArgumentsCountMask = 0xFFFF8000;
Steve Blocka7e24c12009-10-30 11:49:00 +00003542
3543 static const int kFlagsNotUsedInLookup =
Steve Block8defd9f2010-07-08 12:39:36 +01003544 (kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
Steve Blocka7e24c12009-10-30 11:49:00 +00003545
3546 private:
3547 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
3548};
3549
3550
3551// All heap objects have a Map that describes their structure.
3552// A Map contains information about:
3553// - Size information about the object
3554// - How to iterate over an object (for garbage collection)
3555class Map: public HeapObject {
3556 public:
3557 // Instance size.
Steve Block791712a2010-08-27 10:21:07 +01003558 // Size in bytes or kVariableSizeSentinel if instances do not have
3559 // a fixed size.
Steve Blocka7e24c12009-10-30 11:49:00 +00003560 inline int instance_size();
3561 inline void set_instance_size(int value);
3562
3563 // Count of properties allocated in the object.
3564 inline int inobject_properties();
3565 inline void set_inobject_properties(int value);
3566
3567 // Count of property fields pre-allocated in the object when first allocated.
3568 inline int pre_allocated_property_fields();
3569 inline void set_pre_allocated_property_fields(int value);
3570
3571 // Instance type.
3572 inline InstanceType instance_type();
3573 inline void set_instance_type(InstanceType value);
3574
3575 // Tells how many unused property fields are available in the
3576 // instance (only used for JSObject in fast mode).
3577 inline int unused_property_fields();
3578 inline void set_unused_property_fields(int value);
3579
3580 // Bit field.
3581 inline byte bit_field();
3582 inline void set_bit_field(byte value);
3583
3584 // Bit field 2.
3585 inline byte bit_field2();
3586 inline void set_bit_field2(byte value);
3587
3588 // Tells whether the object in the prototype property will be used
3589 // for instances created from this function. If the prototype
3590 // property is set to a value that is not a JSObject, the prototype
3591 // property will not be used to create instances of the function.
3592 // See ECMA-262, 13.2.2.
3593 inline void set_non_instance_prototype(bool value);
3594 inline bool has_non_instance_prototype();
3595
Steve Block6ded16b2010-05-10 14:33:55 +01003596 // Tells whether function has special prototype property. If not, prototype
3597 // property will not be created when accessed (will return undefined),
3598 // and construction from this function will not be allowed.
3599 inline void set_function_with_prototype(bool value);
3600 inline bool function_with_prototype();
3601
Steve Blocka7e24c12009-10-30 11:49:00 +00003602 // Tells whether the instance with this map should be ignored by the
3603 // __proto__ accessor.
3604 inline void set_is_hidden_prototype() {
3605 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
3606 }
3607
3608 inline bool is_hidden_prototype() {
3609 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
3610 }
3611
3612 // Records and queries whether the instance has a named interceptor.
3613 inline void set_has_named_interceptor() {
3614 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
3615 }
3616
3617 inline bool has_named_interceptor() {
3618 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
3619 }
3620
3621 // Records and queries whether the instance has an indexed interceptor.
3622 inline void set_has_indexed_interceptor() {
3623 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
3624 }
3625
3626 inline bool has_indexed_interceptor() {
3627 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
3628 }
3629
3630 // Tells whether the instance is undetectable.
3631 // An undetectable object is a special class of JSObject: 'typeof' operator
3632 // returns undefined, ToBoolean returns false. Otherwise it behaves like
3633 // a normal JS object. It is useful for implementing undetectable
3634 // document.all in Firefox & Safari.
3635 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
3636 inline void set_is_undetectable() {
3637 set_bit_field(bit_field() | (1 << kIsUndetectable));
3638 }
3639
3640 inline bool is_undetectable() {
3641 return ((1 << kIsUndetectable) & bit_field()) != 0;
3642 }
3643
Steve Blocka7e24c12009-10-30 11:49:00 +00003644 // Tells whether the instance has a call-as-function handler.
3645 inline void set_has_instance_call_handler() {
3646 set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
3647 }
3648
3649 inline bool has_instance_call_handler() {
3650 return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
3651 }
3652
Steve Block8defd9f2010-07-08 12:39:36 +01003653 inline void set_is_extensible(bool value);
3654 inline bool is_extensible();
3655
3656 // Tells whether the instance has fast elements.
Iain Merrick75681382010-08-19 15:07:18 +01003657 // Equivalent to instance->GetElementsKind() == FAST_ELEMENTS.
3658 inline void set_has_fast_elements(bool value) {
Steve Block8defd9f2010-07-08 12:39:36 +01003659 if (value) {
3660 set_bit_field2(bit_field2() | (1 << kHasFastElements));
3661 } else {
3662 set_bit_field2(bit_field2() & ~(1 << kHasFastElements));
3663 }
Leon Clarkee46be812010-01-19 14:06:41 +00003664 }
3665
Iain Merrick75681382010-08-19 15:07:18 +01003666 inline bool has_fast_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01003667 return ((1 << kHasFastElements) & bit_field2()) != 0;
Leon Clarkee46be812010-01-19 14:06:41 +00003668 }
3669
Steve Block1e0659c2011-05-24 12:43:12 +01003670 // Tells whether an instance has pixel array elements.
Steve Block44f0eee2011-05-26 01:26:41 +01003671 inline void set_has_external_array_elements(bool value) {
Steve Block1e0659c2011-05-24 12:43:12 +01003672 if (value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003673 set_bit_field2(bit_field2() | (1 << kHasExternalArrayElements));
Steve Block1e0659c2011-05-24 12:43:12 +01003674 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01003675 set_bit_field2(bit_field2() & ~(1 << kHasExternalArrayElements));
Steve Block1e0659c2011-05-24 12:43:12 +01003676 }
3677 }
3678
Steve Block44f0eee2011-05-26 01:26:41 +01003679 inline bool has_external_array_elements() {
3680 return ((1 << kHasExternalArrayElements) & bit_field2()) != 0;
Steve Block1e0659c2011-05-24 12:43:12 +01003681 }
3682
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003683 // Tells whether the map is attached to SharedFunctionInfo
3684 // (for inobject slack tracking).
3685 inline void set_attached_to_shared_function_info(bool value);
3686
3687 inline bool attached_to_shared_function_info();
3688
3689 // Tells whether the map is shared between objects that may have different
3690 // behavior. If true, the map should never be modified, instead a clone
3691 // should be created and modified.
3692 inline void set_is_shared(bool value);
3693
3694 inline bool is_shared();
3695
Steve Blocka7e24c12009-10-30 11:49:00 +00003696 // Tells whether the instance needs security checks when accessing its
3697 // properties.
3698 inline void set_is_access_check_needed(bool access_check_needed);
3699 inline bool is_access_check_needed();
3700
3701 // [prototype]: implicit prototype object.
3702 DECL_ACCESSORS(prototype, Object)
3703
3704 // [constructor]: points back to the function responsible for this map.
3705 DECL_ACCESSORS(constructor, Object)
3706
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003707 inline JSFunction* unchecked_constructor();
3708
Steve Blocka7e24c12009-10-30 11:49:00 +00003709 // [instance descriptors]: describes the object.
3710 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
3711
3712 // [stub cache]: contains stubs compiled for this map.
Steve Block6ded16b2010-05-10 14:33:55 +01003713 DECL_ACCESSORS(code_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00003714
Ben Murdochb0fe1622011-05-05 13:52:32 +01003715 // Lookup in the map's instance descriptors and fill out the result
3716 // with the given holder if the name is found. The holder may be
3717 // NULL when this function is used from the compiler.
3718 void LookupInDescriptors(JSObject* holder,
3719 String* name,
3720 LookupResult* result);
3721
John Reck59135872010-11-02 12:39:01 -07003722 MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003723
John Reck59135872010-11-02 12:39:01 -07003724 MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
3725 NormalizedMapSharingMode sharing);
Steve Blocka7e24c12009-10-30 11:49:00 +00003726
3727 // Returns a copy of the map, with all transitions dropped from the
3728 // instance descriptors.
John Reck59135872010-11-02 12:39:01 -07003729 MUST_USE_RESULT MaybeObject* CopyDropTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00003730
Steve Block8defd9f2010-07-08 12:39:36 +01003731 // Returns this map if it has the fast elements bit set, otherwise
3732 // returns a copy of the map, with all transitions dropped from the
3733 // descriptors and the fast elements bit set.
John Reck59135872010-11-02 12:39:01 -07003734 MUST_USE_RESULT inline MaybeObject* GetFastElementsMap();
Steve Block8defd9f2010-07-08 12:39:36 +01003735
3736 // Returns this map if it has the fast elements bit cleared,
3737 // otherwise returns a copy of the map, with all transitions dropped
3738 // from the descriptors and the fast elements bit cleared.
John Reck59135872010-11-02 12:39:01 -07003739 MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
Steve Block8defd9f2010-07-08 12:39:36 +01003740
Steve Block44f0eee2011-05-26 01:26:41 +01003741 // Returns a new map with all transitions dropped from the descriptors and the
3742 // external array elements bit set.
3743 MUST_USE_RESULT MaybeObject* GetExternalArrayElementsMap(
3744 ExternalArrayType array_type,
3745 bool safe_to_add_transition);
Steve Block1e0659c2011-05-24 12:43:12 +01003746
Steve Blocka7e24c12009-10-30 11:49:00 +00003747 // Returns the property index for name (only valid for FAST MODE).
3748 int PropertyIndexFor(String* name);
3749
3750 // Returns the next free property index (only valid for FAST MODE).
3751 int NextFreePropertyIndex();
3752
3753 // Returns the number of properties described in instance_descriptors.
3754 int NumberOfDescribedProperties();
3755
3756 // Casting.
3757 static inline Map* cast(Object* obj);
3758
3759 // Locate an accessor in the instance descriptor.
3760 AccessorDescriptor* FindAccessor(String* name);
3761
3762 // Code cache operations.
3763
3764 // Clears the code cache.
Steve Block44f0eee2011-05-26 01:26:41 +01003765 inline void ClearCodeCache(Heap* heap);
Steve Blocka7e24c12009-10-30 11:49:00 +00003766
3767 // Update code cache.
John Reck59135872010-11-02 12:39:01 -07003768 MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00003769
3770 // Returns the found code or undefined if absent.
3771 Object* FindInCodeCache(String* name, Code::Flags flags);
3772
3773 // Returns the non-negative index of the code object if it is in the
3774 // cache and -1 otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +01003775 int IndexInCodeCache(Object* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00003776
3777 // Removes a code object from the code cache at the given index.
Steve Block6ded16b2010-05-10 14:33:55 +01003778 void RemoveFromCodeCache(String* name, Code* code, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003779
3780 // For every transition in this map, makes the transition's
3781 // target's prototype pointer point back to this map.
3782 // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
3783 void CreateBackPointers();
3784
3785 // Set all map transitions from this map to dead maps to null.
3786 // Also, restore the original prototype on the targets of these
3787 // transitions, so that we do not process this map again while
3788 // following back pointers.
Steve Block44f0eee2011-05-26 01:26:41 +01003789 void ClearNonLiveTransitions(Heap* heap, Object* real_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00003790
3791 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003792#ifdef OBJECT_PRINT
3793 inline void MapPrint() {
3794 MapPrint(stdout);
3795 }
3796 void MapPrint(FILE* out);
3797#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003798#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003799 void MapVerify();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003800 void SharedMapVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00003801#endif
3802
Iain Merrick75681382010-08-19 15:07:18 +01003803 inline int visitor_id();
3804 inline void set_visitor_id(int visitor_id);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003805
Steve Block44f0eee2011-05-26 01:26:41 +01003806 // Returns the isolate/heap this map belongs to.
3807 inline Isolate* isolate();
3808 inline Heap* heap();
3809
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003810 typedef void (*TraverseCallback)(Map* map, void* data);
3811
3812 void TraverseTransitionTree(TraverseCallback callback, void* data);
3813
Steve Blocka7e24c12009-10-30 11:49:00 +00003814 static const int kMaxPreAllocatedPropertyFields = 255;
3815
3816 // Layout description.
3817 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
3818 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
3819 static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
3820 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
3821 static const int kInstanceDescriptorsOffset =
3822 kConstructorOffset + kPointerSize;
3823 static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
Iain Merrick9ac36c92010-09-13 15:29:50 +01003824 static const int kPadStart = kCodeCacheOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003825 static const int kSize = MAP_POINTER_ALIGN(kPadStart);
3826
3827 // Layout of pointer fields. Heap iteration code relies on them
3828 // being continiously allocated.
3829 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
3830 static const int kPointerFieldsEndOffset =
3831 Map::kCodeCacheOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003832
3833 // Byte offsets within kInstanceSizesOffset.
3834 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
3835 static const int kInObjectPropertiesByte = 1;
3836 static const int kInObjectPropertiesOffset =
3837 kInstanceSizesOffset + kInObjectPropertiesByte;
3838 static const int kPreAllocatedPropertyFieldsByte = 2;
3839 static const int kPreAllocatedPropertyFieldsOffset =
3840 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
Iain Merrick9ac36c92010-09-13 15:29:50 +01003841 static const int kVisitorIdByte = 3;
3842 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
Steve Blocka7e24c12009-10-30 11:49:00 +00003843
3844 // Byte offsets within kInstanceAttributesOffset attributes.
3845 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
3846 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
3847 static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
3848 static const int kBitField2Offset = kInstanceAttributesOffset + 3;
3849
3850 STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
3851
3852 // Bit positions for bit field.
3853 static const int kUnused = 0; // To be used for marking recently used maps.
3854 static const int kHasNonInstancePrototype = 1;
3855 static const int kIsHiddenPrototype = 2;
3856 static const int kHasNamedInterceptor = 3;
3857 static const int kHasIndexedInterceptor = 4;
3858 static const int kIsUndetectable = 5;
3859 static const int kHasInstanceCallHandler = 6;
3860 static const int kIsAccessCheckNeeded = 7;
3861
3862 // Bit positions for bit field 2
Andrei Popescu31002712010-02-23 13:46:05 +00003863 static const int kIsExtensible = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003864 static const int kFunctionWithPrototype = 1;
Steve Block8defd9f2010-07-08 12:39:36 +01003865 static const int kHasFastElements = 2;
Iain Merrick75681382010-08-19 15:07:18 +01003866 static const int kStringWrapperSafeForDefaultValueOf = 3;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003867 static const int kAttachedToSharedFunctionInfo = 4;
3868 static const int kIsShared = 5;
Steve Block44f0eee2011-05-26 01:26:41 +01003869 static const int kHasExternalArrayElements = 6;
Steve Block6ded16b2010-05-10 14:33:55 +01003870
3871 // Layout of the default cache. It holds alternating name and code objects.
3872 static const int kCodeCacheEntrySize = 2;
3873 static const int kCodeCacheEntryNameOffset = 0;
3874 static const int kCodeCacheEntryCodeOffset = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00003875
Iain Merrick75681382010-08-19 15:07:18 +01003876 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
3877 kPointerFieldsEndOffset,
3878 kSize> BodyDescriptor;
3879
Steve Blocka7e24c12009-10-30 11:49:00 +00003880 private:
3881 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
3882};
3883
3884
3885// An abstract superclass, a marker class really, for simple structure classes.
3886// It doesn't carry much functionality but allows struct classes to me
3887// identified in the type system.
3888class Struct: public HeapObject {
3889 public:
3890 inline void InitializeBody(int object_size);
3891 static inline Struct* cast(Object* that);
3892};
3893
3894
3895// Script describes a script which has been added to the VM.
3896class Script: public Struct {
3897 public:
3898 // Script types.
3899 enum Type {
3900 TYPE_NATIVE = 0,
3901 TYPE_EXTENSION = 1,
3902 TYPE_NORMAL = 2
3903 };
3904
3905 // Script compilation types.
3906 enum CompilationType {
3907 COMPILATION_TYPE_HOST = 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003908 COMPILATION_TYPE_EVAL = 1
Steve Blocka7e24c12009-10-30 11:49:00 +00003909 };
3910
3911 // [source]: the script source.
3912 DECL_ACCESSORS(source, Object)
3913
3914 // [name]: the script name.
3915 DECL_ACCESSORS(name, Object)
3916
3917 // [id]: the script id.
3918 DECL_ACCESSORS(id, Object)
3919
3920 // [line_offset]: script line offset in resource from where it was extracted.
3921 DECL_ACCESSORS(line_offset, Smi)
3922
3923 // [column_offset]: script column offset in resource from where it was
3924 // extracted.
3925 DECL_ACCESSORS(column_offset, Smi)
3926
3927 // [data]: additional data associated with this script.
3928 DECL_ACCESSORS(data, Object)
3929
3930 // [context_data]: context data for the context this script was compiled in.
3931 DECL_ACCESSORS(context_data, Object)
3932
3933 // [wrapper]: the wrapper cache.
3934 DECL_ACCESSORS(wrapper, Proxy)
3935
3936 // [type]: the script type.
3937 DECL_ACCESSORS(type, Smi)
3938
3939 // [compilation]: how the the script was compiled.
3940 DECL_ACCESSORS(compilation_type, Smi)
3941
Steve Blockd0582a62009-12-15 09:54:21 +00003942 // [line_ends]: FixedArray of line ends positions.
Steve Blocka7e24c12009-10-30 11:49:00 +00003943 DECL_ACCESSORS(line_ends, Object)
3944
Steve Blockd0582a62009-12-15 09:54:21 +00003945 // [eval_from_shared]: for eval scripts the shared funcion info for the
3946 // function from which eval was called.
3947 DECL_ACCESSORS(eval_from_shared, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00003948
3949 // [eval_from_instructions_offset]: the instruction offset in the code for the
3950 // function from which eval was called where eval was called.
3951 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
3952
3953 static inline Script* cast(Object* obj);
3954
Steve Block3ce2e202009-11-05 08:53:23 +00003955 // If script source is an external string, check that the underlying
3956 // resource is accessible. Otherwise, always return true.
3957 inline bool HasValidSource();
3958
Ben Murdochb0fe1622011-05-05 13:52:32 +01003959#ifdef OBJECT_PRINT
3960 inline void ScriptPrint() {
3961 ScriptPrint(stdout);
3962 }
3963 void ScriptPrint(FILE* out);
3964#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003965#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003966 void ScriptVerify();
3967#endif
3968
3969 static const int kSourceOffset = HeapObject::kHeaderSize;
3970 static const int kNameOffset = kSourceOffset + kPointerSize;
3971 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
3972 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
3973 static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
3974 static const int kContextOffset = kDataOffset + kPointerSize;
3975 static const int kWrapperOffset = kContextOffset + kPointerSize;
3976 static const int kTypeOffset = kWrapperOffset + kPointerSize;
3977 static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
3978 static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
3979 static const int kIdOffset = kLineEndsOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00003980 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003981 static const int kEvalFrominstructionsOffsetOffset =
Steve Blockd0582a62009-12-15 09:54:21 +00003982 kEvalFromSharedOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003983 static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
3984
3985 private:
3986 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
3987};
3988
3989
Ben Murdochb0fe1622011-05-05 13:52:32 +01003990// List of builtin functions we want to identify to improve code
3991// generation.
3992//
3993// Each entry has a name of a global object property holding an object
3994// optionally followed by ".prototype", a name of a builtin function
3995// on the object (the one the id is set for), and a label.
3996//
3997// Installation of ids for the selected builtin functions is handled
3998// by the bootstrapper.
3999//
4000// NOTE: Order is important: math functions should be at the end of
4001// the list and MathFloor should be the first math function.
4002#define FUNCTIONS_WITH_ID_LIST(V) \
4003 V(Array.prototype, push, ArrayPush) \
4004 V(Array.prototype, pop, ArrayPop) \
4005 V(String.prototype, charCodeAt, StringCharCodeAt) \
4006 V(String.prototype, charAt, StringCharAt) \
4007 V(String, fromCharCode, StringFromCharCode) \
4008 V(Math, floor, MathFloor) \
4009 V(Math, round, MathRound) \
4010 V(Math, ceil, MathCeil) \
4011 V(Math, abs, MathAbs) \
4012 V(Math, log, MathLog) \
4013 V(Math, sin, MathSin) \
4014 V(Math, cos, MathCos) \
4015 V(Math, tan, MathTan) \
4016 V(Math, asin, MathASin) \
4017 V(Math, acos, MathACos) \
4018 V(Math, atan, MathATan) \
4019 V(Math, exp, MathExp) \
4020 V(Math, sqrt, MathSqrt) \
4021 V(Math, pow, MathPow)
4022
4023
4024enum BuiltinFunctionId {
4025#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
4026 k##name,
4027 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
4028#undef DECLARE_FUNCTION_ID
4029 // Fake id for a special case of Math.pow. Note, it continues the
4030 // list of math functions.
4031 kMathPowHalf,
4032 kFirstMathFunctionId = kMathFloor
4033};
4034
4035
Steve Blocka7e24c12009-10-30 11:49:00 +00004036// SharedFunctionInfo describes the JSFunction information that can be
4037// shared by multiple instances of the function.
4038class SharedFunctionInfo: public HeapObject {
4039 public:
4040 // [name]: Function name.
4041 DECL_ACCESSORS(name, Object)
4042
4043 // [code]: Function code.
4044 DECL_ACCESSORS(code, Code)
4045
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004046 // [scope_info]: Scope info.
4047 DECL_ACCESSORS(scope_info, SerializedScopeInfo)
4048
Steve Blocka7e24c12009-10-30 11:49:00 +00004049 // [construct stub]: Code stub for constructing instances of this function.
4050 DECL_ACCESSORS(construct_stub, Code)
4051
Iain Merrick75681382010-08-19 15:07:18 +01004052 inline Code* unchecked_code();
4053
Steve Blocka7e24c12009-10-30 11:49:00 +00004054 // Returns if this function has been compiled to native code yet.
4055 inline bool is_compiled();
4056
4057 // [length]: The function length - usually the number of declared parameters.
4058 // Use up to 2^30 parameters.
4059 inline int length();
4060 inline void set_length(int value);
4061
4062 // [formal parameter count]: The declared number of parameters.
4063 inline int formal_parameter_count();
4064 inline void set_formal_parameter_count(int value);
4065
4066 // Set the formal parameter count so the function code will be
4067 // called without using argument adaptor frames.
4068 inline void DontAdaptArguments();
4069
4070 // [expected_nof_properties]: Expected number of properties for the function.
4071 inline int expected_nof_properties();
4072 inline void set_expected_nof_properties(int value);
4073
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004074 // Inobject slack tracking is the way to reclaim unused inobject space.
4075 //
4076 // The instance size is initially determined by adding some slack to
4077 // expected_nof_properties (to allow for a few extra properties added
4078 // after the constructor). There is no guarantee that the extra space
4079 // will not be wasted.
4080 //
4081 // Here is the algorithm to reclaim the unused inobject space:
4082 // - Detect the first constructor call for this SharedFunctionInfo.
4083 // When it happens enter the "in progress" state: remember the
4084 // constructor's initial_map and install a special construct stub that
4085 // counts constructor calls.
4086 // - While the tracking is in progress create objects filled with
4087 // one_pointer_filler_map instead of undefined_value. This way they can be
4088 // resized quickly and safely.
4089 // - Once enough (kGenerousAllocationCount) objects have been created
4090 // compute the 'slack' (traverse the map transition tree starting from the
4091 // initial_map and find the lowest value of unused_property_fields).
4092 // - Traverse the transition tree again and decrease the instance size
4093 // of every map. Existing objects will resize automatically (they are
4094 // filled with one_pointer_filler_map). All further allocations will
4095 // use the adjusted instance size.
4096 // - Decrease expected_nof_properties so that an allocations made from
4097 // another context will use the adjusted instance size too.
4098 // - Exit "in progress" state by clearing the reference to the initial_map
4099 // and setting the regular construct stub (generic or inline).
4100 //
4101 // The above is the main event sequence. Some special cases are possible
4102 // while the tracking is in progress:
4103 //
4104 // - GC occurs.
4105 // Check if the initial_map is referenced by any live objects (except this
4106 // SharedFunctionInfo). If it is, continue tracking as usual.
4107 // If it is not, clear the reference and reset the tracking state. The
4108 // tracking will be initiated again on the next constructor call.
4109 //
4110 // - The constructor is called from another context.
4111 // Immediately complete the tracking, perform all the necessary changes
4112 // to maps. This is necessary because there is no efficient way to track
4113 // multiple initial_maps.
4114 // Proceed to create an object in the current context (with the adjusted
4115 // size).
4116 //
4117 // - A different constructor function sharing the same SharedFunctionInfo is
4118 // called in the same context. This could be another closure in the same
4119 // context, or the first function could have been disposed.
4120 // This is handled the same way as the previous case.
4121 //
4122 // Important: inobject slack tracking is not attempted during the snapshot
4123 // creation.
4124
Ben Murdochf87a2032010-10-22 12:50:53 +01004125 static const int kGenerousAllocationCount = 8;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004126
4127 // [construction_count]: Counter for constructor calls made during
4128 // the tracking phase.
4129 inline int construction_count();
4130 inline void set_construction_count(int value);
4131
4132 // [initial_map]: initial map of the first function called as a constructor.
4133 // Saved for the duration of the tracking phase.
4134 // This is a weak link (GC resets it to undefined_value if no other live
4135 // object reference this map).
4136 DECL_ACCESSORS(initial_map, Object)
4137
4138 // True if the initial_map is not undefined and the countdown stub is
4139 // installed.
4140 inline bool IsInobjectSlackTrackingInProgress();
4141
4142 // Starts the tracking.
4143 // Stores the initial map and installs the countdown stub.
4144 // IsInobjectSlackTrackingInProgress is normally true after this call,
4145 // except when tracking have not been started (e.g. the map has no unused
4146 // properties or the snapshot is being built).
4147 void StartInobjectSlackTracking(Map* map);
4148
4149 // Completes the tracking.
4150 // IsInobjectSlackTrackingInProgress is false after this call.
4151 void CompleteInobjectSlackTracking();
4152
4153 // Clears the initial_map before the GC marking phase to ensure the reference
4154 // is weak. IsInobjectSlackTrackingInProgress is false after this call.
4155 void DetachInitialMap();
4156
4157 // Restores the link to the initial map after the GC marking phase.
4158 // IsInobjectSlackTrackingInProgress is true after this call.
4159 void AttachInitialMap(Map* map);
4160
4161 // False if there are definitely no live objects created from this function.
4162 // True if live objects _may_ exist (existence not guaranteed).
4163 // May go back from true to false after GC.
4164 inline bool live_objects_may_exist();
4165
4166 inline void set_live_objects_may_exist(bool value);
4167
Steve Blocka7e24c12009-10-30 11:49:00 +00004168 // [instance class name]: class name for instances.
4169 DECL_ACCESSORS(instance_class_name, Object)
4170
Steve Block6ded16b2010-05-10 14:33:55 +01004171 // [function data]: This field holds some additional data for function.
4172 // Currently it either has FunctionTemplateInfo to make benefit the API
Ben Murdochb0fe1622011-05-05 13:52:32 +01004173 // or Smi identifying a builtin function.
Steve Blocka7e24c12009-10-30 11:49:00 +00004174 // In the long run we don't want all functions to have this field but
4175 // we can fix that when we have a better model for storing hidden data
4176 // on objects.
4177 DECL_ACCESSORS(function_data, Object)
4178
Steve Block6ded16b2010-05-10 14:33:55 +01004179 inline bool IsApiFunction();
4180 inline FunctionTemplateInfo* get_api_func_data();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004181 inline bool HasBuiltinFunctionId();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004182 inline BuiltinFunctionId builtin_function_id();
Steve Block6ded16b2010-05-10 14:33:55 +01004183
Steve Blocka7e24c12009-10-30 11:49:00 +00004184 // [script info]: Script from which the function originates.
4185 DECL_ACCESSORS(script, Object)
4186
Steve Block6ded16b2010-05-10 14:33:55 +01004187 // [num_literals]: Number of literals used by this function.
4188 inline int num_literals();
4189 inline void set_num_literals(int value);
4190
Steve Blocka7e24c12009-10-30 11:49:00 +00004191 // [start_position_and_type]: Field used to store both the source code
4192 // position, whether or not the function is a function expression,
4193 // and whether or not the function is a toplevel function. The two
4194 // least significants bit indicates whether the function is an
4195 // expression and the rest contains the source code position.
4196 inline int start_position_and_type();
4197 inline void set_start_position_and_type(int value);
4198
4199 // [debug info]: Debug information.
4200 DECL_ACCESSORS(debug_info, Object)
4201
4202 // [inferred name]: Name inferred from variable or property
4203 // assignment of this function. Used to facilitate debugging and
4204 // profiling of JavaScript code written in OO style, where almost
4205 // all functions are anonymous but are assigned to object
4206 // properties.
4207 DECL_ACCESSORS(inferred_name, String)
4208
Ben Murdochf87a2032010-10-22 12:50:53 +01004209 // The function's name if it is non-empty, otherwise the inferred name.
4210 String* DebugName();
4211
Steve Blocka7e24c12009-10-30 11:49:00 +00004212 // Position of the 'function' token in the script source.
4213 inline int function_token_position();
4214 inline void set_function_token_position(int function_token_position);
4215
4216 // Position of this function in the script source.
4217 inline int start_position();
4218 inline void set_start_position(int start_position);
4219
4220 // End position of this function in the script source.
4221 inline int end_position();
4222 inline void set_end_position(int end_position);
4223
4224 // Is this function a function expression in the source code.
4225 inline bool is_expression();
4226 inline void set_is_expression(bool value);
4227
4228 // Is this function a top-level function (scripts, evals).
4229 inline bool is_toplevel();
4230 inline void set_is_toplevel(bool value);
4231
4232 // Bit field containing various information collected by the compiler to
4233 // drive optimization.
4234 inline int compiler_hints();
4235 inline void set_compiler_hints(int value);
4236
Ben Murdochb0fe1622011-05-05 13:52:32 +01004237 // A counter used to determine when to stress the deoptimizer with a
4238 // deopt.
4239 inline Smi* deopt_counter();
4240 inline void set_deopt_counter(Smi* counter);
4241
Steve Blocka7e24c12009-10-30 11:49:00 +00004242 // Add information on assignments of the form this.x = ...;
4243 void SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +00004244 bool has_only_simple_this_property_assignments,
4245 FixedArray* this_property_assignments);
4246
4247 // Clear information on assignments of the form this.x = ...;
4248 void ClearThisPropertyAssignmentsInfo();
4249
4250 // Indicate that this function only consists of assignments of the form
Steve Blocka7e24c12009-10-30 11:49:00 +00004251 // this.x = y; where y is either a constant or refers to an argument.
4252 inline bool has_only_simple_this_property_assignments();
4253
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004254 // Indicates if this function can be lazy compiled.
4255 // This is used to determine if we can safely flush code from a function
4256 // when doing GC if we expect that the function will no longer be used.
4257 inline bool allows_lazy_compilation();
4258 inline void set_allows_lazy_compilation(bool flag);
4259
Iain Merrick75681382010-08-19 15:07:18 +01004260 // Indicates how many full GCs this function has survived with assigned
4261 // code object. Used to determine when it is relatively safe to flush
4262 // this code object and replace it with lazy compilation stub.
4263 // Age is reset when GC notices that the code object is referenced
4264 // from the stack or compilation cache.
4265 inline int code_age();
4266 inline void set_code_age(int age);
4267
Ben Murdochb0fe1622011-05-05 13:52:32 +01004268 // Indicates whether optimizations have been disabled for this
4269 // shared function info. If a function is repeatedly optimized or if
4270 // we cannot optimize the function we disable optimization to avoid
4271 // spending time attempting to optimize it again.
4272 inline bool optimization_disabled();
4273 inline void set_optimization_disabled(bool value);
4274
Steve Block1e0659c2011-05-24 12:43:12 +01004275 // Indicates whether the function is a strict mode function.
4276 inline bool strict_mode();
4277 inline void set_strict_mode(bool value);
4278
Ben Murdochb0fe1622011-05-05 13:52:32 +01004279 // Indicates whether or not the code in the shared function support
4280 // deoptimization.
4281 inline bool has_deoptimization_support();
4282
4283 // Enable deoptimization support through recompiled code.
4284 void EnableDeoptimizationSupport(Code* recompiled);
4285
4286 // Lookup the bailout ID and ASSERT that it exists in the non-optimized
4287 // code, returns whether it asserted (i.e., always true if assertions are
4288 // disabled).
4289 bool VerifyBailoutId(int id);
Iain Merrick75681382010-08-19 15:07:18 +01004290
Andrei Popescu402d9372010-02-26 13:31:12 +00004291 // Check whether a inlined constructor can be generated with the given
4292 // prototype.
4293 bool CanGenerateInlineConstructor(Object* prototype);
4294
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004295 // Prevents further attempts to generate inline constructors.
4296 // To be called if generation failed for any reason.
4297 void ForbidInlineConstructor();
4298
Steve Blocka7e24c12009-10-30 11:49:00 +00004299 // For functions which only contains this property assignments this provides
4300 // access to the names for the properties assigned.
4301 DECL_ACCESSORS(this_property_assignments, Object)
4302 inline int this_property_assignments_count();
4303 inline void set_this_property_assignments_count(int value);
4304 String* GetThisPropertyAssignmentName(int index);
4305 bool IsThisPropertyAssignmentArgument(int index);
4306 int GetThisPropertyAssignmentArgument(int index);
4307 Object* GetThisPropertyAssignmentConstant(int index);
4308
4309 // [source code]: Source code for the function.
4310 bool HasSourceCode();
4311 Object* GetSourceCode();
4312
Ben Murdochb0fe1622011-05-05 13:52:32 +01004313 inline int opt_count();
4314 inline void set_opt_count(int opt_count);
4315
4316 // Source size of this function.
4317 int SourceSize();
4318
Steve Blocka7e24c12009-10-30 11:49:00 +00004319 // Calculate the instance size.
4320 int CalculateInstanceSize();
4321
4322 // Calculate the number of in-object properties.
4323 int CalculateInObjectProperties();
4324
4325 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00004326 // Set max_length to -1 for unlimited length.
4327 void SourceCodePrint(StringStream* accumulator, int max_length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004328#ifdef OBJECT_PRINT
4329 inline void SharedFunctionInfoPrint() {
4330 SharedFunctionInfoPrint(stdout);
4331 }
4332 void SharedFunctionInfoPrint(FILE* out);
4333#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004334#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004335 void SharedFunctionInfoVerify();
4336#endif
4337
4338 // Casting.
4339 static inline SharedFunctionInfo* cast(Object* obj);
4340
4341 // Constants.
4342 static const int kDontAdaptArgumentsSentinel = -1;
4343
4344 // Layout description.
Steve Block6ded16b2010-05-10 14:33:55 +01004345 // Pointer fields.
Steve Blocka7e24c12009-10-30 11:49:00 +00004346 static const int kNameOffset = HeapObject::kHeaderSize;
4347 static const int kCodeOffset = kNameOffset + kPointerSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004348 static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
4349 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004350 static const int kInstanceClassNameOffset =
4351 kConstructStubOffset + kPointerSize;
4352 static const int kFunctionDataOffset =
4353 kInstanceClassNameOffset + kPointerSize;
4354 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
4355 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
4356 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004357 static const int kInitialMapOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01004358 kInferredNameOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004359 static const int kThisPropertyAssignmentsOffset =
4360 kInitialMapOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004361 static const int kDeoptCounterOffset =
4362 kThisPropertyAssignmentsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004363#if V8_HOST_ARCH_32_BIT
4364 // Smi fields.
Steve Block6ded16b2010-05-10 14:33:55 +01004365 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01004366 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004367 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
4368 static const int kExpectedNofPropertiesOffset =
4369 kFormalParameterCountOffset + kPointerSize;
4370 static const int kNumLiteralsOffset =
4371 kExpectedNofPropertiesOffset + kPointerSize;
4372 static const int kStartPositionAndTypeOffset =
4373 kNumLiteralsOffset + kPointerSize;
4374 static const int kEndPositionOffset =
4375 kStartPositionAndTypeOffset + kPointerSize;
4376 static const int kFunctionTokenPositionOffset =
4377 kEndPositionOffset + kPointerSize;
4378 static const int kCompilerHintsOffset =
4379 kFunctionTokenPositionOffset + kPointerSize;
4380 static const int kThisPropertyAssignmentsCountOffset =
4381 kCompilerHintsOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004382 static const int kOptCountOffset =
4383 kThisPropertyAssignmentsCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004384 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004385 static const int kSize = kOptCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004386#else
4387 // The only reason to use smi fields instead of int fields
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004388 // is to allow iteration without maps decoding during
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004389 // garbage collections.
4390 // To avoid wasting space on 64-bit architectures we use
4391 // the following trick: we group integer fields into pairs
4392 // First integer in each pair is shifted left by 1.
4393 // By doing this we guarantee that LSB of each kPointerSize aligned
4394 // word is not set and thus this word cannot be treated as pointer
4395 // to HeapObject during old space traversal.
4396 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01004397 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004398 static const int kFormalParameterCountOffset =
4399 kLengthOffset + kIntSize;
4400
Steve Blocka7e24c12009-10-30 11:49:00 +00004401 static const int kExpectedNofPropertiesOffset =
4402 kFormalParameterCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004403 static const int kNumLiteralsOffset =
4404 kExpectedNofPropertiesOffset + kIntSize;
4405
4406 static const int kEndPositionOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01004407 kNumLiteralsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004408 static const int kStartPositionAndTypeOffset =
4409 kEndPositionOffset + kIntSize;
4410
4411 static const int kFunctionTokenPositionOffset =
4412 kStartPositionAndTypeOffset + kIntSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004413 static const int kCompilerHintsOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00004414 kFunctionTokenPositionOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004415
Steve Blocka7e24c12009-10-30 11:49:00 +00004416 static const int kThisPropertyAssignmentsCountOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01004417 kCompilerHintsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004418 static const int kOptCountOffset =
4419 kThisPropertyAssignmentsCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004420
Steve Block6ded16b2010-05-10 14:33:55 +01004421 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004422 static const int kSize = kOptCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004423
4424#endif
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004425
4426 // The construction counter for inobject slack tracking is stored in the
4427 // most significant byte of compiler_hints which is otherwise unused.
4428 // Its offset depends on the endian-ness of the architecture.
4429#if __BYTE_ORDER == __LITTLE_ENDIAN
4430 static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
4431#elif __BYTE_ORDER == __BIG_ENDIAN
4432 static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
4433#else
4434#error Unknown byte ordering
4435#endif
4436
Steve Block6ded16b2010-05-10 14:33:55 +01004437 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004438
Iain Merrick75681382010-08-19 15:07:18 +01004439 typedef FixedBodyDescriptor<kNameOffset,
4440 kThisPropertyAssignmentsOffset + kPointerSize,
4441 kSize> BodyDescriptor;
4442
Steve Blocka7e24c12009-10-30 11:49:00 +00004443 // Bit positions in start_position_and_type.
4444 // The source code start position is in the 30 most significant bits of
4445 // the start_position_and_type field.
4446 static const int kIsExpressionBit = 0;
4447 static const int kIsTopLevelBit = 1;
4448 static const int kStartPositionShift = 2;
4449 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
4450
4451 // Bit positions in compiler_hints.
Steve Blockd0582a62009-12-15 09:54:21 +00004452 static const int kHasOnlySimpleThisPropertyAssignments = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004453 static const int kAllowLazyCompilation = 1;
4454 static const int kLiveObjectsMayExist = 2;
4455 static const int kCodeAgeShift = 3;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004456 static const int kCodeAgeMask = 0x7;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004457 static const int kOptimizationDisabled = 6;
4458 static const int kStrictModeFunction = 7;
Steve Blocka7e24c12009-10-30 11:49:00 +00004459
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004460 private:
4461#if V8_HOST_ARCH_32_BIT
4462 // On 32 bit platforms, compiler hints is a smi.
4463 static const int kCompilerHintsSmiTagSize = kSmiTagSize;
4464 static const int kCompilerHintsSize = kPointerSize;
4465#else
4466 // On 64 bit platforms, compiler hints is not a smi, see comment above.
4467 static const int kCompilerHintsSmiTagSize = 0;
4468 static const int kCompilerHintsSize = kIntSize;
4469#endif
4470
4471 public:
4472 // Constants for optimizing codegen for strict mode function tests.
4473 // Allows to use byte-widgh instructions.
4474 static const int kStrictModeBitWithinByte =
4475 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
4476
4477#if __BYTE_ORDER == __LITTLE_ENDIAN
4478 static const int kStrictModeByteOffset = kCompilerHintsOffset +
4479 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
4480#elif __BYTE_ORDER == __BIG_ENDIAN
4481 static const int kStrictModeByteOffset = kCompilerHintsOffset +
4482 (kCompilerHintsSize - 1) -
4483 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
4484#else
4485#error Unknown byte ordering
4486#endif
4487
4488 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00004489 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
4490};
4491
4492
4493// JSFunction describes JavaScript functions.
4494class JSFunction: public JSObject {
4495 public:
4496 // [prototype_or_initial_map]:
4497 DECL_ACCESSORS(prototype_or_initial_map, Object)
4498
4499 // [shared_function_info]: The information about the function that
4500 // can be shared by instances.
4501 DECL_ACCESSORS(shared, SharedFunctionInfo)
4502
Iain Merrick75681382010-08-19 15:07:18 +01004503 inline SharedFunctionInfo* unchecked_shared();
4504
Steve Blocka7e24c12009-10-30 11:49:00 +00004505 // [context]: The context for this function.
4506 inline Context* context();
4507 inline Object* unchecked_context();
4508 inline void set_context(Object* context);
4509
4510 // [code]: The generated code object for this function. Executed
4511 // when the function is invoked, e.g. foo() or new foo(). See
4512 // [[Call]] and [[Construct]] description in ECMA-262, section
4513 // 8.6.2, page 27.
4514 inline Code* code();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004515 inline void set_code(Code* code);
4516 inline void ReplaceCode(Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00004517
Iain Merrick75681382010-08-19 15:07:18 +01004518 inline Code* unchecked_code();
4519
Steve Blocka7e24c12009-10-30 11:49:00 +00004520 // Tells whether this function is builtin.
4521 inline bool IsBuiltin();
4522
Ben Murdochb0fe1622011-05-05 13:52:32 +01004523 // Tells whether or not the function needs arguments adaption.
4524 inline bool NeedsArgumentsAdaption();
4525
4526 // Tells whether or not this function has been optimized.
4527 inline bool IsOptimized();
4528
Ben Murdoch8b112d22011-06-08 16:22:53 +01004529 // Tells whether or not this function can be optimized.
4530 inline bool IsOptimizable();
4531
Ben Murdochb0fe1622011-05-05 13:52:32 +01004532 // Mark this function for lazy recompilation. The function will be
4533 // recompiled the next time it is executed.
4534 void MarkForLazyRecompilation();
4535
4536 // Tells whether or not the function is already marked for lazy
4537 // recompilation.
4538 inline bool IsMarkedForLazyRecompilation();
4539
4540 // Compute a hash code for the source code of this function.
4541 uint32_t SourceHash();
4542
4543 // Check whether or not this function is inlineable.
4544 bool IsInlineable();
4545
Steve Blocka7e24c12009-10-30 11:49:00 +00004546 // [literals]: Fixed array holding the materialized literals.
4547 //
4548 // If the function contains object, regexp or array literals, the
4549 // literals array prefix contains the object, regexp, and array
4550 // function to be used when creating these literals. This is
4551 // necessary so that we do not dynamically lookup the object, regexp
4552 // or array functions. Performing a dynamic lookup, we might end up
4553 // using the functions from a new context that we should not have
4554 // access to.
4555 DECL_ACCESSORS(literals, FixedArray)
4556
4557 // The initial map for an object created by this constructor.
4558 inline Map* initial_map();
4559 inline void set_initial_map(Map* value);
4560 inline bool has_initial_map();
4561
4562 // Get and set the prototype property on a JSFunction. If the
4563 // function has an initial map the prototype is set on the initial
4564 // map. Otherwise, the prototype is put in the initial map field
4565 // until an initial map is needed.
4566 inline bool has_prototype();
4567 inline bool has_instance_prototype();
4568 inline Object* prototype();
4569 inline Object* instance_prototype();
4570 Object* SetInstancePrototype(Object* value);
John Reck59135872010-11-02 12:39:01 -07004571 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004572
Steve Block6ded16b2010-05-10 14:33:55 +01004573 // After prototype is removed, it will not be created when accessed, and
4574 // [[Construct]] from this function will not be allowed.
4575 Object* RemovePrototype();
4576 inline bool should_have_prototype();
4577
Steve Blocka7e24c12009-10-30 11:49:00 +00004578 // Accessor for this function's initial map's [[class]]
4579 // property. This is primarily used by ECMA native functions. This
4580 // method sets the class_name field of this function's initial map
4581 // to a given value. It creates an initial map if this function does
4582 // not have one. Note that this method does not copy the initial map
4583 // if it has one already, but simply replaces it with the new value.
4584 // Instances created afterwards will have a map whose [[class]] is
4585 // set to 'value', but there is no guarantees on instances created
4586 // before.
4587 Object* SetInstanceClassName(String* name);
4588
4589 // Returns if this function has been compiled to native code yet.
4590 inline bool is_compiled();
4591
Ben Murdochb0fe1622011-05-05 13:52:32 +01004592 // [next_function_link]: Field for linking functions. This list is treated as
4593 // a weak list by the GC.
4594 DECL_ACCESSORS(next_function_link, Object)
4595
4596 // Prints the name of the function using PrintF.
4597 inline void PrintName() {
4598 PrintName(stdout);
4599 }
4600 void PrintName(FILE* out);
4601
Steve Blocka7e24c12009-10-30 11:49:00 +00004602 // Casting.
4603 static inline JSFunction* cast(Object* obj);
4604
Steve Block791712a2010-08-27 10:21:07 +01004605 // Iterates the objects, including code objects indirectly referenced
4606 // through pointers to the first instruction in the code object.
4607 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
4608
Steve Blocka7e24c12009-10-30 11:49:00 +00004609 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004610#ifdef OBJECT_PRINT
4611 inline void JSFunctionPrint() {
4612 JSFunctionPrint(stdout);
4613 }
4614 void JSFunctionPrint(FILE* out);
4615#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004616#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004617 void JSFunctionVerify();
4618#endif
4619
4620 // Returns the number of allocated literals.
4621 inline int NumberOfLiterals();
4622
4623 // Retrieve the global context from a function's literal array.
4624 static Context* GlobalContextFromLiterals(FixedArray* literals);
4625
Ben Murdochb0fe1622011-05-05 13:52:32 +01004626 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
4627 // kSize) is weak and has special handling during garbage collection.
Steve Block791712a2010-08-27 10:21:07 +01004628 static const int kCodeEntryOffset = JSObject::kHeaderSize;
Iain Merrick75681382010-08-19 15:07:18 +01004629 static const int kPrototypeOrInitialMapOffset =
Steve Block791712a2010-08-27 10:21:07 +01004630 kCodeEntryOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004631 static const int kSharedFunctionInfoOffset =
4632 kPrototypeOrInitialMapOffset + kPointerSize;
4633 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
4634 static const int kLiteralsOffset = kContextOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004635 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
4636 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
4637 static const int kSize = kNextFunctionLinkOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004638
4639 // Layout of the literals array.
4640 static const int kLiteralsPrefixSize = 1;
4641 static const int kLiteralGlobalContextIndex = 0;
4642 private:
4643 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
4644};
4645
4646
4647// JSGlobalProxy's prototype must be a JSGlobalObject or null,
4648// and the prototype is hidden. JSGlobalProxy always delegates
4649// property accesses to its prototype if the prototype is not null.
4650//
4651// A JSGlobalProxy can be reinitialized which will preserve its identity.
4652//
4653// Accessing a JSGlobalProxy requires security check.
4654
4655class JSGlobalProxy : public JSObject {
4656 public:
4657 // [context]: the owner global context of this proxy object.
4658 // It is null value if this object is not used by any context.
4659 DECL_ACCESSORS(context, Object)
4660
4661 // Casting.
4662 static inline JSGlobalProxy* cast(Object* obj);
4663
4664 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004665#ifdef OBJECT_PRINT
4666 inline void JSGlobalProxyPrint() {
4667 JSGlobalProxyPrint(stdout);
4668 }
4669 void JSGlobalProxyPrint(FILE* out);
4670#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004671#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004672 void JSGlobalProxyVerify();
4673#endif
4674
4675 // Layout description.
4676 static const int kContextOffset = JSObject::kHeaderSize;
4677 static const int kSize = kContextOffset + kPointerSize;
4678
4679 private:
4680
4681 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
4682};
4683
4684
4685// Forward declaration.
4686class JSBuiltinsObject;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004687class JSGlobalPropertyCell;
Steve Blocka7e24c12009-10-30 11:49:00 +00004688
4689// Common super class for JavaScript global objects and the special
4690// builtins global objects.
4691class GlobalObject: public JSObject {
4692 public:
4693 // [builtins]: the object holding the runtime routines written in JS.
4694 DECL_ACCESSORS(builtins, JSBuiltinsObject)
4695
4696 // [global context]: the global context corresponding to this global object.
4697 DECL_ACCESSORS(global_context, Context)
4698
4699 // [global receiver]: the global receiver object of the context
4700 DECL_ACCESSORS(global_receiver, JSObject)
4701
4702 // Retrieve the property cell used to store a property.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004703 JSGlobalPropertyCell* GetPropertyCell(LookupResult* result);
Steve Blocka7e24c12009-10-30 11:49:00 +00004704
John Reck59135872010-11-02 12:39:01 -07004705 // This is like GetProperty, but is used when you know the lookup won't fail
4706 // by throwing an exception. This is for the debug and builtins global
4707 // objects, where it is known which properties can be expected to be present
4708 // on the object.
4709 Object* GetPropertyNoExceptionThrown(String* key) {
4710 Object* answer = GetProperty(key)->ToObjectUnchecked();
4711 return answer;
4712 }
4713
Steve Blocka7e24c12009-10-30 11:49:00 +00004714 // Ensure that the global object has a cell for the given property name.
John Reck59135872010-11-02 12:39:01 -07004715 MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004716
4717 // Casting.
4718 static inline GlobalObject* cast(Object* obj);
4719
4720 // Layout description.
4721 static const int kBuiltinsOffset = JSObject::kHeaderSize;
4722 static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
4723 static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
4724 static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
4725
4726 private:
4727 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
4728
4729 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
4730};
4731
4732
4733// JavaScript global object.
4734class JSGlobalObject: public GlobalObject {
4735 public:
4736
4737 // Casting.
4738 static inline JSGlobalObject* cast(Object* obj);
4739
4740 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004741#ifdef OBJECT_PRINT
4742 inline void JSGlobalObjectPrint() {
4743 JSGlobalObjectPrint(stdout);
4744 }
4745 void JSGlobalObjectPrint(FILE* out);
4746#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004747#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004748 void JSGlobalObjectVerify();
4749#endif
4750
4751 // Layout description.
4752 static const int kSize = GlobalObject::kHeaderSize;
4753
4754 private:
4755 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
4756};
4757
4758
4759// Builtins global object which holds the runtime routines written in
4760// JavaScript.
4761class JSBuiltinsObject: public GlobalObject {
4762 public:
4763 // Accessors for the runtime routines written in JavaScript.
4764 inline Object* javascript_builtin(Builtins::JavaScript id);
4765 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
4766
Steve Block6ded16b2010-05-10 14:33:55 +01004767 // Accessors for code of the runtime routines written in JavaScript.
4768 inline Code* javascript_builtin_code(Builtins::JavaScript id);
4769 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
4770
Steve Blocka7e24c12009-10-30 11:49:00 +00004771 // Casting.
4772 static inline JSBuiltinsObject* cast(Object* obj);
4773
4774 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004775#ifdef OBJECT_PRINT
4776 inline void JSBuiltinsObjectPrint() {
4777 JSBuiltinsObjectPrint(stdout);
4778 }
4779 void JSBuiltinsObjectPrint(FILE* out);
4780#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004781#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004782 void JSBuiltinsObjectVerify();
4783#endif
4784
4785 // Layout description. The size of the builtins object includes
Steve Block6ded16b2010-05-10 14:33:55 +01004786 // room for two pointers per runtime routine written in javascript
4787 // (function and code object).
Steve Blocka7e24c12009-10-30 11:49:00 +00004788 static const int kJSBuiltinsCount = Builtins::id_count;
4789 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004790 static const int kJSBuiltinsCodeOffset =
4791 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004792 static const int kSize =
Steve Block6ded16b2010-05-10 14:33:55 +01004793 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
4794
4795 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
4796 return kJSBuiltinsOffset + id * kPointerSize;
4797 }
4798
4799 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
4800 return kJSBuiltinsCodeOffset + id * kPointerSize;
4801 }
4802
Steve Blocka7e24c12009-10-30 11:49:00 +00004803 private:
4804 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
4805};
4806
4807
4808// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
4809class JSValue: public JSObject {
4810 public:
4811 // [value]: the object being wrapped.
4812 DECL_ACCESSORS(value, Object)
4813
4814 // Casting.
4815 static inline JSValue* cast(Object* obj);
4816
4817 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004818#ifdef OBJECT_PRINT
4819 inline void JSValuePrint() {
4820 JSValuePrint(stdout);
4821 }
4822 void JSValuePrint(FILE* out);
4823#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004824#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004825 void JSValueVerify();
4826#endif
4827
4828 // Layout description.
4829 static const int kValueOffset = JSObject::kHeaderSize;
4830 static const int kSize = kValueOffset + kPointerSize;
4831
4832 private:
4833 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
4834};
4835
Steve Block1e0659c2011-05-24 12:43:12 +01004836
4837// Representation of message objects used for error reporting through
4838// the API. The messages are formatted in JavaScript so this object is
4839// a real JavaScript object. The information used for formatting the
4840// error messages are not directly accessible from JavaScript to
4841// prevent leaking information to user code called during error
4842// formatting.
4843class JSMessageObject: public JSObject {
4844 public:
4845 // [type]: the type of error message.
4846 DECL_ACCESSORS(type, String)
4847
4848 // [arguments]: the arguments for formatting the error message.
4849 DECL_ACCESSORS(arguments, JSArray)
4850
4851 // [script]: the script from which the error message originated.
4852 DECL_ACCESSORS(script, Object)
4853
4854 // [stack_trace]: the stack trace for this error message.
4855 DECL_ACCESSORS(stack_trace, Object)
4856
4857 // [stack_frames]: an array of stack frames for this error object.
4858 DECL_ACCESSORS(stack_frames, Object)
4859
4860 // [start_position]: the start position in the script for the error message.
4861 inline int start_position();
4862 inline void set_start_position(int value);
4863
4864 // [end_position]: the end position in the script for the error message.
4865 inline int end_position();
4866 inline void set_end_position(int value);
4867
4868 // Casting.
4869 static inline JSMessageObject* cast(Object* obj);
4870
4871 // Dispatched behavior.
4872#ifdef OBJECT_PRINT
4873 inline void JSMessageObjectPrint() {
4874 JSMessageObjectPrint(stdout);
4875 }
4876 void JSMessageObjectPrint(FILE* out);
4877#endif
4878#ifdef DEBUG
4879 void JSMessageObjectVerify();
4880#endif
4881
4882 // Layout description.
4883 static const int kTypeOffset = JSObject::kHeaderSize;
4884 static const int kArgumentsOffset = kTypeOffset + kPointerSize;
4885 static const int kScriptOffset = kArgumentsOffset + kPointerSize;
4886 static const int kStackTraceOffset = kScriptOffset + kPointerSize;
4887 static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
4888 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
4889 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
4890 static const int kSize = kEndPositionOffset + kPointerSize;
4891
4892 typedef FixedBodyDescriptor<HeapObject::kMapOffset,
4893 kStackFramesOffset + kPointerSize,
4894 kSize> BodyDescriptor;
4895};
4896
4897
Steve Blocka7e24c12009-10-30 11:49:00 +00004898// Regular expressions
4899// The regular expression holds a single reference to a FixedArray in
4900// the kDataOffset field.
4901// The FixedArray contains the following data:
4902// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
4903// - reference to the original source string
4904// - reference to the original flag string
4905// If it is an atom regexp
4906// - a reference to a literal string to search for
4907// If it is an irregexp regexp:
4908// - a reference to code for ASCII inputs (bytecode or compiled).
4909// - a reference to code for UC16 inputs (bytecode or compiled).
4910// - max number of registers used by irregexp implementations.
4911// - number of capture registers (output values) of the regexp.
4912class JSRegExp: public JSObject {
4913 public:
4914 // Meaning of Type:
4915 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
4916 // ATOM: A simple string to match against using an indexOf operation.
4917 // IRREGEXP: Compiled with Irregexp.
4918 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
4919 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
4920 enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
4921
4922 class Flags {
4923 public:
4924 explicit Flags(uint32_t value) : value_(value) { }
4925 bool is_global() { return (value_ & GLOBAL) != 0; }
4926 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
4927 bool is_multiline() { return (value_ & MULTILINE) != 0; }
4928 uint32_t value() { return value_; }
4929 private:
4930 uint32_t value_;
4931 };
4932
4933 DECL_ACCESSORS(data, Object)
4934
4935 inline Type TypeTag();
4936 inline int CaptureCount();
4937 inline Flags GetFlags();
4938 inline String* Pattern();
4939 inline Object* DataAt(int index);
4940 // Set implementation data after the object has been prepared.
4941 inline void SetDataAt(int index, Object* value);
4942 static int code_index(bool is_ascii) {
4943 if (is_ascii) {
4944 return kIrregexpASCIICodeIndex;
4945 } else {
4946 return kIrregexpUC16CodeIndex;
4947 }
4948 }
4949
4950 static inline JSRegExp* cast(Object* obj);
4951
4952 // Dispatched behavior.
4953#ifdef DEBUG
4954 void JSRegExpVerify();
4955#endif
4956
4957 static const int kDataOffset = JSObject::kHeaderSize;
4958 static const int kSize = kDataOffset + kPointerSize;
4959
4960 // Indices in the data array.
4961 static const int kTagIndex = 0;
4962 static const int kSourceIndex = kTagIndex + 1;
4963 static const int kFlagsIndex = kSourceIndex + 1;
4964 static const int kDataIndex = kFlagsIndex + 1;
4965 // The data fields are used in different ways depending on the
4966 // value of the tag.
4967 // Atom regexps (literal strings).
4968 static const int kAtomPatternIndex = kDataIndex;
4969
4970 static const int kAtomDataSize = kAtomPatternIndex + 1;
4971
4972 // Irregexp compiled code or bytecode for ASCII. If compilation
4973 // fails, this fields hold an exception object that should be
4974 // thrown if the regexp is used again.
4975 static const int kIrregexpASCIICodeIndex = kDataIndex;
4976 // Irregexp compiled code or bytecode for UC16. If compilation
4977 // fails, this fields hold an exception object that should be
4978 // thrown if the regexp is used again.
4979 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
4980 // Maximal number of registers used by either ASCII or UC16.
4981 // Only used to check that there is enough stack space
4982 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 2;
4983 // Number of captures in the compiled regexp.
4984 static const int kIrregexpCaptureCountIndex = kDataIndex + 3;
4985
4986 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
Leon Clarkee46be812010-01-19 14:06:41 +00004987
4988 // Offsets directly into the data fixed array.
4989 static const int kDataTagOffset =
4990 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
4991 static const int kDataAsciiCodeOffset =
4992 FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +00004993 static const int kDataUC16CodeOffset =
4994 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00004995 static const int kIrregexpCaptureCountOffset =
4996 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004997
4998 // In-object fields.
4999 static const int kSourceFieldIndex = 0;
5000 static const int kGlobalFieldIndex = 1;
5001 static const int kIgnoreCaseFieldIndex = 2;
5002 static const int kMultilineFieldIndex = 3;
5003 static const int kLastIndexFieldIndex = 4;
Ben Murdochbb769b22010-08-11 14:56:33 +01005004 static const int kInObjectFieldCount = 5;
Steve Blocka7e24c12009-10-30 11:49:00 +00005005};
5006
5007
5008class CompilationCacheShape {
5009 public:
5010 static inline bool IsMatch(HashTableKey* key, Object* value) {
5011 return key->IsMatch(value);
5012 }
5013
5014 static inline uint32_t Hash(HashTableKey* key) {
5015 return key->Hash();
5016 }
5017
5018 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5019 return key->HashForObject(object);
5020 }
5021
John Reck59135872010-11-02 12:39:01 -07005022 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005023 return key->AsObject();
5024 }
5025
5026 static const int kPrefixSize = 0;
5027 static const int kEntrySize = 2;
5028};
5029
Steve Block3ce2e202009-11-05 08:53:23 +00005030
Steve Blocka7e24c12009-10-30 11:49:00 +00005031class CompilationCacheTable: public HashTable<CompilationCacheShape,
5032 HashTableKey*> {
5033 public:
5034 // Find cached value for a string key, otherwise return null.
5035 Object* Lookup(String* src);
Steve Block1e0659c2011-05-24 12:43:12 +01005036 Object* LookupEval(String* src, Context* context, StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00005037 Object* LookupRegExp(String* source, JSRegExp::Flags flags);
John Reck59135872010-11-02 12:39:01 -07005038 MaybeObject* Put(String* src, Object* value);
Steve Block1e0659c2011-05-24 12:43:12 +01005039 MaybeObject* PutEval(String* src,
5040 Context* context,
5041 SharedFunctionInfo* value);
John Reck59135872010-11-02 12:39:01 -07005042 MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005043
Ben Murdochb0fe1622011-05-05 13:52:32 +01005044 // Remove given value from cache.
5045 void Remove(Object* value);
5046
Steve Blocka7e24c12009-10-30 11:49:00 +00005047 static inline CompilationCacheTable* cast(Object* obj);
5048
5049 private:
5050 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
5051};
5052
5053
Steve Block6ded16b2010-05-10 14:33:55 +01005054class CodeCache: public Struct {
5055 public:
5056 DECL_ACCESSORS(default_cache, FixedArray)
5057 DECL_ACCESSORS(normal_type_cache, Object)
5058
5059 // Add the code object to the cache.
John Reck59135872010-11-02 12:39:01 -07005060 MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005061
5062 // Lookup code object in the cache. Returns code object if found and undefined
5063 // if not.
5064 Object* Lookup(String* name, Code::Flags flags);
5065
5066 // Get the internal index of a code object in the cache. Returns -1 if the
5067 // code object is not in that cache. This index can be used to later call
5068 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
5069 // RemoveByIndex.
5070 int GetIndex(Object* name, Code* code);
5071
5072 // Remove an object from the cache with the provided internal index.
5073 void RemoveByIndex(Object* name, Code* code, int index);
5074
5075 static inline CodeCache* cast(Object* obj);
5076
Ben Murdochb0fe1622011-05-05 13:52:32 +01005077#ifdef OBJECT_PRINT
5078 inline void CodeCachePrint() {
5079 CodeCachePrint(stdout);
5080 }
5081 void CodeCachePrint(FILE* out);
5082#endif
Steve Block6ded16b2010-05-10 14:33:55 +01005083#ifdef DEBUG
Steve Block6ded16b2010-05-10 14:33:55 +01005084 void CodeCacheVerify();
5085#endif
5086
5087 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
5088 static const int kNormalTypeCacheOffset =
5089 kDefaultCacheOffset + kPointerSize;
5090 static const int kSize = kNormalTypeCacheOffset + kPointerSize;
5091
5092 private:
John Reck59135872010-11-02 12:39:01 -07005093 MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
5094 MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005095 Object* LookupDefaultCache(String* name, Code::Flags flags);
5096 Object* LookupNormalTypeCache(String* name, Code::Flags flags);
5097
5098 // Code cache layout of the default cache. Elements are alternating name and
5099 // code objects for non normal load/store/call IC's.
5100 static const int kCodeCacheEntrySize = 2;
5101 static const int kCodeCacheEntryNameOffset = 0;
5102 static const int kCodeCacheEntryCodeOffset = 1;
5103
5104 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
5105};
5106
5107
5108class CodeCacheHashTableShape {
5109 public:
5110 static inline bool IsMatch(HashTableKey* key, Object* value) {
5111 return key->IsMatch(value);
5112 }
5113
5114 static inline uint32_t Hash(HashTableKey* key) {
5115 return key->Hash();
5116 }
5117
5118 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5119 return key->HashForObject(object);
5120 }
5121
John Reck59135872010-11-02 12:39:01 -07005122 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Block6ded16b2010-05-10 14:33:55 +01005123 return key->AsObject();
5124 }
5125
5126 static const int kPrefixSize = 0;
5127 static const int kEntrySize = 2;
5128};
5129
5130
5131class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
5132 HashTableKey*> {
5133 public:
5134 Object* Lookup(String* name, Code::Flags flags);
John Reck59135872010-11-02 12:39:01 -07005135 MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005136
5137 int GetIndex(String* name, Code::Flags flags);
5138 void RemoveByIndex(int index);
5139
5140 static inline CodeCacheHashTable* cast(Object* obj);
5141
5142 // Initial size of the fixed array backing the hash table.
5143 static const int kInitialSize = 64;
5144
5145 private:
5146 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
5147};
5148
5149
Steve Blocka7e24c12009-10-30 11:49:00 +00005150enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
5151enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
5152
5153
5154class StringHasher {
5155 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +01005156 explicit inline StringHasher(int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00005157
5158 // Returns true if the hash of this string can be computed without
5159 // looking at the contents.
5160 inline bool has_trivial_hash();
5161
5162 // Add a character to the hash and update the array index calculation.
5163 inline void AddCharacter(uc32 c);
5164
5165 // Adds a character to the hash but does not update the array index
5166 // calculation. This can only be called when it has been verified
5167 // that the input is not an array index.
5168 inline void AddCharacterNoIndex(uc32 c);
5169
5170 // Returns the value to store in the hash field of a string with
5171 // the given length and contents.
5172 uint32_t GetHashField();
5173
5174 // Returns true if the characters seen so far make up a legal array
5175 // index.
5176 bool is_array_index() { return is_array_index_; }
5177
5178 bool is_valid() { return is_valid_; }
5179
5180 void invalidate() { is_valid_ = false; }
5181
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005182 // Calculated hash value for a string consisting of 1 to
5183 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
5184 // value is represented decimal value.
Iain Merrick9ac36c92010-09-13 15:29:50 +01005185 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005186
Steve Blocka7e24c12009-10-30 11:49:00 +00005187 private:
5188
5189 uint32_t array_index() {
5190 ASSERT(is_array_index());
5191 return array_index_;
5192 }
5193
5194 inline uint32_t GetHash();
5195
5196 int length_;
5197 uint32_t raw_running_hash_;
5198 uint32_t array_index_;
5199 bool is_array_index_;
5200 bool is_first_char_;
5201 bool is_valid_;
Steve Blockd0582a62009-12-15 09:54:21 +00005202 friend class TwoCharHashTableKey;
Steve Blocka7e24c12009-10-30 11:49:00 +00005203};
5204
5205
Steve Block44f0eee2011-05-26 01:26:41 +01005206// Calculates string hash.
5207template <typename schar>
5208inline uint32_t HashSequentialString(const schar* chars, int length);
5209
5210
Steve Blocka7e24c12009-10-30 11:49:00 +00005211// The characteristics of a string are stored in its map. Retrieving these
5212// few bits of information is moderately expensive, involving two memory
5213// loads where the second is dependent on the first. To improve efficiency
5214// the shape of the string is given its own class so that it can be retrieved
5215// once and used for several string operations. A StringShape is small enough
5216// to be passed by value and is immutable, but be aware that flattening a
5217// string can potentially alter its shape. Also be aware that a GC caused by
5218// something else can alter the shape of a string due to ConsString
5219// shortcutting. Keeping these restrictions in mind has proven to be error-
5220// prone and so we no longer put StringShapes in variables unless there is a
5221// concrete performance benefit at that particular point in the code.
5222class StringShape BASE_EMBEDDED {
5223 public:
5224 inline explicit StringShape(String* s);
5225 inline explicit StringShape(Map* s);
5226 inline explicit StringShape(InstanceType t);
5227 inline bool IsSequential();
5228 inline bool IsExternal();
5229 inline bool IsCons();
Steve Blocka7e24c12009-10-30 11:49:00 +00005230 inline bool IsExternalAscii();
5231 inline bool IsExternalTwoByte();
5232 inline bool IsSequentialAscii();
5233 inline bool IsSequentialTwoByte();
5234 inline bool IsSymbol();
5235 inline StringRepresentationTag representation_tag();
5236 inline uint32_t full_representation_tag();
5237 inline uint32_t size_tag();
5238#ifdef DEBUG
5239 inline uint32_t type() { return type_; }
5240 inline void invalidate() { valid_ = false; }
5241 inline bool valid() { return valid_; }
5242#else
5243 inline void invalidate() { }
5244#endif
5245 private:
5246 uint32_t type_;
5247#ifdef DEBUG
5248 inline void set_valid() { valid_ = true; }
5249 bool valid_;
5250#else
5251 inline void set_valid() { }
5252#endif
5253};
5254
5255
5256// The String abstract class captures JavaScript string values:
5257//
5258// Ecma-262:
5259// 4.3.16 String Value
5260// A string value is a member of the type String and is a finite
5261// ordered sequence of zero or more 16-bit unsigned integer values.
5262//
5263// All string values have a length field.
5264class String: public HeapObject {
5265 public:
5266 // Get and set the length of the string.
5267 inline int length();
5268 inline void set_length(int value);
5269
Steve Blockd0582a62009-12-15 09:54:21 +00005270 // Get and set the hash field of the string.
5271 inline uint32_t hash_field();
5272 inline void set_hash_field(uint32_t value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005273
5274 inline bool IsAsciiRepresentation();
5275 inline bool IsTwoByteRepresentation();
5276
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005277 // Returns whether this string has ascii chars, i.e. all of them can
5278 // be ascii encoded. This might be the case even if the string is
5279 // two-byte. Such strings may appear when the embedder prefers
5280 // two-byte external representations even for ascii data.
Steve Block6ded16b2010-05-10 14:33:55 +01005281 //
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005282 // NOTE: this should be considered only a hint. False negatives are
5283 // possible.
5284 inline bool HasOnlyAsciiChars();
Steve Block6ded16b2010-05-10 14:33:55 +01005285
Steve Blocka7e24c12009-10-30 11:49:00 +00005286 // Get and set individual two byte chars in the string.
5287 inline void Set(int index, uint16_t value);
5288 // Get individual two byte char in the string. Repeated calls
5289 // to this method are not efficient unless the string is flat.
5290 inline uint16_t Get(int index);
5291
Leon Clarkef7060e22010-06-03 12:02:55 +01005292 // Try to flatten the string. Checks first inline to see if it is
5293 // necessary. Does nothing if the string is not a cons string.
5294 // Flattening allocates a sequential string with the same data as
5295 // the given string and mutates the cons string to a degenerate
5296 // form, where the first component is the new sequential string and
5297 // the second component is the empty string. If allocation fails,
5298 // this function returns a failure. If flattening succeeds, this
5299 // function returns the sequential string that is now the first
5300 // component of the cons string.
5301 //
5302 // Degenerate cons strings are handled specially by the garbage
5303 // collector (see IsShortcutCandidate).
5304 //
5305 // Use FlattenString from Handles.cc to flatten even in case an
5306 // allocation failure happens.
John Reck59135872010-11-02 12:39:01 -07005307 inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005308
Leon Clarkef7060e22010-06-03 12:02:55 +01005309 // Convenience function. Has exactly the same behavior as
5310 // TryFlatten(), except in the case of failure returns the original
5311 // string.
5312 inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
5313
Steve Blocka7e24c12009-10-30 11:49:00 +00005314 Vector<const char> ToAsciiVector();
5315 Vector<const uc16> ToUC16Vector();
5316
5317 // Mark the string as an undetectable object. It only applies to
5318 // ascii and two byte string types.
5319 bool MarkAsUndetectable();
5320
Steve Blockd0582a62009-12-15 09:54:21 +00005321 // Return a substring.
John Reck59135872010-11-02 12:39:01 -07005322 MUST_USE_RESULT MaybeObject* SubString(int from,
5323 int to,
5324 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005325
5326 // String equality operations.
5327 inline bool Equals(String* other);
5328 bool IsEqualTo(Vector<const char> str);
Steve Block9fac8402011-05-12 15:51:54 +01005329 bool IsAsciiEqualTo(Vector<const char> str);
5330 bool IsTwoByteEqualTo(Vector<const uc16> str);
Steve Blocka7e24c12009-10-30 11:49:00 +00005331
5332 // Return a UTF8 representation of the string. The string is null
5333 // terminated but may optionally contain nulls. Length is returned
5334 // in length_output if length_output is not a null pointer The string
5335 // should be nearly flat, otherwise the performance of this method may
5336 // be very slow (quadratic in the length). Setting robustness_flag to
5337 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
5338 // handles unexpected data without causing assert failures and it does not
5339 // do any heap allocations. This is useful when printing stack traces.
5340 SmartPointer<char> ToCString(AllowNullsFlag allow_nulls,
5341 RobustnessFlag robustness_flag,
5342 int offset,
5343 int length,
5344 int* length_output = 0);
5345 SmartPointer<char> ToCString(
5346 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
5347 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
5348 int* length_output = 0);
5349
5350 int Utf8Length();
5351
5352 // Return a 16 bit Unicode representation of the string.
5353 // The string should be nearly flat, otherwise the performance of
5354 // of this method may be very bad. Setting robustness_flag to
5355 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
5356 // handles unexpected data without causing assert failures and it does not
5357 // do any heap allocations. This is useful when printing stack traces.
5358 SmartPointer<uc16> ToWideCString(
5359 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
5360
5361 // Tells whether the hash code has been computed.
5362 inline bool HasHashCode();
5363
5364 // Returns a hash value used for the property table
5365 inline uint32_t Hash();
5366
Steve Blockd0582a62009-12-15 09:54:21 +00005367 static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
5368 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00005369
5370 static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
5371 uint32_t* index,
5372 int length);
5373
5374 // Externalization.
5375 bool MakeExternal(v8::String::ExternalStringResource* resource);
5376 bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
5377
5378 // Conversion.
5379 inline bool AsArrayIndex(uint32_t* index);
5380
5381 // Casting.
5382 static inline String* cast(Object* obj);
5383
5384 void PrintOn(FILE* out);
5385
5386 // For use during stack traces. Performs rudimentary sanity check.
5387 bool LooksValid();
5388
5389 // Dispatched behavior.
5390 void StringShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005391#ifdef OBJECT_PRINT
5392 inline void StringPrint() {
5393 StringPrint(stdout);
5394 }
5395 void StringPrint(FILE* out);
5396#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005397#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005398 void StringVerify();
5399#endif
5400 inline bool IsFlat();
5401
5402 // Layout description.
5403 static const int kLengthOffset = HeapObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005404 static const int kHashFieldOffset = kLengthOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005405 static const int kSize = kHashFieldOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005406
Steve Blockd0582a62009-12-15 09:54:21 +00005407 // Maximum number of characters to consider when trying to convert a string
5408 // value into an array index.
Steve Blocka7e24c12009-10-30 11:49:00 +00005409 static const int kMaxArrayIndexSize = 10;
5410
5411 // Max ascii char code.
5412 static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
5413 static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
5414 static const int kMaxUC16CharCode = 0xffff;
5415
Steve Blockd0582a62009-12-15 09:54:21 +00005416 // Minimum length for a cons string.
Steve Blocka7e24c12009-10-30 11:49:00 +00005417 static const int kMinNonFlatLength = 13;
5418
5419 // Mask constant for checking if a string has a computed hash code
5420 // and if it is an array index. The least significant bit indicates
5421 // whether a hash code has been computed. If the hash code has been
5422 // computed the 2nd bit tells whether the string can be used as an
5423 // array index.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005424 static const int kHashNotComputedMask = 1;
5425 static const int kIsNotArrayIndexMask = 1 << 1;
5426 static const int kNofHashBitFields = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +00005427
Steve Blockd0582a62009-12-15 09:54:21 +00005428 // Shift constant retrieving hash code from hash field.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005429 static const int kHashShift = kNofHashBitFields;
Steve Blockd0582a62009-12-15 09:54:21 +00005430
Steve Blocka7e24c12009-10-30 11:49:00 +00005431 // Array index strings this short can keep their index in the hash
5432 // field.
5433 static const int kMaxCachedArrayIndexLength = 7;
5434
Steve Blockd0582a62009-12-15 09:54:21 +00005435 // For strings which are array indexes the hash value has the string length
5436 // mixed into the hash, mainly to avoid a hash value of zero which would be
5437 // the case for the string '0'. 24 bits are used for the array index value.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005438 static const int kArrayIndexValueBits = 24;
5439 static const int kArrayIndexLengthBits =
5440 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
5441
5442 STATIC_CHECK((kArrayIndexLengthBits > 0));
Iain Merrick9ac36c92010-09-13 15:29:50 +01005443 STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005444
5445 static const int kArrayIndexHashLengthShift =
5446 kArrayIndexValueBits + kNofHashBitFields;
5447
Steve Blockd0582a62009-12-15 09:54:21 +00005448 static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005449
5450 static const int kArrayIndexValueMask =
5451 ((1 << kArrayIndexValueBits) - 1) << kHashShift;
5452
5453 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
5454 // could use a mask to test if the length of string is less than or equal to
5455 // kMaxCachedArrayIndexLength.
5456 STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
5457
5458 static const int kContainsCachedArrayIndexMask =
5459 (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
5460 kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00005461
5462 // Value of empty hash field indicating that the hash is not computed.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005463 static const int kEmptyHashField =
5464 kIsNotArrayIndexMask | kHashNotComputedMask;
5465
5466 // Value of hash field containing computed hash equal to zero.
5467 static const int kZeroHash = kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00005468
5469 // Maximal string length.
5470 static const int kMaxLength = (1 << (32 - 2)) - 1;
5471
5472 // Max length for computing hash. For strings longer than this limit the
5473 // string length is used as the hash value.
5474 static const int kMaxHashCalcLength = 16383;
Steve Blocka7e24c12009-10-30 11:49:00 +00005475
5476 // Limit for truncation in short printing.
5477 static const int kMaxShortPrintLength = 1024;
5478
5479 // Support for regular expressions.
5480 const uc16* GetTwoByteData();
5481 const uc16* GetTwoByteData(unsigned start);
5482
5483 // Support for StringInputBuffer
5484 static const unibrow::byte* ReadBlock(String* input,
5485 unibrow::byte* util_buffer,
5486 unsigned capacity,
5487 unsigned* remaining,
5488 unsigned* offset);
5489 static const unibrow::byte* ReadBlock(String** input,
5490 unibrow::byte* util_buffer,
5491 unsigned capacity,
5492 unsigned* remaining,
5493 unsigned* offset);
5494
5495 // Helper function for flattening strings.
5496 template <typename sinkchar>
5497 static void WriteToFlat(String* source,
5498 sinkchar* sink,
5499 int from,
5500 int to);
5501
Steve Block9fac8402011-05-12 15:51:54 +01005502 static inline bool IsAscii(const char* chars, int length) {
5503 const char* limit = chars + length;
5504#ifdef V8_HOST_CAN_READ_UNALIGNED
5505 ASSERT(kMaxAsciiCharCode == 0x7F);
5506 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
5507 while (chars <= limit - sizeof(uintptr_t)) {
5508 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
5509 return false;
5510 }
5511 chars += sizeof(uintptr_t);
5512 }
5513#endif
5514 while (chars < limit) {
5515 if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
5516 ++chars;
5517 }
5518 return true;
5519 }
5520
5521 static inline bool IsAscii(const uc16* chars, int length) {
5522 const uc16* limit = chars + length;
5523 while (chars < limit) {
5524 if (*chars > kMaxAsciiCharCodeU) return false;
5525 ++chars;
5526 }
5527 return true;
5528 }
5529
Steve Blocka7e24c12009-10-30 11:49:00 +00005530 protected:
5531 class ReadBlockBuffer {
5532 public:
5533 ReadBlockBuffer(unibrow::byte* util_buffer_,
5534 unsigned cursor_,
5535 unsigned capacity_,
5536 unsigned remaining_) :
5537 util_buffer(util_buffer_),
5538 cursor(cursor_),
5539 capacity(capacity_),
5540 remaining(remaining_) {
5541 }
5542 unibrow::byte* util_buffer;
5543 unsigned cursor;
5544 unsigned capacity;
5545 unsigned remaining;
5546 };
5547
Steve Blocka7e24c12009-10-30 11:49:00 +00005548 static inline const unibrow::byte* ReadBlock(String* input,
5549 ReadBlockBuffer* buffer,
5550 unsigned* offset,
5551 unsigned max_chars);
5552 static void ReadBlockIntoBuffer(String* input,
5553 ReadBlockBuffer* buffer,
5554 unsigned* offset_ptr,
5555 unsigned max_chars);
5556
5557 private:
Leon Clarkef7060e22010-06-03 12:02:55 +01005558 // Try to flatten the top level ConsString that is hiding behind this
5559 // string. This is a no-op unless the string is a ConsString. Flatten
5560 // mutates the ConsString and might return a failure.
John Reck59135872010-11-02 12:39:01 -07005561 MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
Leon Clarkef7060e22010-06-03 12:02:55 +01005562
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005563 static inline bool IsHashFieldComputed(uint32_t field);
5564
Steve Blocka7e24c12009-10-30 11:49:00 +00005565 // Slow case of String::Equals. This implementation works on any strings
5566 // but it is most efficient on strings that are almost flat.
5567 bool SlowEquals(String* other);
5568
5569 // Slow case of AsArrayIndex.
5570 bool SlowAsArrayIndex(uint32_t* index);
5571
5572 // Compute and set the hash code.
5573 uint32_t ComputeAndSetHash();
5574
5575 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
5576};
5577
5578
5579// The SeqString abstract class captures sequential string values.
5580class SeqString: public String {
5581 public:
5582
5583 // Casting.
5584 static inline SeqString* cast(Object* obj);
5585
Steve Blocka7e24c12009-10-30 11:49:00 +00005586 private:
5587 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
5588};
5589
5590
5591// The AsciiString class captures sequential ascii string objects.
5592// Each character in the AsciiString is an ascii character.
5593class SeqAsciiString: public SeqString {
5594 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005595 static const bool kHasAsciiEncoding = true;
5596
Steve Blocka7e24c12009-10-30 11:49:00 +00005597 // Dispatched behavior.
5598 inline uint16_t SeqAsciiStringGet(int index);
5599 inline void SeqAsciiStringSet(int index, uint16_t value);
5600
5601 // Get the address of the characters in this string.
5602 inline Address GetCharsAddress();
5603
5604 inline char* GetChars();
5605
5606 // Casting
5607 static inline SeqAsciiString* cast(Object* obj);
5608
5609 // Garbage collection support. This method is called by the
5610 // garbage collector to compute the actual size of an AsciiString
5611 // instance.
5612 inline int SeqAsciiStringSize(InstanceType instance_type);
5613
5614 // Computes the size for an AsciiString instance of a given length.
5615 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005616 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005617 }
5618
5619 // Layout description.
5620 static const int kHeaderSize = String::kSize;
5621 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
5622
Leon Clarkee46be812010-01-19 14:06:41 +00005623 // Maximal memory usage for a single sequential ASCII string.
5624 static const int kMaxSize = 512 * MB;
5625 // Maximal length of a single sequential ASCII string.
5626 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
5627 static const int kMaxLength = (kMaxSize - kHeaderSize);
5628
Steve Blocka7e24c12009-10-30 11:49:00 +00005629 // Support for StringInputBuffer.
5630 inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5631 unsigned* offset,
5632 unsigned chars);
5633 inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
5634 unsigned* offset,
5635 unsigned chars);
5636
5637 private:
5638 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
5639};
5640
5641
5642// The TwoByteString class captures sequential unicode string objects.
5643// Each character in the TwoByteString is a two-byte uint16_t.
5644class SeqTwoByteString: public SeqString {
5645 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005646 static const bool kHasAsciiEncoding = false;
5647
Steve Blocka7e24c12009-10-30 11:49:00 +00005648 // Dispatched behavior.
5649 inline uint16_t SeqTwoByteStringGet(int index);
5650 inline void SeqTwoByteStringSet(int index, uint16_t value);
5651
5652 // Get the address of the characters in this string.
5653 inline Address GetCharsAddress();
5654
5655 inline uc16* GetChars();
5656
5657 // For regexp code.
5658 const uint16_t* SeqTwoByteStringGetData(unsigned start);
5659
5660 // Casting
5661 static inline SeqTwoByteString* cast(Object* obj);
5662
5663 // Garbage collection support. This method is called by the
5664 // garbage collector to compute the actual size of a TwoByteString
5665 // instance.
5666 inline int SeqTwoByteStringSize(InstanceType instance_type);
5667
5668 // Computes the size for a TwoByteString instance of a given length.
5669 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005670 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005671 }
5672
5673 // Layout description.
5674 static const int kHeaderSize = String::kSize;
5675 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
5676
Leon Clarkee46be812010-01-19 14:06:41 +00005677 // Maximal memory usage for a single sequential two-byte string.
5678 static const int kMaxSize = 512 * MB;
5679 // Maximal length of a single sequential two-byte string.
5680 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
5681 static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
5682
Steve Blocka7e24c12009-10-30 11:49:00 +00005683 // Support for StringInputBuffer.
5684 inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5685 unsigned* offset_ptr,
5686 unsigned chars);
5687
5688 private:
5689 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
5690};
5691
5692
5693// The ConsString class describes string values built by using the
5694// addition operator on strings. A ConsString is a pair where the
5695// first and second components are pointers to other string values.
5696// One or both components of a ConsString can be pointers to other
5697// ConsStrings, creating a binary tree of ConsStrings where the leaves
5698// are non-ConsString string values. The string value represented by
5699// a ConsString can be obtained by concatenating the leaf string
5700// values in a left-to-right depth-first traversal of the tree.
5701class ConsString: public String {
5702 public:
5703 // First string of the cons cell.
5704 inline String* first();
5705 // Doesn't check that the result is a string, even in debug mode. This is
5706 // useful during GC where the mark bits confuse the checks.
5707 inline Object* unchecked_first();
5708 inline void set_first(String* first,
5709 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
5710
5711 // Second string of the cons cell.
5712 inline String* second();
5713 // Doesn't check that the result is a string, even in debug mode. This is
5714 // useful during GC where the mark bits confuse the checks.
5715 inline Object* unchecked_second();
5716 inline void set_second(String* second,
5717 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
5718
5719 // Dispatched behavior.
5720 uint16_t ConsStringGet(int index);
5721
5722 // Casting.
5723 static inline ConsString* cast(Object* obj);
5724
Steve Blocka7e24c12009-10-30 11:49:00 +00005725 // Layout description.
5726 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
5727 static const int kSecondOffset = kFirstOffset + kPointerSize;
5728 static const int kSize = kSecondOffset + kPointerSize;
5729
5730 // Support for StringInputBuffer.
5731 inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
5732 unsigned* offset_ptr,
5733 unsigned chars);
5734 inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5735 unsigned* offset_ptr,
5736 unsigned chars);
5737
5738 // Minimum length for a cons string.
5739 static const int kMinLength = 13;
5740
Iain Merrick75681382010-08-19 15:07:18 +01005741 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
5742 BodyDescriptor;
5743
Steve Blocka7e24c12009-10-30 11:49:00 +00005744 private:
5745 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
5746};
5747
5748
Steve Blocka7e24c12009-10-30 11:49:00 +00005749// The ExternalString class describes string values that are backed by
5750// a string resource that lies outside the V8 heap. ExternalStrings
5751// consist of the length field common to all strings, a pointer to the
5752// external resource. It is important to ensure (externally) that the
5753// resource is not deallocated while the ExternalString is live in the
5754// V8 heap.
5755//
5756// The API expects that all ExternalStrings are created through the
5757// API. Therefore, ExternalStrings should not be used internally.
5758class ExternalString: public String {
5759 public:
5760 // Casting
5761 static inline ExternalString* cast(Object* obj);
5762
5763 // Layout description.
5764 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
5765 static const int kSize = kResourceOffset + kPointerSize;
5766
5767 STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
5768
5769 private:
5770 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
5771};
5772
5773
5774// The ExternalAsciiString class is an external string backed by an
5775// ASCII string.
5776class ExternalAsciiString: public ExternalString {
5777 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005778 static const bool kHasAsciiEncoding = true;
5779
Steve Blocka7e24c12009-10-30 11:49:00 +00005780 typedef v8::String::ExternalAsciiStringResource Resource;
5781
5782 // The underlying resource.
5783 inline Resource* resource();
5784 inline void set_resource(Resource* buffer);
5785
5786 // Dispatched behavior.
5787 uint16_t ExternalAsciiStringGet(int index);
5788
5789 // Casting.
5790 static inline ExternalAsciiString* cast(Object* obj);
5791
Steve Blockd0582a62009-12-15 09:54:21 +00005792 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01005793 inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
5794
5795 template<typename StaticVisitor>
5796 inline void ExternalAsciiStringIterateBody();
Steve Blockd0582a62009-12-15 09:54:21 +00005797
Steve Blocka7e24c12009-10-30 11:49:00 +00005798 // Support for StringInputBuffer.
5799 const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
5800 unsigned* offset,
5801 unsigned chars);
5802 inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5803 unsigned* offset,
5804 unsigned chars);
5805
Steve Blocka7e24c12009-10-30 11:49:00 +00005806 private:
5807 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
5808};
5809
5810
5811// The ExternalTwoByteString class is an external string backed by a UTF-16
5812// encoded string.
5813class ExternalTwoByteString: public ExternalString {
5814 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005815 static const bool kHasAsciiEncoding = false;
5816
Steve Blocka7e24c12009-10-30 11:49:00 +00005817 typedef v8::String::ExternalStringResource Resource;
5818
5819 // The underlying string resource.
5820 inline Resource* resource();
5821 inline void set_resource(Resource* buffer);
5822
5823 // Dispatched behavior.
5824 uint16_t ExternalTwoByteStringGet(int index);
5825
5826 // For regexp code.
5827 const uint16_t* ExternalTwoByteStringGetData(unsigned start);
5828
5829 // Casting.
5830 static inline ExternalTwoByteString* cast(Object* obj);
5831
Steve Blockd0582a62009-12-15 09:54:21 +00005832 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01005833 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
5834
5835 template<typename StaticVisitor>
5836 inline void ExternalTwoByteStringIterateBody();
5837
Steve Blockd0582a62009-12-15 09:54:21 +00005838
Steve Blocka7e24c12009-10-30 11:49:00 +00005839 // Support for StringInputBuffer.
5840 void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5841 unsigned* offset_ptr,
5842 unsigned chars);
5843
Steve Blocka7e24c12009-10-30 11:49:00 +00005844 private:
5845 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
5846};
5847
5848
5849// Utility superclass for stack-allocated objects that must be updated
5850// on gc. It provides two ways for the gc to update instances, either
5851// iterating or updating after gc.
5852class Relocatable BASE_EMBEDDED {
5853 public:
Steve Block44f0eee2011-05-26 01:26:41 +01005854 explicit inline Relocatable(Isolate* isolate);
5855 inline virtual ~Relocatable();
Steve Blocka7e24c12009-10-30 11:49:00 +00005856 virtual void IterateInstance(ObjectVisitor* v) { }
5857 virtual void PostGarbageCollection() { }
5858
5859 static void PostGarbageCollectionProcessing();
5860 static int ArchiveSpacePerThread();
5861 static char* ArchiveState(char* to);
5862 static char* RestoreState(char* from);
5863 static void Iterate(ObjectVisitor* v);
5864 static void Iterate(ObjectVisitor* v, Relocatable* top);
5865 static char* Iterate(ObjectVisitor* v, char* t);
5866 private:
Steve Block44f0eee2011-05-26 01:26:41 +01005867 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005868 Relocatable* prev_;
5869};
5870
5871
5872// A flat string reader provides random access to the contents of a
5873// string independent of the character width of the string. The handle
5874// must be valid as long as the reader is being used.
5875class FlatStringReader : public Relocatable {
5876 public:
Steve Block44f0eee2011-05-26 01:26:41 +01005877 FlatStringReader(Isolate* isolate, Handle<String> str);
5878 FlatStringReader(Isolate* isolate, Vector<const char> input);
Steve Blocka7e24c12009-10-30 11:49:00 +00005879 void PostGarbageCollection();
5880 inline uc32 Get(int index);
5881 int length() { return length_; }
5882 private:
5883 String** str_;
5884 bool is_ascii_;
5885 int length_;
5886 const void* start_;
5887};
5888
5889
5890// Note that StringInputBuffers are not valid across a GC! To fix this
5891// it would have to store a String Handle instead of a String* and
5892// AsciiStringReadBlock would have to be modified to use memcpy.
5893//
5894// StringInputBuffer is able to traverse any string regardless of how
5895// deeply nested a sequence of ConsStrings it is made of. However,
5896// performance will be better if deep strings are flattened before they
5897// are traversed. Since flattening requires memory allocation this is
5898// not always desirable, however (esp. in debugging situations).
5899class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
5900 public:
5901 virtual void Seek(unsigned pos);
5902 inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
Ben Murdoch8b112d22011-06-08 16:22:53 +01005903 explicit inline StringInputBuffer(String* backing):
Steve Blocka7e24c12009-10-30 11:49:00 +00005904 unibrow::InputBuffer<String, String*, 1024>(backing) {}
5905};
5906
5907
5908class SafeStringInputBuffer
5909 : public unibrow::InputBuffer<String, String**, 256> {
5910 public:
5911 virtual void Seek(unsigned pos);
5912 inline SafeStringInputBuffer()
5913 : unibrow::InputBuffer<String, String**, 256>() {}
Ben Murdoch8b112d22011-06-08 16:22:53 +01005914 explicit inline SafeStringInputBuffer(String** backing)
Steve Blocka7e24c12009-10-30 11:49:00 +00005915 : unibrow::InputBuffer<String, String**, 256>(backing) {}
5916};
5917
5918
5919template <typename T>
5920class VectorIterator {
5921 public:
5922 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
5923 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
5924 T GetNext() { return data_[index_++]; }
5925 bool has_more() { return index_ < data_.length(); }
5926 private:
5927 Vector<const T> data_;
5928 int index_;
5929};
5930
5931
5932// The Oddball describes objects null, undefined, true, and false.
5933class Oddball: public HeapObject {
5934 public:
5935 // [to_string]: Cached to_string computed at startup.
5936 DECL_ACCESSORS(to_string, String)
5937
5938 // [to_number]: Cached to_number computed at startup.
5939 DECL_ACCESSORS(to_number, Object)
5940
Steve Block44f0eee2011-05-26 01:26:41 +01005941 inline byte kind();
5942 inline void set_kind(byte kind);
5943
Steve Blocka7e24c12009-10-30 11:49:00 +00005944 // Casting.
5945 static inline Oddball* cast(Object* obj);
5946
5947 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00005948#ifdef DEBUG
5949 void OddballVerify();
5950#endif
5951
5952 // Initialize the fields.
John Reck59135872010-11-02 12:39:01 -07005953 MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
Steve Block44f0eee2011-05-26 01:26:41 +01005954 Object* to_number,
5955 byte kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00005956
5957 // Layout description.
5958 static const int kToStringOffset = HeapObject::kHeaderSize;
5959 static const int kToNumberOffset = kToStringOffset + kPointerSize;
Steve Block44f0eee2011-05-26 01:26:41 +01005960 static const int kKindOffset = kToNumberOffset + kPointerSize;
5961 static const int kSize = kKindOffset + kPointerSize;
5962
5963 static const byte kFalse = 0;
5964 static const byte kTrue = 1;
5965 static const byte kNotBooleanMask = ~1;
5966 static const byte kTheHole = 2;
5967 static const byte kNull = 3;
5968 static const byte kArgumentMarker = 4;
5969 static const byte kUndefined = 5;
5970 static const byte kOther = 6;
Steve Blocka7e24c12009-10-30 11:49:00 +00005971
Iain Merrick75681382010-08-19 15:07:18 +01005972 typedef FixedBodyDescriptor<kToStringOffset,
5973 kToNumberOffset + kPointerSize,
5974 kSize> BodyDescriptor;
5975
Steve Blocka7e24c12009-10-30 11:49:00 +00005976 private:
5977 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
5978};
5979
5980
5981class JSGlobalPropertyCell: public HeapObject {
5982 public:
5983 // [value]: value of the global property.
5984 DECL_ACCESSORS(value, Object)
5985
5986 // Casting.
5987 static inline JSGlobalPropertyCell* cast(Object* obj);
5988
Steve Blocka7e24c12009-10-30 11:49:00 +00005989#ifdef DEBUG
5990 void JSGlobalPropertyCellVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005991#endif
5992#ifdef OBJECT_PRINT
5993 inline void JSGlobalPropertyCellPrint() {
5994 JSGlobalPropertyCellPrint(stdout);
5995 }
5996 void JSGlobalPropertyCellPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00005997#endif
5998
5999 // Layout description.
6000 static const int kValueOffset = HeapObject::kHeaderSize;
6001 static const int kSize = kValueOffset + kPointerSize;
6002
Iain Merrick75681382010-08-19 15:07:18 +01006003 typedef FixedBodyDescriptor<kValueOffset,
6004 kValueOffset + kPointerSize,
6005 kSize> BodyDescriptor;
6006
Ben Murdoch8b112d22011-06-08 16:22:53 +01006007 // Returns the isolate/heap this cell object belongs to.
6008 inline Isolate* isolate();
6009 inline Heap* heap();
6010
Steve Blocka7e24c12009-10-30 11:49:00 +00006011 private:
6012 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
6013};
6014
6015
6016
6017// Proxy describes objects pointing from JavaScript to C structures.
6018// Since they cannot contain references to JS HeapObjects they can be
6019// placed in old_data_space.
6020class Proxy: public HeapObject {
6021 public:
6022 // [proxy]: field containing the address.
6023 inline Address proxy();
6024 inline void set_proxy(Address value);
6025
6026 // Casting.
6027 static inline Proxy* cast(Object* obj);
6028
6029 // Dispatched behavior.
6030 inline void ProxyIterateBody(ObjectVisitor* v);
Iain Merrick75681382010-08-19 15:07:18 +01006031
6032 template<typename StaticVisitor>
6033 inline void ProxyIterateBody();
6034
Ben Murdochb0fe1622011-05-05 13:52:32 +01006035#ifdef OBJECT_PRINT
6036 inline void ProxyPrint() {
6037 ProxyPrint(stdout);
6038 }
6039 void ProxyPrint(FILE* out);
6040#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006041#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006042 void ProxyVerify();
6043#endif
6044
6045 // Layout description.
6046
6047 static const int kProxyOffset = HeapObject::kHeaderSize;
6048 static const int kSize = kProxyOffset + kPointerSize;
6049
6050 STATIC_CHECK(kProxyOffset == Internals::kProxyProxyOffset);
6051
6052 private:
6053 DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
6054};
6055
6056
6057// The JSArray describes JavaScript Arrays
6058// Such an array can be in one of two modes:
6059// - fast, backing storage is a FixedArray and length <= elements.length();
6060// Please note: push and pop can be used to grow and shrink the array.
6061// - slow, backing storage is a HashTable with numbers as keys.
6062class JSArray: public JSObject {
6063 public:
6064 // [length]: The length property.
6065 DECL_ACCESSORS(length, Object)
6066
Leon Clarke4515c472010-02-03 11:58:03 +00006067 // Overload the length setter to skip write barrier when the length
6068 // is set to a smi. This matches the set function on FixedArray.
6069 inline void set_length(Smi* length);
6070
John Reck59135872010-11-02 12:39:01 -07006071 MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
6072 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006073
6074 // Initialize the array with the given capacity. The function may
6075 // fail due to out-of-memory situations, but only if the requested
6076 // capacity is non-zero.
John Reck59135872010-11-02 12:39:01 -07006077 MUST_USE_RESULT MaybeObject* Initialize(int capacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00006078
6079 // Set the content of the array to the content of storage.
6080 inline void SetContent(FixedArray* storage);
6081
6082 // Casting.
6083 static inline JSArray* cast(Object* obj);
6084
6085 // Uses handles. Ensures that the fixed array backing the JSArray has at
6086 // least the stated size.
6087 inline void EnsureSize(int minimum_size_of_backing_fixed_array);
6088
6089 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01006090#ifdef OBJECT_PRINT
6091 inline void JSArrayPrint() {
6092 JSArrayPrint(stdout);
6093 }
6094 void JSArrayPrint(FILE* out);
6095#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006096#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006097 void JSArrayVerify();
6098#endif
6099
6100 // Number of element slots to pre-allocate for an empty array.
6101 static const int kPreallocatedArrayElements = 4;
6102
6103 // Layout description.
6104 static const int kLengthOffset = JSObject::kHeaderSize;
6105 static const int kSize = kLengthOffset + kPointerSize;
6106
6107 private:
6108 // Expand the fixed array backing of a fast-case JSArray to at least
6109 // the requested size.
6110 void Expand(int minimum_size_of_backing_fixed_array);
6111
6112 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
6113};
6114
6115
Steve Block6ded16b2010-05-10 14:33:55 +01006116// JSRegExpResult is just a JSArray with a specific initial map.
6117// This initial map adds in-object properties for "index" and "input"
6118// properties, as assigned by RegExp.prototype.exec, which allows
6119// faster creation of RegExp exec results.
6120// This class just holds constants used when creating the result.
6121// After creation the result must be treated as a JSArray in all regards.
6122class JSRegExpResult: public JSArray {
6123 public:
6124 // Offsets of object fields.
6125 static const int kIndexOffset = JSArray::kSize;
6126 static const int kInputOffset = kIndexOffset + kPointerSize;
6127 static const int kSize = kInputOffset + kPointerSize;
6128 // Indices of in-object properties.
6129 static const int kIndexIndex = 0;
6130 static const int kInputIndex = 1;
6131 private:
6132 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
6133};
6134
6135
Steve Blocka7e24c12009-10-30 11:49:00 +00006136// An accessor must have a getter, but can have no setter.
6137//
6138// When setting a property, V8 searches accessors in prototypes.
6139// If an accessor was found and it does not have a setter,
6140// the request is ignored.
6141//
6142// If the accessor in the prototype has the READ_ONLY property attribute, then
6143// a new value is added to the local object when the property is set.
6144// This shadows the accessor in the prototype.
6145class AccessorInfo: public Struct {
6146 public:
6147 DECL_ACCESSORS(getter, Object)
6148 DECL_ACCESSORS(setter, Object)
6149 DECL_ACCESSORS(data, Object)
6150 DECL_ACCESSORS(name, Object)
6151 DECL_ACCESSORS(flag, Smi)
6152
6153 inline bool all_can_read();
6154 inline void set_all_can_read(bool value);
6155
6156 inline bool all_can_write();
6157 inline void set_all_can_write(bool value);
6158
6159 inline bool prohibits_overwriting();
6160 inline void set_prohibits_overwriting(bool value);
6161
6162 inline PropertyAttributes property_attributes();
6163 inline void set_property_attributes(PropertyAttributes attributes);
6164
6165 static inline AccessorInfo* cast(Object* obj);
6166
Ben Murdochb0fe1622011-05-05 13:52:32 +01006167#ifdef OBJECT_PRINT
6168 inline void AccessorInfoPrint() {
6169 AccessorInfoPrint(stdout);
6170 }
6171 void AccessorInfoPrint(FILE* out);
6172#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006173#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006174 void AccessorInfoVerify();
6175#endif
6176
6177 static const int kGetterOffset = HeapObject::kHeaderSize;
6178 static const int kSetterOffset = kGetterOffset + kPointerSize;
6179 static const int kDataOffset = kSetterOffset + kPointerSize;
6180 static const int kNameOffset = kDataOffset + kPointerSize;
6181 static const int kFlagOffset = kNameOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08006182 static const int kSize = kFlagOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006183
6184 private:
6185 // Bit positions in flag.
6186 static const int kAllCanReadBit = 0;
6187 static const int kAllCanWriteBit = 1;
6188 static const int kProhibitsOverwritingBit = 2;
6189 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
6190
6191 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
6192};
6193
6194
6195class AccessCheckInfo: public Struct {
6196 public:
6197 DECL_ACCESSORS(named_callback, Object)
6198 DECL_ACCESSORS(indexed_callback, Object)
6199 DECL_ACCESSORS(data, Object)
6200
6201 static inline AccessCheckInfo* cast(Object* obj);
6202
Ben Murdochb0fe1622011-05-05 13:52:32 +01006203#ifdef OBJECT_PRINT
6204 inline void AccessCheckInfoPrint() {
6205 AccessCheckInfoPrint(stdout);
6206 }
6207 void AccessCheckInfoPrint(FILE* out);
6208#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006209#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006210 void AccessCheckInfoVerify();
6211#endif
6212
6213 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
6214 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
6215 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
6216 static const int kSize = kDataOffset + kPointerSize;
6217
6218 private:
6219 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
6220};
6221
6222
6223class InterceptorInfo: public Struct {
6224 public:
6225 DECL_ACCESSORS(getter, Object)
6226 DECL_ACCESSORS(setter, Object)
6227 DECL_ACCESSORS(query, Object)
6228 DECL_ACCESSORS(deleter, Object)
6229 DECL_ACCESSORS(enumerator, Object)
6230 DECL_ACCESSORS(data, Object)
6231
6232 static inline InterceptorInfo* cast(Object* obj);
6233
Ben Murdochb0fe1622011-05-05 13:52:32 +01006234#ifdef OBJECT_PRINT
6235 inline void InterceptorInfoPrint() {
6236 InterceptorInfoPrint(stdout);
6237 }
6238 void InterceptorInfoPrint(FILE* out);
6239#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006240#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006241 void InterceptorInfoVerify();
6242#endif
6243
6244 static const int kGetterOffset = HeapObject::kHeaderSize;
6245 static const int kSetterOffset = kGetterOffset + kPointerSize;
6246 static const int kQueryOffset = kSetterOffset + kPointerSize;
6247 static const int kDeleterOffset = kQueryOffset + kPointerSize;
6248 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
6249 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
6250 static const int kSize = kDataOffset + kPointerSize;
6251
6252 private:
6253 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
6254};
6255
6256
6257class CallHandlerInfo: public Struct {
6258 public:
6259 DECL_ACCESSORS(callback, Object)
6260 DECL_ACCESSORS(data, Object)
6261
6262 static inline CallHandlerInfo* cast(Object* obj);
6263
Ben Murdochb0fe1622011-05-05 13:52:32 +01006264#ifdef OBJECT_PRINT
6265 inline void CallHandlerInfoPrint() {
6266 CallHandlerInfoPrint(stdout);
6267 }
6268 void CallHandlerInfoPrint(FILE* out);
6269#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006270#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006271 void CallHandlerInfoVerify();
6272#endif
6273
6274 static const int kCallbackOffset = HeapObject::kHeaderSize;
6275 static const int kDataOffset = kCallbackOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08006276 static const int kSize = kDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006277
6278 private:
6279 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
6280};
6281
6282
6283class TemplateInfo: public Struct {
6284 public:
6285 DECL_ACCESSORS(tag, Object)
6286 DECL_ACCESSORS(property_list, Object)
6287
6288#ifdef DEBUG
6289 void TemplateInfoVerify();
6290#endif
6291
6292 static const int kTagOffset = HeapObject::kHeaderSize;
6293 static const int kPropertyListOffset = kTagOffset + kPointerSize;
6294 static const int kHeaderSize = kPropertyListOffset + kPointerSize;
6295 protected:
6296 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
6297 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
6298};
6299
6300
6301class FunctionTemplateInfo: public TemplateInfo {
6302 public:
6303 DECL_ACCESSORS(serial_number, Object)
6304 DECL_ACCESSORS(call_code, Object)
6305 DECL_ACCESSORS(property_accessors, Object)
6306 DECL_ACCESSORS(prototype_template, Object)
6307 DECL_ACCESSORS(parent_template, Object)
6308 DECL_ACCESSORS(named_property_handler, Object)
6309 DECL_ACCESSORS(indexed_property_handler, Object)
6310 DECL_ACCESSORS(instance_template, Object)
6311 DECL_ACCESSORS(class_name, Object)
6312 DECL_ACCESSORS(signature, Object)
6313 DECL_ACCESSORS(instance_call_handler, Object)
6314 DECL_ACCESSORS(access_check_info, Object)
6315 DECL_ACCESSORS(flag, Smi)
6316
6317 // Following properties use flag bits.
6318 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
6319 DECL_BOOLEAN_ACCESSORS(undetectable)
6320 // If the bit is set, object instances created by this function
6321 // requires access check.
6322 DECL_BOOLEAN_ACCESSORS(needs_access_check)
6323
6324 static inline FunctionTemplateInfo* cast(Object* obj);
6325
Ben Murdochb0fe1622011-05-05 13:52:32 +01006326#ifdef OBJECT_PRINT
6327 inline void FunctionTemplateInfoPrint() {
6328 FunctionTemplateInfoPrint(stdout);
6329 }
6330 void FunctionTemplateInfoPrint(FILE* out);
6331#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006332#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006333 void FunctionTemplateInfoVerify();
6334#endif
6335
6336 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
6337 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
6338 static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
6339 static const int kPrototypeTemplateOffset =
6340 kPropertyAccessorsOffset + kPointerSize;
6341 static const int kParentTemplateOffset =
6342 kPrototypeTemplateOffset + kPointerSize;
6343 static const int kNamedPropertyHandlerOffset =
6344 kParentTemplateOffset + kPointerSize;
6345 static const int kIndexedPropertyHandlerOffset =
6346 kNamedPropertyHandlerOffset + kPointerSize;
6347 static const int kInstanceTemplateOffset =
6348 kIndexedPropertyHandlerOffset + kPointerSize;
6349 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
6350 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
6351 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
6352 static const int kAccessCheckInfoOffset =
6353 kInstanceCallHandlerOffset + kPointerSize;
6354 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
6355 static const int kSize = kFlagOffset + kPointerSize;
6356
6357 private:
6358 // Bit position in the flag, from least significant bit position.
6359 static const int kHiddenPrototypeBit = 0;
6360 static const int kUndetectableBit = 1;
6361 static const int kNeedsAccessCheckBit = 2;
6362
6363 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
6364};
6365
6366
6367class ObjectTemplateInfo: public TemplateInfo {
6368 public:
6369 DECL_ACCESSORS(constructor, Object)
6370 DECL_ACCESSORS(internal_field_count, Object)
6371
6372 static inline ObjectTemplateInfo* cast(Object* obj);
6373
Ben Murdochb0fe1622011-05-05 13:52:32 +01006374#ifdef OBJECT_PRINT
6375 inline void ObjectTemplateInfoPrint() {
6376 ObjectTemplateInfoPrint(stdout);
6377 }
6378 void ObjectTemplateInfoPrint(FILE* out);
6379#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006380#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006381 void ObjectTemplateInfoVerify();
6382#endif
6383
6384 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
6385 static const int kInternalFieldCountOffset =
6386 kConstructorOffset + kPointerSize;
6387 static const int kSize = kInternalFieldCountOffset + kPointerSize;
6388};
6389
6390
6391class SignatureInfo: public Struct {
6392 public:
6393 DECL_ACCESSORS(receiver, Object)
6394 DECL_ACCESSORS(args, Object)
6395
6396 static inline SignatureInfo* cast(Object* obj);
6397
Ben Murdochb0fe1622011-05-05 13:52:32 +01006398#ifdef OBJECT_PRINT
6399 inline void SignatureInfoPrint() {
6400 SignatureInfoPrint(stdout);
6401 }
6402 void SignatureInfoPrint(FILE* out);
6403#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006404#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006405 void SignatureInfoVerify();
6406#endif
6407
6408 static const int kReceiverOffset = Struct::kHeaderSize;
6409 static const int kArgsOffset = kReceiverOffset + kPointerSize;
6410 static const int kSize = kArgsOffset + kPointerSize;
6411
6412 private:
6413 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
6414};
6415
6416
6417class TypeSwitchInfo: public Struct {
6418 public:
6419 DECL_ACCESSORS(types, Object)
6420
6421 static inline TypeSwitchInfo* cast(Object* obj);
6422
Ben Murdochb0fe1622011-05-05 13:52:32 +01006423#ifdef OBJECT_PRINT
6424 inline void TypeSwitchInfoPrint() {
6425 TypeSwitchInfoPrint(stdout);
6426 }
6427 void TypeSwitchInfoPrint(FILE* out);
6428#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006429#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006430 void TypeSwitchInfoVerify();
6431#endif
6432
6433 static const int kTypesOffset = Struct::kHeaderSize;
6434 static const int kSize = kTypesOffset + kPointerSize;
6435};
6436
6437
6438#ifdef ENABLE_DEBUGGER_SUPPORT
6439// The DebugInfo class holds additional information for a function being
6440// debugged.
6441class DebugInfo: public Struct {
6442 public:
6443 // The shared function info for the source being debugged.
6444 DECL_ACCESSORS(shared, SharedFunctionInfo)
6445 // Code object for the original code.
6446 DECL_ACCESSORS(original_code, Code)
6447 // Code object for the patched code. This code object is the code object
6448 // currently active for the function.
6449 DECL_ACCESSORS(code, Code)
6450 // Fixed array holding status information for each active break point.
6451 DECL_ACCESSORS(break_points, FixedArray)
6452
6453 // Check if there is a break point at a code position.
6454 bool HasBreakPoint(int code_position);
6455 // Get the break point info object for a code position.
6456 Object* GetBreakPointInfo(int code_position);
6457 // Clear a break point.
6458 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
6459 int code_position,
6460 Handle<Object> break_point_object);
6461 // Set a break point.
6462 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
6463 int source_position, int statement_position,
6464 Handle<Object> break_point_object);
6465 // Get the break point objects for a code position.
6466 Object* GetBreakPointObjects(int code_position);
6467 // Find the break point info holding this break point object.
6468 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
6469 Handle<Object> break_point_object);
6470 // Get the number of break points for this function.
6471 int GetBreakPointCount();
6472
6473 static inline DebugInfo* cast(Object* obj);
6474
Ben Murdochb0fe1622011-05-05 13:52:32 +01006475#ifdef OBJECT_PRINT
6476 inline void DebugInfoPrint() {
6477 DebugInfoPrint(stdout);
6478 }
6479 void DebugInfoPrint(FILE* out);
6480#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006481#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006482 void DebugInfoVerify();
6483#endif
6484
6485 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
6486 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
6487 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
6488 static const int kActiveBreakPointsCountIndex =
6489 kPatchedCodeIndex + kPointerSize;
6490 static const int kBreakPointsStateIndex =
6491 kActiveBreakPointsCountIndex + kPointerSize;
6492 static const int kSize = kBreakPointsStateIndex + kPointerSize;
6493
6494 private:
6495 static const int kNoBreakPointInfo = -1;
6496
6497 // Lookup the index in the break_points array for a code position.
6498 int GetBreakPointInfoIndex(int code_position);
6499
6500 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
6501};
6502
6503
6504// The BreakPointInfo class holds information for break points set in a
6505// function. The DebugInfo object holds a BreakPointInfo object for each code
6506// position with one or more break points.
6507class BreakPointInfo: public Struct {
6508 public:
6509 // The position in the code for the break point.
6510 DECL_ACCESSORS(code_position, Smi)
6511 // The position in the source for the break position.
6512 DECL_ACCESSORS(source_position, Smi)
6513 // The position in the source for the last statement before this break
6514 // position.
6515 DECL_ACCESSORS(statement_position, Smi)
6516 // List of related JavaScript break points.
6517 DECL_ACCESSORS(break_point_objects, Object)
6518
6519 // Removes a break point.
6520 static void ClearBreakPoint(Handle<BreakPointInfo> info,
6521 Handle<Object> break_point_object);
6522 // Set a break point.
6523 static void SetBreakPoint(Handle<BreakPointInfo> info,
6524 Handle<Object> break_point_object);
6525 // Check if break point info has this break point object.
6526 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
6527 Handle<Object> break_point_object);
6528 // Get the number of break points for this code position.
6529 int GetBreakPointCount();
6530
6531 static inline BreakPointInfo* cast(Object* obj);
6532
Ben Murdochb0fe1622011-05-05 13:52:32 +01006533#ifdef OBJECT_PRINT
6534 inline void BreakPointInfoPrint() {
6535 BreakPointInfoPrint(stdout);
6536 }
6537 void BreakPointInfoPrint(FILE* out);
6538#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006539#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006540 void BreakPointInfoVerify();
6541#endif
6542
6543 static const int kCodePositionIndex = Struct::kHeaderSize;
6544 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
6545 static const int kStatementPositionIndex =
6546 kSourcePositionIndex + kPointerSize;
6547 static const int kBreakPointObjectsIndex =
6548 kStatementPositionIndex + kPointerSize;
6549 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
6550
6551 private:
6552 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
6553};
6554#endif // ENABLE_DEBUGGER_SUPPORT
6555
6556
6557#undef DECL_BOOLEAN_ACCESSORS
6558#undef DECL_ACCESSORS
6559
6560
6561// Abstract base class for visiting, and optionally modifying, the
6562// pointers contained in Objects. Used in GC and serialization/deserialization.
6563class ObjectVisitor BASE_EMBEDDED {
6564 public:
6565 virtual ~ObjectVisitor() {}
6566
6567 // Visits a contiguous arrays of pointers in the half-open range
6568 // [start, end). Any or all of the values may be modified on return.
6569 virtual void VisitPointers(Object** start, Object** end) = 0;
6570
6571 // To allow lazy clearing of inline caches the visitor has
6572 // a rich interface for iterating over Code objects..
6573
6574 // Visits a code target in the instruction stream.
6575 virtual void VisitCodeTarget(RelocInfo* rinfo);
6576
Steve Block791712a2010-08-27 10:21:07 +01006577 // Visits a code entry in a JS function.
6578 virtual void VisitCodeEntry(Address entry_address);
6579
Ben Murdochb0fe1622011-05-05 13:52:32 +01006580 // Visits a global property cell reference in the instruction stream.
6581 virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
6582
Steve Blocka7e24c12009-10-30 11:49:00 +00006583 // Visits a runtime entry in the instruction stream.
6584 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
6585
Steve Blockd0582a62009-12-15 09:54:21 +00006586 // Visits the resource of an ASCII or two-byte string.
6587 virtual void VisitExternalAsciiString(
6588 v8::String::ExternalAsciiStringResource** resource) {}
6589 virtual void VisitExternalTwoByteString(
6590 v8::String::ExternalStringResource** resource) {}
6591
Steve Blocka7e24c12009-10-30 11:49:00 +00006592 // Visits a debug call target in the instruction stream.
6593 virtual void VisitDebugTarget(RelocInfo* rinfo);
6594
6595 // Handy shorthand for visiting a single pointer.
6596 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
6597
6598 // Visits a contiguous arrays of external references (references to the C++
6599 // heap) in the half-open range [start, end). Any or all of the values
6600 // may be modified on return.
6601 virtual void VisitExternalReferences(Address* start, Address* end) {}
6602
6603 inline void VisitExternalReference(Address* p) {
6604 VisitExternalReferences(p, p + 1);
6605 }
6606
Steve Block44f0eee2011-05-26 01:26:41 +01006607 // Visits a handle that has an embedder-assigned class ID.
6608 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
6609
Steve Blocka7e24c12009-10-30 11:49:00 +00006610#ifdef DEBUG
6611 // Intended for serialization/deserialization checking: insert, or
6612 // check for the presence of, a tag at this position in the stream.
6613 virtual void Synchronize(const char* tag) {}
Steve Blockd0582a62009-12-15 09:54:21 +00006614#else
6615 inline void Synchronize(const char* tag) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00006616#endif
6617};
6618
6619
Iain Merrick75681382010-08-19 15:07:18 +01006620class StructBodyDescriptor : public
6621 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
6622 public:
6623 static inline int SizeOf(Map* map, HeapObject* object) {
6624 return map->instance_size();
6625 }
6626};
6627
6628
Steve Blocka7e24c12009-10-30 11:49:00 +00006629// BooleanBit is a helper class for setting and getting a bit in an
6630// integer or Smi.
6631class BooleanBit : public AllStatic {
6632 public:
6633 static inline bool get(Smi* smi, int bit_position) {
6634 return get(smi->value(), bit_position);
6635 }
6636
6637 static inline bool get(int value, int bit_position) {
6638 return (value & (1 << bit_position)) != 0;
6639 }
6640
6641 static inline Smi* set(Smi* smi, int bit_position, bool v) {
6642 return Smi::FromInt(set(smi->value(), bit_position, v));
6643 }
6644
6645 static inline int set(int value, int bit_position, bool v) {
6646 if (v) {
6647 value |= (1 << bit_position);
6648 } else {
6649 value &= ~(1 << bit_position);
6650 }
6651 return value;
6652 }
6653};
6654
6655} } // namespace v8::internal
6656
6657#endif // V8_OBJECTS_H_