blob: 96e5cb692e82ac32325e6c7a9b5f766db55c92a3 [file] [log] [blame]
Ben Murdochf87a2032010-10-22 12:50:53 +01001// Copyright 2010 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*.
170 inline PropertyDetails(Smi* smi);
171 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 Block3ce2e202009-11-05 08:53:23 +00001296#if !defined(V8_HOST_ARCH_ARM) || defined(USE_ARM_EABI)
Steve Blocka7e24c12009-10-30 11:49:00 +00001297 static const int kMantissaOffset = kValueOffset;
1298 static const int kExponentOffset = kValueOffset + 4;
1299#else
1300 static const int kMantissaOffset = kValueOffset + 4;
1301 static const int kExponentOffset = kValueOffset;
1302# define BIG_ENDIAN_FLOATING_POINT 1
1303#endif
1304 static const int kSize = kValueOffset + kDoubleSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001305 static const uint32_t kSignMask = 0x80000000u;
1306 static const uint32_t kExponentMask = 0x7ff00000u;
1307 static const uint32_t kMantissaMask = 0xfffffu;
Steve Block6ded16b2010-05-10 14:33:55 +01001308 static const int kMantissaBits = 52;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001309 static const int kExponentBits = 11;
Steve Blocka7e24c12009-10-30 11:49:00 +00001310 static const int kExponentBias = 1023;
1311 static const int kExponentShift = 20;
1312 static const int kMantissaBitsInTopWord = 20;
1313 static const int kNonMantissaBitsInTopWord = 12;
1314
1315 private:
1316 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1317};
1318
1319
1320// The JSObject describes real heap allocated JavaScript objects with
1321// properties.
1322// Note that the map of JSObject changes during execution to enable inline
1323// caching.
1324class JSObject: public HeapObject {
1325 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001326 enum DeleteMode {
1327 NORMAL_DELETION,
1328 STRICT_DELETION,
1329 FORCE_DELETION
1330 };
1331
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 enum ElementsKind {
Iain Merrick75681382010-08-19 15:07:18 +01001333 // The only "fast" kind.
Steve Blocka7e24c12009-10-30 11:49:00 +00001334 FAST_ELEMENTS,
Iain Merrick75681382010-08-19 15:07:18 +01001335 // All the kinds below are "slow".
Steve Blocka7e24c12009-10-30 11:49:00 +00001336 DICTIONARY_ELEMENTS,
Steve Block3ce2e202009-11-05 08:53:23 +00001337 EXTERNAL_BYTE_ELEMENTS,
1338 EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
1339 EXTERNAL_SHORT_ELEMENTS,
1340 EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
1341 EXTERNAL_INT_ELEMENTS,
1342 EXTERNAL_UNSIGNED_INT_ELEMENTS,
Steve Block44f0eee2011-05-26 01:26:41 +01001343 EXTERNAL_FLOAT_ELEMENTS,
1344 EXTERNAL_PIXEL_ELEMENTS
Steve Blocka7e24c12009-10-30 11:49:00 +00001345 };
1346
1347 // [properties]: Backing storage for properties.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001348 // properties is a FixedArray in the fast case and a Dictionary in the
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 // slow case.
1350 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
1351 inline void initialize_properties();
1352 inline bool HasFastProperties();
1353 inline StringDictionary* property_dictionary(); // Gets slow properties.
1354
1355 // [elements]: The elements (properties with names that are integers).
Iain Merrick75681382010-08-19 15:07:18 +01001356 //
1357 // Elements can be in two general modes: fast and slow. Each mode
1358 // corrensponds to a set of object representations of elements that
1359 // have something in common.
1360 //
1361 // In the fast mode elements is a FixedArray and so each element can
1362 // be quickly accessed. This fact is used in the generated code. The
1363 // elements array can have one of the two maps in this mode:
1364 // fixed_array_map or fixed_cow_array_map (for copy-on-write
1365 // arrays). In the latter case the elements array may be shared by a
1366 // few objects and so before writing to any element the array must
1367 // be copied. Use EnsureWritableFastElements in this case.
1368 //
Steve Block44f0eee2011-05-26 01:26:41 +01001369 // In the slow mode elements is either a NumberDictionary or an ExternalArray.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001370 DECL_ACCESSORS(elements, HeapObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 inline void initialize_elements();
John Reck59135872010-11-02 12:39:01 -07001372 MUST_USE_RESULT inline MaybeObject* ResetElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 inline ElementsKind GetElementsKind();
1374 inline bool HasFastElements();
1375 inline bool HasDictionaryElements();
Steve Block44f0eee2011-05-26 01:26:41 +01001376 inline bool HasExternalPixelElements();
Steve Block3ce2e202009-11-05 08:53:23 +00001377 inline bool HasExternalArrayElements();
1378 inline bool HasExternalByteElements();
1379 inline bool HasExternalUnsignedByteElements();
1380 inline bool HasExternalShortElements();
1381 inline bool HasExternalUnsignedShortElements();
1382 inline bool HasExternalIntElements();
1383 inline bool HasExternalUnsignedIntElements();
1384 inline bool HasExternalFloatElements();
Steve Block6ded16b2010-05-10 14:33:55 +01001385 inline bool AllowsSetElementsLength();
Steve Blocka7e24c12009-10-30 11:49:00 +00001386 inline NumberDictionary* element_dictionary(); // Gets slow elements.
Iain Merrick75681382010-08-19 15:07:18 +01001387 // Requires: this->HasFastElements().
John Reck59135872010-11-02 12:39:01 -07001388 MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001389
1390 // Collects elements starting at index 0.
1391 // Undefined values are placed after non-undefined values.
1392 // Returns the number of non-undefined values.
John Reck59135872010-11-02 12:39:01 -07001393 MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001394 // As PrepareElementsForSort, but only on objects where elements is
1395 // a dictionary, and it will stay a dictionary.
John Reck59135872010-11-02 12:39:01 -07001396 MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001397
John Reck59135872010-11-02 12:39:01 -07001398 MUST_USE_RESULT MaybeObject* SetProperty(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* SetProperty(LookupResult* result,
1403 String* key,
1404 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001405 PropertyAttributes attributes,
1406 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001407 MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
1408 LookupResult* result,
1409 String* name,
Ben Murdoch086aeea2011-05-13 15:57:08 +01001410 Object* value,
1411 bool check_prototype);
John Reck59135872010-11-02 12:39:01 -07001412 MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(Object* structure,
1413 String* name,
1414 Object* value,
1415 JSObject* holder);
1416 MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSFunction* setter,
1417 Object* value);
1418 MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
1419 String* name,
1420 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001421 PropertyAttributes attributes,
1422 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001423 MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
1424 String* name,
1425 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001426 PropertyAttributes attributes,
1427 StrictModeFlag strict_mode);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001428 MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
John Reck59135872010-11-02 12:39:01 -07001429 String* key,
1430 Object* value,
1431 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001432
1433 // Retrieve a value in a normalized object given a lookup result.
1434 // Handles the special representation of JS global objects.
1435 Object* GetNormalizedProperty(LookupResult* result);
1436
1437 // Sets the property value in a normalized object given a lookup result.
1438 // Handles the special representation of JS global objects.
1439 Object* SetNormalizedProperty(LookupResult* result, Object* value);
1440
1441 // Sets the property value in a normalized object given (key, value, details).
1442 // Handles the special representation of JS global objects.
John Reck59135872010-11-02 12:39:01 -07001443 MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
1444 Object* value,
1445 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00001446
1447 // Deletes the named property in a normalized object.
John Reck59135872010-11-02 12:39:01 -07001448 MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
1449 DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001450
Steve Blocka7e24c12009-10-30 11:49:00 +00001451 // Returns the class name ([[Class]] property in the specification).
1452 String* class_name();
1453
1454 // Returns the constructor name (the name (possibly, inferred name) of the
1455 // function that was used to instantiate the object).
1456 String* constructor_name();
1457
1458 // Retrieve interceptors.
1459 InterceptorInfo* GetNamedInterceptor();
1460 InterceptorInfo* GetIndexedInterceptor();
1461
1462 inline PropertyAttributes GetPropertyAttribute(String* name);
1463 PropertyAttributes GetPropertyAttributeWithReceiver(JSObject* receiver,
1464 String* name);
1465 PropertyAttributes GetLocalPropertyAttribute(String* name);
1466
John Reck59135872010-11-02 12:39:01 -07001467 MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
1468 bool is_getter,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001469 Object* fun,
John Reck59135872010-11-02 12:39:01 -07001470 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001471 Object* LookupAccessor(String* name, bool is_getter);
1472
John Reck59135872010-11-02 12:39:01 -07001473 MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
Leon Clarkef7060e22010-06-03 12:02:55 +01001474
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 // Used from Object::GetProperty().
John Reck59135872010-11-02 12:39:01 -07001476 MaybeObject* GetPropertyWithFailedAccessCheck(
1477 Object* receiver,
1478 LookupResult* result,
1479 String* name,
1480 PropertyAttributes* attributes);
1481 MaybeObject* GetPropertyWithInterceptor(
1482 JSObject* receiver,
1483 String* name,
1484 PropertyAttributes* attributes);
1485 MaybeObject* GetPropertyPostInterceptor(
1486 JSObject* receiver,
1487 String* name,
1488 PropertyAttributes* attributes);
1489 MaybeObject* GetLocalPropertyPostInterceptor(JSObject* receiver,
1490 String* name,
1491 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001492
1493 // Returns true if this is an instance of an api function and has
1494 // been modified since it was created. May give false positives.
1495 bool IsDirty();
1496
1497 bool HasProperty(String* name) {
1498 return GetPropertyAttribute(name) != ABSENT;
1499 }
1500
1501 // Can cause a GC if it hits an interceptor.
1502 bool HasLocalProperty(String* name) {
1503 return GetLocalPropertyAttribute(name) != ABSENT;
1504 }
1505
Steve Blockd0582a62009-12-15 09:54:21 +00001506 // If the receiver is a JSGlobalProxy this method will return its prototype,
1507 // otherwise the result is the receiver itself.
1508 inline Object* BypassGlobalProxy();
1509
1510 // Accessors for hidden properties object.
1511 //
1512 // Hidden properties are not local properties of the object itself.
1513 // Instead they are stored on an auxiliary JSObject stored as a local
1514 // property with a special name Heap::hidden_symbol(). But if the
1515 // receiver is a JSGlobalProxy then the auxiliary object is a property
1516 // of its prototype.
1517 //
1518 // Has/Get/SetHiddenPropertiesObject methods don't allow the holder to be
1519 // a JSGlobalProxy. Use BypassGlobalProxy method above to get to the real
1520 // holder.
1521 //
1522 // These accessors do not touch interceptors or accessors.
1523 inline bool HasHiddenPropertiesObject();
1524 inline Object* GetHiddenPropertiesObject();
John Reck59135872010-11-02 12:39:01 -07001525 MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject(
1526 Object* hidden_obj);
Steve Blockd0582a62009-12-15 09:54:21 +00001527
John Reck59135872010-11-02 12:39:01 -07001528 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
1529 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001530
1531 // Tests for the fast common case for property enumeration.
1532 bool IsSimpleEnum();
1533
1534 // Do we want to keep the elements in fast case when increasing the
1535 // capacity?
1536 bool ShouldConvertToSlowElements(int new_capacity);
1537 // Returns true if the backing storage for the slow-case elements of
1538 // this object takes up nearly as much space as a fast-case backing
1539 // storage would. In that case the JSObject should have fast
1540 // elements.
1541 bool ShouldConvertToFastElements();
1542
1543 // Return the object's prototype (might be Heap::null_value()).
1544 inline Object* GetPrototype();
1545
Andrei Popescu402d9372010-02-26 13:31:12 +00001546 // Set the object's prototype (only JSObject and null are allowed).
John Reck59135872010-11-02 12:39:01 -07001547 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
1548 bool skip_hidden_prototypes);
Andrei Popescu402d9372010-02-26 13:31:12 +00001549
Steve Blocka7e24c12009-10-30 11:49:00 +00001550 // Tells whether the index'th element is present.
1551 inline bool HasElement(uint32_t index);
1552 bool HasElementWithReceiver(JSObject* receiver, uint32_t index);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001553
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001554 // Computes the new capacity when expanding the elements of a JSObject.
1555 static int NewElementsCapacity(int old_capacity) {
1556 // (old_capacity + 50%) + 16
1557 return old_capacity + (old_capacity >> 1) + 16;
1558 }
1559
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001560 // Tells whether the index'th element is present and how it is stored.
1561 enum LocalElementType {
1562 // There is no element with given index.
1563 UNDEFINED_ELEMENT,
1564
1565 // Element with given index is handled by interceptor.
1566 INTERCEPTED_ELEMENT,
1567
1568 // Element with given index is character in string.
1569 STRING_CHARACTER_ELEMENT,
1570
1571 // Element with given index is stored in fast backing store.
1572 FAST_ELEMENT,
1573
1574 // Element with given index is stored in slow backing store.
1575 DICTIONARY_ELEMENT
1576 };
1577
1578 LocalElementType HasLocalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001579
1580 bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
1581 bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
1582
Steve Block9fac8402011-05-12 15:51:54 +01001583 MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
1584 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001585 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01001586 bool check_prototype = true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001587
1588 // Set the index'th array element.
1589 // A Failure object is returned if GC is needed.
Steve Block9fac8402011-05-12 15:51:54 +01001590 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1591 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001592 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01001593 bool check_prototype = true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001594
1595 // Returns the index'th element.
1596 // The undefined object if index is out of bounds.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001597 MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
1598 MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
1599
1600 // Get external element value at index if there is one and undefined
1601 // otherwise. Can return a failure if allocation of a heap number
1602 // failed.
1603 MaybeObject* GetExternalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001604
John Reck59135872010-11-02 12:39:01 -07001605 MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity,
1606 int length);
1607 MUST_USE_RESULT MaybeObject* SetSlowElements(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001608
1609 // Lookup interceptors are used for handling properties controlled by host
1610 // objects.
1611 inline bool HasNamedInterceptor();
1612 inline bool HasIndexedInterceptor();
1613
1614 // Support functions for v8 api (needed for correct interceptor behavior).
1615 bool HasRealNamedProperty(String* key);
1616 bool HasRealElementProperty(uint32_t index);
1617 bool HasRealNamedCallbackProperty(String* key);
1618
1619 // Initializes the array to a certain length
John Reck59135872010-11-02 12:39:01 -07001620 MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001621
1622 // Get the header size for a JSObject. Used to compute the index of
1623 // internal fields as well as the number of internal fields.
1624 inline int GetHeaderSize();
1625
1626 inline int GetInternalFieldCount();
Steve Block44f0eee2011-05-26 01:26:41 +01001627 inline int GetInternalFieldOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001628 inline Object* GetInternalField(int index);
1629 inline void SetInternalField(int index, Object* value);
1630
1631 // Lookup a property. If found, the result is valid and has
1632 // detailed information.
1633 void LocalLookup(String* name, LookupResult* result);
1634 void Lookup(String* name, LookupResult* result);
1635
1636 // The following lookup functions skip interceptors.
1637 void LocalLookupRealNamedProperty(String* name, LookupResult* result);
1638 void LookupRealNamedProperty(String* name, LookupResult* result);
1639 void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
1640 void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
Steve Block1e0659c2011-05-24 12:43:12 +01001641 MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
1642 uint32_t index, Object* value, bool* found);
Steve Blocka7e24c12009-10-30 11:49:00 +00001643 void LookupCallback(String* name, LookupResult* result);
1644
1645 // Returns the number of properties on this object filtering out properties
1646 // with the specified attributes (ignoring interceptors).
1647 int NumberOfLocalProperties(PropertyAttributes filter);
1648 // Returns the number of enumerable properties (ignoring interceptors).
1649 int NumberOfEnumProperties();
1650 // Fill in details for properties into storage starting at the specified
1651 // index.
1652 void GetLocalPropertyNames(FixedArray* storage, int index);
1653
1654 // Returns the number of properties on this object filtering out properties
1655 // with the specified attributes (ignoring interceptors).
1656 int NumberOfLocalElements(PropertyAttributes filter);
1657 // Returns the number of enumerable elements (ignoring interceptors).
1658 int NumberOfEnumElements();
1659 // Returns the number of elements on this object filtering out elements
1660 // with the specified attributes (ignoring interceptors).
1661 int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
1662 // Count and fill in the enumerable elements into storage.
1663 // (storage->length() == NumberOfEnumElements()).
1664 // If storage is NULL, will count the elements without adding
1665 // them to any storage.
1666 // Returns the number of enumerable elements.
1667 int GetEnumElementKeys(FixedArray* storage);
1668
1669 // Add a property to a fast-case object using a map transition to
1670 // new_map.
John Reck59135872010-11-02 12:39:01 -07001671 MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
1672 String* name,
1673 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001674
1675 // Add a constant function property to a fast-case object.
1676 // This leaves a CONSTANT_TRANSITION in the old map, and
1677 // if it is called on a second object with this map, a
1678 // normal property is added instead, with a map transition.
1679 // This avoids the creation of many maps with the same constant
1680 // function, all orphaned.
John Reck59135872010-11-02 12:39:01 -07001681 MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
1682 String* name,
1683 JSFunction* function,
1684 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001685
John Reck59135872010-11-02 12:39:01 -07001686 MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
1687 String* name,
1688 Object* value,
1689 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001690
1691 // Converts a descriptor of any other type to a real field,
1692 // backed by the properties array. Descriptors of visible
1693 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1694 // Converts the descriptor on the original object's map to a
1695 // map transition, and the the new field is on the object's new map.
John Reck59135872010-11-02 12:39:01 -07001696 MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
Steve Blocka7e24c12009-10-30 11:49:00 +00001697 String* name,
1698 Object* new_value,
1699 PropertyAttributes attributes);
1700
1701 // Converts a descriptor of any other type to a real field,
1702 // backed by the properties array. Descriptors of visible
1703 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
John Reck59135872010-11-02 12:39:01 -07001704 MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
1705 String* name,
1706 Object* new_value,
1707 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001708
1709 // Add a property to a fast-case object.
John Reck59135872010-11-02 12:39:01 -07001710 MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
1711 Object* value,
1712 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001713
1714 // Add a property to a slow-case object.
John Reck59135872010-11-02 12:39:01 -07001715 MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
1716 Object* value,
1717 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001718
1719 // Add a property to an object.
John Reck59135872010-11-02 12:39:01 -07001720 MUST_USE_RESULT MaybeObject* AddProperty(String* name,
1721 Object* value,
Steve Block44f0eee2011-05-26 01:26:41 +01001722 PropertyAttributes attributes,
1723 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001724
1725 // Convert the object to use the canonical dictionary
1726 // representation. If the object is expected to have additional properties
1727 // added this number can be indicated to have the backing store allocated to
1728 // an initial capacity for holding these properties.
John Reck59135872010-11-02 12:39:01 -07001729 MUST_USE_RESULT MaybeObject* NormalizeProperties(
1730 PropertyNormalizationMode mode,
1731 int expected_additional_properties);
1732 MUST_USE_RESULT MaybeObject* NormalizeElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001733
John Reck59135872010-11-02 12:39:01 -07001734 MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001735
Steve Blocka7e24c12009-10-30 11:49:00 +00001736 // Transform slow named properties to fast variants.
1737 // Returns failure if allocation failed.
John Reck59135872010-11-02 12:39:01 -07001738 MUST_USE_RESULT MaybeObject* TransformToFastProperties(
1739 int unused_property_fields);
Steve Blocka7e24c12009-10-30 11:49:00 +00001740
1741 // Access fast-case object properties at index.
1742 inline Object* FastPropertyAt(int index);
1743 inline Object* FastPropertyAtPut(int index, Object* value);
1744
1745 // Access to in object properties.
Steve Block44f0eee2011-05-26 01:26:41 +01001746 inline int GetInObjectPropertyOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001747 inline Object* InObjectPropertyAt(int index);
1748 inline Object* InObjectPropertyAtPut(int index,
1749 Object* value,
1750 WriteBarrierMode mode
1751 = UPDATE_WRITE_BARRIER);
1752
1753 // initializes the body after properties slot, properties slot is
1754 // initialized by set_properties
1755 // Note: this call does not update write barrier, it is caller's
1756 // reponsibility to ensure that *v* can be collected without WB here.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001757 inline void InitializeBody(int object_size, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001758
1759 // Check whether this object references another object
1760 bool ReferencesObject(Object* obj);
1761
1762 // Casting.
1763 static inline JSObject* cast(Object* obj);
1764
Steve Block8defd9f2010-07-08 12:39:36 +01001765 // Disalow further properties to be added to the object.
John Reck59135872010-11-02 12:39:01 -07001766 MUST_USE_RESULT MaybeObject* PreventExtensions();
Steve Block8defd9f2010-07-08 12:39:36 +01001767
1768
Steve Blocka7e24c12009-10-30 11:49:00 +00001769 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00001770 void JSObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001771#ifdef OBJECT_PRINT
1772 inline void JSObjectPrint() {
1773 JSObjectPrint(stdout);
1774 }
1775 void JSObjectPrint(FILE* out);
1776#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001777#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001778 void JSObjectVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001779#endif
1780#ifdef OBJECT_PRINT
1781 inline void PrintProperties() {
1782 PrintProperties(stdout);
1783 }
1784 void PrintProperties(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001785
Ben Murdochb0fe1622011-05-05 13:52:32 +01001786 inline void PrintElements() {
1787 PrintElements(stdout);
1788 }
1789 void PrintElements(FILE* out);
1790#endif
1791
1792#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001793 // Structure for collecting spill information about JSObjects.
1794 class SpillInformation {
1795 public:
1796 void Clear();
1797 void Print();
1798 int number_of_objects_;
1799 int number_of_objects_with_fast_properties_;
1800 int number_of_objects_with_fast_elements_;
1801 int number_of_fast_used_fields_;
1802 int number_of_fast_unused_fields_;
1803 int number_of_slow_used_properties_;
1804 int number_of_slow_unused_properties_;
1805 int number_of_fast_used_elements_;
1806 int number_of_fast_unused_elements_;
1807 int number_of_slow_used_elements_;
1808 int number_of_slow_unused_elements_;
1809 };
1810
1811 void IncrementSpillStatistics(SpillInformation* info);
1812#endif
1813 Object* SlowReverseLookup(Object* value);
1814
Steve Block8defd9f2010-07-08 12:39:36 +01001815 // Maximal number of fast properties for the JSObject. Used to
1816 // restrict the number of map transitions to avoid an explosion in
1817 // the number of maps for objects used as dictionaries.
1818 inline int MaxFastProperties();
1819
Leon Clarkee46be812010-01-19 14:06:41 +00001820 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
1821 // Also maximal value of JSArray's length property.
1822 static const uint32_t kMaxElementCount = 0xffffffffu;
1823
Steve Blocka7e24c12009-10-30 11:49:00 +00001824 static const uint32_t kMaxGap = 1024;
1825 static const int kMaxFastElementsLength = 5000;
1826 static const int kInitialMaxFastElementArray = 100000;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001827 static const int kMaxFastProperties = 12;
Steve Blocka7e24c12009-10-30 11:49:00 +00001828 static const int kMaxInstanceSize = 255 * kPointerSize;
1829 // When extending the backing storage for property values, we increase
1830 // its size by more than the 1 entry necessary, so sequentially adding fields
1831 // to the same object requires fewer allocations and copies.
1832 static const int kFieldsAdded = 3;
1833
1834 // Layout description.
1835 static const int kPropertiesOffset = HeapObject::kHeaderSize;
1836 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
1837 static const int kHeaderSize = kElementsOffset + kPointerSize;
1838
1839 STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
1840
Iain Merrick75681382010-08-19 15:07:18 +01001841 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
1842 public:
1843 static inline int SizeOf(Map* map, HeapObject* object);
1844 };
1845
Steve Blocka7e24c12009-10-30 11:49:00 +00001846 private:
John Reck59135872010-11-02 12:39:01 -07001847 MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
1848 Object* structure,
1849 uint32_t index,
1850 Object* holder);
1851 MaybeObject* SetElementWithCallback(Object* structure,
1852 uint32_t index,
1853 Object* value,
1854 JSObject* holder);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001855 MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
1856 uint32_t index,
1857 Object* value,
1858 StrictModeFlag strict_mode,
1859 bool check_prototype);
Steve Block9fac8402011-05-12 15:51:54 +01001860 MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
1861 uint32_t index,
1862 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001863 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01001864 bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00001865
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001866 MaybeObject* GetElementPostInterceptor(Object* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001867
John Reck59135872010-11-02 12:39:01 -07001868 MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
1869 DeleteMode mode);
1870 MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001871
John Reck59135872010-11-02 12:39:01 -07001872 MUST_USE_RESULT MaybeObject* DeleteElementPostInterceptor(uint32_t index,
1873 DeleteMode mode);
1874 MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001875
1876 PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
1877 String* name,
1878 bool continue_search);
1879 PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
1880 String* name,
1881 bool continue_search);
1882 PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
1883 Object* receiver,
1884 LookupResult* result,
1885 String* name,
1886 bool continue_search);
1887 PropertyAttributes GetPropertyAttribute(JSObject* receiver,
1888 LookupResult* result,
1889 String* name,
1890 bool continue_search);
1891
1892 // Returns true if most of the elements backing storage is used.
1893 bool HasDenseElements();
1894
Leon Clarkef7060e22010-06-03 12:02:55 +01001895 bool CanSetCallback(String* name);
John Reck59135872010-11-02 12:39:01 -07001896 MUST_USE_RESULT MaybeObject* SetElementCallback(
1897 uint32_t index,
1898 Object* structure,
1899 PropertyAttributes attributes);
1900 MUST_USE_RESULT MaybeObject* SetPropertyCallback(
1901 String* name,
1902 Object* structure,
1903 PropertyAttributes attributes);
1904 MUST_USE_RESULT MaybeObject* DefineGetterSetter(
1905 String* name,
1906 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001907
1908 void LookupInDescriptor(String* name, LookupResult* result);
1909
1910 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
1911};
1912
1913
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001914// FixedArray describes fixed-sized arrays with element type Object*.
1915class FixedArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001916 public:
1917 // [length]: length of the array.
1918 inline int length();
1919 inline void set_length(int value);
1920
Steve Blocka7e24c12009-10-30 11:49:00 +00001921 // Setter and getter for elements.
1922 inline Object* get(int index);
1923 // Setter that uses write barrier.
1924 inline void set(int index, Object* value);
1925
1926 // Setter that doesn't need write barrier).
1927 inline void set(int index, Smi* value);
1928 // Setter with explicit barrier mode.
1929 inline void set(int index, Object* value, WriteBarrierMode mode);
1930
1931 // Setters for frequently used oddballs located in old space.
1932 inline void set_undefined(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01001933 // TODO(isolates): duplicate.
1934 inline void set_undefined(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001935 inline void set_null(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01001936 // TODO(isolates): duplicate.
1937 inline void set_null(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001938 inline void set_the_hole(int index);
1939
Iain Merrick75681382010-08-19 15:07:18 +01001940 // Setters with less debug checks for the GC to use.
1941 inline void set_unchecked(int index, Smi* value);
Steve Block44f0eee2011-05-26 01:26:41 +01001942 inline void set_null_unchecked(Heap* heap, int index);
1943 inline void set_unchecked(Heap* heap, int index, Object* value,
1944 WriteBarrierMode mode);
Iain Merrick75681382010-08-19 15:07:18 +01001945
Steve Block6ded16b2010-05-10 14:33:55 +01001946 // Gives access to raw memory which stores the array's data.
1947 inline Object** data_start();
1948
Steve Blocka7e24c12009-10-30 11:49:00 +00001949 // Copy operations.
John Reck59135872010-11-02 12:39:01 -07001950 MUST_USE_RESULT inline MaybeObject* Copy();
1951 MUST_USE_RESULT MaybeObject* CopySize(int new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001952
1953 // Add the elements of a JSArray to this FixedArray.
John Reck59135872010-11-02 12:39:01 -07001954 MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001955
1956 // Compute the union of this and other.
John Reck59135872010-11-02 12:39:01 -07001957 MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
Steve Blocka7e24c12009-10-30 11:49:00 +00001958
1959 // Copy a sub array from the receiver to dest.
1960 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
1961
1962 // Garbage collection support.
1963 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
1964
1965 // Code Generation support.
1966 static int OffsetOfElementAt(int index) { return SizeFor(index); }
1967
1968 // Casting.
1969 static inline FixedArray* cast(Object* obj);
1970
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001971 // Layout description.
1972 // Length is smi tagged when it is stored.
1973 static const int kLengthOffset = HeapObject::kHeaderSize;
1974 static const int kHeaderSize = kLengthOffset + kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00001975
1976 // Maximal allowed size, in bytes, of a single FixedArray.
1977 // Prevents overflowing size computations, as well as extreme memory
1978 // consumption.
1979 static const int kMaxSize = 512 * MB;
1980 // Maximally allowed length of a FixedArray.
1981 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001982
1983 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001984#ifdef OBJECT_PRINT
1985 inline void FixedArrayPrint() {
1986 FixedArrayPrint(stdout);
1987 }
1988 void FixedArrayPrint(FILE* out);
1989#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001990#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001991 void FixedArrayVerify();
1992 // Checks if two FixedArrays have identical contents.
1993 bool IsEqualTo(FixedArray* other);
1994#endif
1995
1996 // Swap two elements in a pair of arrays. If this array and the
1997 // numbers array are the same object, the elements are only swapped
1998 // once.
1999 void SwapPairs(FixedArray* numbers, int i, int j);
2000
2001 // Sort prefix of this array and the numbers array as pairs wrt. the
2002 // numbers. If the numbers array and the this array are the same
2003 // object, the prefix of this array is sorted.
2004 void SortPairs(FixedArray* numbers, uint32_t len);
2005
Iain Merrick75681382010-08-19 15:07:18 +01002006 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
2007 public:
2008 static inline int SizeOf(Map* map, HeapObject* object) {
2009 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
2010 }
2011 };
2012
Steve Blocka7e24c12009-10-30 11:49:00 +00002013 protected:
Leon Clarke4515c472010-02-03 11:58:03 +00002014 // Set operation on FixedArray without using write barriers. Can
2015 // only be used for storing old space objects or smis.
Steve Blocka7e24c12009-10-30 11:49:00 +00002016 static inline void fast_set(FixedArray* array, int index, Object* value);
2017
2018 private:
2019 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
2020};
2021
2022
2023// DescriptorArrays are fixed arrays used to hold instance descriptors.
2024// The format of the these objects is:
2025// [0]: point to a fixed array with (value, detail) pairs.
2026// [1]: next enumeration index (Smi), or pointer to small fixed array:
2027// [0]: next enumeration index (Smi)
2028// [1]: pointer to fixed array with enum cache
2029// [2]: first key
2030// [length() - 1]: last key
2031//
2032class DescriptorArray: public FixedArray {
2033 public:
2034 // Is this the singleton empty_descriptor_array?
2035 inline bool IsEmpty();
Leon Clarkee46be812010-01-19 14:06:41 +00002036
Steve Blocka7e24c12009-10-30 11:49:00 +00002037 // Returns the number of descriptors in the array.
2038 int number_of_descriptors() {
Steve Block44f0eee2011-05-26 01:26:41 +01002039 ASSERT(length() > kFirstIndex || IsEmpty());
2040 int len = length();
2041 return len <= kFirstIndex ? 0 : len - kFirstIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00002042 }
2043
2044 int NextEnumerationIndex() {
2045 if (IsEmpty()) return PropertyDetails::kInitialIndex;
2046 Object* obj = get(kEnumerationIndexIndex);
2047 if (obj->IsSmi()) {
2048 return Smi::cast(obj)->value();
2049 } else {
2050 Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
2051 return Smi::cast(index)->value();
2052 }
2053 }
2054
2055 // Set next enumeration index and flush any enum cache.
2056 void SetNextEnumerationIndex(int value) {
2057 if (!IsEmpty()) {
2058 fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
2059 }
2060 }
2061 bool HasEnumCache() {
2062 return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
2063 }
2064
2065 Object* GetEnumCache() {
2066 ASSERT(HasEnumCache());
2067 FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
2068 return bridge->get(kEnumCacheBridgeCacheIndex);
2069 }
2070
2071 // Initialize or change the enum cache,
2072 // using the supplied storage for the small "bridge".
2073 void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
2074
2075 // Accessors for fetching instance descriptor at descriptor number.
2076 inline String* GetKey(int descriptor_number);
2077 inline Object* GetValue(int descriptor_number);
2078 inline Smi* GetDetails(int descriptor_number);
2079 inline PropertyType GetType(int descriptor_number);
2080 inline int GetFieldIndex(int descriptor_number);
2081 inline JSFunction* GetConstantFunction(int descriptor_number);
2082 inline Object* GetCallbacksObject(int descriptor_number);
2083 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
2084 inline bool IsProperty(int descriptor_number);
2085 inline bool IsTransition(int descriptor_number);
2086 inline bool IsNullDescriptor(int descriptor_number);
2087 inline bool IsDontEnum(int descriptor_number);
2088
2089 // Accessor for complete descriptor.
2090 inline void Get(int descriptor_number, Descriptor* desc);
2091 inline void Set(int descriptor_number, Descriptor* desc);
2092
2093 // Transfer complete descriptor from another descriptor array to
2094 // this one.
2095 inline void CopyFrom(int index, DescriptorArray* src, int src_index);
2096
2097 // Copy the descriptor array, insert a new descriptor and optionally
2098 // remove map transitions. If the descriptor is already present, it is
2099 // replaced. If a replaced descriptor is a real property (not a transition
2100 // or null), its enumeration index is kept as is.
2101 // If adding a real property, map transitions must be removed. If adding
2102 // a transition, they must not be removed. All null descriptors are removed.
John Reck59135872010-11-02 12:39:01 -07002103 MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
2104 TransitionFlag transition_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +00002105
2106 // Remove all transitions. Return a copy of the array with all transitions
2107 // removed, or a Failure object if the new array could not be allocated.
John Reck59135872010-11-02 12:39:01 -07002108 MUST_USE_RESULT MaybeObject* RemoveTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002109
2110 // Sort the instance descriptors by the hash codes of their keys.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002111 // Does not check for duplicates.
2112 void SortUnchecked();
2113
2114 // Sort the instance descriptors by the hash codes of their keys.
2115 // Checks the result for duplicates.
Steve Blocka7e24c12009-10-30 11:49:00 +00002116 void Sort();
2117
2118 // Search the instance descriptors for given name.
2119 inline int Search(String* name);
2120
Iain Merrick75681382010-08-19 15:07:18 +01002121 // As the above, but uses DescriptorLookupCache and updates it when
2122 // necessary.
2123 inline int SearchWithCache(String* name);
2124
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 // Tells whether the name is present int the array.
2126 bool Contains(String* name) { return kNotFound != Search(name); }
2127
2128 // Perform a binary search in the instance descriptors represented
2129 // by this fixed array. low and high are descriptor indices. If there
2130 // are three instance descriptors in this array it should be called
2131 // with low=0 and high=2.
2132 int BinarySearch(String* name, int low, int high);
2133
2134 // Perform a linear search in the instance descriptors represented
2135 // by this fixed array. len is the number of descriptor indices that are
2136 // valid. Does not require the descriptors to be sorted.
2137 int LinearSearch(String* name, int len);
2138
2139 // Allocates a DescriptorArray, but returns the singleton
2140 // empty descriptor array object if number_of_descriptors is 0.
John Reck59135872010-11-02 12:39:01 -07002141 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
Steve Blocka7e24c12009-10-30 11:49:00 +00002142
2143 // Casting.
2144 static inline DescriptorArray* cast(Object* obj);
2145
2146 // Constant for denoting key was not found.
2147 static const int kNotFound = -1;
2148
2149 static const int kContentArrayIndex = 0;
2150 static const int kEnumerationIndexIndex = 1;
2151 static const int kFirstIndex = 2;
2152
2153 // The length of the "bridge" to the enum cache.
2154 static const int kEnumCacheBridgeLength = 2;
2155 static const int kEnumCacheBridgeEnumIndex = 0;
2156 static const int kEnumCacheBridgeCacheIndex = 1;
2157
2158 // Layout description.
2159 static const int kContentArrayOffset = FixedArray::kHeaderSize;
2160 static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
2161 static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
2162
2163 // Layout description for the bridge array.
2164 static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
2165 static const int kEnumCacheBridgeCacheOffset =
2166 kEnumCacheBridgeEnumOffset + kPointerSize;
2167
Ben Murdochb0fe1622011-05-05 13:52:32 +01002168#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +00002169 // Print all the descriptors.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002170 inline void PrintDescriptors() {
2171 PrintDescriptors(stdout);
2172 }
2173 void PrintDescriptors(FILE* out);
2174#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002175
Ben Murdochb0fe1622011-05-05 13:52:32 +01002176#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002177 // Is the descriptor array sorted and without duplicates?
2178 bool IsSortedNoDuplicates();
2179
2180 // Are two DescriptorArrays equal?
2181 bool IsEqualTo(DescriptorArray* other);
2182#endif
2183
2184 // The maximum number of descriptors we want in a descriptor array (should
2185 // fit in a page).
2186 static const int kMaxNumberOfDescriptors = 1024 + 512;
2187
2188 private:
2189 // Conversion from descriptor number to array indices.
2190 static int ToKeyIndex(int descriptor_number) {
2191 return descriptor_number+kFirstIndex;
2192 }
Leon Clarkee46be812010-01-19 14:06:41 +00002193
2194 static int ToDetailsIndex(int descriptor_number) {
2195 return (descriptor_number << 1) + 1;
2196 }
2197
Steve Blocka7e24c12009-10-30 11:49:00 +00002198 static int ToValueIndex(int descriptor_number) {
2199 return descriptor_number << 1;
2200 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002201
2202 bool is_null_descriptor(int descriptor_number) {
2203 return PropertyDetails(GetDetails(descriptor_number)).type() ==
2204 NULL_DESCRIPTOR;
2205 }
2206 // Swap operation on FixedArray without using write barriers.
2207 static inline void fast_swap(FixedArray* array, int first, int second);
2208
2209 // Swap descriptor first and second.
2210 inline void Swap(int first, int second);
2211
2212 FixedArray* GetContentArray() {
2213 return FixedArray::cast(get(kContentArrayIndex));
2214 }
2215 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
2216};
2217
2218
2219// HashTable is a subclass of FixedArray that implements a hash table
2220// that uses open addressing and quadratic probing.
2221//
2222// In order for the quadratic probing to work, elements that have not
2223// yet been used and elements that have been deleted are
2224// distinguished. Probing continues when deleted elements are
2225// encountered and stops when unused elements are encountered.
2226//
2227// - Elements with key == undefined have not been used yet.
2228// - Elements with key == null have been deleted.
2229//
2230// The hash table class is parameterized with a Shape and a Key.
2231// Shape must be a class with the following interface:
2232// class ExampleShape {
2233// public:
2234// // Tells whether key matches other.
2235// static bool IsMatch(Key key, Object* other);
2236// // Returns the hash value for key.
2237// static uint32_t Hash(Key key);
2238// // Returns the hash value for object.
2239// static uint32_t HashForObject(Key key, Object* object);
2240// // Convert key to an object.
2241// static inline Object* AsObject(Key key);
2242// // The prefix size indicates number of elements in the beginning
2243// // of the backing storage.
2244// static const int kPrefixSize = ..;
2245// // The Element size indicates number of elements per entry.
2246// static const int kEntrySize = ..;
2247// };
Steve Block3ce2e202009-11-05 08:53:23 +00002248// The prefix size indicates an amount of memory in the
Steve Blocka7e24c12009-10-30 11:49:00 +00002249// beginning of the backing storage that can be used for non-element
2250// information by subclasses.
2251
2252template<typename Shape, typename Key>
2253class HashTable: public FixedArray {
2254 public:
Steve Block3ce2e202009-11-05 08:53:23 +00002255 // Returns the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002256 int NumberOfElements() {
2257 return Smi::cast(get(kNumberOfElementsIndex))->value();
2258 }
2259
Leon Clarkee46be812010-01-19 14:06:41 +00002260 // Returns the number of deleted elements in the hash table.
2261 int NumberOfDeletedElements() {
2262 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
2263 }
2264
Steve Block3ce2e202009-11-05 08:53:23 +00002265 // Returns the capacity of the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002266 int Capacity() {
2267 return Smi::cast(get(kCapacityIndex))->value();
2268 }
2269
2270 // ElementAdded should be called whenever an element is added to a
Steve Block3ce2e202009-11-05 08:53:23 +00002271 // hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002272 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
2273
2274 // ElementRemoved should be called whenever an element is removed from
Steve Block3ce2e202009-11-05 08:53:23 +00002275 // a hash table.
Leon Clarkee46be812010-01-19 14:06:41 +00002276 void ElementRemoved() {
2277 SetNumberOfElements(NumberOfElements() - 1);
2278 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
2279 }
2280 void ElementsRemoved(int n) {
2281 SetNumberOfElements(NumberOfElements() - n);
2282 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
2283 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002284
Steve Block3ce2e202009-11-05 08:53:23 +00002285 // Returns a new HashTable object. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002286 MUST_USE_RESULT static MaybeObject* Allocate(
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002287 int at_least_space_for,
2288 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002289
2290 // Returns the key at entry.
2291 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
2292
2293 // Tells whether k is a real key. Null and undefined are not allowed
2294 // as keys and can be used to indicate missing or deleted elements.
2295 bool IsKey(Object* k) {
2296 return !k->IsNull() && !k->IsUndefined();
2297 }
2298
2299 // Garbage collection support.
2300 void IteratePrefix(ObjectVisitor* visitor);
2301 void IterateElements(ObjectVisitor* visitor);
2302
2303 // Casting.
2304 static inline HashTable* cast(Object* obj);
2305
2306 // Compute the probe offset (quadratic probing).
2307 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
2308 return (n + n * n) >> 1;
2309 }
2310
2311 static const int kNumberOfElementsIndex = 0;
Leon Clarkee46be812010-01-19 14:06:41 +00002312 static const int kNumberOfDeletedElementsIndex = 1;
2313 static const int kCapacityIndex = 2;
2314 static const int kPrefixStartIndex = 3;
2315 static const int kElementsStartIndex =
Steve Blocka7e24c12009-10-30 11:49:00 +00002316 kPrefixStartIndex + Shape::kPrefixSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002317 static const int kEntrySize = Shape::kEntrySize;
2318 static const int kElementsStartOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00002319 kHeaderSize + kElementsStartIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01002320 static const int kCapacityOffset =
2321 kHeaderSize + kCapacityIndex * kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002322
2323 // Constant used for denoting a absent entry.
2324 static const int kNotFound = -1;
2325
Leon Clarkee46be812010-01-19 14:06:41 +00002326 // Maximal capacity of HashTable. Based on maximal length of underlying
2327 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
2328 // cannot overflow.
2329 static const int kMaxCapacity =
2330 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
2331
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002332 // Find entry for key otherwise return kNotFound.
Steve Block44f0eee2011-05-26 01:26:41 +01002333 inline int FindEntry(Key key);
2334 int FindEntry(Isolate* isolate, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002335
2336 protected:
2337
2338 // Find the entry at which to insert element with the given key that
2339 // has the given hash value.
2340 uint32_t FindInsertionEntry(uint32_t hash);
2341
2342 // Returns the index for an entry (of the key)
2343 static inline int EntryToIndex(int entry) {
2344 return (entry * kEntrySize) + kElementsStartIndex;
2345 }
2346
Steve Block3ce2e202009-11-05 08:53:23 +00002347 // Update the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002348 void SetNumberOfElements(int nof) {
2349 fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
2350 }
2351
Leon Clarkee46be812010-01-19 14:06:41 +00002352 // Update the number of deleted elements in the hash table.
2353 void SetNumberOfDeletedElements(int nod) {
2354 fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
2355 }
2356
Steve Blocka7e24c12009-10-30 11:49:00 +00002357 // Sets the capacity of the hash table.
2358 void SetCapacity(int capacity) {
2359 // To scale a computed hash code to fit within the hash table, we
2360 // use bit-wise AND with a mask, so the capacity must be positive
2361 // and non-zero.
2362 ASSERT(capacity > 0);
Leon Clarkee46be812010-01-19 14:06:41 +00002363 ASSERT(capacity <= kMaxCapacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00002364 fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
2365 }
2366
2367
2368 // Returns probe entry.
2369 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
2370 ASSERT(IsPowerOf2(size));
2371 return (hash + GetProbeOffset(number)) & (size - 1);
2372 }
2373
Leon Clarkee46be812010-01-19 14:06:41 +00002374 static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
2375 return hash & (size - 1);
2376 }
2377
2378 static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
2379 return (last + number) & (size - 1);
2380 }
2381
Steve Blocka7e24c12009-10-30 11:49:00 +00002382 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002383 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002384};
2385
2386
2387
2388// HashTableKey is an abstract superclass for virtual key behavior.
2389class HashTableKey {
2390 public:
2391 // Returns whether the other object matches this key.
2392 virtual bool IsMatch(Object* other) = 0;
2393 // Returns the hash value for this key.
2394 virtual uint32_t Hash() = 0;
2395 // Returns the hash value for object.
2396 virtual uint32_t HashForObject(Object* key) = 0;
Steve Block3ce2e202009-11-05 08:53:23 +00002397 // Returns the key object for storing into the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002398 // If allocations fails a failure object is returned.
John Reck59135872010-11-02 12:39:01 -07002399 MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002400 // Required.
2401 virtual ~HashTableKey() {}
2402};
2403
2404class SymbolTableShape {
2405 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002406 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002407 return key->IsMatch(value);
2408 }
Steve Block44f0eee2011-05-26 01:26:41 +01002409 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002410 return key->Hash();
2411 }
Steve Block44f0eee2011-05-26 01:26:41 +01002412 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002413 return key->HashForObject(object);
2414 }
Steve Block44f0eee2011-05-26 01:26:41 +01002415 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002416 return key->AsObject();
2417 }
2418
2419 static const int kPrefixSize = 0;
2420 static const int kEntrySize = 1;
2421};
2422
2423// SymbolTable.
2424//
2425// No special elements in the prefix and the element size is 1
2426// because only the symbol itself (the key) needs to be stored.
2427class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
2428 public:
2429 // Find symbol in the symbol table. If it is not there yet, it is
2430 // added. The return value is the symbol table which might have
2431 // been enlarged. If the return value is not a failure, the symbol
2432 // pointer *s is set to the symbol found.
John Reck59135872010-11-02 12:39:01 -07002433 MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
Steve Block9fac8402011-05-12 15:51:54 +01002434 MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
2435 Object** s);
2436 MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
2437 Object** s);
John Reck59135872010-11-02 12:39:01 -07002438 MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002439
2440 // Looks up a symbol that is equal to the given string and returns
2441 // true if it is found, assigning the symbol to the given output
2442 // parameter.
2443 bool LookupSymbolIfExists(String* str, String** symbol);
Steve Blockd0582a62009-12-15 09:54:21 +00002444 bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002445
2446 // Casting.
2447 static inline SymbolTable* cast(Object* obj);
2448
2449 private:
John Reck59135872010-11-02 12:39:01 -07002450 MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002451
2452 DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
2453};
2454
2455
2456class MapCacheShape {
2457 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002458 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002459 return key->IsMatch(value);
2460 }
Steve Block44f0eee2011-05-26 01:26:41 +01002461 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002462 return key->Hash();
2463 }
2464
Steve Block44f0eee2011-05-26 01:26:41 +01002465 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002466 return key->HashForObject(object);
2467 }
2468
Steve Block44f0eee2011-05-26 01:26:41 +01002469 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002470 return key->AsObject();
2471 }
2472
2473 static const int kPrefixSize = 0;
2474 static const int kEntrySize = 2;
2475};
2476
2477
2478// MapCache.
2479//
2480// Maps keys that are a fixed array of symbols to a map.
2481// Used for canonicalize maps for object literals.
2482class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
2483 public:
2484 // Find cached value for a string key, otherwise return null.
2485 Object* Lookup(FixedArray* key);
John Reck59135872010-11-02 12:39:01 -07002486 MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002487 static inline MapCache* cast(Object* obj);
2488
2489 private:
2490 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
2491};
2492
2493
2494template <typename Shape, typename Key>
2495class Dictionary: public HashTable<Shape, Key> {
2496 public:
2497
2498 static inline Dictionary<Shape, Key>* cast(Object* obj) {
2499 return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
2500 }
2501
2502 // Returns the value at entry.
2503 Object* ValueAt(int entry) {
Steve Block6ded16b2010-05-10 14:33:55 +01002504 return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002505 }
2506
2507 // Set the value for entry.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002508 // Returns false if the put wasn't performed due to property being read only.
2509 // Returns true on successful put.
2510 bool ValueAtPut(int entry, Object* value) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002511 // Check that this value can actually be written.
2512 PropertyDetails details = DetailsAt(entry);
2513 // If a value has not been initilized we allow writing to it even if
2514 // it is read only (a declared const that has not been initialized).
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002515 if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
2516 return false;
2517 }
2518 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
2519 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002520 }
2521
2522 // Returns the property details for the property at entry.
2523 PropertyDetails DetailsAt(int entry) {
2524 ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
2525 return PropertyDetails(
Steve Block6ded16b2010-05-10 14:33:55 +01002526 Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002527 }
2528
2529 // Set the details for entry.
2530 void DetailsAtPut(int entry, PropertyDetails value) {
Steve Block6ded16b2010-05-10 14:33:55 +01002531 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002532 }
2533
2534 // Sorting support
2535 void CopyValuesTo(FixedArray* elements);
2536
2537 // Delete a property from the dictionary.
2538 Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
2539
2540 // Returns the number of elements in the dictionary filtering out properties
2541 // with the specified attributes.
2542 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
2543
2544 // Returns the number of enumerable elements in the dictionary.
2545 int NumberOfEnumElements();
2546
2547 // Copies keys to preallocated fixed array.
2548 void CopyKeysTo(FixedArray* storage, PropertyAttributes filter);
2549 // Fill in details for properties into storage.
2550 void CopyKeysTo(FixedArray* storage);
2551
2552 // Accessors for next enumeration index.
2553 void SetNextEnumerationIndex(int index) {
Steve Block6ded16b2010-05-10 14:33:55 +01002554 this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00002555 }
2556
2557 int NextEnumerationIndex() {
2558 return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
2559 }
2560
2561 // Returns a new array for dictionary usage. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002562 MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
Steve Blocka7e24c12009-10-30 11:49:00 +00002563
2564 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002565 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002566
Ben Murdochb0fe1622011-05-05 13:52:32 +01002567#ifdef OBJECT_PRINT
2568 inline void Print() {
2569 Print(stdout);
2570 }
2571 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00002572#endif
2573 // Returns the key (slow).
2574 Object* SlowReverseLookup(Object* value);
2575
2576 // Sets the entry to (key, value) pair.
2577 inline void SetEntry(int entry,
2578 Object* key,
2579 Object* value,
2580 PropertyDetails details);
2581
John Reck59135872010-11-02 12:39:01 -07002582 MUST_USE_RESULT MaybeObject* Add(Key key,
2583 Object* value,
2584 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002585
2586 protected:
2587 // Generic at put operation.
John Reck59135872010-11-02 12:39:01 -07002588 MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002589
2590 // Add entry to dictionary.
John Reck59135872010-11-02 12:39:01 -07002591 MUST_USE_RESULT MaybeObject* AddEntry(Key key,
2592 Object* value,
2593 PropertyDetails details,
2594 uint32_t hash);
Steve Blocka7e24c12009-10-30 11:49:00 +00002595
2596 // Generate new enumeration indices to avoid enumeration index overflow.
John Reck59135872010-11-02 12:39:01 -07002597 MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
Steve Blocka7e24c12009-10-30 11:49:00 +00002598 static const int kMaxNumberKeyIndex =
2599 HashTable<Shape, Key>::kPrefixStartIndex;
2600 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
2601};
2602
2603
2604class StringDictionaryShape {
2605 public:
2606 static inline bool IsMatch(String* key, Object* other);
2607 static inline uint32_t Hash(String* key);
2608 static inline uint32_t HashForObject(String* key, Object* object);
John Reck59135872010-11-02 12:39:01 -07002609 MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002610 static const int kPrefixSize = 2;
2611 static const int kEntrySize = 3;
2612 static const bool kIsEnumerable = true;
2613};
2614
2615
2616class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
2617 public:
2618 static inline StringDictionary* cast(Object* obj) {
2619 ASSERT(obj->IsDictionary());
2620 return reinterpret_cast<StringDictionary*>(obj);
2621 }
2622
2623 // Copies enumerable keys to preallocated fixed array.
2624 void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
2625
2626 // For transforming properties of a JSObject.
John Reck59135872010-11-02 12:39:01 -07002627 MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
2628 JSObject* obj,
2629 int unused_property_fields);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002630
2631 // Find entry for key otherwise return kNotFound. Optimzed version of
2632 // HashTable::FindEntry.
2633 int FindEntry(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002634};
2635
2636
2637class NumberDictionaryShape {
2638 public:
2639 static inline bool IsMatch(uint32_t key, Object* other);
2640 static inline uint32_t Hash(uint32_t key);
2641 static inline uint32_t HashForObject(uint32_t key, Object* object);
John Reck59135872010-11-02 12:39:01 -07002642 MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002643 static const int kPrefixSize = 2;
2644 static const int kEntrySize = 3;
2645 static const bool kIsEnumerable = false;
2646};
2647
2648
2649class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
2650 public:
2651 static NumberDictionary* cast(Object* obj) {
2652 ASSERT(obj->IsDictionary());
2653 return reinterpret_cast<NumberDictionary*>(obj);
2654 }
2655
2656 // Type specific at put (default NONE attributes is used when adding).
John Reck59135872010-11-02 12:39:01 -07002657 MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
2658 MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
2659 Object* value,
2660 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002661
2662 // Set an existing entry or add a new one if needed.
John Reck59135872010-11-02 12:39:01 -07002663 MUST_USE_RESULT MaybeObject* Set(uint32_t key,
2664 Object* value,
2665 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002666
2667 void UpdateMaxNumberKey(uint32_t key);
2668
2669 // If slow elements are required we will never go back to fast-case
2670 // for the elements kept in this dictionary. We require slow
2671 // elements if an element has been added at an index larger than
2672 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
2673 // when defining a getter or setter with a number key.
2674 inline bool requires_slow_elements();
2675 inline void set_requires_slow_elements();
2676
2677 // Get the value of the max number key that has been added to this
2678 // dictionary. max_number_key can only be called if
2679 // requires_slow_elements returns false.
2680 inline uint32_t max_number_key();
2681
2682 // Remove all entries were key is a number and (from <= key && key < to).
2683 void RemoveNumberEntries(uint32_t from, uint32_t to);
2684
2685 // Bit masks.
2686 static const int kRequiresSlowElementsMask = 1;
2687 static const int kRequiresSlowElementsTagSize = 1;
2688 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
2689};
2690
2691
Steve Block6ded16b2010-05-10 14:33:55 +01002692// JSFunctionResultCache caches results of some JSFunction invocation.
2693// It is a fixed array with fixed structure:
2694// [0]: factory function
2695// [1]: finger index
2696// [2]: current cache size
2697// [3]: dummy field.
2698// The rest of array are key/value pairs.
2699class JSFunctionResultCache: public FixedArray {
2700 public:
2701 static const int kFactoryIndex = 0;
2702 static const int kFingerIndex = kFactoryIndex + 1;
2703 static const int kCacheSizeIndex = kFingerIndex + 1;
2704 static const int kDummyIndex = kCacheSizeIndex + 1;
2705 static const int kEntriesIndex = kDummyIndex + 1;
2706
2707 static const int kEntrySize = 2; // key + value
2708
Kristian Monsen25f61362010-05-21 11:50:48 +01002709 static const int kFactoryOffset = kHeaderSize;
2710 static const int kFingerOffset = kFactoryOffset + kPointerSize;
2711 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
2712
Steve Block6ded16b2010-05-10 14:33:55 +01002713 inline void MakeZeroSize();
2714 inline void Clear();
2715
Ben Murdochb8e0da22011-05-16 14:20:40 +01002716 inline int size();
2717 inline void set_size(int size);
2718 inline int finger_index();
2719 inline void set_finger_index(int finger_index);
2720
Steve Block6ded16b2010-05-10 14:33:55 +01002721 // Casting
2722 static inline JSFunctionResultCache* cast(Object* obj);
2723
2724#ifdef DEBUG
2725 void JSFunctionResultCacheVerify();
2726#endif
2727};
2728
2729
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002730// The cache for maps used by normalized (dictionary mode) objects.
2731// Such maps do not have property descriptors, so a typical program
2732// needs very limited number of distinct normalized maps.
2733class NormalizedMapCache: public FixedArray {
2734 public:
2735 static const int kEntries = 64;
2736
John Reck59135872010-11-02 12:39:01 -07002737 MUST_USE_RESULT MaybeObject* Get(JSObject* object,
2738 PropertyNormalizationMode mode);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002739
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002740 void Clear();
2741
2742 // Casting
2743 static inline NormalizedMapCache* cast(Object* obj);
2744
2745#ifdef DEBUG
2746 void NormalizedMapCacheVerify();
2747#endif
2748
2749 private:
2750 static int Hash(Map* fast);
2751
2752 static bool CheckHit(Map* slow, Map* fast, PropertyNormalizationMode mode);
2753};
2754
2755
Steve Blocka7e24c12009-10-30 11:49:00 +00002756// ByteArray represents fixed sized byte arrays. Used by the outside world,
2757// such as PCRE, and also by the memory allocator and garbage collector to
2758// fill in free blocks in the heap.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002759class ByteArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002760 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002761 // [length]: length of the array.
2762 inline int length();
2763 inline void set_length(int value);
2764
Steve Blocka7e24c12009-10-30 11:49:00 +00002765 // Setter and getter.
2766 inline byte get(int index);
2767 inline void set(int index, byte value);
2768
2769 // Treat contents as an int array.
2770 inline int get_int(int index);
2771
2772 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002773 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
Steve Blocka7e24c12009-10-30 11:49:00 +00002774 }
2775 // We use byte arrays for free blocks in the heap. Given a desired size in
2776 // bytes that is a multiple of the word size and big enough to hold a byte
2777 // array, this function returns the number of elements a byte array should
2778 // have.
2779 static int LengthFor(int size_in_bytes) {
2780 ASSERT(IsAligned(size_in_bytes, kPointerSize));
2781 ASSERT(size_in_bytes >= kHeaderSize);
2782 return size_in_bytes - kHeaderSize;
2783 }
2784
2785 // Returns data start address.
2786 inline Address GetDataStartAddress();
2787
2788 // Returns a pointer to the ByteArray object for a given data start address.
2789 static inline ByteArray* FromDataStartAddress(Address address);
2790
2791 // Casting.
2792 static inline ByteArray* cast(Object* obj);
2793
2794 // Dispatched behavior.
Iain Merrick75681382010-08-19 15:07:18 +01002795 inline int ByteArraySize() {
2796 return SizeFor(this->length());
2797 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002798#ifdef OBJECT_PRINT
2799 inline void ByteArrayPrint() {
2800 ByteArrayPrint(stdout);
2801 }
2802 void ByteArrayPrint(FILE* out);
2803#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002804#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002805 void ByteArrayVerify();
2806#endif
2807
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002808 // Layout description.
2809 // Length is smi tagged when it is stored.
2810 static const int kLengthOffset = HeapObject::kHeaderSize;
2811 static const int kHeaderSize = kLengthOffset + kPointerSize;
2812
2813 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002814
Leon Clarkee46be812010-01-19 14:06:41 +00002815 // Maximal memory consumption for a single ByteArray.
2816 static const int kMaxSize = 512 * MB;
2817 // Maximal length of a single ByteArray.
2818 static const int kMaxLength = kMaxSize - kHeaderSize;
2819
Steve Blocka7e24c12009-10-30 11:49:00 +00002820 private:
2821 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
2822};
2823
2824
Steve Block3ce2e202009-11-05 08:53:23 +00002825// An ExternalArray represents a fixed-size array of primitive values
2826// which live outside the JavaScript heap. Its subclasses are used to
2827// implement the CanvasArray types being defined in the WebGL
2828// specification. As of this writing the first public draft is not yet
2829// available, but Khronos members can access the draft at:
2830// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
2831//
2832// The semantics of these arrays differ from CanvasPixelArray.
2833// Out-of-range values passed to the setter are converted via a C
2834// cast, not clamping. Out-of-range indices cause exceptions to be
2835// raised rather than being silently ignored.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002836class ExternalArray: public HeapObject {
Steve Block3ce2e202009-11-05 08:53:23 +00002837 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002838 // [length]: length of the array.
2839 inline int length();
2840 inline void set_length(int value);
2841
Steve Block3ce2e202009-11-05 08:53:23 +00002842 // [external_pointer]: The pointer to the external memory area backing this
2843 // external array.
2844 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
2845
2846 // Casting.
2847 static inline ExternalArray* cast(Object* obj);
2848
2849 // Maximal acceptable length for an external array.
2850 static const int kMaxLength = 0x3fffffff;
2851
2852 // ExternalArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002853 static const int kLengthOffset = HeapObject::kHeaderSize;
2854 static const int kExternalPointerOffset =
2855 POINTER_SIZE_ALIGN(kLengthOffset + kIntSize);
Steve Block3ce2e202009-11-05 08:53:23 +00002856 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002857 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Block3ce2e202009-11-05 08:53:23 +00002858
2859 private:
2860 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
2861};
2862
2863
Steve Block44f0eee2011-05-26 01:26:41 +01002864// A ExternalPixelArray represents a fixed-size byte array with special
2865// semantics used for implementing the CanvasPixelArray object. Please see the
2866// specification at:
2867
2868// http://www.whatwg.org/specs/web-apps/current-work/
2869// multipage/the-canvas-element.html#canvaspixelarray
2870// In particular, write access clamps the value written to 0 or 255 if the
2871// value written is outside this range.
2872class ExternalPixelArray: public ExternalArray {
2873 public:
2874 inline uint8_t* external_pixel_pointer();
2875
2876 // Setter and getter.
2877 inline uint8_t get(int index);
2878 inline void set(int index, uint8_t value);
2879
2880 // This accessor applies the correct conversion from Smi, HeapNumber and
2881 // undefined and clamps the converted value between 0 and 255.
2882 Object* SetValue(uint32_t index, Object* value);
2883
2884 // Casting.
2885 static inline ExternalPixelArray* cast(Object* obj);
2886
2887#ifdef OBJECT_PRINT
2888 inline void ExternalPixelArrayPrint() {
2889 ExternalPixelArrayPrint(stdout);
2890 }
2891 void ExternalPixelArrayPrint(FILE* out);
2892#endif
2893#ifdef DEBUG
2894 void ExternalPixelArrayVerify();
2895#endif // DEBUG
2896
2897 private:
2898 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
2899};
2900
2901
Steve Block3ce2e202009-11-05 08:53:23 +00002902class ExternalByteArray: public ExternalArray {
2903 public:
2904 // Setter and getter.
2905 inline int8_t get(int index);
2906 inline void set(int index, int8_t value);
2907
2908 // This accessor applies the correct conversion from Smi, HeapNumber
2909 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002910 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002911
2912 // Casting.
2913 static inline ExternalByteArray* cast(Object* obj);
2914
Ben Murdochb0fe1622011-05-05 13:52:32 +01002915#ifdef OBJECT_PRINT
2916 inline void ExternalByteArrayPrint() {
2917 ExternalByteArrayPrint(stdout);
2918 }
2919 void ExternalByteArrayPrint(FILE* out);
2920#endif
Steve Block3ce2e202009-11-05 08:53:23 +00002921#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00002922 void ExternalByteArrayVerify();
2923#endif // DEBUG
2924
2925 private:
2926 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
2927};
2928
2929
2930class ExternalUnsignedByteArray: public ExternalArray {
2931 public:
2932 // Setter and getter.
2933 inline uint8_t get(int index);
2934 inline void set(int index, uint8_t value);
2935
2936 // This accessor applies the correct conversion from Smi, HeapNumber
2937 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002938 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002939
2940 // Casting.
2941 static inline ExternalUnsignedByteArray* cast(Object* obj);
2942
Ben Murdochb0fe1622011-05-05 13:52:32 +01002943#ifdef OBJECT_PRINT
2944 inline void ExternalUnsignedByteArrayPrint() {
2945 ExternalUnsignedByteArrayPrint(stdout);
2946 }
2947 void ExternalUnsignedByteArrayPrint(FILE* out);
2948#endif
Steve Block3ce2e202009-11-05 08:53:23 +00002949#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00002950 void ExternalUnsignedByteArrayVerify();
2951#endif // DEBUG
2952
2953 private:
2954 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
2955};
2956
2957
2958class ExternalShortArray: public ExternalArray {
2959 public:
2960 // Setter and getter.
2961 inline int16_t get(int index);
2962 inline void set(int index, int16_t value);
2963
2964 // This accessor applies the correct conversion from Smi, HeapNumber
2965 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002966 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002967
2968 // Casting.
2969 static inline ExternalShortArray* cast(Object* obj);
2970
Ben Murdochb0fe1622011-05-05 13:52:32 +01002971#ifdef OBJECT_PRINT
2972 inline void ExternalShortArrayPrint() {
2973 ExternalShortArrayPrint(stdout);
2974 }
2975 void ExternalShortArrayPrint(FILE* out);
2976#endif
Steve Block3ce2e202009-11-05 08:53:23 +00002977#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00002978 void ExternalShortArrayVerify();
2979#endif // DEBUG
2980
2981 private:
2982 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
2983};
2984
2985
2986class ExternalUnsignedShortArray: public ExternalArray {
2987 public:
2988 // Setter and getter.
2989 inline uint16_t get(int index);
2990 inline void set(int index, uint16_t value);
2991
2992 // This accessor applies the correct conversion from Smi, HeapNumber
2993 // and undefined.
John Reck59135872010-11-02 12:39:01 -07002994 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00002995
2996 // Casting.
2997 static inline ExternalUnsignedShortArray* cast(Object* obj);
2998
Ben Murdochb0fe1622011-05-05 13:52:32 +01002999#ifdef OBJECT_PRINT
3000 inline void ExternalUnsignedShortArrayPrint() {
3001 ExternalUnsignedShortArrayPrint(stdout);
3002 }
3003 void ExternalUnsignedShortArrayPrint(FILE* out);
3004#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003005#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003006 void ExternalUnsignedShortArrayVerify();
3007#endif // DEBUG
3008
3009 private:
3010 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
3011};
3012
3013
3014class ExternalIntArray: public ExternalArray {
3015 public:
3016 // Setter and getter.
3017 inline int32_t get(int index);
3018 inline void set(int index, int32_t value);
3019
3020 // This accessor applies the correct conversion from Smi, HeapNumber
3021 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003022 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003023
3024 // Casting.
3025 static inline ExternalIntArray* cast(Object* obj);
3026
Ben Murdochb0fe1622011-05-05 13:52:32 +01003027#ifdef OBJECT_PRINT
3028 inline void ExternalIntArrayPrint() {
3029 ExternalIntArrayPrint(stdout);
3030 }
3031 void ExternalIntArrayPrint(FILE* out);
3032#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003033#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003034 void ExternalIntArrayVerify();
3035#endif // DEBUG
3036
3037 private:
3038 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
3039};
3040
3041
3042class ExternalUnsignedIntArray: public ExternalArray {
3043 public:
3044 // Setter and getter.
3045 inline uint32_t get(int index);
3046 inline void set(int index, uint32_t value);
3047
3048 // This accessor applies the correct conversion from Smi, HeapNumber
3049 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003050 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003051
3052 // Casting.
3053 static inline ExternalUnsignedIntArray* cast(Object* obj);
3054
Ben Murdochb0fe1622011-05-05 13:52:32 +01003055#ifdef OBJECT_PRINT
3056 inline void ExternalUnsignedIntArrayPrint() {
3057 ExternalUnsignedIntArrayPrint(stdout);
3058 }
3059 void ExternalUnsignedIntArrayPrint(FILE* out);
3060#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003061#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003062 void ExternalUnsignedIntArrayVerify();
3063#endif // DEBUG
3064
3065 private:
3066 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
3067};
3068
3069
3070class ExternalFloatArray: public ExternalArray {
3071 public:
3072 // Setter and getter.
3073 inline float get(int index);
3074 inline void set(int index, float value);
3075
3076 // This accessor applies the correct conversion from Smi, HeapNumber
3077 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003078 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003079
3080 // Casting.
3081 static inline ExternalFloatArray* cast(Object* obj);
3082
Ben Murdochb0fe1622011-05-05 13:52:32 +01003083#ifdef OBJECT_PRINT
3084 inline void ExternalFloatArrayPrint() {
3085 ExternalFloatArrayPrint(stdout);
3086 }
3087 void ExternalFloatArrayPrint(FILE* out);
3088#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003089#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003090 void ExternalFloatArrayVerify();
3091#endif // DEBUG
3092
3093 private:
3094 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
3095};
3096
3097
Ben Murdochb0fe1622011-05-05 13:52:32 +01003098// DeoptimizationInputData is a fixed array used to hold the deoptimization
3099// data for code generated by the Hydrogen/Lithium compiler. It also
3100// contains information about functions that were inlined. If N different
3101// functions were inlined then first N elements of the literal array will
3102// contain these functions.
3103//
3104// It can be empty.
3105class DeoptimizationInputData: public FixedArray {
3106 public:
3107 // Layout description. Indices in the array.
3108 static const int kTranslationByteArrayIndex = 0;
3109 static const int kInlinedFunctionCountIndex = 1;
3110 static const int kLiteralArrayIndex = 2;
3111 static const int kOsrAstIdIndex = 3;
3112 static const int kOsrPcOffsetIndex = 4;
3113 static const int kFirstDeoptEntryIndex = 5;
3114
3115 // Offsets of deopt entry elements relative to the start of the entry.
3116 static const int kAstIdOffset = 0;
3117 static const int kTranslationIndexOffset = 1;
3118 static const int kArgumentsStackHeightOffset = 2;
3119 static const int kDeoptEntrySize = 3;
3120
3121 // Simple element accessors.
3122#define DEFINE_ELEMENT_ACCESSORS(name, type) \
3123 type* name() { \
3124 return type::cast(get(k##name##Index)); \
3125 } \
3126 void Set##name(type* value) { \
3127 set(k##name##Index, value); \
3128 }
3129
3130 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
3131 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
3132 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
3133 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
3134 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
3135
3136 // Unchecked accessor to be used during GC.
3137 FixedArray* UncheckedLiteralArray() {
3138 return reinterpret_cast<FixedArray*>(get(kLiteralArrayIndex));
3139 }
3140
3141#undef DEFINE_ELEMENT_ACCESSORS
3142
3143 // Accessors for elements of the ith deoptimization entry.
3144#define DEFINE_ENTRY_ACCESSORS(name, type) \
3145 type* name(int i) { \
3146 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
3147 } \
3148 void Set##name(int i, type* value) { \
3149 set(IndexForEntry(i) + k##name##Offset, value); \
3150 }
3151
3152 DEFINE_ENTRY_ACCESSORS(AstId, Smi)
3153 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
3154 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
3155
3156#undef DEFINE_ENTRY_ACCESSORS
3157
3158 int DeoptCount() {
3159 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
3160 }
3161
3162 // Allocates a DeoptimizationInputData.
3163 MUST_USE_RESULT static MaybeObject* Allocate(int deopt_entry_count,
3164 PretenureFlag pretenure);
3165
3166 // Casting.
3167 static inline DeoptimizationInputData* cast(Object* obj);
3168
3169#ifdef OBJECT_PRINT
3170 void DeoptimizationInputDataPrint(FILE* out);
3171#endif
3172
3173 private:
3174 static int IndexForEntry(int i) {
3175 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
3176 }
3177
3178 static int LengthFor(int entry_count) {
3179 return IndexForEntry(entry_count);
3180 }
3181};
3182
3183
3184// DeoptimizationOutputData is a fixed array used to hold the deoptimization
3185// data for code generated by the full compiler.
3186// The format of the these objects is
3187// [i * 2]: Ast ID for ith deoptimization.
3188// [i * 2 + 1]: PC and state of ith deoptimization
3189class DeoptimizationOutputData: public FixedArray {
3190 public:
3191 int DeoptPoints() { return length() / 2; }
3192 Smi* AstId(int index) { return Smi::cast(get(index * 2)); }
3193 void SetAstId(int index, Smi* id) { set(index * 2, id); }
3194 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
3195 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
3196
3197 static int LengthOfFixedArray(int deopt_points) {
3198 return deopt_points * 2;
3199 }
3200
3201 // Allocates a DeoptimizationOutputData.
3202 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_deopt_points,
3203 PretenureFlag pretenure);
3204
3205 // Casting.
3206 static inline DeoptimizationOutputData* cast(Object* obj);
3207
3208#ifdef OBJECT_PRINT
3209 void DeoptimizationOutputDataPrint(FILE* out);
3210#endif
3211};
3212
3213
Ben Murdochb8e0da22011-05-16 14:20:40 +01003214class SafepointEntry;
3215
3216
Steve Blocka7e24c12009-10-30 11:49:00 +00003217// Code describes objects with on-the-fly generated machine code.
3218class Code: public HeapObject {
3219 public:
3220 // Opaque data type for encapsulating code flags like kind, inline
3221 // cache state, and arguments count.
Iain Merrick75681382010-08-19 15:07:18 +01003222 // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
3223 // enumeration type has correct value range (see Issue 830 for more details).
3224 enum Flags {
3225 FLAGS_MIN_VALUE = kMinInt,
3226 FLAGS_MAX_VALUE = kMaxInt
3227 };
Steve Blocka7e24c12009-10-30 11:49:00 +00003228
3229 enum Kind {
3230 FUNCTION,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003231 OPTIMIZED_FUNCTION,
Steve Blocka7e24c12009-10-30 11:49:00 +00003232 STUB,
3233 BUILTIN,
3234 LOAD_IC,
3235 KEYED_LOAD_IC,
Steve Block44f0eee2011-05-26 01:26:41 +01003236 KEYED_EXTERNAL_ARRAY_LOAD_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00003237 CALL_IC,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003238 KEYED_CALL_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00003239 STORE_IC,
3240 KEYED_STORE_IC,
Steve Block44f0eee2011-05-26 01:26:41 +01003241 KEYED_EXTERNAL_ARRAY_STORE_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01003242 BINARY_OP_IC,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003243 TYPE_RECORDING_BINARY_OP_IC,
3244 COMPARE_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01003245 // No more than 16 kinds. The value currently encoded in four bits in
Steve Blocka7e24c12009-10-30 11:49:00 +00003246 // Flags.
3247
3248 // Pseudo-kinds.
3249 REGEXP = BUILTIN,
3250 FIRST_IC_KIND = LOAD_IC,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003251 LAST_IC_KIND = COMPARE_IC
Steve Blocka7e24c12009-10-30 11:49:00 +00003252 };
3253
3254 enum {
Kristian Monsen50ef84f2010-07-29 15:18:00 +01003255 NUMBER_OF_KINDS = LAST_IC_KIND + 1
Steve Blocka7e24c12009-10-30 11:49:00 +00003256 };
3257
Ben Murdochb8e0da22011-05-16 14:20:40 +01003258 typedef int ExtraICState;
3259
3260 static const ExtraICState kNoExtraICState = 0;
3261
Steve Blocka7e24c12009-10-30 11:49:00 +00003262#ifdef ENABLE_DISASSEMBLER
3263 // Printing
3264 static const char* Kind2String(Kind kind);
3265 static const char* ICState2String(InlineCacheState state);
3266 static const char* PropertyType2String(PropertyType type);
Steve Block1e0659c2011-05-24 12:43:12 +01003267 static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003268 inline void Disassemble(const char* name) {
3269 Disassemble(name, stdout);
3270 }
3271 void Disassemble(const char* name, FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00003272#endif // ENABLE_DISASSEMBLER
3273
3274 // [instruction_size]: Size of the native instructions
3275 inline int instruction_size();
3276 inline void set_instruction_size(int value);
3277
Leon Clarkeac952652010-07-15 11:15:24 +01003278 // [relocation_info]: Code relocation information
3279 DECL_ACCESSORS(relocation_info, ByteArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003280 void InvalidateRelocation();
Leon Clarkeac952652010-07-15 11:15:24 +01003281
Ben Murdochb0fe1622011-05-05 13:52:32 +01003282 // [deoptimization_data]: Array containing data for deopt.
3283 DECL_ACCESSORS(deoptimization_data, FixedArray)
3284
3285 // Unchecked accessors to be used during GC.
Leon Clarkeac952652010-07-15 11:15:24 +01003286 inline ByteArray* unchecked_relocation_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003287 inline FixedArray* unchecked_deoptimization_data();
Leon Clarkeac952652010-07-15 11:15:24 +01003288
Steve Blocka7e24c12009-10-30 11:49:00 +00003289 inline int relocation_size();
Steve Blocka7e24c12009-10-30 11:49:00 +00003290
Steve Blocka7e24c12009-10-30 11:49:00 +00003291 // [flags]: Various code flags.
3292 inline Flags flags();
3293 inline void set_flags(Flags flags);
3294
3295 // [flags]: Access to specific code flags.
3296 inline Kind kind();
3297 inline InlineCacheState ic_state(); // Only valid for IC stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003298 inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
Steve Blocka7e24c12009-10-30 11:49:00 +00003299 inline InLoopFlag ic_in_loop(); // Only valid for IC stubs.
3300 inline PropertyType type(); // Only valid for monomorphic IC stubs.
3301 inline int arguments_count(); // Only valid for call IC stubs.
3302
3303 // Testers for IC stub kinds.
3304 inline bool is_inline_cache_stub();
3305 inline bool is_load_stub() { return kind() == LOAD_IC; }
3306 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
3307 inline bool is_store_stub() { return kind() == STORE_IC; }
3308 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
3309 inline bool is_call_stub() { return kind() == CALL_IC; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003310 inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003311 inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
3312 inline bool is_type_recording_binary_op_stub() {
3313 return kind() == TYPE_RECORDING_BINARY_OP_IC;
3314 }
3315 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
Steve Block44f0eee2011-05-26 01:26:41 +01003316 inline bool is_external_array_load_stub() {
3317 return kind() == KEYED_EXTERNAL_ARRAY_LOAD_IC;
3318 }
3319 inline bool is_external_array_store_stub() {
3320 return kind() == KEYED_EXTERNAL_ARRAY_STORE_IC;
3321 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003322
Steve Block6ded16b2010-05-10 14:33:55 +01003323 // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003324 inline int major_key();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003325 inline void set_major_key(int value);
3326
3327 // [optimizable]: For FUNCTION kind, tells if it is optimizable.
3328 inline bool optimizable();
3329 inline void set_optimizable(bool value);
3330
3331 // [has_deoptimization_support]: For FUNCTION kind, tells if it has
3332 // deoptimization support.
3333 inline bool has_deoptimization_support();
3334 inline void set_has_deoptimization_support(bool value);
3335
3336 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
3337 // how long the function has been marked for OSR and therefore which
3338 // level of loop nesting we are willing to do on-stack replacement
3339 // for.
3340 inline void set_allow_osr_at_loop_nesting_level(int level);
3341 inline int allow_osr_at_loop_nesting_level();
3342
3343 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
3344 // reserved in the code prologue.
3345 inline unsigned stack_slots();
3346 inline void set_stack_slots(unsigned slots);
3347
3348 // [safepoint_table_start]: For kind OPTIMIZED_CODE, the offset in
3349 // the instruction stream where the safepoint table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01003350 inline unsigned safepoint_table_offset();
3351 inline void set_safepoint_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003352
3353 // [stack_check_table_start]: For kind FUNCTION, the offset in the
3354 // instruction stream where the stack check table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01003355 inline unsigned stack_check_table_offset();
3356 inline void set_stack_check_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003357
3358 // [check type]: For kind CALL_IC, tells how to check if the
3359 // receiver is valid for the given call.
3360 inline CheckType check_type();
3361 inline void set_check_type(CheckType value);
3362
Steve Block44f0eee2011-05-26 01:26:41 +01003363 // [external array type]: For kind KEYED_EXTERNAL_ARRAY_LOAD_IC and
3364 // KEYED_EXTERNAL_ARRAY_STORE_IC, identifies the type of external
3365 // array that the code stub is specialized for.
3366 inline ExternalArrayType external_array_type();
3367 inline void set_external_array_type(ExternalArrayType value);
3368
Ben Murdochb0fe1622011-05-05 13:52:32 +01003369 // [binary op type]: For all BINARY_OP_IC.
3370 inline byte binary_op_type();
3371 inline void set_binary_op_type(byte value);
3372
3373 // [type-recording binary op type]: For all TYPE_RECORDING_BINARY_OP_IC.
3374 inline byte type_recording_binary_op_type();
3375 inline void set_type_recording_binary_op_type(byte value);
3376 inline byte type_recording_binary_op_result_type();
3377 inline void set_type_recording_binary_op_result_type(byte value);
3378
3379 // [compare state]: For kind compare IC stubs, tells what state the
3380 // stub is in.
3381 inline byte compare_state();
3382 inline void set_compare_state(byte value);
3383
Ben Murdochb8e0da22011-05-16 14:20:40 +01003384 // Get the safepoint entry for the given pc.
3385 SafepointEntry GetSafepointEntry(Address pc);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003386
3387 // Mark this code object as not having a stack check table. Assumes kind
3388 // is FUNCTION.
3389 void SetNoStackCheckTable();
3390
3391 // Find the first map in an IC stub.
3392 Map* FindFirstMap();
Steve Blocka7e24c12009-10-30 11:49:00 +00003393
3394 // Flags operations.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003395 static inline Flags ComputeFlags(
3396 Kind kind,
3397 InLoopFlag in_loop = NOT_IN_LOOP,
3398 InlineCacheState ic_state = UNINITIALIZED,
3399 ExtraICState extra_ic_state = kNoExtraICState,
3400 PropertyType type = NORMAL,
3401 int argc = -1,
3402 InlineCacheHolderFlag holder = OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +00003403
3404 static inline Flags ComputeMonomorphicFlags(
3405 Kind kind,
3406 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01003407 ExtraICState extra_ic_state = kNoExtraICState,
Steve Block8defd9f2010-07-08 12:39:36 +01003408 InlineCacheHolderFlag holder = OWN_MAP,
Steve Blocka7e24c12009-10-30 11:49:00 +00003409 InLoopFlag in_loop = NOT_IN_LOOP,
3410 int argc = -1);
3411
3412 static inline Kind ExtractKindFromFlags(Flags flags);
3413 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003414 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003415 static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
3416 static inline PropertyType ExtractTypeFromFlags(Flags flags);
3417 static inline int ExtractArgumentsCountFromFlags(Flags flags);
Steve Block8defd9f2010-07-08 12:39:36 +01003418 static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00003419 static inline Flags RemoveTypeFromFlags(Flags flags);
3420
3421 // Convert a target address into a code object.
3422 static inline Code* GetCodeFromTargetAddress(Address address);
3423
Steve Block791712a2010-08-27 10:21:07 +01003424 // Convert an entry address into an object.
3425 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
3426
Steve Blocka7e24c12009-10-30 11:49:00 +00003427 // Returns the address of the first instruction.
3428 inline byte* instruction_start();
3429
Leon Clarkeac952652010-07-15 11:15:24 +01003430 // Returns the address right after the last instruction.
3431 inline byte* instruction_end();
3432
Steve Blocka7e24c12009-10-30 11:49:00 +00003433 // Returns the size of the instructions, padding, and relocation information.
3434 inline int body_size();
3435
3436 // Returns the address of the first relocation info (read backwards!).
3437 inline byte* relocation_start();
3438
3439 // Code entry point.
3440 inline byte* entry();
3441
3442 // Returns true if pc is inside this object's instructions.
3443 inline bool contains(byte* pc);
3444
Steve Blocka7e24c12009-10-30 11:49:00 +00003445 // Relocate the code by delta bytes. Called to signal that this code
3446 // object has been moved by delta bytes.
Steve Blockd0582a62009-12-15 09:54:21 +00003447 void Relocate(intptr_t delta);
Steve Blocka7e24c12009-10-30 11:49:00 +00003448
3449 // Migrate code described by desc.
3450 void CopyFrom(const CodeDesc& desc);
3451
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003452 // Returns the object size for a given body (used for allocation).
3453 static int SizeFor(int body_size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003454 ASSERT_SIZE_TAG_ALIGNED(body_size);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003455 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
Steve Blocka7e24c12009-10-30 11:49:00 +00003456 }
3457
3458 // Calculate the size of the code object to report for log events. This takes
3459 // the layout of the code object into account.
3460 int ExecutableSize() {
3461 // Check that the assumptions about the layout of the code object holds.
3462 ASSERT_EQ(static_cast<int>(instruction_start() - address()),
3463 Code::kHeaderSize);
3464 return instruction_size() + Code::kHeaderSize;
3465 }
3466
3467 // Locating source position.
3468 int SourcePosition(Address pc);
3469 int SourceStatementPosition(Address pc);
3470
3471 // Casting.
3472 static inline Code* cast(Object* obj);
3473
3474 // Dispatched behavior.
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003475 int CodeSize() { return SizeFor(body_size()); }
Iain Merrick75681382010-08-19 15:07:18 +01003476 inline void CodeIterateBody(ObjectVisitor* v);
3477
3478 template<typename StaticVisitor>
Steve Block44f0eee2011-05-26 01:26:41 +01003479 inline void CodeIterateBody(Heap* heap);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003480#ifdef OBJECT_PRINT
3481 inline void CodePrint() {
3482 CodePrint(stdout);
3483 }
3484 void CodePrint(FILE* out);
3485#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003486#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003487 void CodeVerify();
3488#endif
Ben Murdochb0fe1622011-05-05 13:52:32 +01003489
3490 // Max loop nesting marker used to postpose OSR. We don't take loop
3491 // nesting that is deeper than 5 levels into account.
3492 static const int kMaxLoopNestingMarker = 6;
3493
Steve Blocka7e24c12009-10-30 11:49:00 +00003494 // Layout description.
3495 static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
Leon Clarkeac952652010-07-15 11:15:24 +01003496 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003497 static const int kDeoptimizationDataOffset =
3498 kRelocationInfoOffset + kPointerSize;
3499 static const int kFlagsOffset = kDeoptimizationDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003500 static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003501
3502 static const int kKindSpecificFlagsSize = 2 * kIntSize;
3503
3504 static const int kHeaderPaddingStart = kKindSpecificFlagsOffset +
3505 kKindSpecificFlagsSize;
3506
Steve Blocka7e24c12009-10-30 11:49:00 +00003507 // Add padding to align the instruction start following right after
3508 // the Code object header.
3509 static const int kHeaderSize =
Ben Murdochb0fe1622011-05-05 13:52:32 +01003510 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00003511
3512 // Byte offsets within kKindSpecificFlagsOffset.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003513 static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset;
3514 static const int kOptimizableOffset = kKindSpecificFlagsOffset;
3515 static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
3516 static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
Steve Block44f0eee2011-05-26 01:26:41 +01003517 static const int kExternalArrayTypeOffset = kKindSpecificFlagsOffset;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003518
3519 static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
3520 static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
3521 static const int kHasDeoptimizationSupportOffset = kOptimizableOffset + 1;
3522
3523 static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;
3524 static const int kAllowOSRAtLoopNestingLevelOffset =
3525 kHasDeoptimizationSupportOffset + 1;
3526
Steve Block1e0659c2011-05-24 12:43:12 +01003527 static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
3528 static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003529
3530 // Flags layout.
3531 static const int kFlagsICStateShift = 0;
3532 static const int kFlagsICInLoopShift = 3;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01003533 static const int kFlagsTypeShift = 4;
Steve Block44f0eee2011-05-26 01:26:41 +01003534 static const int kFlagsKindShift = 8;
3535 static const int kFlagsICHolderShift = 12;
3536 static const int kFlagsExtraICStateShift = 13;
3537 static const int kFlagsArgumentsCountShift = 15;
Steve Blocka7e24c12009-10-30 11:49:00 +00003538
Steve Block6ded16b2010-05-10 14:33:55 +01003539 static const int kFlagsICStateMask = 0x00000007; // 00000000111
3540 static const int kFlagsICInLoopMask = 0x00000008; // 00000001000
Steve Block44f0eee2011-05-26 01:26:41 +01003541 static const int kFlagsTypeMask = 0x000000F0; // 00001110000
3542 static const int kFlagsKindMask = 0x00000F00; // 11110000000
3543 static const int kFlagsCacheInPrototypeMapMask = 0x00001000;
3544 static const int kFlagsExtraICStateMask = 0x00006000;
3545 static const int kFlagsArgumentsCountMask = 0xFFFF8000;
Steve Blocka7e24c12009-10-30 11:49:00 +00003546
3547 static const int kFlagsNotUsedInLookup =
Steve Block8defd9f2010-07-08 12:39:36 +01003548 (kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
Steve Blocka7e24c12009-10-30 11:49:00 +00003549
3550 private:
3551 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
3552};
3553
3554
3555// All heap objects have a Map that describes their structure.
3556// A Map contains information about:
3557// - Size information about the object
3558// - How to iterate over an object (for garbage collection)
3559class Map: public HeapObject {
3560 public:
3561 // Instance size.
Steve Block791712a2010-08-27 10:21:07 +01003562 // Size in bytes or kVariableSizeSentinel if instances do not have
3563 // a fixed size.
Steve Blocka7e24c12009-10-30 11:49:00 +00003564 inline int instance_size();
3565 inline void set_instance_size(int value);
3566
3567 // Count of properties allocated in the object.
3568 inline int inobject_properties();
3569 inline void set_inobject_properties(int value);
3570
3571 // Count of property fields pre-allocated in the object when first allocated.
3572 inline int pre_allocated_property_fields();
3573 inline void set_pre_allocated_property_fields(int value);
3574
3575 // Instance type.
3576 inline InstanceType instance_type();
3577 inline void set_instance_type(InstanceType value);
3578
3579 // Tells how many unused property fields are available in the
3580 // instance (only used for JSObject in fast mode).
3581 inline int unused_property_fields();
3582 inline void set_unused_property_fields(int value);
3583
3584 // Bit field.
3585 inline byte bit_field();
3586 inline void set_bit_field(byte value);
3587
3588 // Bit field 2.
3589 inline byte bit_field2();
3590 inline void set_bit_field2(byte value);
3591
3592 // Tells whether the object in the prototype property will be used
3593 // for instances created from this function. If the prototype
3594 // property is set to a value that is not a JSObject, the prototype
3595 // property will not be used to create instances of the function.
3596 // See ECMA-262, 13.2.2.
3597 inline void set_non_instance_prototype(bool value);
3598 inline bool has_non_instance_prototype();
3599
Steve Block6ded16b2010-05-10 14:33:55 +01003600 // Tells whether function has special prototype property. If not, prototype
3601 // property will not be created when accessed (will return undefined),
3602 // and construction from this function will not be allowed.
3603 inline void set_function_with_prototype(bool value);
3604 inline bool function_with_prototype();
3605
Steve Blocka7e24c12009-10-30 11:49:00 +00003606 // Tells whether the instance with this map should be ignored by the
3607 // __proto__ accessor.
3608 inline void set_is_hidden_prototype() {
3609 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
3610 }
3611
3612 inline bool is_hidden_prototype() {
3613 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
3614 }
3615
3616 // Records and queries whether the instance has a named interceptor.
3617 inline void set_has_named_interceptor() {
3618 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
3619 }
3620
3621 inline bool has_named_interceptor() {
3622 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
3623 }
3624
3625 // Records and queries whether the instance has an indexed interceptor.
3626 inline void set_has_indexed_interceptor() {
3627 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
3628 }
3629
3630 inline bool has_indexed_interceptor() {
3631 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
3632 }
3633
3634 // Tells whether the instance is undetectable.
3635 // An undetectable object is a special class of JSObject: 'typeof' operator
3636 // returns undefined, ToBoolean returns false. Otherwise it behaves like
3637 // a normal JS object. It is useful for implementing undetectable
3638 // document.all in Firefox & Safari.
3639 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
3640 inline void set_is_undetectable() {
3641 set_bit_field(bit_field() | (1 << kIsUndetectable));
3642 }
3643
3644 inline bool is_undetectable() {
3645 return ((1 << kIsUndetectable) & bit_field()) != 0;
3646 }
3647
Steve Blocka7e24c12009-10-30 11:49:00 +00003648 // Tells whether the instance has a call-as-function handler.
3649 inline void set_has_instance_call_handler() {
3650 set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
3651 }
3652
3653 inline bool has_instance_call_handler() {
3654 return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
3655 }
3656
Steve Block8defd9f2010-07-08 12:39:36 +01003657 inline void set_is_extensible(bool value);
3658 inline bool is_extensible();
3659
3660 // Tells whether the instance has fast elements.
Iain Merrick75681382010-08-19 15:07:18 +01003661 // Equivalent to instance->GetElementsKind() == FAST_ELEMENTS.
3662 inline void set_has_fast_elements(bool value) {
Steve Block8defd9f2010-07-08 12:39:36 +01003663 if (value) {
3664 set_bit_field2(bit_field2() | (1 << kHasFastElements));
3665 } else {
3666 set_bit_field2(bit_field2() & ~(1 << kHasFastElements));
3667 }
Leon Clarkee46be812010-01-19 14:06:41 +00003668 }
3669
Iain Merrick75681382010-08-19 15:07:18 +01003670 inline bool has_fast_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01003671 return ((1 << kHasFastElements) & bit_field2()) != 0;
Leon Clarkee46be812010-01-19 14:06:41 +00003672 }
3673
Steve Block1e0659c2011-05-24 12:43:12 +01003674 // Tells whether an instance has pixel array elements.
Steve Block44f0eee2011-05-26 01:26:41 +01003675 inline void set_has_external_array_elements(bool value) {
Steve Block1e0659c2011-05-24 12:43:12 +01003676 if (value) {
Steve Block44f0eee2011-05-26 01:26:41 +01003677 set_bit_field2(bit_field2() | (1 << kHasExternalArrayElements));
Steve Block1e0659c2011-05-24 12:43:12 +01003678 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01003679 set_bit_field2(bit_field2() & ~(1 << kHasExternalArrayElements));
Steve Block1e0659c2011-05-24 12:43:12 +01003680 }
3681 }
3682
Steve Block44f0eee2011-05-26 01:26:41 +01003683 inline bool has_external_array_elements() {
3684 return ((1 << kHasExternalArrayElements) & bit_field2()) != 0;
Steve Block1e0659c2011-05-24 12:43:12 +01003685 }
3686
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003687 // Tells whether the map is attached to SharedFunctionInfo
3688 // (for inobject slack tracking).
3689 inline void set_attached_to_shared_function_info(bool value);
3690
3691 inline bool attached_to_shared_function_info();
3692
3693 // Tells whether the map is shared between objects that may have different
3694 // behavior. If true, the map should never be modified, instead a clone
3695 // should be created and modified.
3696 inline void set_is_shared(bool value);
3697
3698 inline bool is_shared();
3699
Steve Blocka7e24c12009-10-30 11:49:00 +00003700 // Tells whether the instance needs security checks when accessing its
3701 // properties.
3702 inline void set_is_access_check_needed(bool access_check_needed);
3703 inline bool is_access_check_needed();
3704
3705 // [prototype]: implicit prototype object.
3706 DECL_ACCESSORS(prototype, Object)
3707
3708 // [constructor]: points back to the function responsible for this map.
3709 DECL_ACCESSORS(constructor, Object)
3710
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003711 inline JSFunction* unchecked_constructor();
3712
Steve Blocka7e24c12009-10-30 11:49:00 +00003713 // [instance descriptors]: describes the object.
3714 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
3715
3716 // [stub cache]: contains stubs compiled for this map.
Steve Block6ded16b2010-05-10 14:33:55 +01003717 DECL_ACCESSORS(code_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00003718
Ben Murdochb0fe1622011-05-05 13:52:32 +01003719 // Lookup in the map's instance descriptors and fill out the result
3720 // with the given holder if the name is found. The holder may be
3721 // NULL when this function is used from the compiler.
3722 void LookupInDescriptors(JSObject* holder,
3723 String* name,
3724 LookupResult* result);
3725
John Reck59135872010-11-02 12:39:01 -07003726 MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003727
John Reck59135872010-11-02 12:39:01 -07003728 MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
3729 NormalizedMapSharingMode sharing);
Steve Blocka7e24c12009-10-30 11:49:00 +00003730
3731 // Returns a copy of the map, with all transitions dropped from the
3732 // instance descriptors.
John Reck59135872010-11-02 12:39:01 -07003733 MUST_USE_RESULT MaybeObject* CopyDropTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00003734
Steve Block8defd9f2010-07-08 12:39:36 +01003735 // Returns this map if it has the fast elements bit set, otherwise
3736 // returns a copy of the map, with all transitions dropped from the
3737 // descriptors and the fast elements bit set.
John Reck59135872010-11-02 12:39:01 -07003738 MUST_USE_RESULT inline MaybeObject* GetFastElementsMap();
Steve Block8defd9f2010-07-08 12:39:36 +01003739
3740 // Returns this map if it has the fast elements bit cleared,
3741 // otherwise returns a copy of the map, with all transitions dropped
3742 // from the descriptors and the fast elements bit cleared.
John Reck59135872010-11-02 12:39:01 -07003743 MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
Steve Block8defd9f2010-07-08 12:39:36 +01003744
Steve Block44f0eee2011-05-26 01:26:41 +01003745 // Returns a new map with all transitions dropped from the descriptors and the
3746 // external array elements bit set.
3747 MUST_USE_RESULT MaybeObject* GetExternalArrayElementsMap(
3748 ExternalArrayType array_type,
3749 bool safe_to_add_transition);
Steve Block1e0659c2011-05-24 12:43:12 +01003750
Steve Blocka7e24c12009-10-30 11:49:00 +00003751 // Returns the property index for name (only valid for FAST MODE).
3752 int PropertyIndexFor(String* name);
3753
3754 // Returns the next free property index (only valid for FAST MODE).
3755 int NextFreePropertyIndex();
3756
3757 // Returns the number of properties described in instance_descriptors.
3758 int NumberOfDescribedProperties();
3759
3760 // Casting.
3761 static inline Map* cast(Object* obj);
3762
3763 // Locate an accessor in the instance descriptor.
3764 AccessorDescriptor* FindAccessor(String* name);
3765
3766 // Code cache operations.
3767
3768 // Clears the code cache.
Steve Block44f0eee2011-05-26 01:26:41 +01003769 inline void ClearCodeCache(Heap* heap);
Steve Blocka7e24c12009-10-30 11:49:00 +00003770
3771 // Update code cache.
John Reck59135872010-11-02 12:39:01 -07003772 MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00003773
3774 // Returns the found code or undefined if absent.
3775 Object* FindInCodeCache(String* name, Code::Flags flags);
3776
3777 // Returns the non-negative index of the code object if it is in the
3778 // cache and -1 otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +01003779 int IndexInCodeCache(Object* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00003780
3781 // Removes a code object from the code cache at the given index.
Steve Block6ded16b2010-05-10 14:33:55 +01003782 void RemoveFromCodeCache(String* name, Code* code, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003783
3784 // For every transition in this map, makes the transition's
3785 // target's prototype pointer point back to this map.
3786 // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
3787 void CreateBackPointers();
3788
3789 // Set all map transitions from this map to dead maps to null.
3790 // Also, restore the original prototype on the targets of these
3791 // transitions, so that we do not process this map again while
3792 // following back pointers.
Steve Block44f0eee2011-05-26 01:26:41 +01003793 void ClearNonLiveTransitions(Heap* heap, Object* real_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00003794
3795 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003796#ifdef OBJECT_PRINT
3797 inline void MapPrint() {
3798 MapPrint(stdout);
3799 }
3800 void MapPrint(FILE* out);
3801#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003802#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003803 void MapVerify();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003804 void SharedMapVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00003805#endif
3806
Iain Merrick75681382010-08-19 15:07:18 +01003807 inline int visitor_id();
3808 inline void set_visitor_id(int visitor_id);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003809
Steve Block44f0eee2011-05-26 01:26:41 +01003810 // Returns the isolate/heap this map belongs to.
3811 inline Isolate* isolate();
3812 inline Heap* heap();
3813
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003814 typedef void (*TraverseCallback)(Map* map, void* data);
3815
3816 void TraverseTransitionTree(TraverseCallback callback, void* data);
3817
Steve Blocka7e24c12009-10-30 11:49:00 +00003818 static const int kMaxPreAllocatedPropertyFields = 255;
3819
3820 // Layout description.
3821 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
3822 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
3823 static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
3824 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
3825 static const int kInstanceDescriptorsOffset =
3826 kConstructorOffset + kPointerSize;
3827 static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
Iain Merrick9ac36c92010-09-13 15:29:50 +01003828 static const int kPadStart = kCodeCacheOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003829 static const int kSize = MAP_POINTER_ALIGN(kPadStart);
3830
3831 // Layout of pointer fields. Heap iteration code relies on them
3832 // being continiously allocated.
3833 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
3834 static const int kPointerFieldsEndOffset =
3835 Map::kCodeCacheOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003836
3837 // Byte offsets within kInstanceSizesOffset.
3838 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
3839 static const int kInObjectPropertiesByte = 1;
3840 static const int kInObjectPropertiesOffset =
3841 kInstanceSizesOffset + kInObjectPropertiesByte;
3842 static const int kPreAllocatedPropertyFieldsByte = 2;
3843 static const int kPreAllocatedPropertyFieldsOffset =
3844 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
Iain Merrick9ac36c92010-09-13 15:29:50 +01003845 static const int kVisitorIdByte = 3;
3846 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
Steve Blocka7e24c12009-10-30 11:49:00 +00003847
3848 // Byte offsets within kInstanceAttributesOffset attributes.
3849 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
3850 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
3851 static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
3852 static const int kBitField2Offset = kInstanceAttributesOffset + 3;
3853
3854 STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
3855
3856 // Bit positions for bit field.
3857 static const int kUnused = 0; // To be used for marking recently used maps.
3858 static const int kHasNonInstancePrototype = 1;
3859 static const int kIsHiddenPrototype = 2;
3860 static const int kHasNamedInterceptor = 3;
3861 static const int kHasIndexedInterceptor = 4;
3862 static const int kIsUndetectable = 5;
3863 static const int kHasInstanceCallHandler = 6;
3864 static const int kIsAccessCheckNeeded = 7;
3865
3866 // Bit positions for bit field 2
Andrei Popescu31002712010-02-23 13:46:05 +00003867 static const int kIsExtensible = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003868 static const int kFunctionWithPrototype = 1;
Steve Block8defd9f2010-07-08 12:39:36 +01003869 static const int kHasFastElements = 2;
Iain Merrick75681382010-08-19 15:07:18 +01003870 static const int kStringWrapperSafeForDefaultValueOf = 3;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003871 static const int kAttachedToSharedFunctionInfo = 4;
3872 static const int kIsShared = 5;
Steve Block44f0eee2011-05-26 01:26:41 +01003873 static const int kHasExternalArrayElements = 6;
Steve Block6ded16b2010-05-10 14:33:55 +01003874
3875 // Layout of the default cache. It holds alternating name and code objects.
3876 static const int kCodeCacheEntrySize = 2;
3877 static const int kCodeCacheEntryNameOffset = 0;
3878 static const int kCodeCacheEntryCodeOffset = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00003879
Iain Merrick75681382010-08-19 15:07:18 +01003880 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
3881 kPointerFieldsEndOffset,
3882 kSize> BodyDescriptor;
3883
Steve Blocka7e24c12009-10-30 11:49:00 +00003884 private:
3885 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
3886};
3887
3888
3889// An abstract superclass, a marker class really, for simple structure classes.
3890// It doesn't carry much functionality but allows struct classes to me
3891// identified in the type system.
3892class Struct: public HeapObject {
3893 public:
3894 inline void InitializeBody(int object_size);
3895 static inline Struct* cast(Object* that);
3896};
3897
3898
3899// Script describes a script which has been added to the VM.
3900class Script: public Struct {
3901 public:
3902 // Script types.
3903 enum Type {
3904 TYPE_NATIVE = 0,
3905 TYPE_EXTENSION = 1,
3906 TYPE_NORMAL = 2
3907 };
3908
3909 // Script compilation types.
3910 enum CompilationType {
3911 COMPILATION_TYPE_HOST = 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003912 COMPILATION_TYPE_EVAL = 1
Steve Blocka7e24c12009-10-30 11:49:00 +00003913 };
3914
3915 // [source]: the script source.
3916 DECL_ACCESSORS(source, Object)
3917
3918 // [name]: the script name.
3919 DECL_ACCESSORS(name, Object)
3920
3921 // [id]: the script id.
3922 DECL_ACCESSORS(id, Object)
3923
3924 // [line_offset]: script line offset in resource from where it was extracted.
3925 DECL_ACCESSORS(line_offset, Smi)
3926
3927 // [column_offset]: script column offset in resource from where it was
3928 // extracted.
3929 DECL_ACCESSORS(column_offset, Smi)
3930
3931 // [data]: additional data associated with this script.
3932 DECL_ACCESSORS(data, Object)
3933
3934 // [context_data]: context data for the context this script was compiled in.
3935 DECL_ACCESSORS(context_data, Object)
3936
3937 // [wrapper]: the wrapper cache.
3938 DECL_ACCESSORS(wrapper, Proxy)
3939
3940 // [type]: the script type.
3941 DECL_ACCESSORS(type, Smi)
3942
3943 // [compilation]: how the the script was compiled.
3944 DECL_ACCESSORS(compilation_type, Smi)
3945
Steve Blockd0582a62009-12-15 09:54:21 +00003946 // [line_ends]: FixedArray of line ends positions.
Steve Blocka7e24c12009-10-30 11:49:00 +00003947 DECL_ACCESSORS(line_ends, Object)
3948
Steve Blockd0582a62009-12-15 09:54:21 +00003949 // [eval_from_shared]: for eval scripts the shared funcion info for the
3950 // function from which eval was called.
3951 DECL_ACCESSORS(eval_from_shared, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00003952
3953 // [eval_from_instructions_offset]: the instruction offset in the code for the
3954 // function from which eval was called where eval was called.
3955 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
3956
3957 static inline Script* cast(Object* obj);
3958
Steve Block3ce2e202009-11-05 08:53:23 +00003959 // If script source is an external string, check that the underlying
3960 // resource is accessible. Otherwise, always return true.
3961 inline bool HasValidSource();
3962
Ben Murdochb0fe1622011-05-05 13:52:32 +01003963#ifdef OBJECT_PRINT
3964 inline void ScriptPrint() {
3965 ScriptPrint(stdout);
3966 }
3967 void ScriptPrint(FILE* out);
3968#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003969#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003970 void ScriptVerify();
3971#endif
3972
3973 static const int kSourceOffset = HeapObject::kHeaderSize;
3974 static const int kNameOffset = kSourceOffset + kPointerSize;
3975 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
3976 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
3977 static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
3978 static const int kContextOffset = kDataOffset + kPointerSize;
3979 static const int kWrapperOffset = kContextOffset + kPointerSize;
3980 static const int kTypeOffset = kWrapperOffset + kPointerSize;
3981 static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
3982 static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
3983 static const int kIdOffset = kLineEndsOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00003984 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003985 static const int kEvalFrominstructionsOffsetOffset =
Steve Blockd0582a62009-12-15 09:54:21 +00003986 kEvalFromSharedOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003987 static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
3988
3989 private:
3990 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
3991};
3992
3993
Ben Murdochb0fe1622011-05-05 13:52:32 +01003994// List of builtin functions we want to identify to improve code
3995// generation.
3996//
3997// Each entry has a name of a global object property holding an object
3998// optionally followed by ".prototype", a name of a builtin function
3999// on the object (the one the id is set for), and a label.
4000//
4001// Installation of ids for the selected builtin functions is handled
4002// by the bootstrapper.
4003//
4004// NOTE: Order is important: math functions should be at the end of
4005// the list and MathFloor should be the first math function.
4006#define FUNCTIONS_WITH_ID_LIST(V) \
4007 V(Array.prototype, push, ArrayPush) \
4008 V(Array.prototype, pop, ArrayPop) \
4009 V(String.prototype, charCodeAt, StringCharCodeAt) \
4010 V(String.prototype, charAt, StringCharAt) \
4011 V(String, fromCharCode, StringFromCharCode) \
4012 V(Math, floor, MathFloor) \
4013 V(Math, round, MathRound) \
4014 V(Math, ceil, MathCeil) \
4015 V(Math, abs, MathAbs) \
4016 V(Math, log, MathLog) \
4017 V(Math, sin, MathSin) \
4018 V(Math, cos, MathCos) \
4019 V(Math, tan, MathTan) \
4020 V(Math, asin, MathASin) \
4021 V(Math, acos, MathACos) \
4022 V(Math, atan, MathATan) \
4023 V(Math, exp, MathExp) \
4024 V(Math, sqrt, MathSqrt) \
4025 V(Math, pow, MathPow)
4026
4027
4028enum BuiltinFunctionId {
4029#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
4030 k##name,
4031 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
4032#undef DECLARE_FUNCTION_ID
4033 // Fake id for a special case of Math.pow. Note, it continues the
4034 // list of math functions.
4035 kMathPowHalf,
4036 kFirstMathFunctionId = kMathFloor
4037};
4038
4039
Steve Blocka7e24c12009-10-30 11:49:00 +00004040// SharedFunctionInfo describes the JSFunction information that can be
4041// shared by multiple instances of the function.
4042class SharedFunctionInfo: public HeapObject {
4043 public:
4044 // [name]: Function name.
4045 DECL_ACCESSORS(name, Object)
4046
4047 // [code]: Function code.
4048 DECL_ACCESSORS(code, Code)
4049
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004050 // [scope_info]: Scope info.
4051 DECL_ACCESSORS(scope_info, SerializedScopeInfo)
4052
Steve Blocka7e24c12009-10-30 11:49:00 +00004053 // [construct stub]: Code stub for constructing instances of this function.
4054 DECL_ACCESSORS(construct_stub, Code)
4055
Iain Merrick75681382010-08-19 15:07:18 +01004056 inline Code* unchecked_code();
4057
Steve Blocka7e24c12009-10-30 11:49:00 +00004058 // Returns if this function has been compiled to native code yet.
4059 inline bool is_compiled();
4060
4061 // [length]: The function length - usually the number of declared parameters.
4062 // Use up to 2^30 parameters.
4063 inline int length();
4064 inline void set_length(int value);
4065
4066 // [formal parameter count]: The declared number of parameters.
4067 inline int formal_parameter_count();
4068 inline void set_formal_parameter_count(int value);
4069
4070 // Set the formal parameter count so the function code will be
4071 // called without using argument adaptor frames.
4072 inline void DontAdaptArguments();
4073
4074 // [expected_nof_properties]: Expected number of properties for the function.
4075 inline int expected_nof_properties();
4076 inline void set_expected_nof_properties(int value);
4077
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004078 // Inobject slack tracking is the way to reclaim unused inobject space.
4079 //
4080 // The instance size is initially determined by adding some slack to
4081 // expected_nof_properties (to allow for a few extra properties added
4082 // after the constructor). There is no guarantee that the extra space
4083 // will not be wasted.
4084 //
4085 // Here is the algorithm to reclaim the unused inobject space:
4086 // - Detect the first constructor call for this SharedFunctionInfo.
4087 // When it happens enter the "in progress" state: remember the
4088 // constructor's initial_map and install a special construct stub that
4089 // counts constructor calls.
4090 // - While the tracking is in progress create objects filled with
4091 // one_pointer_filler_map instead of undefined_value. This way they can be
4092 // resized quickly and safely.
4093 // - Once enough (kGenerousAllocationCount) objects have been created
4094 // compute the 'slack' (traverse the map transition tree starting from the
4095 // initial_map and find the lowest value of unused_property_fields).
4096 // - Traverse the transition tree again and decrease the instance size
4097 // of every map. Existing objects will resize automatically (they are
4098 // filled with one_pointer_filler_map). All further allocations will
4099 // use the adjusted instance size.
4100 // - Decrease expected_nof_properties so that an allocations made from
4101 // another context will use the adjusted instance size too.
4102 // - Exit "in progress" state by clearing the reference to the initial_map
4103 // and setting the regular construct stub (generic or inline).
4104 //
4105 // The above is the main event sequence. Some special cases are possible
4106 // while the tracking is in progress:
4107 //
4108 // - GC occurs.
4109 // Check if the initial_map is referenced by any live objects (except this
4110 // SharedFunctionInfo). If it is, continue tracking as usual.
4111 // If it is not, clear the reference and reset the tracking state. The
4112 // tracking will be initiated again on the next constructor call.
4113 //
4114 // - The constructor is called from another context.
4115 // Immediately complete the tracking, perform all the necessary changes
4116 // to maps. This is necessary because there is no efficient way to track
4117 // multiple initial_maps.
4118 // Proceed to create an object in the current context (with the adjusted
4119 // size).
4120 //
4121 // - A different constructor function sharing the same SharedFunctionInfo is
4122 // called in the same context. This could be another closure in the same
4123 // context, or the first function could have been disposed.
4124 // This is handled the same way as the previous case.
4125 //
4126 // Important: inobject slack tracking is not attempted during the snapshot
4127 // creation.
4128
Ben Murdochf87a2032010-10-22 12:50:53 +01004129 static const int kGenerousAllocationCount = 8;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004130
4131 // [construction_count]: Counter for constructor calls made during
4132 // the tracking phase.
4133 inline int construction_count();
4134 inline void set_construction_count(int value);
4135
4136 // [initial_map]: initial map of the first function called as a constructor.
4137 // Saved for the duration of the tracking phase.
4138 // This is a weak link (GC resets it to undefined_value if no other live
4139 // object reference this map).
4140 DECL_ACCESSORS(initial_map, Object)
4141
4142 // True if the initial_map is not undefined and the countdown stub is
4143 // installed.
4144 inline bool IsInobjectSlackTrackingInProgress();
4145
4146 // Starts the tracking.
4147 // Stores the initial map and installs the countdown stub.
4148 // IsInobjectSlackTrackingInProgress is normally true after this call,
4149 // except when tracking have not been started (e.g. the map has no unused
4150 // properties or the snapshot is being built).
4151 void StartInobjectSlackTracking(Map* map);
4152
4153 // Completes the tracking.
4154 // IsInobjectSlackTrackingInProgress is false after this call.
4155 void CompleteInobjectSlackTracking();
4156
4157 // Clears the initial_map before the GC marking phase to ensure the reference
4158 // is weak. IsInobjectSlackTrackingInProgress is false after this call.
4159 void DetachInitialMap();
4160
4161 // Restores the link to the initial map after the GC marking phase.
4162 // IsInobjectSlackTrackingInProgress is true after this call.
4163 void AttachInitialMap(Map* map);
4164
4165 // False if there are definitely no live objects created from this function.
4166 // True if live objects _may_ exist (existence not guaranteed).
4167 // May go back from true to false after GC.
4168 inline bool live_objects_may_exist();
4169
4170 inline void set_live_objects_may_exist(bool value);
4171
Steve Blocka7e24c12009-10-30 11:49:00 +00004172 // [instance class name]: class name for instances.
4173 DECL_ACCESSORS(instance_class_name, Object)
4174
Steve Block6ded16b2010-05-10 14:33:55 +01004175 // [function data]: This field holds some additional data for function.
4176 // Currently it either has FunctionTemplateInfo to make benefit the API
Ben Murdochb0fe1622011-05-05 13:52:32 +01004177 // or Smi identifying a builtin function.
Steve Blocka7e24c12009-10-30 11:49:00 +00004178 // In the long run we don't want all functions to have this field but
4179 // we can fix that when we have a better model for storing hidden data
4180 // on objects.
4181 DECL_ACCESSORS(function_data, Object)
4182
Steve Block6ded16b2010-05-10 14:33:55 +01004183 inline bool IsApiFunction();
4184 inline FunctionTemplateInfo* get_api_func_data();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004185 inline bool HasBuiltinFunctionId();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004186 inline BuiltinFunctionId builtin_function_id();
Steve Block6ded16b2010-05-10 14:33:55 +01004187
Steve Blocka7e24c12009-10-30 11:49:00 +00004188 // [script info]: Script from which the function originates.
4189 DECL_ACCESSORS(script, Object)
4190
Steve Block6ded16b2010-05-10 14:33:55 +01004191 // [num_literals]: Number of literals used by this function.
4192 inline int num_literals();
4193 inline void set_num_literals(int value);
4194
Steve Blocka7e24c12009-10-30 11:49:00 +00004195 // [start_position_and_type]: Field used to store both the source code
4196 // position, whether or not the function is a function expression,
4197 // and whether or not the function is a toplevel function. The two
4198 // least significants bit indicates whether the function is an
4199 // expression and the rest contains the source code position.
4200 inline int start_position_and_type();
4201 inline void set_start_position_and_type(int value);
4202
4203 // [debug info]: Debug information.
4204 DECL_ACCESSORS(debug_info, Object)
4205
4206 // [inferred name]: Name inferred from variable or property
4207 // assignment of this function. Used to facilitate debugging and
4208 // profiling of JavaScript code written in OO style, where almost
4209 // all functions are anonymous but are assigned to object
4210 // properties.
4211 DECL_ACCESSORS(inferred_name, String)
4212
Ben Murdochf87a2032010-10-22 12:50:53 +01004213 // The function's name if it is non-empty, otherwise the inferred name.
4214 String* DebugName();
4215
Steve Blocka7e24c12009-10-30 11:49:00 +00004216 // Position of the 'function' token in the script source.
4217 inline int function_token_position();
4218 inline void set_function_token_position(int function_token_position);
4219
4220 // Position of this function in the script source.
4221 inline int start_position();
4222 inline void set_start_position(int start_position);
4223
4224 // End position of this function in the script source.
4225 inline int end_position();
4226 inline void set_end_position(int end_position);
4227
4228 // Is this function a function expression in the source code.
4229 inline bool is_expression();
4230 inline void set_is_expression(bool value);
4231
4232 // Is this function a top-level function (scripts, evals).
4233 inline bool is_toplevel();
4234 inline void set_is_toplevel(bool value);
4235
4236 // Bit field containing various information collected by the compiler to
4237 // drive optimization.
4238 inline int compiler_hints();
4239 inline void set_compiler_hints(int value);
4240
Ben Murdochb0fe1622011-05-05 13:52:32 +01004241 // A counter used to determine when to stress the deoptimizer with a
4242 // deopt.
4243 inline Smi* deopt_counter();
4244 inline void set_deopt_counter(Smi* counter);
4245
Steve Blocka7e24c12009-10-30 11:49:00 +00004246 // Add information on assignments of the form this.x = ...;
4247 void SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +00004248 bool has_only_simple_this_property_assignments,
4249 FixedArray* this_property_assignments);
4250
4251 // Clear information on assignments of the form this.x = ...;
4252 void ClearThisPropertyAssignmentsInfo();
4253
4254 // Indicate that this function only consists of assignments of the form
Steve Blocka7e24c12009-10-30 11:49:00 +00004255 // this.x = y; where y is either a constant or refers to an argument.
4256 inline bool has_only_simple_this_property_assignments();
4257
Leon Clarked91b9f72010-01-27 17:25:45 +00004258 inline bool try_full_codegen();
4259 inline void set_try_full_codegen(bool flag);
Steve Blockd0582a62009-12-15 09:54:21 +00004260
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004261 // Indicates if this function can be lazy compiled.
4262 // This is used to determine if we can safely flush code from a function
4263 // when doing GC if we expect that the function will no longer be used.
4264 inline bool allows_lazy_compilation();
4265 inline void set_allows_lazy_compilation(bool flag);
4266
Iain Merrick75681382010-08-19 15:07:18 +01004267 // Indicates how many full GCs this function has survived with assigned
4268 // code object. Used to determine when it is relatively safe to flush
4269 // this code object and replace it with lazy compilation stub.
4270 // Age is reset when GC notices that the code object is referenced
4271 // from the stack or compilation cache.
4272 inline int code_age();
4273 inline void set_code_age(int age);
4274
Ben Murdochb0fe1622011-05-05 13:52:32 +01004275 // Indicates whether optimizations have been disabled for this
4276 // shared function info. If a function is repeatedly optimized or if
4277 // we cannot optimize the function we disable optimization to avoid
4278 // spending time attempting to optimize it again.
4279 inline bool optimization_disabled();
4280 inline void set_optimization_disabled(bool value);
4281
Steve Block1e0659c2011-05-24 12:43:12 +01004282 // Indicates whether the function is a strict mode function.
4283 inline bool strict_mode();
4284 inline void set_strict_mode(bool value);
4285
Ben Murdochb0fe1622011-05-05 13:52:32 +01004286 // Indicates whether or not the code in the shared function support
4287 // deoptimization.
4288 inline bool has_deoptimization_support();
4289
4290 // Enable deoptimization support through recompiled code.
4291 void EnableDeoptimizationSupport(Code* recompiled);
4292
4293 // Lookup the bailout ID and ASSERT that it exists in the non-optimized
4294 // code, returns whether it asserted (i.e., always true if assertions are
4295 // disabled).
4296 bool VerifyBailoutId(int id);
Iain Merrick75681382010-08-19 15:07:18 +01004297
Andrei Popescu402d9372010-02-26 13:31:12 +00004298 // Check whether a inlined constructor can be generated with the given
4299 // prototype.
4300 bool CanGenerateInlineConstructor(Object* prototype);
4301
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004302 // Prevents further attempts to generate inline constructors.
4303 // To be called if generation failed for any reason.
4304 void ForbidInlineConstructor();
4305
Steve Blocka7e24c12009-10-30 11:49:00 +00004306 // For functions which only contains this property assignments this provides
4307 // access to the names for the properties assigned.
4308 DECL_ACCESSORS(this_property_assignments, Object)
4309 inline int this_property_assignments_count();
4310 inline void set_this_property_assignments_count(int value);
4311 String* GetThisPropertyAssignmentName(int index);
4312 bool IsThisPropertyAssignmentArgument(int index);
4313 int GetThisPropertyAssignmentArgument(int index);
4314 Object* GetThisPropertyAssignmentConstant(int index);
4315
4316 // [source code]: Source code for the function.
4317 bool HasSourceCode();
4318 Object* GetSourceCode();
4319
Ben Murdochb0fe1622011-05-05 13:52:32 +01004320 inline int opt_count();
4321 inline void set_opt_count(int opt_count);
4322
4323 // Source size of this function.
4324 int SourceSize();
4325
Steve Blocka7e24c12009-10-30 11:49:00 +00004326 // Calculate the instance size.
4327 int CalculateInstanceSize();
4328
4329 // Calculate the number of in-object properties.
4330 int CalculateInObjectProperties();
4331
4332 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00004333 // Set max_length to -1 for unlimited length.
4334 void SourceCodePrint(StringStream* accumulator, int max_length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004335#ifdef OBJECT_PRINT
4336 inline void SharedFunctionInfoPrint() {
4337 SharedFunctionInfoPrint(stdout);
4338 }
4339 void SharedFunctionInfoPrint(FILE* out);
4340#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004341#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004342 void SharedFunctionInfoVerify();
4343#endif
4344
4345 // Casting.
4346 static inline SharedFunctionInfo* cast(Object* obj);
4347
4348 // Constants.
4349 static const int kDontAdaptArgumentsSentinel = -1;
4350
4351 // Layout description.
Steve Block6ded16b2010-05-10 14:33:55 +01004352 // Pointer fields.
Steve Blocka7e24c12009-10-30 11:49:00 +00004353 static const int kNameOffset = HeapObject::kHeaderSize;
4354 static const int kCodeOffset = kNameOffset + kPointerSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004355 static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
4356 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004357 static const int kInstanceClassNameOffset =
4358 kConstructStubOffset + kPointerSize;
4359 static const int kFunctionDataOffset =
4360 kInstanceClassNameOffset + kPointerSize;
4361 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
4362 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
4363 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004364 static const int kInitialMapOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01004365 kInferredNameOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004366 static const int kThisPropertyAssignmentsOffset =
4367 kInitialMapOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004368 static const int kDeoptCounterOffset =
4369 kThisPropertyAssignmentsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004370#if V8_HOST_ARCH_32_BIT
4371 // Smi fields.
Steve Block6ded16b2010-05-10 14:33:55 +01004372 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01004373 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004374 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
4375 static const int kExpectedNofPropertiesOffset =
4376 kFormalParameterCountOffset + kPointerSize;
4377 static const int kNumLiteralsOffset =
4378 kExpectedNofPropertiesOffset + kPointerSize;
4379 static const int kStartPositionAndTypeOffset =
4380 kNumLiteralsOffset + kPointerSize;
4381 static const int kEndPositionOffset =
4382 kStartPositionAndTypeOffset + kPointerSize;
4383 static const int kFunctionTokenPositionOffset =
4384 kEndPositionOffset + kPointerSize;
4385 static const int kCompilerHintsOffset =
4386 kFunctionTokenPositionOffset + kPointerSize;
4387 static const int kThisPropertyAssignmentsCountOffset =
4388 kCompilerHintsOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004389 static const int kOptCountOffset =
4390 kThisPropertyAssignmentsCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004391 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004392 static const int kSize = kOptCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004393#else
4394 // The only reason to use smi fields instead of int fields
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004395 // is to allow iteration without maps decoding during
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004396 // garbage collections.
4397 // To avoid wasting space on 64-bit architectures we use
4398 // the following trick: we group integer fields into pairs
4399 // First integer in each pair is shifted left by 1.
4400 // By doing this we guarantee that LSB of each kPointerSize aligned
4401 // word is not set and thus this word cannot be treated as pointer
4402 // to HeapObject during old space traversal.
4403 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01004404 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004405 static const int kFormalParameterCountOffset =
4406 kLengthOffset + kIntSize;
4407
Steve Blocka7e24c12009-10-30 11:49:00 +00004408 static const int kExpectedNofPropertiesOffset =
4409 kFormalParameterCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004410 static const int kNumLiteralsOffset =
4411 kExpectedNofPropertiesOffset + kIntSize;
4412
4413 static const int kEndPositionOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01004414 kNumLiteralsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004415 static const int kStartPositionAndTypeOffset =
4416 kEndPositionOffset + kIntSize;
4417
4418 static const int kFunctionTokenPositionOffset =
4419 kStartPositionAndTypeOffset + kIntSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004420 static const int kCompilerHintsOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00004421 kFunctionTokenPositionOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004422
Steve Blocka7e24c12009-10-30 11:49:00 +00004423 static const int kThisPropertyAssignmentsCountOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01004424 kCompilerHintsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004425 static const int kOptCountOffset =
4426 kThisPropertyAssignmentsCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004427
Steve Block6ded16b2010-05-10 14:33:55 +01004428 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004429 static const int kSize = kOptCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004430
4431#endif
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004432
4433 // The construction counter for inobject slack tracking is stored in the
4434 // most significant byte of compiler_hints which is otherwise unused.
4435 // Its offset depends on the endian-ness of the architecture.
4436#if __BYTE_ORDER == __LITTLE_ENDIAN
4437 static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
4438#elif __BYTE_ORDER == __BIG_ENDIAN
4439 static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
4440#else
4441#error Unknown byte ordering
4442#endif
4443
Steve Block6ded16b2010-05-10 14:33:55 +01004444 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004445
Iain Merrick75681382010-08-19 15:07:18 +01004446 typedef FixedBodyDescriptor<kNameOffset,
4447 kThisPropertyAssignmentsOffset + kPointerSize,
4448 kSize> BodyDescriptor;
4449
Steve Blocka7e24c12009-10-30 11:49:00 +00004450 // Bit positions in start_position_and_type.
4451 // The source code start position is in the 30 most significant bits of
4452 // the start_position_and_type field.
4453 static const int kIsExpressionBit = 0;
4454 static const int kIsTopLevelBit = 1;
4455 static const int kStartPositionShift = 2;
4456 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
4457
4458 // Bit positions in compiler_hints.
Steve Blockd0582a62009-12-15 09:54:21 +00004459 static const int kHasOnlySimpleThisPropertyAssignments = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +00004460 static const int kTryFullCodegen = 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004461 static const int kAllowLazyCompilation = 2;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004462 static const int kLiveObjectsMayExist = 3;
4463 static const int kCodeAgeShift = 4;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004464 static const int kCodeAgeMask = 0x7;
4465 static const int kOptimizationDisabled = 7;
Steve Block1e0659c2011-05-24 12:43:12 +01004466 static const int kStrictModeFunction = 8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004467
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004468 private:
4469#if V8_HOST_ARCH_32_BIT
4470 // On 32 bit platforms, compiler hints is a smi.
4471 static const int kCompilerHintsSmiTagSize = kSmiTagSize;
4472 static const int kCompilerHintsSize = kPointerSize;
4473#else
4474 // On 64 bit platforms, compiler hints is not a smi, see comment above.
4475 static const int kCompilerHintsSmiTagSize = 0;
4476 static const int kCompilerHintsSize = kIntSize;
4477#endif
4478
4479 public:
4480 // Constants for optimizing codegen for strict mode function tests.
4481 // Allows to use byte-widgh instructions.
4482 static const int kStrictModeBitWithinByte =
4483 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
4484
4485#if __BYTE_ORDER == __LITTLE_ENDIAN
4486 static const int kStrictModeByteOffset = kCompilerHintsOffset +
4487 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
4488#elif __BYTE_ORDER == __BIG_ENDIAN
4489 static const int kStrictModeByteOffset = kCompilerHintsOffset +
4490 (kCompilerHintsSize - 1) -
4491 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
4492#else
4493#error Unknown byte ordering
4494#endif
4495
4496 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00004497 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
4498};
4499
4500
4501// JSFunction describes JavaScript functions.
4502class JSFunction: public JSObject {
4503 public:
4504 // [prototype_or_initial_map]:
4505 DECL_ACCESSORS(prototype_or_initial_map, Object)
4506
4507 // [shared_function_info]: The information about the function that
4508 // can be shared by instances.
4509 DECL_ACCESSORS(shared, SharedFunctionInfo)
4510
Iain Merrick75681382010-08-19 15:07:18 +01004511 inline SharedFunctionInfo* unchecked_shared();
4512
Steve Blocka7e24c12009-10-30 11:49:00 +00004513 // [context]: The context for this function.
4514 inline Context* context();
4515 inline Object* unchecked_context();
4516 inline void set_context(Object* context);
4517
4518 // [code]: The generated code object for this function. Executed
4519 // when the function is invoked, e.g. foo() or new foo(). See
4520 // [[Call]] and [[Construct]] description in ECMA-262, section
4521 // 8.6.2, page 27.
4522 inline Code* code();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004523 inline void set_code(Code* code);
4524 inline void ReplaceCode(Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00004525
Iain Merrick75681382010-08-19 15:07:18 +01004526 inline Code* unchecked_code();
4527
Steve Blocka7e24c12009-10-30 11:49:00 +00004528 // Tells whether this function is builtin.
4529 inline bool IsBuiltin();
4530
Ben Murdochb0fe1622011-05-05 13:52:32 +01004531 // Tells whether or not the function needs arguments adaption.
4532 inline bool NeedsArgumentsAdaption();
4533
4534 // Tells whether or not this function has been optimized.
4535 inline bool IsOptimized();
4536
4537 // Mark this function for lazy recompilation. The function will be
4538 // recompiled the next time it is executed.
4539 void MarkForLazyRecompilation();
4540
4541 // Tells whether or not the function is already marked for lazy
4542 // recompilation.
4543 inline bool IsMarkedForLazyRecompilation();
4544
4545 // Compute a hash code for the source code of this function.
4546 uint32_t SourceHash();
4547
4548 // Check whether or not this function is inlineable.
4549 bool IsInlineable();
4550
Steve Blocka7e24c12009-10-30 11:49:00 +00004551 // [literals]: Fixed array holding the materialized literals.
4552 //
4553 // If the function contains object, regexp or array literals, the
4554 // literals array prefix contains the object, regexp, and array
4555 // function to be used when creating these literals. This is
4556 // necessary so that we do not dynamically lookup the object, regexp
4557 // or array functions. Performing a dynamic lookup, we might end up
4558 // using the functions from a new context that we should not have
4559 // access to.
4560 DECL_ACCESSORS(literals, FixedArray)
4561
4562 // The initial map for an object created by this constructor.
4563 inline Map* initial_map();
4564 inline void set_initial_map(Map* value);
4565 inline bool has_initial_map();
4566
4567 // Get and set the prototype property on a JSFunction. If the
4568 // function has an initial map the prototype is set on the initial
4569 // map. Otherwise, the prototype is put in the initial map field
4570 // until an initial map is needed.
4571 inline bool has_prototype();
4572 inline bool has_instance_prototype();
4573 inline Object* prototype();
4574 inline Object* instance_prototype();
4575 Object* SetInstancePrototype(Object* value);
John Reck59135872010-11-02 12:39:01 -07004576 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004577
Steve Block6ded16b2010-05-10 14:33:55 +01004578 // After prototype is removed, it will not be created when accessed, and
4579 // [[Construct]] from this function will not be allowed.
4580 Object* RemovePrototype();
4581 inline bool should_have_prototype();
4582
Steve Blocka7e24c12009-10-30 11:49:00 +00004583 // Accessor for this function's initial map's [[class]]
4584 // property. This is primarily used by ECMA native functions. This
4585 // method sets the class_name field of this function's initial map
4586 // to a given value. It creates an initial map if this function does
4587 // not have one. Note that this method does not copy the initial map
4588 // if it has one already, but simply replaces it with the new value.
4589 // Instances created afterwards will have a map whose [[class]] is
4590 // set to 'value', but there is no guarantees on instances created
4591 // before.
4592 Object* SetInstanceClassName(String* name);
4593
4594 // Returns if this function has been compiled to native code yet.
4595 inline bool is_compiled();
4596
Ben Murdochb0fe1622011-05-05 13:52:32 +01004597 // [next_function_link]: Field for linking functions. This list is treated as
4598 // a weak list by the GC.
4599 DECL_ACCESSORS(next_function_link, Object)
4600
4601 // Prints the name of the function using PrintF.
4602 inline void PrintName() {
4603 PrintName(stdout);
4604 }
4605 void PrintName(FILE* out);
4606
Steve Blocka7e24c12009-10-30 11:49:00 +00004607 // Casting.
4608 static inline JSFunction* cast(Object* obj);
4609
Steve Block791712a2010-08-27 10:21:07 +01004610 // Iterates the objects, including code objects indirectly referenced
4611 // through pointers to the first instruction in the code object.
4612 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
4613
Steve Blocka7e24c12009-10-30 11:49:00 +00004614 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004615#ifdef OBJECT_PRINT
4616 inline void JSFunctionPrint() {
4617 JSFunctionPrint(stdout);
4618 }
4619 void JSFunctionPrint(FILE* out);
4620#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004621#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004622 void JSFunctionVerify();
4623#endif
4624
4625 // Returns the number of allocated literals.
4626 inline int NumberOfLiterals();
4627
4628 // Retrieve the global context from a function's literal array.
4629 static Context* GlobalContextFromLiterals(FixedArray* literals);
4630
Ben Murdochb0fe1622011-05-05 13:52:32 +01004631 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
4632 // kSize) is weak and has special handling during garbage collection.
Steve Block791712a2010-08-27 10:21:07 +01004633 static const int kCodeEntryOffset = JSObject::kHeaderSize;
Iain Merrick75681382010-08-19 15:07:18 +01004634 static const int kPrototypeOrInitialMapOffset =
Steve Block791712a2010-08-27 10:21:07 +01004635 kCodeEntryOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004636 static const int kSharedFunctionInfoOffset =
4637 kPrototypeOrInitialMapOffset + kPointerSize;
4638 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
4639 static const int kLiteralsOffset = kContextOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004640 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
4641 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
4642 static const int kSize = kNextFunctionLinkOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004643
4644 // Layout of the literals array.
4645 static const int kLiteralsPrefixSize = 1;
4646 static const int kLiteralGlobalContextIndex = 0;
4647 private:
4648 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
4649};
4650
4651
4652// JSGlobalProxy's prototype must be a JSGlobalObject or null,
4653// and the prototype is hidden. JSGlobalProxy always delegates
4654// property accesses to its prototype if the prototype is not null.
4655//
4656// A JSGlobalProxy can be reinitialized which will preserve its identity.
4657//
4658// Accessing a JSGlobalProxy requires security check.
4659
4660class JSGlobalProxy : public JSObject {
4661 public:
4662 // [context]: the owner global context of this proxy object.
4663 // It is null value if this object is not used by any context.
4664 DECL_ACCESSORS(context, Object)
4665
4666 // Casting.
4667 static inline JSGlobalProxy* cast(Object* obj);
4668
4669 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004670#ifdef OBJECT_PRINT
4671 inline void JSGlobalProxyPrint() {
4672 JSGlobalProxyPrint(stdout);
4673 }
4674 void JSGlobalProxyPrint(FILE* out);
4675#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004676#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004677 void JSGlobalProxyVerify();
4678#endif
4679
4680 // Layout description.
4681 static const int kContextOffset = JSObject::kHeaderSize;
4682 static const int kSize = kContextOffset + kPointerSize;
4683
4684 private:
4685
4686 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
4687};
4688
4689
4690// Forward declaration.
4691class JSBuiltinsObject;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004692class JSGlobalPropertyCell;
Steve Blocka7e24c12009-10-30 11:49:00 +00004693
4694// Common super class for JavaScript global objects and the special
4695// builtins global objects.
4696class GlobalObject: public JSObject {
4697 public:
4698 // [builtins]: the object holding the runtime routines written in JS.
4699 DECL_ACCESSORS(builtins, JSBuiltinsObject)
4700
4701 // [global context]: the global context corresponding to this global object.
4702 DECL_ACCESSORS(global_context, Context)
4703
4704 // [global receiver]: the global receiver object of the context
4705 DECL_ACCESSORS(global_receiver, JSObject)
4706
4707 // Retrieve the property cell used to store a property.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004708 JSGlobalPropertyCell* GetPropertyCell(LookupResult* result);
Steve Blocka7e24c12009-10-30 11:49:00 +00004709
John Reck59135872010-11-02 12:39:01 -07004710 // This is like GetProperty, but is used when you know the lookup won't fail
4711 // by throwing an exception. This is for the debug and builtins global
4712 // objects, where it is known which properties can be expected to be present
4713 // on the object.
4714 Object* GetPropertyNoExceptionThrown(String* key) {
4715 Object* answer = GetProperty(key)->ToObjectUnchecked();
4716 return answer;
4717 }
4718
Steve Blocka7e24c12009-10-30 11:49:00 +00004719 // Ensure that the global object has a cell for the given property name.
John Reck59135872010-11-02 12:39:01 -07004720 MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004721
4722 // Casting.
4723 static inline GlobalObject* cast(Object* obj);
4724
4725 // Layout description.
4726 static const int kBuiltinsOffset = JSObject::kHeaderSize;
4727 static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
4728 static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
4729 static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
4730
4731 private:
4732 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
4733
4734 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
4735};
4736
4737
4738// JavaScript global object.
4739class JSGlobalObject: public GlobalObject {
4740 public:
4741
4742 // Casting.
4743 static inline JSGlobalObject* cast(Object* obj);
4744
4745 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004746#ifdef OBJECT_PRINT
4747 inline void JSGlobalObjectPrint() {
4748 JSGlobalObjectPrint(stdout);
4749 }
4750 void JSGlobalObjectPrint(FILE* out);
4751#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004752#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004753 void JSGlobalObjectVerify();
4754#endif
4755
4756 // Layout description.
4757 static const int kSize = GlobalObject::kHeaderSize;
4758
4759 private:
4760 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
4761};
4762
4763
4764// Builtins global object which holds the runtime routines written in
4765// JavaScript.
4766class JSBuiltinsObject: public GlobalObject {
4767 public:
4768 // Accessors for the runtime routines written in JavaScript.
4769 inline Object* javascript_builtin(Builtins::JavaScript id);
4770 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
4771
Steve Block6ded16b2010-05-10 14:33:55 +01004772 // Accessors for code of the runtime routines written in JavaScript.
4773 inline Code* javascript_builtin_code(Builtins::JavaScript id);
4774 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
4775
Steve Blocka7e24c12009-10-30 11:49:00 +00004776 // Casting.
4777 static inline JSBuiltinsObject* cast(Object* obj);
4778
4779 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004780#ifdef OBJECT_PRINT
4781 inline void JSBuiltinsObjectPrint() {
4782 JSBuiltinsObjectPrint(stdout);
4783 }
4784 void JSBuiltinsObjectPrint(FILE* out);
4785#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004786#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004787 void JSBuiltinsObjectVerify();
4788#endif
4789
4790 // Layout description. The size of the builtins object includes
Steve Block6ded16b2010-05-10 14:33:55 +01004791 // room for two pointers per runtime routine written in javascript
4792 // (function and code object).
Steve Blocka7e24c12009-10-30 11:49:00 +00004793 static const int kJSBuiltinsCount = Builtins::id_count;
4794 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004795 static const int kJSBuiltinsCodeOffset =
4796 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004797 static const int kSize =
Steve Block6ded16b2010-05-10 14:33:55 +01004798 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
4799
4800 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
4801 return kJSBuiltinsOffset + id * kPointerSize;
4802 }
4803
4804 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
4805 return kJSBuiltinsCodeOffset + id * kPointerSize;
4806 }
4807
Steve Blocka7e24c12009-10-30 11:49:00 +00004808 private:
4809 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
4810};
4811
4812
4813// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
4814class JSValue: public JSObject {
4815 public:
4816 // [value]: the object being wrapped.
4817 DECL_ACCESSORS(value, Object)
4818
4819 // Casting.
4820 static inline JSValue* cast(Object* obj);
4821
4822 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004823#ifdef OBJECT_PRINT
4824 inline void JSValuePrint() {
4825 JSValuePrint(stdout);
4826 }
4827 void JSValuePrint(FILE* out);
4828#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004829#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004830 void JSValueVerify();
4831#endif
4832
4833 // Layout description.
4834 static const int kValueOffset = JSObject::kHeaderSize;
4835 static const int kSize = kValueOffset + kPointerSize;
4836
4837 private:
4838 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
4839};
4840
Steve Block1e0659c2011-05-24 12:43:12 +01004841
4842// Representation of message objects used for error reporting through
4843// the API. The messages are formatted in JavaScript so this object is
4844// a real JavaScript object. The information used for formatting the
4845// error messages are not directly accessible from JavaScript to
4846// prevent leaking information to user code called during error
4847// formatting.
4848class JSMessageObject: public JSObject {
4849 public:
4850 // [type]: the type of error message.
4851 DECL_ACCESSORS(type, String)
4852
4853 // [arguments]: the arguments for formatting the error message.
4854 DECL_ACCESSORS(arguments, JSArray)
4855
4856 // [script]: the script from which the error message originated.
4857 DECL_ACCESSORS(script, Object)
4858
4859 // [stack_trace]: the stack trace for this error message.
4860 DECL_ACCESSORS(stack_trace, Object)
4861
4862 // [stack_frames]: an array of stack frames for this error object.
4863 DECL_ACCESSORS(stack_frames, Object)
4864
4865 // [start_position]: the start position in the script for the error message.
4866 inline int start_position();
4867 inline void set_start_position(int value);
4868
4869 // [end_position]: the end position in the script for the error message.
4870 inline int end_position();
4871 inline void set_end_position(int value);
4872
4873 // Casting.
4874 static inline JSMessageObject* cast(Object* obj);
4875
4876 // Dispatched behavior.
4877#ifdef OBJECT_PRINT
4878 inline void JSMessageObjectPrint() {
4879 JSMessageObjectPrint(stdout);
4880 }
4881 void JSMessageObjectPrint(FILE* out);
4882#endif
4883#ifdef DEBUG
4884 void JSMessageObjectVerify();
4885#endif
4886
4887 // Layout description.
4888 static const int kTypeOffset = JSObject::kHeaderSize;
4889 static const int kArgumentsOffset = kTypeOffset + kPointerSize;
4890 static const int kScriptOffset = kArgumentsOffset + kPointerSize;
4891 static const int kStackTraceOffset = kScriptOffset + kPointerSize;
4892 static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
4893 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
4894 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
4895 static const int kSize = kEndPositionOffset + kPointerSize;
4896
4897 typedef FixedBodyDescriptor<HeapObject::kMapOffset,
4898 kStackFramesOffset + kPointerSize,
4899 kSize> BodyDescriptor;
4900};
4901
4902
Steve Blocka7e24c12009-10-30 11:49:00 +00004903// Regular expressions
4904// The regular expression holds a single reference to a FixedArray in
4905// the kDataOffset field.
4906// The FixedArray contains the following data:
4907// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
4908// - reference to the original source string
4909// - reference to the original flag string
4910// If it is an atom regexp
4911// - a reference to a literal string to search for
4912// If it is an irregexp regexp:
4913// - a reference to code for ASCII inputs (bytecode or compiled).
4914// - a reference to code for UC16 inputs (bytecode or compiled).
4915// - max number of registers used by irregexp implementations.
4916// - number of capture registers (output values) of the regexp.
4917class JSRegExp: public JSObject {
4918 public:
4919 // Meaning of Type:
4920 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
4921 // ATOM: A simple string to match against using an indexOf operation.
4922 // IRREGEXP: Compiled with Irregexp.
4923 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
4924 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
4925 enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
4926
4927 class Flags {
4928 public:
4929 explicit Flags(uint32_t value) : value_(value) { }
4930 bool is_global() { return (value_ & GLOBAL) != 0; }
4931 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
4932 bool is_multiline() { return (value_ & MULTILINE) != 0; }
4933 uint32_t value() { return value_; }
4934 private:
4935 uint32_t value_;
4936 };
4937
4938 DECL_ACCESSORS(data, Object)
4939
4940 inline Type TypeTag();
4941 inline int CaptureCount();
4942 inline Flags GetFlags();
4943 inline String* Pattern();
4944 inline Object* DataAt(int index);
4945 // Set implementation data after the object has been prepared.
4946 inline void SetDataAt(int index, Object* value);
4947 static int code_index(bool is_ascii) {
4948 if (is_ascii) {
4949 return kIrregexpASCIICodeIndex;
4950 } else {
4951 return kIrregexpUC16CodeIndex;
4952 }
4953 }
4954
4955 static inline JSRegExp* cast(Object* obj);
4956
4957 // Dispatched behavior.
4958#ifdef DEBUG
4959 void JSRegExpVerify();
4960#endif
4961
4962 static const int kDataOffset = JSObject::kHeaderSize;
4963 static const int kSize = kDataOffset + kPointerSize;
4964
4965 // Indices in the data array.
4966 static const int kTagIndex = 0;
4967 static const int kSourceIndex = kTagIndex + 1;
4968 static const int kFlagsIndex = kSourceIndex + 1;
4969 static const int kDataIndex = kFlagsIndex + 1;
4970 // The data fields are used in different ways depending on the
4971 // value of the tag.
4972 // Atom regexps (literal strings).
4973 static const int kAtomPatternIndex = kDataIndex;
4974
4975 static const int kAtomDataSize = kAtomPatternIndex + 1;
4976
4977 // Irregexp compiled code or bytecode for ASCII. If compilation
4978 // fails, this fields hold an exception object that should be
4979 // thrown if the regexp is used again.
4980 static const int kIrregexpASCIICodeIndex = kDataIndex;
4981 // Irregexp compiled code or bytecode for UC16. If compilation
4982 // fails, this fields hold an exception object that should be
4983 // thrown if the regexp is used again.
4984 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
4985 // Maximal number of registers used by either ASCII or UC16.
4986 // Only used to check that there is enough stack space
4987 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 2;
4988 // Number of captures in the compiled regexp.
4989 static const int kIrregexpCaptureCountIndex = kDataIndex + 3;
4990
4991 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
Leon Clarkee46be812010-01-19 14:06:41 +00004992
4993 // Offsets directly into the data fixed array.
4994 static const int kDataTagOffset =
4995 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
4996 static const int kDataAsciiCodeOffset =
4997 FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +00004998 static const int kDataUC16CodeOffset =
4999 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00005000 static const int kIrregexpCaptureCountOffset =
5001 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005002
5003 // In-object fields.
5004 static const int kSourceFieldIndex = 0;
5005 static const int kGlobalFieldIndex = 1;
5006 static const int kIgnoreCaseFieldIndex = 2;
5007 static const int kMultilineFieldIndex = 3;
5008 static const int kLastIndexFieldIndex = 4;
Ben Murdochbb769b22010-08-11 14:56:33 +01005009 static const int kInObjectFieldCount = 5;
Steve Blocka7e24c12009-10-30 11:49:00 +00005010};
5011
5012
5013class CompilationCacheShape {
5014 public:
5015 static inline bool IsMatch(HashTableKey* key, Object* value) {
5016 return key->IsMatch(value);
5017 }
5018
5019 static inline uint32_t Hash(HashTableKey* key) {
5020 return key->Hash();
5021 }
5022
5023 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5024 return key->HashForObject(object);
5025 }
5026
John Reck59135872010-11-02 12:39:01 -07005027 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005028 return key->AsObject();
5029 }
5030
5031 static const int kPrefixSize = 0;
5032 static const int kEntrySize = 2;
5033};
5034
Steve Block3ce2e202009-11-05 08:53:23 +00005035
Steve Blocka7e24c12009-10-30 11:49:00 +00005036class CompilationCacheTable: public HashTable<CompilationCacheShape,
5037 HashTableKey*> {
5038 public:
5039 // Find cached value for a string key, otherwise return null.
5040 Object* Lookup(String* src);
Steve Block1e0659c2011-05-24 12:43:12 +01005041 Object* LookupEval(String* src, Context* context, StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00005042 Object* LookupRegExp(String* source, JSRegExp::Flags flags);
John Reck59135872010-11-02 12:39:01 -07005043 MaybeObject* Put(String* src, Object* value);
Steve Block1e0659c2011-05-24 12:43:12 +01005044 MaybeObject* PutEval(String* src,
5045 Context* context,
5046 SharedFunctionInfo* value);
John Reck59135872010-11-02 12:39:01 -07005047 MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005048
Ben Murdochb0fe1622011-05-05 13:52:32 +01005049 // Remove given value from cache.
5050 void Remove(Object* value);
5051
Steve Blocka7e24c12009-10-30 11:49:00 +00005052 static inline CompilationCacheTable* cast(Object* obj);
5053
5054 private:
5055 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
5056};
5057
5058
Steve Block6ded16b2010-05-10 14:33:55 +01005059class CodeCache: public Struct {
5060 public:
5061 DECL_ACCESSORS(default_cache, FixedArray)
5062 DECL_ACCESSORS(normal_type_cache, Object)
5063
5064 // Add the code object to the cache.
John Reck59135872010-11-02 12:39:01 -07005065 MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005066
5067 // Lookup code object in the cache. Returns code object if found and undefined
5068 // if not.
5069 Object* Lookup(String* name, Code::Flags flags);
5070
5071 // Get the internal index of a code object in the cache. Returns -1 if the
5072 // code object is not in that cache. This index can be used to later call
5073 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
5074 // RemoveByIndex.
5075 int GetIndex(Object* name, Code* code);
5076
5077 // Remove an object from the cache with the provided internal index.
5078 void RemoveByIndex(Object* name, Code* code, int index);
5079
5080 static inline CodeCache* cast(Object* obj);
5081
Ben Murdochb0fe1622011-05-05 13:52:32 +01005082#ifdef OBJECT_PRINT
5083 inline void CodeCachePrint() {
5084 CodeCachePrint(stdout);
5085 }
5086 void CodeCachePrint(FILE* out);
5087#endif
Steve Block6ded16b2010-05-10 14:33:55 +01005088#ifdef DEBUG
Steve Block6ded16b2010-05-10 14:33:55 +01005089 void CodeCacheVerify();
5090#endif
5091
5092 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
5093 static const int kNormalTypeCacheOffset =
5094 kDefaultCacheOffset + kPointerSize;
5095 static const int kSize = kNormalTypeCacheOffset + kPointerSize;
5096
5097 private:
John Reck59135872010-11-02 12:39:01 -07005098 MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
5099 MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005100 Object* LookupDefaultCache(String* name, Code::Flags flags);
5101 Object* LookupNormalTypeCache(String* name, Code::Flags flags);
5102
5103 // Code cache layout of the default cache. Elements are alternating name and
5104 // code objects for non normal load/store/call IC's.
5105 static const int kCodeCacheEntrySize = 2;
5106 static const int kCodeCacheEntryNameOffset = 0;
5107 static const int kCodeCacheEntryCodeOffset = 1;
5108
5109 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
5110};
5111
5112
5113class CodeCacheHashTableShape {
5114 public:
5115 static inline bool IsMatch(HashTableKey* key, Object* value) {
5116 return key->IsMatch(value);
5117 }
5118
5119 static inline uint32_t Hash(HashTableKey* key) {
5120 return key->Hash();
5121 }
5122
5123 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5124 return key->HashForObject(object);
5125 }
5126
John Reck59135872010-11-02 12:39:01 -07005127 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Block6ded16b2010-05-10 14:33:55 +01005128 return key->AsObject();
5129 }
5130
5131 static const int kPrefixSize = 0;
5132 static const int kEntrySize = 2;
5133};
5134
5135
5136class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
5137 HashTableKey*> {
5138 public:
5139 Object* Lookup(String* name, Code::Flags flags);
John Reck59135872010-11-02 12:39:01 -07005140 MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005141
5142 int GetIndex(String* name, Code::Flags flags);
5143 void RemoveByIndex(int index);
5144
5145 static inline CodeCacheHashTable* cast(Object* obj);
5146
5147 // Initial size of the fixed array backing the hash table.
5148 static const int kInitialSize = 64;
5149
5150 private:
5151 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
5152};
5153
5154
Steve Blocka7e24c12009-10-30 11:49:00 +00005155enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
5156enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
5157
5158
5159class StringHasher {
5160 public:
5161 inline StringHasher(int length);
5162
5163 // Returns true if the hash of this string can be computed without
5164 // looking at the contents.
5165 inline bool has_trivial_hash();
5166
5167 // Add a character to the hash and update the array index calculation.
5168 inline void AddCharacter(uc32 c);
5169
5170 // Adds a character to the hash but does not update the array index
5171 // calculation. This can only be called when it has been verified
5172 // that the input is not an array index.
5173 inline void AddCharacterNoIndex(uc32 c);
5174
5175 // Returns the value to store in the hash field of a string with
5176 // the given length and contents.
5177 uint32_t GetHashField();
5178
5179 // Returns true if the characters seen so far make up a legal array
5180 // index.
5181 bool is_array_index() { return is_array_index_; }
5182
5183 bool is_valid() { return is_valid_; }
5184
5185 void invalidate() { is_valid_ = false; }
5186
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005187 // Calculated hash value for a string consisting of 1 to
5188 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
5189 // value is represented decimal value.
Iain Merrick9ac36c92010-09-13 15:29:50 +01005190 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005191
Steve Blocka7e24c12009-10-30 11:49:00 +00005192 private:
5193
5194 uint32_t array_index() {
5195 ASSERT(is_array_index());
5196 return array_index_;
5197 }
5198
5199 inline uint32_t GetHash();
5200
5201 int length_;
5202 uint32_t raw_running_hash_;
5203 uint32_t array_index_;
5204 bool is_array_index_;
5205 bool is_first_char_;
5206 bool is_valid_;
Steve Blockd0582a62009-12-15 09:54:21 +00005207 friend class TwoCharHashTableKey;
Steve Blocka7e24c12009-10-30 11:49:00 +00005208};
5209
5210
Steve Block44f0eee2011-05-26 01:26:41 +01005211// Calculates string hash.
5212template <typename schar>
5213inline uint32_t HashSequentialString(const schar* chars, int length);
5214
5215
Steve Blocka7e24c12009-10-30 11:49:00 +00005216// The characteristics of a string are stored in its map. Retrieving these
5217// few bits of information is moderately expensive, involving two memory
5218// loads where the second is dependent on the first. To improve efficiency
5219// the shape of the string is given its own class so that it can be retrieved
5220// once and used for several string operations. A StringShape is small enough
5221// to be passed by value and is immutable, but be aware that flattening a
5222// string can potentially alter its shape. Also be aware that a GC caused by
5223// something else can alter the shape of a string due to ConsString
5224// shortcutting. Keeping these restrictions in mind has proven to be error-
5225// prone and so we no longer put StringShapes in variables unless there is a
5226// concrete performance benefit at that particular point in the code.
5227class StringShape BASE_EMBEDDED {
5228 public:
5229 inline explicit StringShape(String* s);
5230 inline explicit StringShape(Map* s);
5231 inline explicit StringShape(InstanceType t);
5232 inline bool IsSequential();
5233 inline bool IsExternal();
5234 inline bool IsCons();
Steve Blocka7e24c12009-10-30 11:49:00 +00005235 inline bool IsExternalAscii();
5236 inline bool IsExternalTwoByte();
5237 inline bool IsSequentialAscii();
5238 inline bool IsSequentialTwoByte();
5239 inline bool IsSymbol();
5240 inline StringRepresentationTag representation_tag();
5241 inline uint32_t full_representation_tag();
5242 inline uint32_t size_tag();
5243#ifdef DEBUG
5244 inline uint32_t type() { return type_; }
5245 inline void invalidate() { valid_ = false; }
5246 inline bool valid() { return valid_; }
5247#else
5248 inline void invalidate() { }
5249#endif
5250 private:
5251 uint32_t type_;
5252#ifdef DEBUG
5253 inline void set_valid() { valid_ = true; }
5254 bool valid_;
5255#else
5256 inline void set_valid() { }
5257#endif
5258};
5259
5260
5261// The String abstract class captures JavaScript string values:
5262//
5263// Ecma-262:
5264// 4.3.16 String Value
5265// A string value is a member of the type String and is a finite
5266// ordered sequence of zero or more 16-bit unsigned integer values.
5267//
5268// All string values have a length field.
5269class String: public HeapObject {
5270 public:
5271 // Get and set the length of the string.
5272 inline int length();
5273 inline void set_length(int value);
5274
Steve Blockd0582a62009-12-15 09:54:21 +00005275 // Get and set the hash field of the string.
5276 inline uint32_t hash_field();
5277 inline void set_hash_field(uint32_t value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005278
5279 inline bool IsAsciiRepresentation();
5280 inline bool IsTwoByteRepresentation();
5281
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005282 // Returns whether this string has ascii chars, i.e. all of them can
5283 // be ascii encoded. This might be the case even if the string is
5284 // two-byte. Such strings may appear when the embedder prefers
5285 // two-byte external representations even for ascii data.
Steve Block6ded16b2010-05-10 14:33:55 +01005286 //
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005287 // NOTE: this should be considered only a hint. False negatives are
5288 // possible.
5289 inline bool HasOnlyAsciiChars();
Steve Block6ded16b2010-05-10 14:33:55 +01005290
Steve Blocka7e24c12009-10-30 11:49:00 +00005291 // Get and set individual two byte chars in the string.
5292 inline void Set(int index, uint16_t value);
5293 // Get individual two byte char in the string. Repeated calls
5294 // to this method are not efficient unless the string is flat.
5295 inline uint16_t Get(int index);
5296
Leon Clarkef7060e22010-06-03 12:02:55 +01005297 // Try to flatten the string. Checks first inline to see if it is
5298 // necessary. Does nothing if the string is not a cons string.
5299 // Flattening allocates a sequential string with the same data as
5300 // the given string and mutates the cons string to a degenerate
5301 // form, where the first component is the new sequential string and
5302 // the second component is the empty string. If allocation fails,
5303 // this function returns a failure. If flattening succeeds, this
5304 // function returns the sequential string that is now the first
5305 // component of the cons string.
5306 //
5307 // Degenerate cons strings are handled specially by the garbage
5308 // collector (see IsShortcutCandidate).
5309 //
5310 // Use FlattenString from Handles.cc to flatten even in case an
5311 // allocation failure happens.
John Reck59135872010-11-02 12:39:01 -07005312 inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005313
Leon Clarkef7060e22010-06-03 12:02:55 +01005314 // Convenience function. Has exactly the same behavior as
5315 // TryFlatten(), except in the case of failure returns the original
5316 // string.
5317 inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
5318
Steve Blocka7e24c12009-10-30 11:49:00 +00005319 Vector<const char> ToAsciiVector();
5320 Vector<const uc16> ToUC16Vector();
5321
5322 // Mark the string as an undetectable object. It only applies to
5323 // ascii and two byte string types.
5324 bool MarkAsUndetectable();
5325
Steve Blockd0582a62009-12-15 09:54:21 +00005326 // Return a substring.
John Reck59135872010-11-02 12:39:01 -07005327 MUST_USE_RESULT MaybeObject* SubString(int from,
5328 int to,
5329 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005330
5331 // String equality operations.
5332 inline bool Equals(String* other);
5333 bool IsEqualTo(Vector<const char> str);
Steve Block9fac8402011-05-12 15:51:54 +01005334 bool IsAsciiEqualTo(Vector<const char> str);
5335 bool IsTwoByteEqualTo(Vector<const uc16> str);
Steve Blocka7e24c12009-10-30 11:49:00 +00005336
5337 // Return a UTF8 representation of the string. The string is null
5338 // terminated but may optionally contain nulls. Length is returned
5339 // in length_output if length_output is not a null pointer The string
5340 // should be nearly flat, otherwise the performance of this method may
5341 // be very slow (quadratic in the length). Setting robustness_flag to
5342 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
5343 // handles unexpected data without causing assert failures and it does not
5344 // do any heap allocations. This is useful when printing stack traces.
5345 SmartPointer<char> ToCString(AllowNullsFlag allow_nulls,
5346 RobustnessFlag robustness_flag,
5347 int offset,
5348 int length,
5349 int* length_output = 0);
5350 SmartPointer<char> ToCString(
5351 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
5352 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
5353 int* length_output = 0);
5354
5355 int Utf8Length();
5356
5357 // Return a 16 bit Unicode representation of the string.
5358 // The string should be nearly flat, otherwise the performance of
5359 // of this method may be very bad. Setting robustness_flag to
5360 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
5361 // handles unexpected data without causing assert failures and it does not
5362 // do any heap allocations. This is useful when printing stack traces.
5363 SmartPointer<uc16> ToWideCString(
5364 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
5365
5366 // Tells whether the hash code has been computed.
5367 inline bool HasHashCode();
5368
5369 // Returns a hash value used for the property table
5370 inline uint32_t Hash();
5371
Steve Blockd0582a62009-12-15 09:54:21 +00005372 static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
5373 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00005374
5375 static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
5376 uint32_t* index,
5377 int length);
5378
5379 // Externalization.
5380 bool MakeExternal(v8::String::ExternalStringResource* resource);
5381 bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
5382
5383 // Conversion.
5384 inline bool AsArrayIndex(uint32_t* index);
5385
5386 // Casting.
5387 static inline String* cast(Object* obj);
5388
5389 void PrintOn(FILE* out);
5390
5391 // For use during stack traces. Performs rudimentary sanity check.
5392 bool LooksValid();
5393
5394 // Dispatched behavior.
5395 void StringShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005396#ifdef OBJECT_PRINT
5397 inline void StringPrint() {
5398 StringPrint(stdout);
5399 }
5400 void StringPrint(FILE* out);
5401#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005402#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005403 void StringVerify();
5404#endif
5405 inline bool IsFlat();
5406
5407 // Layout description.
5408 static const int kLengthOffset = HeapObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005409 static const int kHashFieldOffset = kLengthOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005410 static const int kSize = kHashFieldOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005411
Steve Blockd0582a62009-12-15 09:54:21 +00005412 // Maximum number of characters to consider when trying to convert a string
5413 // value into an array index.
Steve Blocka7e24c12009-10-30 11:49:00 +00005414 static const int kMaxArrayIndexSize = 10;
5415
5416 // Max ascii char code.
5417 static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
5418 static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
5419 static const int kMaxUC16CharCode = 0xffff;
5420
Steve Blockd0582a62009-12-15 09:54:21 +00005421 // Minimum length for a cons string.
Steve Blocka7e24c12009-10-30 11:49:00 +00005422 static const int kMinNonFlatLength = 13;
5423
5424 // Mask constant for checking if a string has a computed hash code
5425 // and if it is an array index. The least significant bit indicates
5426 // whether a hash code has been computed. If the hash code has been
5427 // computed the 2nd bit tells whether the string can be used as an
5428 // array index.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005429 static const int kHashNotComputedMask = 1;
5430 static const int kIsNotArrayIndexMask = 1 << 1;
5431 static const int kNofHashBitFields = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +00005432
Steve Blockd0582a62009-12-15 09:54:21 +00005433 // Shift constant retrieving hash code from hash field.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005434 static const int kHashShift = kNofHashBitFields;
Steve Blockd0582a62009-12-15 09:54:21 +00005435
Steve Blocka7e24c12009-10-30 11:49:00 +00005436 // Array index strings this short can keep their index in the hash
5437 // field.
5438 static const int kMaxCachedArrayIndexLength = 7;
5439
Steve Blockd0582a62009-12-15 09:54:21 +00005440 // For strings which are array indexes the hash value has the string length
5441 // mixed into the hash, mainly to avoid a hash value of zero which would be
5442 // the case for the string '0'. 24 bits are used for the array index value.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005443 static const int kArrayIndexValueBits = 24;
5444 static const int kArrayIndexLengthBits =
5445 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
5446
5447 STATIC_CHECK((kArrayIndexLengthBits > 0));
Iain Merrick9ac36c92010-09-13 15:29:50 +01005448 STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005449
5450 static const int kArrayIndexHashLengthShift =
5451 kArrayIndexValueBits + kNofHashBitFields;
5452
Steve Blockd0582a62009-12-15 09:54:21 +00005453 static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005454
5455 static const int kArrayIndexValueMask =
5456 ((1 << kArrayIndexValueBits) - 1) << kHashShift;
5457
5458 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
5459 // could use a mask to test if the length of string is less than or equal to
5460 // kMaxCachedArrayIndexLength.
5461 STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
5462
5463 static const int kContainsCachedArrayIndexMask =
5464 (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
5465 kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00005466
5467 // Value of empty hash field indicating that the hash is not computed.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005468 static const int kEmptyHashField =
5469 kIsNotArrayIndexMask | kHashNotComputedMask;
5470
5471 // Value of hash field containing computed hash equal to zero.
5472 static const int kZeroHash = kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00005473
5474 // Maximal string length.
5475 static const int kMaxLength = (1 << (32 - 2)) - 1;
5476
5477 // Max length for computing hash. For strings longer than this limit the
5478 // string length is used as the hash value.
5479 static const int kMaxHashCalcLength = 16383;
Steve Blocka7e24c12009-10-30 11:49:00 +00005480
5481 // Limit for truncation in short printing.
5482 static const int kMaxShortPrintLength = 1024;
5483
5484 // Support for regular expressions.
5485 const uc16* GetTwoByteData();
5486 const uc16* GetTwoByteData(unsigned start);
5487
5488 // Support for StringInputBuffer
5489 static const unibrow::byte* ReadBlock(String* input,
5490 unibrow::byte* util_buffer,
5491 unsigned capacity,
5492 unsigned* remaining,
5493 unsigned* offset);
5494 static const unibrow::byte* ReadBlock(String** input,
5495 unibrow::byte* util_buffer,
5496 unsigned capacity,
5497 unsigned* remaining,
5498 unsigned* offset);
5499
5500 // Helper function for flattening strings.
5501 template <typename sinkchar>
5502 static void WriteToFlat(String* source,
5503 sinkchar* sink,
5504 int from,
5505 int to);
5506
Steve Block9fac8402011-05-12 15:51:54 +01005507 static inline bool IsAscii(const char* chars, int length) {
5508 const char* limit = chars + length;
5509#ifdef V8_HOST_CAN_READ_UNALIGNED
5510 ASSERT(kMaxAsciiCharCode == 0x7F);
5511 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
5512 while (chars <= limit - sizeof(uintptr_t)) {
5513 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
5514 return false;
5515 }
5516 chars += sizeof(uintptr_t);
5517 }
5518#endif
5519 while (chars < limit) {
5520 if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
5521 ++chars;
5522 }
5523 return true;
5524 }
5525
5526 static inline bool IsAscii(const uc16* chars, int length) {
5527 const uc16* limit = chars + length;
5528 while (chars < limit) {
5529 if (*chars > kMaxAsciiCharCodeU) return false;
5530 ++chars;
5531 }
5532 return true;
5533 }
5534
Steve Blocka7e24c12009-10-30 11:49:00 +00005535 protected:
5536 class ReadBlockBuffer {
5537 public:
5538 ReadBlockBuffer(unibrow::byte* util_buffer_,
5539 unsigned cursor_,
5540 unsigned capacity_,
5541 unsigned remaining_) :
5542 util_buffer(util_buffer_),
5543 cursor(cursor_),
5544 capacity(capacity_),
5545 remaining(remaining_) {
5546 }
5547 unibrow::byte* util_buffer;
5548 unsigned cursor;
5549 unsigned capacity;
5550 unsigned remaining;
5551 };
5552
Steve Blocka7e24c12009-10-30 11:49:00 +00005553 static inline const unibrow::byte* ReadBlock(String* input,
5554 ReadBlockBuffer* buffer,
5555 unsigned* offset,
5556 unsigned max_chars);
5557 static void ReadBlockIntoBuffer(String* input,
5558 ReadBlockBuffer* buffer,
5559 unsigned* offset_ptr,
5560 unsigned max_chars);
5561
5562 private:
Leon Clarkef7060e22010-06-03 12:02:55 +01005563 // Try to flatten the top level ConsString that is hiding behind this
5564 // string. This is a no-op unless the string is a ConsString. Flatten
5565 // mutates the ConsString and might return a failure.
John Reck59135872010-11-02 12:39:01 -07005566 MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
Leon Clarkef7060e22010-06-03 12:02:55 +01005567
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005568 static inline bool IsHashFieldComputed(uint32_t field);
5569
Steve Blocka7e24c12009-10-30 11:49:00 +00005570 // Slow case of String::Equals. This implementation works on any strings
5571 // but it is most efficient on strings that are almost flat.
5572 bool SlowEquals(String* other);
5573
5574 // Slow case of AsArrayIndex.
5575 bool SlowAsArrayIndex(uint32_t* index);
5576
5577 // Compute and set the hash code.
5578 uint32_t ComputeAndSetHash();
5579
5580 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
5581};
5582
5583
5584// The SeqString abstract class captures sequential string values.
5585class SeqString: public String {
5586 public:
5587
5588 // Casting.
5589 static inline SeqString* cast(Object* obj);
5590
Steve Blocka7e24c12009-10-30 11:49:00 +00005591 private:
5592 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
5593};
5594
5595
5596// The AsciiString class captures sequential ascii string objects.
5597// Each character in the AsciiString is an ascii character.
5598class SeqAsciiString: public SeqString {
5599 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005600 static const bool kHasAsciiEncoding = true;
5601
Steve Blocka7e24c12009-10-30 11:49:00 +00005602 // Dispatched behavior.
5603 inline uint16_t SeqAsciiStringGet(int index);
5604 inline void SeqAsciiStringSet(int index, uint16_t value);
5605
5606 // Get the address of the characters in this string.
5607 inline Address GetCharsAddress();
5608
5609 inline char* GetChars();
5610
5611 // Casting
5612 static inline SeqAsciiString* cast(Object* obj);
5613
5614 // Garbage collection support. This method is called by the
5615 // garbage collector to compute the actual size of an AsciiString
5616 // instance.
5617 inline int SeqAsciiStringSize(InstanceType instance_type);
5618
5619 // Computes the size for an AsciiString instance of a given length.
5620 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005621 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005622 }
5623
5624 // Layout description.
5625 static const int kHeaderSize = String::kSize;
5626 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
5627
Leon Clarkee46be812010-01-19 14:06:41 +00005628 // Maximal memory usage for a single sequential ASCII string.
5629 static const int kMaxSize = 512 * MB;
5630 // Maximal length of a single sequential ASCII string.
5631 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
5632 static const int kMaxLength = (kMaxSize - kHeaderSize);
5633
Steve Blocka7e24c12009-10-30 11:49:00 +00005634 // Support for StringInputBuffer.
5635 inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5636 unsigned* offset,
5637 unsigned chars);
5638 inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
5639 unsigned* offset,
5640 unsigned chars);
5641
5642 private:
5643 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
5644};
5645
5646
5647// The TwoByteString class captures sequential unicode string objects.
5648// Each character in the TwoByteString is a two-byte uint16_t.
5649class SeqTwoByteString: public SeqString {
5650 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005651 static const bool kHasAsciiEncoding = false;
5652
Steve Blocka7e24c12009-10-30 11:49:00 +00005653 // Dispatched behavior.
5654 inline uint16_t SeqTwoByteStringGet(int index);
5655 inline void SeqTwoByteStringSet(int index, uint16_t value);
5656
5657 // Get the address of the characters in this string.
5658 inline Address GetCharsAddress();
5659
5660 inline uc16* GetChars();
5661
5662 // For regexp code.
5663 const uint16_t* SeqTwoByteStringGetData(unsigned start);
5664
5665 // Casting
5666 static inline SeqTwoByteString* cast(Object* obj);
5667
5668 // Garbage collection support. This method is called by the
5669 // garbage collector to compute the actual size of a TwoByteString
5670 // instance.
5671 inline int SeqTwoByteStringSize(InstanceType instance_type);
5672
5673 // Computes the size for a TwoByteString instance of a given length.
5674 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005675 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005676 }
5677
5678 // Layout description.
5679 static const int kHeaderSize = String::kSize;
5680 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
5681
Leon Clarkee46be812010-01-19 14:06:41 +00005682 // Maximal memory usage for a single sequential two-byte string.
5683 static const int kMaxSize = 512 * MB;
5684 // Maximal length of a single sequential two-byte string.
5685 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
5686 static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
5687
Steve Blocka7e24c12009-10-30 11:49:00 +00005688 // Support for StringInputBuffer.
5689 inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5690 unsigned* offset_ptr,
5691 unsigned chars);
5692
5693 private:
5694 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
5695};
5696
5697
5698// The ConsString class describes string values built by using the
5699// addition operator on strings. A ConsString is a pair where the
5700// first and second components are pointers to other string values.
5701// One or both components of a ConsString can be pointers to other
5702// ConsStrings, creating a binary tree of ConsStrings where the leaves
5703// are non-ConsString string values. The string value represented by
5704// a ConsString can be obtained by concatenating the leaf string
5705// values in a left-to-right depth-first traversal of the tree.
5706class ConsString: public String {
5707 public:
5708 // First string of the cons cell.
5709 inline String* first();
5710 // Doesn't check that the result is a string, even in debug mode. This is
5711 // useful during GC where the mark bits confuse the checks.
5712 inline Object* unchecked_first();
5713 inline void set_first(String* first,
5714 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
5715
5716 // Second string of the cons cell.
5717 inline String* second();
5718 // Doesn't check that the result is a string, even in debug mode. This is
5719 // useful during GC where the mark bits confuse the checks.
5720 inline Object* unchecked_second();
5721 inline void set_second(String* second,
5722 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
5723
5724 // Dispatched behavior.
5725 uint16_t ConsStringGet(int index);
5726
5727 // Casting.
5728 static inline ConsString* cast(Object* obj);
5729
Steve Blocka7e24c12009-10-30 11:49:00 +00005730 // Layout description.
5731 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
5732 static const int kSecondOffset = kFirstOffset + kPointerSize;
5733 static const int kSize = kSecondOffset + kPointerSize;
5734
5735 // Support for StringInputBuffer.
5736 inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
5737 unsigned* offset_ptr,
5738 unsigned chars);
5739 inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5740 unsigned* offset_ptr,
5741 unsigned chars);
5742
5743 // Minimum length for a cons string.
5744 static const int kMinLength = 13;
5745
Iain Merrick75681382010-08-19 15:07:18 +01005746 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
5747 BodyDescriptor;
5748
Steve Blocka7e24c12009-10-30 11:49:00 +00005749 private:
5750 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
5751};
5752
5753
Steve Blocka7e24c12009-10-30 11:49:00 +00005754// The ExternalString class describes string values that are backed by
5755// a string resource that lies outside the V8 heap. ExternalStrings
5756// consist of the length field common to all strings, a pointer to the
5757// external resource. It is important to ensure (externally) that the
5758// resource is not deallocated while the ExternalString is live in the
5759// V8 heap.
5760//
5761// The API expects that all ExternalStrings are created through the
5762// API. Therefore, ExternalStrings should not be used internally.
5763class ExternalString: public String {
5764 public:
5765 // Casting
5766 static inline ExternalString* cast(Object* obj);
5767
5768 // Layout description.
5769 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
5770 static const int kSize = kResourceOffset + kPointerSize;
5771
5772 STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
5773
5774 private:
5775 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
5776};
5777
5778
5779// The ExternalAsciiString class is an external string backed by an
5780// ASCII string.
5781class ExternalAsciiString: public ExternalString {
5782 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005783 static const bool kHasAsciiEncoding = true;
5784
Steve Blocka7e24c12009-10-30 11:49:00 +00005785 typedef v8::String::ExternalAsciiStringResource Resource;
5786
5787 // The underlying resource.
5788 inline Resource* resource();
5789 inline void set_resource(Resource* buffer);
5790
5791 // Dispatched behavior.
5792 uint16_t ExternalAsciiStringGet(int index);
5793
5794 // Casting.
5795 static inline ExternalAsciiString* cast(Object* obj);
5796
Steve Blockd0582a62009-12-15 09:54:21 +00005797 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01005798 inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
5799
5800 template<typename StaticVisitor>
5801 inline void ExternalAsciiStringIterateBody();
Steve Blockd0582a62009-12-15 09:54:21 +00005802
Steve Blocka7e24c12009-10-30 11:49:00 +00005803 // Support for StringInputBuffer.
5804 const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
5805 unsigned* offset,
5806 unsigned chars);
5807 inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5808 unsigned* offset,
5809 unsigned chars);
5810
Steve Blocka7e24c12009-10-30 11:49:00 +00005811 private:
5812 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
5813};
5814
5815
5816// The ExternalTwoByteString class is an external string backed by a UTF-16
5817// encoded string.
5818class ExternalTwoByteString: public ExternalString {
5819 public:
Leon Clarkeac952652010-07-15 11:15:24 +01005820 static const bool kHasAsciiEncoding = false;
5821
Steve Blocka7e24c12009-10-30 11:49:00 +00005822 typedef v8::String::ExternalStringResource Resource;
5823
5824 // The underlying string resource.
5825 inline Resource* resource();
5826 inline void set_resource(Resource* buffer);
5827
5828 // Dispatched behavior.
5829 uint16_t ExternalTwoByteStringGet(int index);
5830
5831 // For regexp code.
5832 const uint16_t* ExternalTwoByteStringGetData(unsigned start);
5833
5834 // Casting.
5835 static inline ExternalTwoByteString* cast(Object* obj);
5836
Steve Blockd0582a62009-12-15 09:54:21 +00005837 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01005838 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
5839
5840 template<typename StaticVisitor>
5841 inline void ExternalTwoByteStringIterateBody();
5842
Steve Blockd0582a62009-12-15 09:54:21 +00005843
Steve Blocka7e24c12009-10-30 11:49:00 +00005844 // Support for StringInputBuffer.
5845 void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
5846 unsigned* offset_ptr,
5847 unsigned chars);
5848
Steve Blocka7e24c12009-10-30 11:49:00 +00005849 private:
5850 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
5851};
5852
5853
5854// Utility superclass for stack-allocated objects that must be updated
5855// on gc. It provides two ways for the gc to update instances, either
5856// iterating or updating after gc.
5857class Relocatable BASE_EMBEDDED {
5858 public:
Steve Block44f0eee2011-05-26 01:26:41 +01005859 explicit inline Relocatable(Isolate* isolate);
5860 inline virtual ~Relocatable();
Steve Blocka7e24c12009-10-30 11:49:00 +00005861 virtual void IterateInstance(ObjectVisitor* v) { }
5862 virtual void PostGarbageCollection() { }
5863
5864 static void PostGarbageCollectionProcessing();
5865 static int ArchiveSpacePerThread();
5866 static char* ArchiveState(char* to);
5867 static char* RestoreState(char* from);
5868 static void Iterate(ObjectVisitor* v);
5869 static void Iterate(ObjectVisitor* v, Relocatable* top);
5870 static char* Iterate(ObjectVisitor* v, char* t);
5871 private:
Steve Block44f0eee2011-05-26 01:26:41 +01005872 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005873 Relocatable* prev_;
5874};
5875
5876
5877// A flat string reader provides random access to the contents of a
5878// string independent of the character width of the string. The handle
5879// must be valid as long as the reader is being used.
5880class FlatStringReader : public Relocatable {
5881 public:
Steve Block44f0eee2011-05-26 01:26:41 +01005882 FlatStringReader(Isolate* isolate, Handle<String> str);
5883 FlatStringReader(Isolate* isolate, Vector<const char> input);
Steve Blocka7e24c12009-10-30 11:49:00 +00005884 void PostGarbageCollection();
5885 inline uc32 Get(int index);
5886 int length() { return length_; }
5887 private:
5888 String** str_;
5889 bool is_ascii_;
5890 int length_;
5891 const void* start_;
5892};
5893
5894
5895// Note that StringInputBuffers are not valid across a GC! To fix this
5896// it would have to store a String Handle instead of a String* and
5897// AsciiStringReadBlock would have to be modified to use memcpy.
5898//
5899// StringInputBuffer is able to traverse any string regardless of how
5900// deeply nested a sequence of ConsStrings it is made of. However,
5901// performance will be better if deep strings are flattened before they
5902// are traversed. Since flattening requires memory allocation this is
5903// not always desirable, however (esp. in debugging situations).
5904class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
5905 public:
5906 virtual void Seek(unsigned pos);
5907 inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
5908 inline StringInputBuffer(String* backing):
5909 unibrow::InputBuffer<String, String*, 1024>(backing) {}
5910};
5911
5912
5913class SafeStringInputBuffer
5914 : public unibrow::InputBuffer<String, String**, 256> {
5915 public:
5916 virtual void Seek(unsigned pos);
5917 inline SafeStringInputBuffer()
5918 : unibrow::InputBuffer<String, String**, 256>() {}
5919 inline SafeStringInputBuffer(String** backing)
5920 : unibrow::InputBuffer<String, String**, 256>(backing) {}
5921};
5922
5923
5924template <typename T>
5925class VectorIterator {
5926 public:
5927 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
5928 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
5929 T GetNext() { return data_[index_++]; }
5930 bool has_more() { return index_ < data_.length(); }
5931 private:
5932 Vector<const T> data_;
5933 int index_;
5934};
5935
5936
5937// The Oddball describes objects null, undefined, true, and false.
5938class Oddball: public HeapObject {
5939 public:
5940 // [to_string]: Cached to_string computed at startup.
5941 DECL_ACCESSORS(to_string, String)
5942
5943 // [to_number]: Cached to_number computed at startup.
5944 DECL_ACCESSORS(to_number, Object)
5945
Steve Block44f0eee2011-05-26 01:26:41 +01005946 inline byte kind();
5947 inline void set_kind(byte kind);
5948
Steve Blocka7e24c12009-10-30 11:49:00 +00005949 // Casting.
5950 static inline Oddball* cast(Object* obj);
5951
5952 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00005953#ifdef DEBUG
5954 void OddballVerify();
5955#endif
5956
5957 // Initialize the fields.
John Reck59135872010-11-02 12:39:01 -07005958 MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
Steve Block44f0eee2011-05-26 01:26:41 +01005959 Object* to_number,
5960 byte kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00005961
5962 // Layout description.
5963 static const int kToStringOffset = HeapObject::kHeaderSize;
5964 static const int kToNumberOffset = kToStringOffset + kPointerSize;
Steve Block44f0eee2011-05-26 01:26:41 +01005965 static const int kKindOffset = kToNumberOffset + kPointerSize;
5966 static const int kSize = kKindOffset + kPointerSize;
5967
5968 static const byte kFalse = 0;
5969 static const byte kTrue = 1;
5970 static const byte kNotBooleanMask = ~1;
5971 static const byte kTheHole = 2;
5972 static const byte kNull = 3;
5973 static const byte kArgumentMarker = 4;
5974 static const byte kUndefined = 5;
5975 static const byte kOther = 6;
Steve Blocka7e24c12009-10-30 11:49:00 +00005976
Iain Merrick75681382010-08-19 15:07:18 +01005977 typedef FixedBodyDescriptor<kToStringOffset,
5978 kToNumberOffset + kPointerSize,
5979 kSize> BodyDescriptor;
5980
Steve Blocka7e24c12009-10-30 11:49:00 +00005981 private:
5982 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
5983};
5984
5985
5986class JSGlobalPropertyCell: public HeapObject {
5987 public:
5988 // [value]: value of the global property.
5989 DECL_ACCESSORS(value, Object)
5990
5991 // Casting.
5992 static inline JSGlobalPropertyCell* cast(Object* obj);
5993
Steve Blocka7e24c12009-10-30 11:49:00 +00005994#ifdef DEBUG
5995 void JSGlobalPropertyCellVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005996#endif
5997#ifdef OBJECT_PRINT
5998 inline void JSGlobalPropertyCellPrint() {
5999 JSGlobalPropertyCellPrint(stdout);
6000 }
6001 void JSGlobalPropertyCellPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00006002#endif
6003
6004 // Layout description.
6005 static const int kValueOffset = HeapObject::kHeaderSize;
6006 static const int kSize = kValueOffset + kPointerSize;
6007
Iain Merrick75681382010-08-19 15:07:18 +01006008 typedef FixedBodyDescriptor<kValueOffset,
6009 kValueOffset + kPointerSize,
6010 kSize> BodyDescriptor;
6011
Steve Blocka7e24c12009-10-30 11:49:00 +00006012 private:
6013 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
6014};
6015
6016
6017
6018// Proxy describes objects pointing from JavaScript to C structures.
6019// Since they cannot contain references to JS HeapObjects they can be
6020// placed in old_data_space.
6021class Proxy: public HeapObject {
6022 public:
6023 // [proxy]: field containing the address.
6024 inline Address proxy();
6025 inline void set_proxy(Address value);
6026
6027 // Casting.
6028 static inline Proxy* cast(Object* obj);
6029
6030 // Dispatched behavior.
6031 inline void ProxyIterateBody(ObjectVisitor* v);
Iain Merrick75681382010-08-19 15:07:18 +01006032
6033 template<typename StaticVisitor>
6034 inline void ProxyIterateBody();
6035
Ben Murdochb0fe1622011-05-05 13:52:32 +01006036#ifdef OBJECT_PRINT
6037 inline void ProxyPrint() {
6038 ProxyPrint(stdout);
6039 }
6040 void ProxyPrint(FILE* out);
6041#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006042#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006043 void ProxyVerify();
6044#endif
6045
6046 // Layout description.
6047
6048 static const int kProxyOffset = HeapObject::kHeaderSize;
6049 static const int kSize = kProxyOffset + kPointerSize;
6050
6051 STATIC_CHECK(kProxyOffset == Internals::kProxyProxyOffset);
6052
6053 private:
6054 DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
6055};
6056
6057
6058// The JSArray describes JavaScript Arrays
6059// Such an array can be in one of two modes:
6060// - fast, backing storage is a FixedArray and length <= elements.length();
6061// Please note: push and pop can be used to grow and shrink the array.
6062// - slow, backing storage is a HashTable with numbers as keys.
6063class JSArray: public JSObject {
6064 public:
6065 // [length]: The length property.
6066 DECL_ACCESSORS(length, Object)
6067
Leon Clarke4515c472010-02-03 11:58:03 +00006068 // Overload the length setter to skip write barrier when the length
6069 // is set to a smi. This matches the set function on FixedArray.
6070 inline void set_length(Smi* length);
6071
John Reck59135872010-11-02 12:39:01 -07006072 MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
6073 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006074
6075 // Initialize the array with the given capacity. The function may
6076 // fail due to out-of-memory situations, but only if the requested
6077 // capacity is non-zero.
John Reck59135872010-11-02 12:39:01 -07006078 MUST_USE_RESULT MaybeObject* Initialize(int capacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00006079
6080 // Set the content of the array to the content of storage.
6081 inline void SetContent(FixedArray* storage);
6082
6083 // Casting.
6084 static inline JSArray* cast(Object* obj);
6085
6086 // Uses handles. Ensures that the fixed array backing the JSArray has at
6087 // least the stated size.
6088 inline void EnsureSize(int minimum_size_of_backing_fixed_array);
6089
6090 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01006091#ifdef OBJECT_PRINT
6092 inline void JSArrayPrint() {
6093 JSArrayPrint(stdout);
6094 }
6095 void JSArrayPrint(FILE* out);
6096#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006097#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006098 void JSArrayVerify();
6099#endif
6100
6101 // Number of element slots to pre-allocate for an empty array.
6102 static const int kPreallocatedArrayElements = 4;
6103
6104 // Layout description.
6105 static const int kLengthOffset = JSObject::kHeaderSize;
6106 static const int kSize = kLengthOffset + kPointerSize;
6107
6108 private:
6109 // Expand the fixed array backing of a fast-case JSArray to at least
6110 // the requested size.
6111 void Expand(int minimum_size_of_backing_fixed_array);
6112
6113 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
6114};
6115
6116
Steve Block6ded16b2010-05-10 14:33:55 +01006117// JSRegExpResult is just a JSArray with a specific initial map.
6118// This initial map adds in-object properties for "index" and "input"
6119// properties, as assigned by RegExp.prototype.exec, which allows
6120// faster creation of RegExp exec results.
6121// This class just holds constants used when creating the result.
6122// After creation the result must be treated as a JSArray in all regards.
6123class JSRegExpResult: public JSArray {
6124 public:
6125 // Offsets of object fields.
6126 static const int kIndexOffset = JSArray::kSize;
6127 static const int kInputOffset = kIndexOffset + kPointerSize;
6128 static const int kSize = kInputOffset + kPointerSize;
6129 // Indices of in-object properties.
6130 static const int kIndexIndex = 0;
6131 static const int kInputIndex = 1;
6132 private:
6133 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
6134};
6135
6136
Steve Blocka7e24c12009-10-30 11:49:00 +00006137// An accessor must have a getter, but can have no setter.
6138//
6139// When setting a property, V8 searches accessors in prototypes.
6140// If an accessor was found and it does not have a setter,
6141// the request is ignored.
6142//
6143// If the accessor in the prototype has the READ_ONLY property attribute, then
6144// a new value is added to the local object when the property is set.
6145// This shadows the accessor in the prototype.
6146class AccessorInfo: public Struct {
6147 public:
6148 DECL_ACCESSORS(getter, Object)
6149 DECL_ACCESSORS(setter, Object)
6150 DECL_ACCESSORS(data, Object)
6151 DECL_ACCESSORS(name, Object)
6152 DECL_ACCESSORS(flag, Smi)
6153
6154 inline bool all_can_read();
6155 inline void set_all_can_read(bool value);
6156
6157 inline bool all_can_write();
6158 inline void set_all_can_write(bool value);
6159
6160 inline bool prohibits_overwriting();
6161 inline void set_prohibits_overwriting(bool value);
6162
6163 inline PropertyAttributes property_attributes();
6164 inline void set_property_attributes(PropertyAttributes attributes);
6165
6166 static inline AccessorInfo* cast(Object* obj);
6167
Ben Murdochb0fe1622011-05-05 13:52:32 +01006168#ifdef OBJECT_PRINT
6169 inline void AccessorInfoPrint() {
6170 AccessorInfoPrint(stdout);
6171 }
6172 void AccessorInfoPrint(FILE* out);
6173#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006174#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006175 void AccessorInfoVerify();
6176#endif
6177
6178 static const int kGetterOffset = HeapObject::kHeaderSize;
6179 static const int kSetterOffset = kGetterOffset + kPointerSize;
6180 static const int kDataOffset = kSetterOffset + kPointerSize;
6181 static const int kNameOffset = kDataOffset + kPointerSize;
6182 static const int kFlagOffset = kNameOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08006183 static const int kSize = kFlagOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006184
6185 private:
6186 // Bit positions in flag.
6187 static const int kAllCanReadBit = 0;
6188 static const int kAllCanWriteBit = 1;
6189 static const int kProhibitsOverwritingBit = 2;
6190 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
6191
6192 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
6193};
6194
6195
6196class AccessCheckInfo: public Struct {
6197 public:
6198 DECL_ACCESSORS(named_callback, Object)
6199 DECL_ACCESSORS(indexed_callback, Object)
6200 DECL_ACCESSORS(data, Object)
6201
6202 static inline AccessCheckInfo* cast(Object* obj);
6203
Ben Murdochb0fe1622011-05-05 13:52:32 +01006204#ifdef OBJECT_PRINT
6205 inline void AccessCheckInfoPrint() {
6206 AccessCheckInfoPrint(stdout);
6207 }
6208 void AccessCheckInfoPrint(FILE* out);
6209#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006210#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006211 void AccessCheckInfoVerify();
6212#endif
6213
6214 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
6215 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
6216 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
6217 static const int kSize = kDataOffset + kPointerSize;
6218
6219 private:
6220 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
6221};
6222
6223
6224class InterceptorInfo: public Struct {
6225 public:
6226 DECL_ACCESSORS(getter, Object)
6227 DECL_ACCESSORS(setter, Object)
6228 DECL_ACCESSORS(query, Object)
6229 DECL_ACCESSORS(deleter, Object)
6230 DECL_ACCESSORS(enumerator, Object)
6231 DECL_ACCESSORS(data, Object)
6232
6233 static inline InterceptorInfo* cast(Object* obj);
6234
Ben Murdochb0fe1622011-05-05 13:52:32 +01006235#ifdef OBJECT_PRINT
6236 inline void InterceptorInfoPrint() {
6237 InterceptorInfoPrint(stdout);
6238 }
6239 void InterceptorInfoPrint(FILE* out);
6240#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006241#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006242 void InterceptorInfoVerify();
6243#endif
6244
6245 static const int kGetterOffset = HeapObject::kHeaderSize;
6246 static const int kSetterOffset = kGetterOffset + kPointerSize;
6247 static const int kQueryOffset = kSetterOffset + kPointerSize;
6248 static const int kDeleterOffset = kQueryOffset + kPointerSize;
6249 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
6250 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
6251 static const int kSize = kDataOffset + kPointerSize;
6252
6253 private:
6254 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
6255};
6256
6257
6258class CallHandlerInfo: public Struct {
6259 public:
6260 DECL_ACCESSORS(callback, Object)
6261 DECL_ACCESSORS(data, Object)
6262
6263 static inline CallHandlerInfo* cast(Object* obj);
6264
Ben Murdochb0fe1622011-05-05 13:52:32 +01006265#ifdef OBJECT_PRINT
6266 inline void CallHandlerInfoPrint() {
6267 CallHandlerInfoPrint(stdout);
6268 }
6269 void CallHandlerInfoPrint(FILE* out);
6270#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006271#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006272 void CallHandlerInfoVerify();
6273#endif
6274
6275 static const int kCallbackOffset = HeapObject::kHeaderSize;
6276 static const int kDataOffset = kCallbackOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08006277 static const int kSize = kDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006278
6279 private:
6280 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
6281};
6282
6283
6284class TemplateInfo: public Struct {
6285 public:
6286 DECL_ACCESSORS(tag, Object)
6287 DECL_ACCESSORS(property_list, Object)
6288
6289#ifdef DEBUG
6290 void TemplateInfoVerify();
6291#endif
6292
6293 static const int kTagOffset = HeapObject::kHeaderSize;
6294 static const int kPropertyListOffset = kTagOffset + kPointerSize;
6295 static const int kHeaderSize = kPropertyListOffset + kPointerSize;
6296 protected:
6297 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
6298 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
6299};
6300
6301
6302class FunctionTemplateInfo: public TemplateInfo {
6303 public:
6304 DECL_ACCESSORS(serial_number, Object)
6305 DECL_ACCESSORS(call_code, Object)
6306 DECL_ACCESSORS(property_accessors, Object)
6307 DECL_ACCESSORS(prototype_template, Object)
6308 DECL_ACCESSORS(parent_template, Object)
6309 DECL_ACCESSORS(named_property_handler, Object)
6310 DECL_ACCESSORS(indexed_property_handler, Object)
6311 DECL_ACCESSORS(instance_template, Object)
6312 DECL_ACCESSORS(class_name, Object)
6313 DECL_ACCESSORS(signature, Object)
6314 DECL_ACCESSORS(instance_call_handler, Object)
6315 DECL_ACCESSORS(access_check_info, Object)
6316 DECL_ACCESSORS(flag, Smi)
6317
6318 // Following properties use flag bits.
6319 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
6320 DECL_BOOLEAN_ACCESSORS(undetectable)
6321 // If the bit is set, object instances created by this function
6322 // requires access check.
6323 DECL_BOOLEAN_ACCESSORS(needs_access_check)
6324
6325 static inline FunctionTemplateInfo* cast(Object* obj);
6326
Ben Murdochb0fe1622011-05-05 13:52:32 +01006327#ifdef OBJECT_PRINT
6328 inline void FunctionTemplateInfoPrint() {
6329 FunctionTemplateInfoPrint(stdout);
6330 }
6331 void FunctionTemplateInfoPrint(FILE* out);
6332#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006333#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006334 void FunctionTemplateInfoVerify();
6335#endif
6336
6337 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
6338 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
6339 static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
6340 static const int kPrototypeTemplateOffset =
6341 kPropertyAccessorsOffset + kPointerSize;
6342 static const int kParentTemplateOffset =
6343 kPrototypeTemplateOffset + kPointerSize;
6344 static const int kNamedPropertyHandlerOffset =
6345 kParentTemplateOffset + kPointerSize;
6346 static const int kIndexedPropertyHandlerOffset =
6347 kNamedPropertyHandlerOffset + kPointerSize;
6348 static const int kInstanceTemplateOffset =
6349 kIndexedPropertyHandlerOffset + kPointerSize;
6350 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
6351 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
6352 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
6353 static const int kAccessCheckInfoOffset =
6354 kInstanceCallHandlerOffset + kPointerSize;
6355 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
6356 static const int kSize = kFlagOffset + kPointerSize;
6357
6358 private:
6359 // Bit position in the flag, from least significant bit position.
6360 static const int kHiddenPrototypeBit = 0;
6361 static const int kUndetectableBit = 1;
6362 static const int kNeedsAccessCheckBit = 2;
6363
6364 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
6365};
6366
6367
6368class ObjectTemplateInfo: public TemplateInfo {
6369 public:
6370 DECL_ACCESSORS(constructor, Object)
6371 DECL_ACCESSORS(internal_field_count, Object)
6372
6373 static inline ObjectTemplateInfo* cast(Object* obj);
6374
Ben Murdochb0fe1622011-05-05 13:52:32 +01006375#ifdef OBJECT_PRINT
6376 inline void ObjectTemplateInfoPrint() {
6377 ObjectTemplateInfoPrint(stdout);
6378 }
6379 void ObjectTemplateInfoPrint(FILE* out);
6380#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006381#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006382 void ObjectTemplateInfoVerify();
6383#endif
6384
6385 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
6386 static const int kInternalFieldCountOffset =
6387 kConstructorOffset + kPointerSize;
6388 static const int kSize = kInternalFieldCountOffset + kPointerSize;
6389};
6390
6391
6392class SignatureInfo: public Struct {
6393 public:
6394 DECL_ACCESSORS(receiver, Object)
6395 DECL_ACCESSORS(args, Object)
6396
6397 static inline SignatureInfo* cast(Object* obj);
6398
Ben Murdochb0fe1622011-05-05 13:52:32 +01006399#ifdef OBJECT_PRINT
6400 inline void SignatureInfoPrint() {
6401 SignatureInfoPrint(stdout);
6402 }
6403 void SignatureInfoPrint(FILE* out);
6404#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006405#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006406 void SignatureInfoVerify();
6407#endif
6408
6409 static const int kReceiverOffset = Struct::kHeaderSize;
6410 static const int kArgsOffset = kReceiverOffset + kPointerSize;
6411 static const int kSize = kArgsOffset + kPointerSize;
6412
6413 private:
6414 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
6415};
6416
6417
6418class TypeSwitchInfo: public Struct {
6419 public:
6420 DECL_ACCESSORS(types, Object)
6421
6422 static inline TypeSwitchInfo* cast(Object* obj);
6423
Ben Murdochb0fe1622011-05-05 13:52:32 +01006424#ifdef OBJECT_PRINT
6425 inline void TypeSwitchInfoPrint() {
6426 TypeSwitchInfoPrint(stdout);
6427 }
6428 void TypeSwitchInfoPrint(FILE* out);
6429#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006430#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006431 void TypeSwitchInfoVerify();
6432#endif
6433
6434 static const int kTypesOffset = Struct::kHeaderSize;
6435 static const int kSize = kTypesOffset + kPointerSize;
6436};
6437
6438
6439#ifdef ENABLE_DEBUGGER_SUPPORT
6440// The DebugInfo class holds additional information for a function being
6441// debugged.
6442class DebugInfo: public Struct {
6443 public:
6444 // The shared function info for the source being debugged.
6445 DECL_ACCESSORS(shared, SharedFunctionInfo)
6446 // Code object for the original code.
6447 DECL_ACCESSORS(original_code, Code)
6448 // Code object for the patched code. This code object is the code object
6449 // currently active for the function.
6450 DECL_ACCESSORS(code, Code)
6451 // Fixed array holding status information for each active break point.
6452 DECL_ACCESSORS(break_points, FixedArray)
6453
6454 // Check if there is a break point at a code position.
6455 bool HasBreakPoint(int code_position);
6456 // Get the break point info object for a code position.
6457 Object* GetBreakPointInfo(int code_position);
6458 // Clear a break point.
6459 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
6460 int code_position,
6461 Handle<Object> break_point_object);
6462 // Set a break point.
6463 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
6464 int source_position, int statement_position,
6465 Handle<Object> break_point_object);
6466 // Get the break point objects for a code position.
6467 Object* GetBreakPointObjects(int code_position);
6468 // Find the break point info holding this break point object.
6469 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
6470 Handle<Object> break_point_object);
6471 // Get the number of break points for this function.
6472 int GetBreakPointCount();
6473
6474 static inline DebugInfo* cast(Object* obj);
6475
Ben Murdochb0fe1622011-05-05 13:52:32 +01006476#ifdef OBJECT_PRINT
6477 inline void DebugInfoPrint() {
6478 DebugInfoPrint(stdout);
6479 }
6480 void DebugInfoPrint(FILE* out);
6481#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006482#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006483 void DebugInfoVerify();
6484#endif
6485
6486 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
6487 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
6488 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
6489 static const int kActiveBreakPointsCountIndex =
6490 kPatchedCodeIndex + kPointerSize;
6491 static const int kBreakPointsStateIndex =
6492 kActiveBreakPointsCountIndex + kPointerSize;
6493 static const int kSize = kBreakPointsStateIndex + kPointerSize;
6494
6495 private:
6496 static const int kNoBreakPointInfo = -1;
6497
6498 // Lookup the index in the break_points array for a code position.
6499 int GetBreakPointInfoIndex(int code_position);
6500
6501 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
6502};
6503
6504
6505// The BreakPointInfo class holds information for break points set in a
6506// function. The DebugInfo object holds a BreakPointInfo object for each code
6507// position with one or more break points.
6508class BreakPointInfo: public Struct {
6509 public:
6510 // The position in the code for the break point.
6511 DECL_ACCESSORS(code_position, Smi)
6512 // The position in the source for the break position.
6513 DECL_ACCESSORS(source_position, Smi)
6514 // The position in the source for the last statement before this break
6515 // position.
6516 DECL_ACCESSORS(statement_position, Smi)
6517 // List of related JavaScript break points.
6518 DECL_ACCESSORS(break_point_objects, Object)
6519
6520 // Removes a break point.
6521 static void ClearBreakPoint(Handle<BreakPointInfo> info,
6522 Handle<Object> break_point_object);
6523 // Set a break point.
6524 static void SetBreakPoint(Handle<BreakPointInfo> info,
6525 Handle<Object> break_point_object);
6526 // Check if break point info has this break point object.
6527 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
6528 Handle<Object> break_point_object);
6529 // Get the number of break points for this code position.
6530 int GetBreakPointCount();
6531
6532 static inline BreakPointInfo* cast(Object* obj);
6533
Ben Murdochb0fe1622011-05-05 13:52:32 +01006534#ifdef OBJECT_PRINT
6535 inline void BreakPointInfoPrint() {
6536 BreakPointInfoPrint(stdout);
6537 }
6538 void BreakPointInfoPrint(FILE* out);
6539#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006540#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006541 void BreakPointInfoVerify();
6542#endif
6543
6544 static const int kCodePositionIndex = Struct::kHeaderSize;
6545 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
6546 static const int kStatementPositionIndex =
6547 kSourcePositionIndex + kPointerSize;
6548 static const int kBreakPointObjectsIndex =
6549 kStatementPositionIndex + kPointerSize;
6550 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
6551
6552 private:
6553 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
6554};
6555#endif // ENABLE_DEBUGGER_SUPPORT
6556
6557
6558#undef DECL_BOOLEAN_ACCESSORS
6559#undef DECL_ACCESSORS
6560
6561
6562// Abstract base class for visiting, and optionally modifying, the
6563// pointers contained in Objects. Used in GC and serialization/deserialization.
6564class ObjectVisitor BASE_EMBEDDED {
6565 public:
6566 virtual ~ObjectVisitor() {}
6567
6568 // Visits a contiguous arrays of pointers in the half-open range
6569 // [start, end). Any or all of the values may be modified on return.
6570 virtual void VisitPointers(Object** start, Object** end) = 0;
6571
6572 // To allow lazy clearing of inline caches the visitor has
6573 // a rich interface for iterating over Code objects..
6574
6575 // Visits a code target in the instruction stream.
6576 virtual void VisitCodeTarget(RelocInfo* rinfo);
6577
Steve Block791712a2010-08-27 10:21:07 +01006578 // Visits a code entry in a JS function.
6579 virtual void VisitCodeEntry(Address entry_address);
6580
Ben Murdochb0fe1622011-05-05 13:52:32 +01006581 // Visits a global property cell reference in the instruction stream.
6582 virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
6583
Steve Blocka7e24c12009-10-30 11:49:00 +00006584 // Visits a runtime entry in the instruction stream.
6585 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
6586
Steve Blockd0582a62009-12-15 09:54:21 +00006587 // Visits the resource of an ASCII or two-byte string.
6588 virtual void VisitExternalAsciiString(
6589 v8::String::ExternalAsciiStringResource** resource) {}
6590 virtual void VisitExternalTwoByteString(
6591 v8::String::ExternalStringResource** resource) {}
6592
Steve Blocka7e24c12009-10-30 11:49:00 +00006593 // Visits a debug call target in the instruction stream.
6594 virtual void VisitDebugTarget(RelocInfo* rinfo);
6595
6596 // Handy shorthand for visiting a single pointer.
6597 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
6598
6599 // Visits a contiguous arrays of external references (references to the C++
6600 // heap) in the half-open range [start, end). Any or all of the values
6601 // may be modified on return.
6602 virtual void VisitExternalReferences(Address* start, Address* end) {}
6603
6604 inline void VisitExternalReference(Address* p) {
6605 VisitExternalReferences(p, p + 1);
6606 }
6607
Steve Block44f0eee2011-05-26 01:26:41 +01006608 // Visits a handle that has an embedder-assigned class ID.
6609 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
6610
Steve Blocka7e24c12009-10-30 11:49:00 +00006611#ifdef DEBUG
6612 // Intended for serialization/deserialization checking: insert, or
6613 // check for the presence of, a tag at this position in the stream.
6614 virtual void Synchronize(const char* tag) {}
Steve Blockd0582a62009-12-15 09:54:21 +00006615#else
6616 inline void Synchronize(const char* tag) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00006617#endif
6618};
6619
6620
Iain Merrick75681382010-08-19 15:07:18 +01006621class StructBodyDescriptor : public
6622 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
6623 public:
6624 static inline int SizeOf(Map* map, HeapObject* object) {
6625 return map->instance_size();
6626 }
6627};
6628
6629
Steve Blocka7e24c12009-10-30 11:49:00 +00006630// BooleanBit is a helper class for setting and getting a bit in an
6631// integer or Smi.
6632class BooleanBit : public AllStatic {
6633 public:
6634 static inline bool get(Smi* smi, int bit_position) {
6635 return get(smi->value(), bit_position);
6636 }
6637
6638 static inline bool get(int value, int bit_position) {
6639 return (value & (1 << bit_position)) != 0;
6640 }
6641
6642 static inline Smi* set(Smi* smi, int bit_position, bool v) {
6643 return Smi::FromInt(set(smi->value(), bit_position, v));
6644 }
6645
6646 static inline int set(int value, int bit_position, bool v) {
6647 if (v) {
6648 value |= (1 << bit_position);
6649 } else {
6650 value &= ~(1 << bit_position);
6651 }
6652 return value;
6653 }
6654};
6655
6656} } // namespace v8::internal
6657
6658#endif // V8_OBJECTS_H_