blob: d917a5751a61c4364b2a4c413d734eab0744008b [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:
44// - Object
45// - Smi (immediate small integer)
46// - Failure (immediate for marking failed operation)
47// - HeapObject (superclass for everything allocated in the heap)
48// - JSObject
49// - JSArray
50// - JSRegExp
51// - JSFunction
52// - GlobalObject
53// - JSGlobalObject
54// - JSBuiltinsObject
55// - JSGlobalProxy
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010056// - JSValue
57// - ByteArray
58// - PixelArray
59// - ExternalArray
60// - ExternalByteArray
61// - ExternalUnsignedByteArray
62// - ExternalShortArray
63// - ExternalUnsignedShortArray
64// - ExternalIntArray
65// - ExternalUnsignedIntArray
66// - ExternalFloatArray
67// - FixedArray
68// - DescriptorArray
69// - HashTable
70// - Dictionary
71// - SymbolTable
72// - CompilationCacheTable
73// - CodeCacheHashTable
74// - MapCache
75// - Context
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010076// - JSFunctionResultCache
Kristian Monsen50ef84f2010-07-29 15:18:00 +010077// - SerializedScopeInfo
Steve Blocka7e24c12009-10-30 11:49:00 +000078// - String
79// - SeqString
80// - SeqAsciiString
81// - SeqTwoByteString
82// - ConsString
Steve Blocka7e24c12009-10-30 11:49:00 +000083// - ExternalString
84// - ExternalAsciiString
85// - ExternalTwoByteString
86// - HeapNumber
87// - Code
88// - Map
89// - Oddball
90// - Proxy
91// - SharedFunctionInfo
92// - Struct
93// - AccessorInfo
94// - AccessCheckInfo
95// - InterceptorInfo
96// - CallHandlerInfo
97// - TemplateInfo
98// - FunctionTemplateInfo
99// - ObjectTemplateInfo
100// - Script
101// - SignatureInfo
102// - TypeSwitchInfo
103// - DebugInfo
104// - BreakPointInfo
Steve Block6ded16b2010-05-10 14:33:55 +0100105// - CodeCache
Steve Blocka7e24c12009-10-30 11:49:00 +0000106//
107// Formats of Object*:
108// Smi: [31 bit signed int] 0
109// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
110// Failure: [30 bit signed int] 11
111
112// Ecma-262 3rd 8.6.1
113enum PropertyAttributes {
114 NONE = v8::None,
115 READ_ONLY = v8::ReadOnly,
116 DONT_ENUM = v8::DontEnum,
117 DONT_DELETE = v8::DontDelete,
118 ABSENT = 16 // Used in runtime to indicate a property is absent.
119 // ABSENT can never be stored in or returned from a descriptor's attributes
120 // bitfield. It is only used as a return value meaning the attributes of
121 // a non-existent property.
122};
123
124namespace v8 {
125namespace internal {
126
127
128// PropertyDetails captures type and attributes for a property.
129// They are used both in property dictionaries and instance descriptors.
130class PropertyDetails BASE_EMBEDDED {
131 public:
132
133 PropertyDetails(PropertyAttributes attributes,
134 PropertyType type,
135 int index = 0) {
136 ASSERT(TypeField::is_valid(type));
137 ASSERT(AttributesField::is_valid(attributes));
138 ASSERT(IndexField::is_valid(index));
139
140 value_ = TypeField::encode(type)
141 | AttributesField::encode(attributes)
142 | IndexField::encode(index);
143
144 ASSERT(type == this->type());
145 ASSERT(attributes == this->attributes());
146 ASSERT(index == this->index());
147 }
148
149 // Conversion for storing details as Object*.
150 inline PropertyDetails(Smi* smi);
151 inline Smi* AsSmi();
152
153 PropertyType type() { return TypeField::decode(value_); }
154
155 bool IsTransition() {
156 PropertyType t = type();
157 ASSERT(t != INTERCEPTOR);
158 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
159 }
160
161 bool IsProperty() {
162 return type() < FIRST_PHANTOM_PROPERTY_TYPE;
163 }
164
165 PropertyAttributes attributes() { return AttributesField::decode(value_); }
166
167 int index() { return IndexField::decode(value_); }
168
169 inline PropertyDetails AsDeleted();
170
171 static bool IsValidIndex(int index) { return IndexField::is_valid(index); }
172
173 bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
174 bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; }
175 bool IsDontEnum() { return (attributes() & DONT_ENUM) != 0; }
176 bool IsDeleted() { return DeletedField::decode(value_) != 0;}
177
178 // Bit fields in value_ (type, shift, size). Must be public so the
179 // constants can be embedded in generated code.
180 class TypeField: public BitField<PropertyType, 0, 3> {};
181 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
182 class DeletedField: public BitField<uint32_t, 6, 1> {};
Andrei Popescu402d9372010-02-26 13:31:12 +0000183 class IndexField: public BitField<uint32_t, 7, 32-7> {};
Steve Blocka7e24c12009-10-30 11:49:00 +0000184
185 static const int kInitialIndex = 1;
186 private:
187 uint32_t value_;
188};
189
190
191// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
192enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
193
194
195// PropertyNormalizationMode is used to specify whether to keep
196// inobject properties when normalizing properties of a JSObject.
197enum PropertyNormalizationMode {
198 CLEAR_INOBJECT_PROPERTIES,
199 KEEP_INOBJECT_PROPERTIES
200};
201
202
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100203// NormalizedMapSharingMode is used to specify whether a map may be shared
204// by different objects with normalized properties.
205enum NormalizedMapSharingMode {
206 UNIQUE_NORMALIZED_MAP,
207 SHARED_NORMALIZED_MAP
208};
209
210
Steve Block791712a2010-08-27 10:21:07 +0100211// Instance size sentinel for objects of variable size.
212static const int kVariableSizeSentinel = 0;
213
214
Steve Blocka7e24c12009-10-30 11:49:00 +0000215// All Maps have a field instance_type containing a InstanceType.
216// It describes the type of the instances.
217//
218// As an example, a JavaScript object is a heap object and its map
219// instance_type is JS_OBJECT_TYPE.
220//
221// The names of the string instance types are intended to systematically
Leon Clarkee46be812010-01-19 14:06:41 +0000222// mirror their encoding in the instance_type field of the map. The default
223// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
224// encoding is mentioned explicitly in the name. Likewise, the default
225// representation is considered sequential. It is not mentioned in the
226// name. The other representations (eg, CONS, EXTERNAL) are explicitly
227// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
228// symbol) or a STRING_TYPE (if it is not a symbol).
Steve Blocka7e24c12009-10-30 11:49:00 +0000229//
230// NOTE: The following things are some that depend on the string types having
231// instance_types that are less than those of all other types:
232// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
233// Object::IsString.
234//
235// NOTE: Everything following JS_VALUE_TYPE is considered a
236// JSObject for GC purposes. The first four entries here have typeof
237// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
Steve Blockd0582a62009-12-15 09:54:21 +0000238#define INSTANCE_TYPE_LIST_ALL(V) \
239 V(SYMBOL_TYPE) \
240 V(ASCII_SYMBOL_TYPE) \
241 V(CONS_SYMBOL_TYPE) \
242 V(CONS_ASCII_SYMBOL_TYPE) \
243 V(EXTERNAL_SYMBOL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100244 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000245 V(EXTERNAL_ASCII_SYMBOL_TYPE) \
246 V(STRING_TYPE) \
247 V(ASCII_STRING_TYPE) \
248 V(CONS_STRING_TYPE) \
249 V(CONS_ASCII_STRING_TYPE) \
250 V(EXTERNAL_STRING_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100251 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000252 V(EXTERNAL_ASCII_STRING_TYPE) \
253 V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
254 \
255 V(MAP_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000256 V(CODE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000257 V(ODDBALL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100258 V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
Leon Clarkee46be812010-01-19 14:06:41 +0000259 \
260 V(HEAP_NUMBER_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000261 V(PROXY_TYPE) \
262 V(BYTE_ARRAY_TYPE) \
263 V(PIXEL_ARRAY_TYPE) \
264 /* Note: the order of these external array */ \
265 /* types is relied upon in */ \
266 /* Object::IsExternalArray(). */ \
267 V(EXTERNAL_BYTE_ARRAY_TYPE) \
268 V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
269 V(EXTERNAL_SHORT_ARRAY_TYPE) \
270 V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
271 V(EXTERNAL_INT_ARRAY_TYPE) \
272 V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
273 V(EXTERNAL_FLOAT_ARRAY_TYPE) \
274 V(FILLER_TYPE) \
275 \
276 V(ACCESSOR_INFO_TYPE) \
277 V(ACCESS_CHECK_INFO_TYPE) \
278 V(INTERCEPTOR_INFO_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000279 V(CALL_HANDLER_INFO_TYPE) \
280 V(FUNCTION_TEMPLATE_INFO_TYPE) \
281 V(OBJECT_TEMPLATE_INFO_TYPE) \
282 V(SIGNATURE_INFO_TYPE) \
283 V(TYPE_SWITCH_INFO_TYPE) \
284 V(SCRIPT_TYPE) \
Steve Block6ded16b2010-05-10 14:33:55 +0100285 V(CODE_CACHE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000286 \
Iain Merrick75681382010-08-19 15:07:18 +0100287 V(FIXED_ARRAY_TYPE) \
288 V(SHARED_FUNCTION_INFO_TYPE) \
289 \
Steve Blockd0582a62009-12-15 09:54:21 +0000290 V(JS_VALUE_TYPE) \
291 V(JS_OBJECT_TYPE) \
292 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
293 V(JS_GLOBAL_OBJECT_TYPE) \
294 V(JS_BUILTINS_OBJECT_TYPE) \
295 V(JS_GLOBAL_PROXY_TYPE) \
296 V(JS_ARRAY_TYPE) \
297 V(JS_REGEXP_TYPE) \
298 \
299 V(JS_FUNCTION_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000300
301#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000302#define INSTANCE_TYPE_LIST_DEBUGGER(V) \
303 V(DEBUG_INFO_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000304 V(BREAK_POINT_INFO_TYPE)
305#else
306#define INSTANCE_TYPE_LIST_DEBUGGER(V)
307#endif
308
Steve Blockd0582a62009-12-15 09:54:21 +0000309#define INSTANCE_TYPE_LIST(V) \
310 INSTANCE_TYPE_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 INSTANCE_TYPE_LIST_DEBUGGER(V)
312
313
314// Since string types are not consecutive, this macro is used to
315// iterate over them.
316#define STRING_TYPE_LIST(V) \
Steve Blockd0582a62009-12-15 09:54:21 +0000317 V(SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100318 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000319 symbol, \
320 Symbol) \
321 V(ASCII_SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100322 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000323 ascii_symbol, \
324 AsciiSymbol) \
325 V(CONS_SYMBOL_TYPE, \
326 ConsString::kSize, \
327 cons_symbol, \
328 ConsSymbol) \
329 V(CONS_ASCII_SYMBOL_TYPE, \
330 ConsString::kSize, \
331 cons_ascii_symbol, \
332 ConsAsciiSymbol) \
333 V(EXTERNAL_SYMBOL_TYPE, \
334 ExternalTwoByteString::kSize, \
335 external_symbol, \
336 ExternalSymbol) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100337 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
338 ExternalTwoByteString::kSize, \
339 external_symbol_with_ascii_data, \
340 ExternalSymbolWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000341 V(EXTERNAL_ASCII_SYMBOL_TYPE, \
342 ExternalAsciiString::kSize, \
343 external_ascii_symbol, \
344 ExternalAsciiSymbol) \
345 V(STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100346 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000347 string, \
348 String) \
349 V(ASCII_STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100350 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000351 ascii_string, \
352 AsciiString) \
353 V(CONS_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000355 cons_string, \
356 ConsString) \
357 V(CONS_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000359 cons_ascii_string, \
360 ConsAsciiString) \
361 V(EXTERNAL_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000362 ExternalTwoByteString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000363 external_string, \
364 ExternalString) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100365 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
366 ExternalTwoByteString::kSize, \
367 external_string_with_ascii_data, \
368 ExternalStringWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000369 V(EXTERNAL_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 ExternalAsciiString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000371 external_ascii_string, \
Steve Block791712a2010-08-27 10:21:07 +0100372 ExternalAsciiString)
Steve Blocka7e24c12009-10-30 11:49:00 +0000373
374// A struct is a simple object a set of object-valued fields. Including an
375// object type in this causes the compiler to generate most of the boilerplate
376// code for the class including allocation and garbage collection routines,
377// casts and predicates. All you need to define is the class, methods and
378// object verification routines. Easy, no?
379//
380// Note that for subtle reasons related to the ordering or numerical values of
381// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
382// manually.
Steve Blockd0582a62009-12-15 09:54:21 +0000383#define STRUCT_LIST_ALL(V) \
384 V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
385 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
386 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
387 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
388 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
389 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
390 V(SIGNATURE_INFO, SignatureInfo, signature_info) \
391 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
Steve Block6ded16b2010-05-10 14:33:55 +0100392 V(SCRIPT, Script, script) \
393 V(CODE_CACHE, CodeCache, code_cache)
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
395#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000396#define STRUCT_LIST_DEBUGGER(V) \
397 V(DEBUG_INFO, DebugInfo, debug_info) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
399#else
400#define STRUCT_LIST_DEBUGGER(V)
401#endif
402
Steve Blockd0582a62009-12-15 09:54:21 +0000403#define STRUCT_LIST(V) \
404 STRUCT_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 STRUCT_LIST_DEBUGGER(V)
406
407// We use the full 8 bits of the instance_type field to encode heap object
408// instance types. The high-order bit (bit 7) is set if the object is not a
409// string, and cleared if it is a string.
410const uint32_t kIsNotStringMask = 0x80;
411const uint32_t kStringTag = 0x0;
412const uint32_t kNotStringTag = 0x80;
413
Leon Clarkee46be812010-01-19 14:06:41 +0000414// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
415// There are not enough types that the non-string types (with bit 7 set) can
416// have bit 6 set too.
417const uint32_t kIsSymbolMask = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000418const uint32_t kNotSymbolTag = 0x0;
Leon Clarkee46be812010-01-19 14:06:41 +0000419const uint32_t kSymbolTag = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000420
Steve Blocka7e24c12009-10-30 11:49:00 +0000421// If bit 7 is clear then bit 2 indicates whether the string consists of
422// two-byte characters or one-byte characters.
423const uint32_t kStringEncodingMask = 0x4;
424const uint32_t kTwoByteStringTag = 0x0;
425const uint32_t kAsciiStringTag = 0x4;
426
427// If bit 7 is clear, the low-order 2 bits indicate the representation
428// of the string.
429const uint32_t kStringRepresentationMask = 0x03;
430enum StringRepresentationTag {
431 kSeqStringTag = 0x0,
432 kConsStringTag = 0x1,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100433 kExternalStringTag = 0x2
Steve Blocka7e24c12009-10-30 11:49:00 +0000434};
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100435const uint32_t kIsConsStringMask = 0x1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000436
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100437// If bit 7 is clear, then bit 3 indicates whether this two-byte
438// string actually contains ascii data.
439const uint32_t kAsciiDataHintMask = 0x08;
440const uint32_t kAsciiDataHintTag = 0x08;
441
Steve Blocka7e24c12009-10-30 11:49:00 +0000442
443// A ConsString with an empty string as the right side is a candidate
444// for being shortcut by the garbage collector unless it is a
445// symbol. It's not common to have non-flat symbols, so we do not
446// shortcut them thereby avoiding turning symbols into strings. See
447// heap.cc and mark-compact.cc.
448const uint32_t kShortcutTypeMask =
449 kIsNotStringMask |
450 kIsSymbolMask |
451 kStringRepresentationMask;
452const uint32_t kShortcutTypeTag = kConsStringTag;
453
454
455enum InstanceType {
Leon Clarkee46be812010-01-19 14:06:41 +0000456 // String types.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100457 SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000458 ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100459 CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000460 CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100461 EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
462 EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
463 kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000464 EXTERNAL_ASCII_SYMBOL_TYPE =
465 kAsciiStringTag | kSymbolTag | kExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100466 STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000467 ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100468 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000469 CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100470 EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
471 EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
472 kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000473 EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
474 PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000475
Leon Clarkee46be812010-01-19 14:06:41 +0000476 // Objects allocated in their own spaces (never in new space).
477 MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 CODE_TYPE,
479 ODDBALL_TYPE,
480 JS_GLOBAL_PROPERTY_CELL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000481
482 // "Data", objects that cannot contain non-map-word pointers to heap
483 // objects.
484 HEAP_NUMBER_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 PROXY_TYPE,
486 BYTE_ARRAY_TYPE,
487 PIXEL_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000488 EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
Steve Block3ce2e202009-11-05 08:53:23 +0000489 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
490 EXTERNAL_SHORT_ARRAY_TYPE,
491 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
492 EXTERNAL_INT_ARRAY_TYPE,
493 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000494 EXTERNAL_FLOAT_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
495 FILLER_TYPE, // LAST_DATA_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000496
Leon Clarkee46be812010-01-19 14:06:41 +0000497 // Structs.
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 ACCESSOR_INFO_TYPE,
499 ACCESS_CHECK_INFO_TYPE,
500 INTERCEPTOR_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 CALL_HANDLER_INFO_TYPE,
502 FUNCTION_TEMPLATE_INFO_TYPE,
503 OBJECT_TEMPLATE_INFO_TYPE,
504 SIGNATURE_INFO_TYPE,
505 TYPE_SWITCH_INFO_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000506 SCRIPT_TYPE,
Steve Block6ded16b2010-05-10 14:33:55 +0100507 CODE_CACHE_TYPE,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100508 // The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
509 // is defined. However as include/v8.h contain some of the instance type
510 // constants always having them avoids them getting different numbers
511 // depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
Steve Blocka7e24c12009-10-30 11:49:00 +0000512 DEBUG_INFO_TYPE,
513 BREAK_POINT_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000514
Leon Clarkee46be812010-01-19 14:06:41 +0000515 FIXED_ARRAY_TYPE,
516 SHARED_FUNCTION_INFO_TYPE,
517
518 JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000519 JS_OBJECT_TYPE,
520 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
521 JS_GLOBAL_OBJECT_TYPE,
522 JS_BUILTINS_OBJECT_TYPE,
523 JS_GLOBAL_PROXY_TYPE,
524 JS_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000525 JS_REGEXP_TYPE, // LAST_JS_OBJECT_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000526
527 JS_FUNCTION_TYPE,
528
529 // Pseudo-types
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 FIRST_TYPE = 0x0,
Steve Blocka7e24c12009-10-30 11:49:00 +0000531 LAST_TYPE = JS_FUNCTION_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000532 INVALID_TYPE = FIRST_TYPE - 1,
533 FIRST_NONSTRING_TYPE = MAP_TYPE,
534 // Boundaries for testing for an external array.
535 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
536 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_FLOAT_ARRAY_TYPE,
537 // Boundary for promotion to old data space/old pointer space.
538 LAST_DATA_TYPE = FILLER_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 // Boundaries for testing the type is a JavaScript "object". Note that
540 // function objects are not counted as objects, even though they are
541 // implemented as such; only values whose typeof is "object" are included.
542 FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
543 LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE
544};
545
546
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100547STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
548STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
549STATIC_CHECK(PROXY_TYPE == Internals::kProxyType);
550
551
Steve Blocka7e24c12009-10-30 11:49:00 +0000552enum CompareResult {
553 LESS = -1,
554 EQUAL = 0,
555 GREATER = 1,
556
557 NOT_EQUAL = GREATER
558};
559
560
561#define DECL_BOOLEAN_ACCESSORS(name) \
562 inline bool name(); \
563 inline void set_##name(bool value); \
564
565
566#define DECL_ACCESSORS(name, type) \
567 inline type* name(); \
568 inline void set_##name(type* value, \
569 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
570
571
572class StringStream;
573class ObjectVisitor;
574
575struct ValueInfo : public Malloced {
576 ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
577 InstanceType type;
578 Object* ptr;
579 const char* str;
580 double number;
581};
582
583
584// A template-ized version of the IsXXX functions.
585template <class C> static inline bool Is(Object* obj);
586
587
588// Object is the abstract superclass for all classes in the
589// object hierarchy.
590// Object does not use any virtual functions to avoid the
591// allocation of the C++ vtable.
592// Since Smi and Failure are subclasses of Object no
593// data members can be present in Object.
594class Object BASE_EMBEDDED {
595 public:
596 // Type testing.
597 inline bool IsSmi();
598 inline bool IsHeapObject();
599 inline bool IsHeapNumber();
600 inline bool IsString();
601 inline bool IsSymbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000602 // See objects-inl.h for more details
603 inline bool IsSeqString();
Steve Blocka7e24c12009-10-30 11:49:00 +0000604 inline bool IsExternalString();
605 inline bool IsExternalTwoByteString();
606 inline bool IsExternalAsciiString();
607 inline bool IsSeqTwoByteString();
608 inline bool IsSeqAsciiString();
Steve Blocka7e24c12009-10-30 11:49:00 +0000609 inline bool IsConsString();
610
611 inline bool IsNumber();
612 inline bool IsByteArray();
613 inline bool IsPixelArray();
Steve Block3ce2e202009-11-05 08:53:23 +0000614 inline bool IsExternalArray();
615 inline bool IsExternalByteArray();
616 inline bool IsExternalUnsignedByteArray();
617 inline bool IsExternalShortArray();
618 inline bool IsExternalUnsignedShortArray();
619 inline bool IsExternalIntArray();
620 inline bool IsExternalUnsignedIntArray();
621 inline bool IsExternalFloatArray();
Steve Blocka7e24c12009-10-30 11:49:00 +0000622 inline bool IsFailure();
623 inline bool IsRetryAfterGC();
624 inline bool IsOutOfMemoryFailure();
625 inline bool IsException();
626 inline bool IsJSObject();
627 inline bool IsJSContextExtensionObject();
628 inline bool IsMap();
629 inline bool IsFixedArray();
630 inline bool IsDescriptorArray();
631 inline bool IsContext();
632 inline bool IsCatchContext();
633 inline bool IsGlobalContext();
634 inline bool IsJSFunction();
635 inline bool IsCode();
636 inline bool IsOddball();
637 inline bool IsSharedFunctionInfo();
638 inline bool IsJSValue();
639 inline bool IsStringWrapper();
640 inline bool IsProxy();
641 inline bool IsBoolean();
642 inline bool IsJSArray();
643 inline bool IsJSRegExp();
644 inline bool IsHashTable();
645 inline bool IsDictionary();
646 inline bool IsSymbolTable();
Steve Block6ded16b2010-05-10 14:33:55 +0100647 inline bool IsJSFunctionResultCache();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100648 inline bool IsNormalizedMapCache();
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 inline bool IsCompilationCacheTable();
Steve Block6ded16b2010-05-10 14:33:55 +0100650 inline bool IsCodeCacheHashTable();
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 inline bool IsMapCache();
652 inline bool IsPrimitive();
653 inline bool IsGlobalObject();
654 inline bool IsJSGlobalObject();
655 inline bool IsJSBuiltinsObject();
656 inline bool IsJSGlobalProxy();
657 inline bool IsUndetectableObject();
658 inline bool IsAccessCheckNeeded();
659 inline bool IsJSGlobalPropertyCell();
660
661 // Returns true if this object is an instance of the specified
662 // function template.
663 inline bool IsInstanceOf(FunctionTemplateInfo* type);
664
665 inline bool IsStruct();
666#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
667 STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
668#undef DECLARE_STRUCT_PREDICATE
669
670 // Oddball testing.
671 INLINE(bool IsUndefined());
672 INLINE(bool IsTheHole());
673 INLINE(bool IsNull());
674 INLINE(bool IsTrue());
675 INLINE(bool IsFalse());
676
677 // Extract the number.
678 inline double Number();
679
680 inline bool HasSpecificClassOf(String* name);
681
682 Object* ToObject(); // ECMA-262 9.9.
683 Object* ToBoolean(); // ECMA-262 9.2.
684
685 // Convert to a JSObject if needed.
686 // global_context is used when creating wrapper object.
687 Object* ToObject(Context* global_context);
688
689 // Converts this to a Smi if possible.
690 // Failure is returned otherwise.
691 inline Object* ToSmi();
692
693 void Lookup(String* name, LookupResult* result);
694
695 // Property access.
696 inline Object* GetProperty(String* key);
697 inline Object* GetProperty(String* key, PropertyAttributes* attributes);
698 Object* GetPropertyWithReceiver(Object* receiver,
699 String* key,
700 PropertyAttributes* attributes);
701 Object* GetProperty(Object* receiver,
702 LookupResult* result,
703 String* key,
704 PropertyAttributes* attributes);
705 Object* GetPropertyWithCallback(Object* receiver,
706 Object* structure,
707 String* name,
708 Object* holder);
709 Object* GetPropertyWithDefinedGetter(Object* receiver,
710 JSFunction* getter);
711
712 inline Object* GetElement(uint32_t index);
713 Object* GetElementWithReceiver(Object* receiver, uint32_t index);
714
715 // Return the object's prototype (might be Heap::null_value()).
716 Object* GetPrototype();
717
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100718 // Tries to convert an object to an array index. Returns true and sets
719 // the output parameter if it succeeds.
720 inline bool ToArrayIndex(uint32_t* index);
721
Steve Blocka7e24c12009-10-30 11:49:00 +0000722 // Returns true if this is a JSValue containing a string and the index is
723 // < the length of the string. Used to implement [] on strings.
724 inline bool IsStringObjectWithCharacterAt(uint32_t index);
725
726#ifdef DEBUG
727 // Prints this object with details.
728 void Print();
729 void PrintLn();
730 // Verifies the object.
731 void Verify();
732
733 // Verify a pointer is a valid object pointer.
734 static void VerifyPointer(Object* p);
735#endif
736
737 // Prints this object without details.
738 void ShortPrint();
739
740 // Prints this object without details to a message accumulator.
741 void ShortPrint(StringStream* accumulator);
742
743 // Casting: This cast is only needed to satisfy macros in objects-inl.h.
744 static Object* cast(Object* value) { return value; }
745
746 // Layout description.
747 static const int kHeaderSize = 0; // Object does not take up any space.
748
749 private:
750 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
751};
752
753
754// Smi represents integer Numbers that can be stored in 31 bits.
755// Smis are immediate which means they are NOT allocated in the heap.
Steve Blocka7e24c12009-10-30 11:49:00 +0000756// The this pointer has the following format: [31 bit signed int] 0
Steve Block3ce2e202009-11-05 08:53:23 +0000757// For long smis it has the following format:
758// [32 bit signed int] [31 bits zero padding] 0
759// Smi stands for small integer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000760class Smi: public Object {
761 public:
762 // Returns the integer value.
763 inline int value();
764
765 // Convert a value to a Smi object.
766 static inline Smi* FromInt(int value);
767
768 static inline Smi* FromIntptr(intptr_t value);
769
770 // Returns whether value can be represented in a Smi.
771 static inline bool IsValid(intptr_t value);
772
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 // Casting.
774 static inline Smi* cast(Object* object);
775
776 // Dispatched behavior.
777 void SmiPrint();
778 void SmiPrint(StringStream* accumulator);
779#ifdef DEBUG
780 void SmiVerify();
781#endif
782
Steve Block3ce2e202009-11-05 08:53:23 +0000783 static const int kMinValue = (-1 << (kSmiValueSize - 1));
784 static const int kMaxValue = -(kMinValue + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000785
786 private:
787 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
788};
789
790
791// Failure is used for reporting out of memory situations and
792// propagating exceptions through the runtime system. Failure objects
793// are transient and cannot occur as part of the object graph.
794//
795// Failures are a single word, encoded as follows:
796// +-------------------------+---+--+--+
Ben Murdochf87a2032010-10-22 12:50:53 +0100797// |.........unused..........|sss|tt|11|
Steve Blocka7e24c12009-10-30 11:49:00 +0000798// +-------------------------+---+--+--+
Steve Block3ce2e202009-11-05 08:53:23 +0000799// 7 6 4 32 10
800//
Steve Blocka7e24c12009-10-30 11:49:00 +0000801//
802// The low two bits, 0-1, are the failure tag, 11. The next two bits,
803// 2-3, are a failure type tag 'tt' with possible values:
804// 00 RETRY_AFTER_GC
805// 01 EXCEPTION
806// 10 INTERNAL_ERROR
807// 11 OUT_OF_MEMORY_EXCEPTION
808//
809// The next three bits, 4-6, are an allocation space tag 'sss'. The
810// allocation space tag is 000 for all failure types except
811// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
812// allocation spaces (the encoding is found in globals.h).
Steve Blocka7e24c12009-10-30 11:49:00 +0000813
814// Failure type tag info.
815const int kFailureTypeTagSize = 2;
816const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
817
818class Failure: public Object {
819 public:
820 // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
821 enum Type {
822 RETRY_AFTER_GC = 0,
823 EXCEPTION = 1, // Returning this marker tells the real exception
824 // is in Top::pending_exception.
825 INTERNAL_ERROR = 2,
826 OUT_OF_MEMORY_EXCEPTION = 3
827 };
828
829 inline Type type() const;
830
831 // Returns the space that needs to be collected for RetryAfterGC failures.
832 inline AllocationSpace allocation_space() const;
833
Steve Blocka7e24c12009-10-30 11:49:00 +0000834 inline bool IsInternalError() const;
835 inline bool IsOutOfMemoryException() const;
836
Ben Murdochf87a2032010-10-22 12:50:53 +0100837 static inline Failure* RetryAfterGC(AllocationSpace space);
838 static inline Failure* RetryAfterGC(); // NEW_SPACE
Steve Blocka7e24c12009-10-30 11:49:00 +0000839 static inline Failure* Exception();
840 static inline Failure* InternalError();
841 static inline Failure* OutOfMemoryException();
842 // Casting.
843 static inline Failure* cast(Object* object);
844
845 // Dispatched behavior.
846 void FailurePrint();
847 void FailurePrint(StringStream* accumulator);
848#ifdef DEBUG
849 void FailureVerify();
850#endif
851
852 private:
Steve Block3ce2e202009-11-05 08:53:23 +0000853 inline intptr_t value() const;
854 static inline Failure* Construct(Type type, intptr_t value = 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000855
856 DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
857};
858
859
860// Heap objects typically have a map pointer in their first word. However,
861// during GC other data (eg, mark bits, forwarding addresses) is sometimes
862// encoded in the first word. The class MapWord is an abstraction of the
863// value in a heap object's first word.
864class MapWord BASE_EMBEDDED {
865 public:
866 // Normal state: the map word contains a map pointer.
867
868 // Create a map word from a map pointer.
869 static inline MapWord FromMap(Map* map);
870
871 // View this map word as a map pointer.
872 inline Map* ToMap();
873
874
875 // Scavenge collection: the map word of live objects in the from space
876 // contains a forwarding address (a heap object pointer in the to space).
877
878 // True if this map word is a forwarding address for a scavenge
879 // collection. Only valid during a scavenge collection (specifically,
880 // when all map words are heap object pointers, ie. not during a full GC).
881 inline bool IsForwardingAddress();
882
883 // Create a map word from a forwarding address.
884 static inline MapWord FromForwardingAddress(HeapObject* object);
885
886 // View this map word as a forwarding address.
887 inline HeapObject* ToForwardingAddress();
888
Steve Blocka7e24c12009-10-30 11:49:00 +0000889 // Marking phase of full collection: the map word of live objects is
890 // marked, and may be marked as overflowed (eg, the object is live, its
891 // children have not been visited, and it does not fit in the marking
892 // stack).
893
894 // True if this map word's mark bit is set.
895 inline bool IsMarked();
896
897 // Return this map word but with its mark bit set.
898 inline void SetMark();
899
900 // Return this map word but with its mark bit cleared.
901 inline void ClearMark();
902
903 // True if this map word's overflow bit is set.
904 inline bool IsOverflowed();
905
906 // Return this map word but with its overflow bit set.
907 inline void SetOverflow();
908
909 // Return this map word but with its overflow bit cleared.
910 inline void ClearOverflow();
911
912
913 // Compacting phase of a full compacting collection: the map word of live
914 // objects contains an encoding of the original map address along with the
915 // forwarding address (represented as an offset from the first live object
916 // in the same page as the (old) object address).
917
918 // Create a map word from a map address and a forwarding address offset.
919 static inline MapWord EncodeAddress(Address map_address, int offset);
920
921 // Return the map address encoded in this map word.
922 inline Address DecodeMapAddress(MapSpace* map_space);
923
924 // Return the forwarding offset encoded in this map word.
925 inline int DecodeOffset();
926
927
928 // During serialization: the map word is used to hold an encoded
929 // address, and possibly a mark bit (set and cleared with SetMark
930 // and ClearMark).
931
932 // Create a map word from an encoded address.
933 static inline MapWord FromEncodedAddress(Address address);
934
935 inline Address ToEncodedAddress();
936
937 // Bits used by the marking phase of the garbage collector.
938 //
939 // The first word of a heap object is normally a map pointer. The last two
940 // bits are tagged as '01' (kHeapObjectTag). We reuse the last two bits to
941 // mark an object as live and/or overflowed:
942 // last bit = 0, marked as alive
943 // second bit = 1, overflowed
944 // An object is only marked as overflowed when it is marked as live while
945 // the marking stack is overflowed.
946 static const int kMarkingBit = 0; // marking bit
947 static const int kMarkingMask = (1 << kMarkingBit); // marking mask
948 static const int kOverflowBit = 1; // overflow bit
949 static const int kOverflowMask = (1 << kOverflowBit); // overflow mask
950
Leon Clarkee46be812010-01-19 14:06:41 +0000951 // Forwarding pointers and map pointer encoding. On 32 bit all the bits are
952 // used.
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 // +-----------------+------------------+-----------------+
954 // |forwarding offset|page offset of map|page index of map|
955 // +-----------------+------------------+-----------------+
Leon Clarkee46be812010-01-19 14:06:41 +0000956 // ^ ^ ^
957 // | | |
958 // | | kMapPageIndexBits
959 // | kMapPageOffsetBits
960 // kForwardingOffsetBits
961 static const int kMapPageOffsetBits = kPageSizeBits - kMapAlignmentBits;
962 static const int kForwardingOffsetBits = kPageSizeBits - kObjectAlignmentBits;
963#ifdef V8_HOST_ARCH_64_BIT
964 static const int kMapPageIndexBits = 16;
965#else
966 // Use all the 32-bits to encode on a 32-bit platform.
967 static const int kMapPageIndexBits =
968 32 - (kMapPageOffsetBits + kForwardingOffsetBits);
969#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000970
971 static const int kMapPageIndexShift = 0;
972 static const int kMapPageOffsetShift =
973 kMapPageIndexShift + kMapPageIndexBits;
974 static const int kForwardingOffsetShift =
975 kMapPageOffsetShift + kMapPageOffsetBits;
976
Leon Clarkee46be812010-01-19 14:06:41 +0000977 // Bit masks covering the different parts the encoding.
978 static const uintptr_t kMapPageIndexMask =
Steve Blocka7e24c12009-10-30 11:49:00 +0000979 (1 << kMapPageOffsetShift) - 1;
Leon Clarkee46be812010-01-19 14:06:41 +0000980 static const uintptr_t kMapPageOffsetMask =
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 ((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask;
Leon Clarkee46be812010-01-19 14:06:41 +0000982 static const uintptr_t kForwardingOffsetMask =
Steve Blocka7e24c12009-10-30 11:49:00 +0000983 ~(kMapPageIndexMask | kMapPageOffsetMask);
984
985 private:
986 // HeapObject calls the private constructor and directly reads the value.
987 friend class HeapObject;
988
989 explicit MapWord(uintptr_t value) : value_(value) {}
990
991 uintptr_t value_;
992};
993
994
995// HeapObject is the superclass for all classes describing heap allocated
996// objects.
997class HeapObject: public Object {
998 public:
999 // [map]: Contains a map which contains the object's reflective
1000 // information.
1001 inline Map* map();
1002 inline void set_map(Map* value);
1003
1004 // During garbage collection, the map word of a heap object does not
1005 // necessarily contain a map pointer.
1006 inline MapWord map_word();
1007 inline void set_map_word(MapWord map_word);
1008
1009 // Converts an address to a HeapObject pointer.
1010 static inline HeapObject* FromAddress(Address address);
1011
1012 // Returns the address of this HeapObject.
1013 inline Address address();
1014
1015 // Iterates over pointers contained in the object (including the Map)
1016 void Iterate(ObjectVisitor* v);
1017
1018 // Iterates over all pointers contained in the object except the
1019 // first map pointer. The object type is given in the first
1020 // parameter. This function does not access the map pointer in the
1021 // object, and so is safe to call while the map pointer is modified.
1022 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
1023
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 // Returns the heap object's size in bytes
1025 inline int Size();
1026
1027 // Given a heap object's map pointer, returns the heap size in bytes
1028 // Useful when the map pointer field is used for other purposes.
1029 // GC internal.
1030 inline int SizeFromMap(Map* map);
1031
1032 // Support for the marking heap objects during the marking phase of GC.
1033 // True if the object is marked live.
1034 inline bool IsMarked();
1035
1036 // Mutate this object's map pointer to indicate that the object is live.
1037 inline void SetMark();
1038
1039 // Mutate this object's map pointer to remove the indication that the
1040 // object is live (ie, partially restore the map pointer).
1041 inline void ClearMark();
1042
1043 // True if this object is marked as overflowed. Overflowed objects have
1044 // been reached and marked during marking of the heap, but their children
1045 // have not necessarily been marked and they have not been pushed on the
1046 // marking stack.
1047 inline bool IsOverflowed();
1048
1049 // Mutate this object's map pointer to indicate that the object is
1050 // overflowed.
1051 inline void SetOverflow();
1052
1053 // Mutate this object's map pointer to remove the indication that the
1054 // object is overflowed (ie, partially restore the map pointer).
1055 inline void ClearOverflow();
1056
1057 // Returns the field at offset in obj, as a read/write Object* reference.
1058 // Does no checking, and is safe to use during GC, while maps are invalid.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001059 // Does not invoke write barrier, so should only be assigned to
Steve Blocka7e24c12009-10-30 11:49:00 +00001060 // during marking GC.
1061 static inline Object** RawField(HeapObject* obj, int offset);
1062
1063 // Casting.
1064 static inline HeapObject* cast(Object* obj);
1065
Leon Clarke4515c472010-02-03 11:58:03 +00001066 // Return the write barrier mode for this. Callers of this function
1067 // must be able to present a reference to an AssertNoAllocation
1068 // object as a sign that they are not going to use this function
1069 // from code that allocates and thus invalidates the returned write
1070 // barrier mode.
1071 inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
Steve Blocka7e24c12009-10-30 11:49:00 +00001072
1073 // Dispatched behavior.
1074 void HeapObjectShortPrint(StringStream* accumulator);
1075#ifdef DEBUG
1076 void HeapObjectPrint();
1077 void HeapObjectVerify();
1078 inline void VerifyObjectField(int offset);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001079 inline void VerifySmiField(int offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001080
1081 void PrintHeader(const char* id);
1082
1083 // Verify a pointer is a valid HeapObject pointer that points to object
1084 // areas in the heap.
1085 static void VerifyHeapPointer(Object* p);
1086#endif
1087
1088 // Layout description.
1089 // First field in a heap object is map.
1090 static const int kMapOffset = Object::kHeaderSize;
1091 static const int kHeaderSize = kMapOffset + kPointerSize;
1092
1093 STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
1094
1095 protected:
1096 // helpers for calling an ObjectVisitor to iterate over pointers in the
1097 // half-open range [start, end) specified as integer offsets
1098 inline void IteratePointers(ObjectVisitor* v, int start, int end);
1099 // as above, for the single element at "offset"
1100 inline void IteratePointer(ObjectVisitor* v, int offset);
1101
Steve Blocka7e24c12009-10-30 11:49:00 +00001102 private:
1103 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
1104};
1105
1106
Iain Merrick75681382010-08-19 15:07:18 +01001107#define SLOT_ADDR(obj, offset) \
1108 reinterpret_cast<Object**>((obj)->address() + offset)
1109
1110// This class describes a body of an object of a fixed size
1111// in which all pointer fields are located in the [start_offset, end_offset)
1112// interval.
1113template<int start_offset, int end_offset, int size>
1114class FixedBodyDescriptor {
1115 public:
1116 static const int kStartOffset = start_offset;
1117 static const int kEndOffset = end_offset;
1118 static const int kSize = size;
1119
1120 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
1121
1122 template<typename StaticVisitor>
1123 static inline void IterateBody(HeapObject* obj) {
1124 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1125 SLOT_ADDR(obj, end_offset));
1126 }
1127};
1128
1129
1130// This class describes a body of an object of a variable size
1131// in which all pointer fields are located in the [start_offset, object_size)
1132// interval.
1133template<int start_offset>
1134class FlexibleBodyDescriptor {
1135 public:
1136 static const int kStartOffset = start_offset;
1137
1138 static inline void IterateBody(HeapObject* obj,
1139 int object_size,
1140 ObjectVisitor* v);
1141
1142 template<typename StaticVisitor>
1143 static inline void IterateBody(HeapObject* obj, int object_size) {
1144 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1145 SLOT_ADDR(obj, object_size));
1146 }
1147};
1148
1149#undef SLOT_ADDR
1150
1151
Steve Blocka7e24c12009-10-30 11:49:00 +00001152// The HeapNumber class describes heap allocated numbers that cannot be
1153// represented in a Smi (small integer)
1154class HeapNumber: public HeapObject {
1155 public:
1156 // [value]: number value.
1157 inline double value();
1158 inline void set_value(double value);
1159
1160 // Casting.
1161 static inline HeapNumber* cast(Object* obj);
1162
1163 // Dispatched behavior.
1164 Object* HeapNumberToBoolean();
1165 void HeapNumberPrint();
1166 void HeapNumberPrint(StringStream* accumulator);
1167#ifdef DEBUG
1168 void HeapNumberVerify();
1169#endif
1170
Steve Block6ded16b2010-05-10 14:33:55 +01001171 inline int get_exponent();
1172 inline int get_sign();
1173
Steve Blocka7e24c12009-10-30 11:49:00 +00001174 // Layout description.
1175 static const int kValueOffset = HeapObject::kHeaderSize;
1176 // IEEE doubles are two 32 bit words. The first is just mantissa, the second
1177 // is a mixture of sign, exponent and mantissa. Our current platforms are all
1178 // little endian apart from non-EABI arm which is little endian with big
1179 // endian floating point word ordering!
Steve Block3ce2e202009-11-05 08:53:23 +00001180#if !defined(V8_HOST_ARCH_ARM) || defined(USE_ARM_EABI)
Steve Blocka7e24c12009-10-30 11:49:00 +00001181 static const int kMantissaOffset = kValueOffset;
1182 static const int kExponentOffset = kValueOffset + 4;
1183#else
1184 static const int kMantissaOffset = kValueOffset + 4;
1185 static const int kExponentOffset = kValueOffset;
1186# define BIG_ENDIAN_FLOATING_POINT 1
1187#endif
1188 static const int kSize = kValueOffset + kDoubleSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001189 static const uint32_t kSignMask = 0x80000000u;
1190 static const uint32_t kExponentMask = 0x7ff00000u;
1191 static const uint32_t kMantissaMask = 0xfffffu;
Steve Block6ded16b2010-05-10 14:33:55 +01001192 static const int kMantissaBits = 52;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001193 static const int kExponentBits = 11;
Steve Blocka7e24c12009-10-30 11:49:00 +00001194 static const int kExponentBias = 1023;
1195 static const int kExponentShift = 20;
1196 static const int kMantissaBitsInTopWord = 20;
1197 static const int kNonMantissaBitsInTopWord = 12;
1198
1199 private:
1200 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1201};
1202
1203
1204// The JSObject describes real heap allocated JavaScript objects with
1205// properties.
1206// Note that the map of JSObject changes during execution to enable inline
1207// caching.
1208class JSObject: public HeapObject {
1209 public:
1210 enum DeleteMode { NORMAL_DELETION, FORCE_DELETION };
1211 enum ElementsKind {
Iain Merrick75681382010-08-19 15:07:18 +01001212 // The only "fast" kind.
Steve Blocka7e24c12009-10-30 11:49:00 +00001213 FAST_ELEMENTS,
Iain Merrick75681382010-08-19 15:07:18 +01001214 // All the kinds below are "slow".
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 DICTIONARY_ELEMENTS,
Steve Block3ce2e202009-11-05 08:53:23 +00001216 PIXEL_ELEMENTS,
1217 EXTERNAL_BYTE_ELEMENTS,
1218 EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
1219 EXTERNAL_SHORT_ELEMENTS,
1220 EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
1221 EXTERNAL_INT_ELEMENTS,
1222 EXTERNAL_UNSIGNED_INT_ELEMENTS,
1223 EXTERNAL_FLOAT_ELEMENTS
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 };
1225
1226 // [properties]: Backing storage for properties.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001227 // properties is a FixedArray in the fast case and a Dictionary in the
Steve Blocka7e24c12009-10-30 11:49:00 +00001228 // slow case.
1229 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
1230 inline void initialize_properties();
1231 inline bool HasFastProperties();
1232 inline StringDictionary* property_dictionary(); // Gets slow properties.
1233
1234 // [elements]: The elements (properties with names that are integers).
Iain Merrick75681382010-08-19 15:07:18 +01001235 //
1236 // Elements can be in two general modes: fast and slow. Each mode
1237 // corrensponds to a set of object representations of elements that
1238 // have something in common.
1239 //
1240 // In the fast mode elements is a FixedArray and so each element can
1241 // be quickly accessed. This fact is used in the generated code. The
1242 // elements array can have one of the two maps in this mode:
1243 // fixed_array_map or fixed_cow_array_map (for copy-on-write
1244 // arrays). In the latter case the elements array may be shared by a
1245 // few objects and so before writing to any element the array must
1246 // be copied. Use EnsureWritableFastElements in this case.
1247 //
1248 // In the slow mode elements is either a NumberDictionary or a
1249 // PixelArray or an ExternalArray.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001250 DECL_ACCESSORS(elements, HeapObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00001251 inline void initialize_elements();
Steve Block8defd9f2010-07-08 12:39:36 +01001252 inline Object* ResetElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001253 inline ElementsKind GetElementsKind();
1254 inline bool HasFastElements();
1255 inline bool HasDictionaryElements();
1256 inline bool HasPixelElements();
Steve Block3ce2e202009-11-05 08:53:23 +00001257 inline bool HasExternalArrayElements();
1258 inline bool HasExternalByteElements();
1259 inline bool HasExternalUnsignedByteElements();
1260 inline bool HasExternalShortElements();
1261 inline bool HasExternalUnsignedShortElements();
1262 inline bool HasExternalIntElements();
1263 inline bool HasExternalUnsignedIntElements();
1264 inline bool HasExternalFloatElements();
Steve Block6ded16b2010-05-10 14:33:55 +01001265 inline bool AllowsSetElementsLength();
Steve Blocka7e24c12009-10-30 11:49:00 +00001266 inline NumberDictionary* element_dictionary(); // Gets slow elements.
Iain Merrick75681382010-08-19 15:07:18 +01001267 // Requires: this->HasFastElements().
1268 inline Object* EnsureWritableFastElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001269
1270 // Collects elements starting at index 0.
1271 // Undefined values are placed after non-undefined values.
1272 // Returns the number of non-undefined values.
1273 Object* PrepareElementsForSort(uint32_t limit);
1274 // As PrepareElementsForSort, but only on objects where elements is
1275 // a dictionary, and it will stay a dictionary.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001276 MUST_USE_RESULT Object* PrepareSlowElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001277
1278 Object* SetProperty(String* key,
1279 Object* value,
1280 PropertyAttributes attributes);
1281 Object* SetProperty(LookupResult* result,
1282 String* key,
1283 Object* value,
1284 PropertyAttributes attributes);
1285 Object* SetPropertyWithFailedAccessCheck(LookupResult* result,
1286 String* name,
1287 Object* value);
1288 Object* SetPropertyWithCallback(Object* structure,
1289 String* name,
1290 Object* value,
1291 JSObject* holder);
1292 Object* SetPropertyWithDefinedSetter(JSFunction* setter,
1293 Object* value);
1294 Object* SetPropertyWithInterceptor(String* name,
1295 Object* value,
1296 PropertyAttributes attributes);
1297 Object* SetPropertyPostInterceptor(String* name,
1298 Object* value,
1299 PropertyAttributes attributes);
1300 Object* IgnoreAttributesAndSetLocalProperty(String* key,
1301 Object* value,
1302 PropertyAttributes attributes);
1303
1304 // Retrieve a value in a normalized object given a lookup result.
1305 // Handles the special representation of JS global objects.
1306 Object* GetNormalizedProperty(LookupResult* result);
1307
1308 // Sets the property value in a normalized object given a lookup result.
1309 // Handles the special representation of JS global objects.
1310 Object* SetNormalizedProperty(LookupResult* result, Object* value);
1311
1312 // Sets the property value in a normalized object given (key, value, details).
1313 // Handles the special representation of JS global objects.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001314 MUST_USE_RESULT Object* SetNormalizedProperty(String* name,
1315 Object* value,
1316 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00001317
1318 // Deletes the named property in a normalized object.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001319 MUST_USE_RESULT Object* DeleteNormalizedProperty(String* name,
1320 DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001321
Steve Blocka7e24c12009-10-30 11:49:00 +00001322 // Returns the class name ([[Class]] property in the specification).
1323 String* class_name();
1324
1325 // Returns the constructor name (the name (possibly, inferred name) of the
1326 // function that was used to instantiate the object).
1327 String* constructor_name();
1328
1329 // Retrieve interceptors.
1330 InterceptorInfo* GetNamedInterceptor();
1331 InterceptorInfo* GetIndexedInterceptor();
1332
1333 inline PropertyAttributes GetPropertyAttribute(String* name);
1334 PropertyAttributes GetPropertyAttributeWithReceiver(JSObject* receiver,
1335 String* name);
1336 PropertyAttributes GetLocalPropertyAttribute(String* name);
1337
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001338 MUST_USE_RESULT Object* DefineAccessor(String* name,
1339 bool is_getter,
1340 JSFunction* fun,
1341 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 Object* LookupAccessor(String* name, bool is_getter);
1343
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001344 MUST_USE_RESULT Object* DefineAccessor(AccessorInfo* info);
Leon Clarkef7060e22010-06-03 12:02:55 +01001345
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 // Used from Object::GetProperty().
1347 Object* GetPropertyWithFailedAccessCheck(Object* receiver,
1348 LookupResult* result,
1349 String* name,
1350 PropertyAttributes* attributes);
1351 Object* GetPropertyWithInterceptor(JSObject* receiver,
1352 String* name,
1353 PropertyAttributes* attributes);
1354 Object* GetPropertyPostInterceptor(JSObject* receiver,
1355 String* name,
1356 PropertyAttributes* attributes);
Steve Blockd0582a62009-12-15 09:54:21 +00001357 Object* GetLocalPropertyPostInterceptor(JSObject* receiver,
1358 String* name,
1359 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001360
1361 // Returns true if this is an instance of an api function and has
1362 // been modified since it was created. May give false positives.
1363 bool IsDirty();
1364
1365 bool HasProperty(String* name) {
1366 return GetPropertyAttribute(name) != ABSENT;
1367 }
1368
1369 // Can cause a GC if it hits an interceptor.
1370 bool HasLocalProperty(String* name) {
1371 return GetLocalPropertyAttribute(name) != ABSENT;
1372 }
1373
Steve Blockd0582a62009-12-15 09:54:21 +00001374 // If the receiver is a JSGlobalProxy this method will return its prototype,
1375 // otherwise the result is the receiver itself.
1376 inline Object* BypassGlobalProxy();
1377
1378 // Accessors for hidden properties object.
1379 //
1380 // Hidden properties are not local properties of the object itself.
1381 // Instead they are stored on an auxiliary JSObject stored as a local
1382 // property with a special name Heap::hidden_symbol(). But if the
1383 // receiver is a JSGlobalProxy then the auxiliary object is a property
1384 // of its prototype.
1385 //
1386 // Has/Get/SetHiddenPropertiesObject methods don't allow the holder to be
1387 // a JSGlobalProxy. Use BypassGlobalProxy method above to get to the real
1388 // holder.
1389 //
1390 // These accessors do not touch interceptors or accessors.
1391 inline bool HasHiddenPropertiesObject();
1392 inline Object* GetHiddenPropertiesObject();
1393 inline Object* SetHiddenPropertiesObject(Object* hidden_obj);
1394
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001395 MUST_USE_RESULT Object* DeleteProperty(String* name, DeleteMode mode);
1396 MUST_USE_RESULT Object* DeleteElement(uint32_t index, DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001397
1398 // Tests for the fast common case for property enumeration.
1399 bool IsSimpleEnum();
1400
1401 // Do we want to keep the elements in fast case when increasing the
1402 // capacity?
1403 bool ShouldConvertToSlowElements(int new_capacity);
1404 // Returns true if the backing storage for the slow-case elements of
1405 // this object takes up nearly as much space as a fast-case backing
1406 // storage would. In that case the JSObject should have fast
1407 // elements.
1408 bool ShouldConvertToFastElements();
1409
1410 // Return the object's prototype (might be Heap::null_value()).
1411 inline Object* GetPrototype();
1412
Andrei Popescu402d9372010-02-26 13:31:12 +00001413 // Set the object's prototype (only JSObject and null are allowed).
1414 Object* SetPrototype(Object* value, bool skip_hidden_prototypes);
1415
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 // Tells whether the index'th element is present.
1417 inline bool HasElement(uint32_t index);
1418 bool HasElementWithReceiver(JSObject* receiver, uint32_t index);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001419
1420 // Tells whether the index'th element is present and how it is stored.
1421 enum LocalElementType {
1422 // There is no element with given index.
1423 UNDEFINED_ELEMENT,
1424
1425 // Element with given index is handled by interceptor.
1426 INTERCEPTED_ELEMENT,
1427
1428 // Element with given index is character in string.
1429 STRING_CHARACTER_ELEMENT,
1430
1431 // Element with given index is stored in fast backing store.
1432 FAST_ELEMENT,
1433
1434 // Element with given index is stored in slow backing store.
1435 DICTIONARY_ELEMENT
1436 };
1437
1438 LocalElementType HasLocalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001439
1440 bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
1441 bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
1442
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001443 MUST_USE_RESULT Object* SetFastElement(uint32_t index, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001444
1445 // Set the index'th array element.
1446 // A Failure object is returned if GC is needed.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001447 MUST_USE_RESULT Object* SetElement(uint32_t index, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001448
1449 // Returns the index'th element.
1450 // The undefined object if index is out of bounds.
1451 Object* GetElementWithReceiver(JSObject* receiver, uint32_t index);
Steve Block8defd9f2010-07-08 12:39:36 +01001452 Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001453
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001454 MUST_USE_RESULT Object* SetFastElementsCapacityAndLength(int capacity,
1455 int length);
1456 MUST_USE_RESULT Object* SetSlowElements(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001457
1458 // Lookup interceptors are used for handling properties controlled by host
1459 // objects.
1460 inline bool HasNamedInterceptor();
1461 inline bool HasIndexedInterceptor();
1462
1463 // Support functions for v8 api (needed for correct interceptor behavior).
1464 bool HasRealNamedProperty(String* key);
1465 bool HasRealElementProperty(uint32_t index);
1466 bool HasRealNamedCallbackProperty(String* key);
1467
1468 // Initializes the array to a certain length
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001469 MUST_USE_RESULT Object* SetElementsLength(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001470
1471 // Get the header size for a JSObject. Used to compute the index of
1472 // internal fields as well as the number of internal fields.
1473 inline int GetHeaderSize();
1474
1475 inline int GetInternalFieldCount();
1476 inline Object* GetInternalField(int index);
1477 inline void SetInternalField(int index, Object* value);
1478
1479 // Lookup a property. If found, the result is valid and has
1480 // detailed information.
1481 void LocalLookup(String* name, LookupResult* result);
1482 void Lookup(String* name, LookupResult* result);
1483
1484 // The following lookup functions skip interceptors.
1485 void LocalLookupRealNamedProperty(String* name, LookupResult* result);
1486 void LookupRealNamedProperty(String* name, LookupResult* result);
1487 void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
1488 void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
Leon Clarkef7060e22010-06-03 12:02:55 +01001489 bool SetElementWithCallbackSetterInPrototypes(uint32_t index, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001490 void LookupCallback(String* name, LookupResult* result);
1491
1492 // Returns the number of properties on this object filtering out properties
1493 // with the specified attributes (ignoring interceptors).
1494 int NumberOfLocalProperties(PropertyAttributes filter);
1495 // Returns the number of enumerable properties (ignoring interceptors).
1496 int NumberOfEnumProperties();
1497 // Fill in details for properties into storage starting at the specified
1498 // index.
1499 void GetLocalPropertyNames(FixedArray* storage, int index);
1500
1501 // Returns the number of properties on this object filtering out properties
1502 // with the specified attributes (ignoring interceptors).
1503 int NumberOfLocalElements(PropertyAttributes filter);
1504 // Returns the number of enumerable elements (ignoring interceptors).
1505 int NumberOfEnumElements();
1506 // Returns the number of elements on this object filtering out elements
1507 // with the specified attributes (ignoring interceptors).
1508 int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
1509 // Count and fill in the enumerable elements into storage.
1510 // (storage->length() == NumberOfEnumElements()).
1511 // If storage is NULL, will count the elements without adding
1512 // them to any storage.
1513 // Returns the number of enumerable elements.
1514 int GetEnumElementKeys(FixedArray* storage);
1515
1516 // Add a property to a fast-case object using a map transition to
1517 // new_map.
1518 Object* AddFastPropertyUsingMap(Map* new_map,
1519 String* name,
1520 Object* value);
1521
1522 // Add a constant function property to a fast-case object.
1523 // This leaves a CONSTANT_TRANSITION in the old map, and
1524 // if it is called on a second object with this map, a
1525 // normal property is added instead, with a map transition.
1526 // This avoids the creation of many maps with the same constant
1527 // function, all orphaned.
1528 Object* AddConstantFunctionProperty(String* name,
1529 JSFunction* function,
1530 PropertyAttributes attributes);
1531
1532 Object* ReplaceSlowProperty(String* name,
1533 Object* value,
1534 PropertyAttributes attributes);
1535
1536 // Converts a descriptor of any other type to a real field,
1537 // backed by the properties array. Descriptors of visible
1538 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1539 // Converts the descriptor on the original object's map to a
1540 // map transition, and the the new field is on the object's new map.
1541 Object* ConvertDescriptorToFieldAndMapTransition(
1542 String* name,
1543 Object* new_value,
1544 PropertyAttributes attributes);
1545
1546 // Converts a descriptor of any other type to a real field,
1547 // backed by the properties array. Descriptors of visible
1548 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1549 Object* ConvertDescriptorToField(String* name,
1550 Object* new_value,
1551 PropertyAttributes attributes);
1552
1553 // Add a property to a fast-case object.
1554 Object* AddFastProperty(String* name,
1555 Object* value,
1556 PropertyAttributes attributes);
1557
1558 // Add a property to a slow-case object.
1559 Object* AddSlowProperty(String* name,
1560 Object* value,
1561 PropertyAttributes attributes);
1562
1563 // Add a property to an object.
1564 Object* AddProperty(String* name,
1565 Object* value,
1566 PropertyAttributes attributes);
1567
1568 // Convert the object to use the canonical dictionary
1569 // representation. If the object is expected to have additional properties
1570 // added this number can be indicated to have the backing store allocated to
1571 // an initial capacity for holding these properties.
1572 Object* NormalizeProperties(PropertyNormalizationMode mode,
1573 int expected_additional_properties);
1574 Object* NormalizeElements();
1575
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001576 Object* UpdateMapCodeCache(String* name, Code* code);
1577
Steve Blocka7e24c12009-10-30 11:49:00 +00001578 // Transform slow named properties to fast variants.
1579 // Returns failure if allocation failed.
1580 Object* TransformToFastProperties(int unused_property_fields);
1581
1582 // Access fast-case object properties at index.
1583 inline Object* FastPropertyAt(int index);
1584 inline Object* FastPropertyAtPut(int index, Object* value);
1585
1586 // Access to in object properties.
1587 inline Object* InObjectPropertyAt(int index);
1588 inline Object* InObjectPropertyAtPut(int index,
1589 Object* value,
1590 WriteBarrierMode mode
1591 = UPDATE_WRITE_BARRIER);
1592
1593 // initializes the body after properties slot, properties slot is
1594 // initialized by set_properties
1595 // Note: this call does not update write barrier, it is caller's
1596 // reponsibility to ensure that *v* can be collected without WB here.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001597 inline void InitializeBody(int object_size, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001598
1599 // Check whether this object references another object
1600 bool ReferencesObject(Object* obj);
1601
1602 // Casting.
1603 static inline JSObject* cast(Object* obj);
1604
Steve Block8defd9f2010-07-08 12:39:36 +01001605 // Disalow further properties to be added to the object.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001606 MUST_USE_RESULT Object* PreventExtensions();
Steve Block8defd9f2010-07-08 12:39:36 +01001607
1608
Steve Blocka7e24c12009-10-30 11:49:00 +00001609 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00001610 void JSObjectShortPrint(StringStream* accumulator);
1611#ifdef DEBUG
1612 void JSObjectPrint();
1613 void JSObjectVerify();
1614 void PrintProperties();
1615 void PrintElements();
1616
1617 // Structure for collecting spill information about JSObjects.
1618 class SpillInformation {
1619 public:
1620 void Clear();
1621 void Print();
1622 int number_of_objects_;
1623 int number_of_objects_with_fast_properties_;
1624 int number_of_objects_with_fast_elements_;
1625 int number_of_fast_used_fields_;
1626 int number_of_fast_unused_fields_;
1627 int number_of_slow_used_properties_;
1628 int number_of_slow_unused_properties_;
1629 int number_of_fast_used_elements_;
1630 int number_of_fast_unused_elements_;
1631 int number_of_slow_used_elements_;
1632 int number_of_slow_unused_elements_;
1633 };
1634
1635 void IncrementSpillStatistics(SpillInformation* info);
1636#endif
1637 Object* SlowReverseLookup(Object* value);
1638
Steve Block8defd9f2010-07-08 12:39:36 +01001639 // Maximal number of fast properties for the JSObject. Used to
1640 // restrict the number of map transitions to avoid an explosion in
1641 // the number of maps for objects used as dictionaries.
1642 inline int MaxFastProperties();
1643
Leon Clarkee46be812010-01-19 14:06:41 +00001644 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
1645 // Also maximal value of JSArray's length property.
1646 static const uint32_t kMaxElementCount = 0xffffffffu;
1647
Steve Blocka7e24c12009-10-30 11:49:00 +00001648 static const uint32_t kMaxGap = 1024;
1649 static const int kMaxFastElementsLength = 5000;
1650 static const int kInitialMaxFastElementArray = 100000;
1651 static const int kMaxFastProperties = 8;
1652 static const int kMaxInstanceSize = 255 * kPointerSize;
1653 // When extending the backing storage for property values, we increase
1654 // its size by more than the 1 entry necessary, so sequentially adding fields
1655 // to the same object requires fewer allocations and copies.
1656 static const int kFieldsAdded = 3;
1657
1658 // Layout description.
1659 static const int kPropertiesOffset = HeapObject::kHeaderSize;
1660 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
1661 static const int kHeaderSize = kElementsOffset + kPointerSize;
1662
1663 STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
1664
Iain Merrick75681382010-08-19 15:07:18 +01001665 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
1666 public:
1667 static inline int SizeOf(Map* map, HeapObject* object);
1668 };
1669
Steve Blocka7e24c12009-10-30 11:49:00 +00001670 private:
Leon Clarkef7060e22010-06-03 12:02:55 +01001671 Object* GetElementWithCallback(Object* receiver,
1672 Object* structure,
1673 uint32_t index,
1674 Object* holder);
1675 Object* SetElementWithCallback(Object* structure,
1676 uint32_t index,
1677 Object* value,
1678 JSObject* holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001679 MUST_USE_RESULT Object* SetElementWithInterceptor(uint32_t index,
1680 Object* value);
1681 MUST_USE_RESULT Object* SetElementWithoutInterceptor(uint32_t index,
1682 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001683
1684 Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
1685
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001686 MUST_USE_RESULT Object* DeletePropertyPostInterceptor(String* name,
1687 DeleteMode mode);
1688 MUST_USE_RESULT Object* DeletePropertyWithInterceptor(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001689
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001690 MUST_USE_RESULT Object* DeleteElementPostInterceptor(uint32_t index,
1691 DeleteMode mode);
1692 MUST_USE_RESULT Object* DeleteElementWithInterceptor(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001693
1694 PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
1695 String* name,
1696 bool continue_search);
1697 PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
1698 String* name,
1699 bool continue_search);
1700 PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
1701 Object* receiver,
1702 LookupResult* result,
1703 String* name,
1704 bool continue_search);
1705 PropertyAttributes GetPropertyAttribute(JSObject* receiver,
1706 LookupResult* result,
1707 String* name,
1708 bool continue_search);
1709
1710 // Returns true if most of the elements backing storage is used.
1711 bool HasDenseElements();
1712
Leon Clarkef7060e22010-06-03 12:02:55 +01001713 bool CanSetCallback(String* name);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001714 MUST_USE_RESULT Object* SetElementCallback(uint32_t index,
1715 Object* structure,
1716 PropertyAttributes attributes);
1717 MUST_USE_RESULT Object* SetPropertyCallback(String* name,
1718 Object* structure,
1719 PropertyAttributes attributes);
1720 MUST_USE_RESULT Object* DefineGetterSetter(String* name,
1721 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001722
1723 void LookupInDescriptor(String* name, LookupResult* result);
1724
1725 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
1726};
1727
1728
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001729// FixedArray describes fixed-sized arrays with element type Object*.
1730class FixedArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001731 public:
1732 // [length]: length of the array.
1733 inline int length();
1734 inline void set_length(int value);
1735
Steve Blocka7e24c12009-10-30 11:49:00 +00001736 // Setter and getter for elements.
1737 inline Object* get(int index);
1738 // Setter that uses write barrier.
1739 inline void set(int index, Object* value);
1740
1741 // Setter that doesn't need write barrier).
1742 inline void set(int index, Smi* value);
1743 // Setter with explicit barrier mode.
1744 inline void set(int index, Object* value, WriteBarrierMode mode);
1745
1746 // Setters for frequently used oddballs located in old space.
1747 inline void set_undefined(int index);
1748 inline void set_null(int index);
1749 inline void set_the_hole(int index);
1750
Iain Merrick75681382010-08-19 15:07:18 +01001751 // Setters with less debug checks for the GC to use.
1752 inline void set_unchecked(int index, Smi* value);
1753 inline void set_null_unchecked(int index);
Ben Murdochf87a2032010-10-22 12:50:53 +01001754 inline void set_unchecked(int index, Object* value, WriteBarrierMode mode);
Iain Merrick75681382010-08-19 15:07:18 +01001755
Steve Block6ded16b2010-05-10 14:33:55 +01001756 // Gives access to raw memory which stores the array's data.
1757 inline Object** data_start();
1758
Steve Blocka7e24c12009-10-30 11:49:00 +00001759 // Copy operations.
1760 inline Object* Copy();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001761 MUST_USE_RESULT Object* CopySize(int new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001762
1763 // Add the elements of a JSArray to this FixedArray.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001764 MUST_USE_RESULT Object* AddKeysFromJSArray(JSArray* array);
Steve Blocka7e24c12009-10-30 11:49:00 +00001765
1766 // Compute the union of this and other.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001767 MUST_USE_RESULT Object* UnionOfKeys(FixedArray* other);
Steve Blocka7e24c12009-10-30 11:49:00 +00001768
1769 // Copy a sub array from the receiver to dest.
1770 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
1771
1772 // Garbage collection support.
1773 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
1774
1775 // Code Generation support.
1776 static int OffsetOfElementAt(int index) { return SizeFor(index); }
1777
1778 // Casting.
1779 static inline FixedArray* cast(Object* obj);
1780
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001781 // Layout description.
1782 // Length is smi tagged when it is stored.
1783 static const int kLengthOffset = HeapObject::kHeaderSize;
1784 static const int kHeaderSize = kLengthOffset + kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00001785
1786 // Maximal allowed size, in bytes, of a single FixedArray.
1787 // Prevents overflowing size computations, as well as extreme memory
1788 // consumption.
1789 static const int kMaxSize = 512 * MB;
1790 // Maximally allowed length of a FixedArray.
1791 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001792
1793 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00001794#ifdef DEBUG
1795 void FixedArrayPrint();
1796 void FixedArrayVerify();
1797 // Checks if two FixedArrays have identical contents.
1798 bool IsEqualTo(FixedArray* other);
1799#endif
1800
1801 // Swap two elements in a pair of arrays. If this array and the
1802 // numbers array are the same object, the elements are only swapped
1803 // once.
1804 void SwapPairs(FixedArray* numbers, int i, int j);
1805
1806 // Sort prefix of this array and the numbers array as pairs wrt. the
1807 // numbers. If the numbers array and the this array are the same
1808 // object, the prefix of this array is sorted.
1809 void SortPairs(FixedArray* numbers, uint32_t len);
1810
Iain Merrick75681382010-08-19 15:07:18 +01001811 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
1812 public:
1813 static inline int SizeOf(Map* map, HeapObject* object) {
1814 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
1815 }
1816 };
1817
Steve Blocka7e24c12009-10-30 11:49:00 +00001818 protected:
Leon Clarke4515c472010-02-03 11:58:03 +00001819 // Set operation on FixedArray without using write barriers. Can
1820 // only be used for storing old space objects or smis.
Steve Blocka7e24c12009-10-30 11:49:00 +00001821 static inline void fast_set(FixedArray* array, int index, Object* value);
1822
1823 private:
1824 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
1825};
1826
1827
1828// DescriptorArrays are fixed arrays used to hold instance descriptors.
1829// The format of the these objects is:
1830// [0]: point to a fixed array with (value, detail) pairs.
1831// [1]: next enumeration index (Smi), or pointer to small fixed array:
1832// [0]: next enumeration index (Smi)
1833// [1]: pointer to fixed array with enum cache
1834// [2]: first key
1835// [length() - 1]: last key
1836//
1837class DescriptorArray: public FixedArray {
1838 public:
1839 // Is this the singleton empty_descriptor_array?
1840 inline bool IsEmpty();
Leon Clarkee46be812010-01-19 14:06:41 +00001841
Steve Blocka7e24c12009-10-30 11:49:00 +00001842 // Returns the number of descriptors in the array.
1843 int number_of_descriptors() {
1844 return IsEmpty() ? 0 : length() - kFirstIndex;
1845 }
1846
1847 int NextEnumerationIndex() {
1848 if (IsEmpty()) return PropertyDetails::kInitialIndex;
1849 Object* obj = get(kEnumerationIndexIndex);
1850 if (obj->IsSmi()) {
1851 return Smi::cast(obj)->value();
1852 } else {
1853 Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
1854 return Smi::cast(index)->value();
1855 }
1856 }
1857
1858 // Set next enumeration index and flush any enum cache.
1859 void SetNextEnumerationIndex(int value) {
1860 if (!IsEmpty()) {
1861 fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
1862 }
1863 }
1864 bool HasEnumCache() {
1865 return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
1866 }
1867
1868 Object* GetEnumCache() {
1869 ASSERT(HasEnumCache());
1870 FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
1871 return bridge->get(kEnumCacheBridgeCacheIndex);
1872 }
1873
1874 // Initialize or change the enum cache,
1875 // using the supplied storage for the small "bridge".
1876 void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
1877
1878 // Accessors for fetching instance descriptor at descriptor number.
1879 inline String* GetKey(int descriptor_number);
1880 inline Object* GetValue(int descriptor_number);
1881 inline Smi* GetDetails(int descriptor_number);
1882 inline PropertyType GetType(int descriptor_number);
1883 inline int GetFieldIndex(int descriptor_number);
1884 inline JSFunction* GetConstantFunction(int descriptor_number);
1885 inline Object* GetCallbacksObject(int descriptor_number);
1886 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
1887 inline bool IsProperty(int descriptor_number);
1888 inline bool IsTransition(int descriptor_number);
1889 inline bool IsNullDescriptor(int descriptor_number);
1890 inline bool IsDontEnum(int descriptor_number);
1891
1892 // Accessor for complete descriptor.
1893 inline void Get(int descriptor_number, Descriptor* desc);
1894 inline void Set(int descriptor_number, Descriptor* desc);
1895
1896 // Transfer complete descriptor from another descriptor array to
1897 // this one.
1898 inline void CopyFrom(int index, DescriptorArray* src, int src_index);
1899
1900 // Copy the descriptor array, insert a new descriptor and optionally
1901 // remove map transitions. If the descriptor is already present, it is
1902 // replaced. If a replaced descriptor is a real property (not a transition
1903 // or null), its enumeration index is kept as is.
1904 // If adding a real property, map transitions must be removed. If adding
1905 // a transition, they must not be removed. All null descriptors are removed.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001906 MUST_USE_RESULT Object* CopyInsert(Descriptor* descriptor,
1907 TransitionFlag transition_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001908
1909 // Remove all transitions. Return a copy of the array with all transitions
1910 // removed, or a Failure object if the new array could not be allocated.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001911 MUST_USE_RESULT Object* RemoveTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001912
1913 // Sort the instance descriptors by the hash codes of their keys.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001914 // Does not check for duplicates.
1915 void SortUnchecked();
1916
1917 // Sort the instance descriptors by the hash codes of their keys.
1918 // Checks the result for duplicates.
Steve Blocka7e24c12009-10-30 11:49:00 +00001919 void Sort();
1920
1921 // Search the instance descriptors for given name.
1922 inline int Search(String* name);
1923
Iain Merrick75681382010-08-19 15:07:18 +01001924 // As the above, but uses DescriptorLookupCache and updates it when
1925 // necessary.
1926 inline int SearchWithCache(String* name);
1927
Steve Blocka7e24c12009-10-30 11:49:00 +00001928 // Tells whether the name is present int the array.
1929 bool Contains(String* name) { return kNotFound != Search(name); }
1930
1931 // Perform a binary search in the instance descriptors represented
1932 // by this fixed array. low and high are descriptor indices. If there
1933 // are three instance descriptors in this array it should be called
1934 // with low=0 and high=2.
1935 int BinarySearch(String* name, int low, int high);
1936
1937 // Perform a linear search in the instance descriptors represented
1938 // by this fixed array. len is the number of descriptor indices that are
1939 // valid. Does not require the descriptors to be sorted.
1940 int LinearSearch(String* name, int len);
1941
1942 // Allocates a DescriptorArray, but returns the singleton
1943 // empty descriptor array object if number_of_descriptors is 0.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001944 MUST_USE_RESULT static Object* Allocate(int number_of_descriptors);
Steve Blocka7e24c12009-10-30 11:49:00 +00001945
1946 // Casting.
1947 static inline DescriptorArray* cast(Object* obj);
1948
1949 // Constant for denoting key was not found.
1950 static const int kNotFound = -1;
1951
1952 static const int kContentArrayIndex = 0;
1953 static const int kEnumerationIndexIndex = 1;
1954 static const int kFirstIndex = 2;
1955
1956 // The length of the "bridge" to the enum cache.
1957 static const int kEnumCacheBridgeLength = 2;
1958 static const int kEnumCacheBridgeEnumIndex = 0;
1959 static const int kEnumCacheBridgeCacheIndex = 1;
1960
1961 // Layout description.
1962 static const int kContentArrayOffset = FixedArray::kHeaderSize;
1963 static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
1964 static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
1965
1966 // Layout description for the bridge array.
1967 static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
1968 static const int kEnumCacheBridgeCacheOffset =
1969 kEnumCacheBridgeEnumOffset + kPointerSize;
1970
1971#ifdef DEBUG
1972 // Print all the descriptors.
1973 void PrintDescriptors();
1974
1975 // Is the descriptor array sorted and without duplicates?
1976 bool IsSortedNoDuplicates();
1977
1978 // Are two DescriptorArrays equal?
1979 bool IsEqualTo(DescriptorArray* other);
1980#endif
1981
1982 // The maximum number of descriptors we want in a descriptor array (should
1983 // fit in a page).
1984 static const int kMaxNumberOfDescriptors = 1024 + 512;
1985
1986 private:
1987 // Conversion from descriptor number to array indices.
1988 static int ToKeyIndex(int descriptor_number) {
1989 return descriptor_number+kFirstIndex;
1990 }
Leon Clarkee46be812010-01-19 14:06:41 +00001991
1992 static int ToDetailsIndex(int descriptor_number) {
1993 return (descriptor_number << 1) + 1;
1994 }
1995
Steve Blocka7e24c12009-10-30 11:49:00 +00001996 static int ToValueIndex(int descriptor_number) {
1997 return descriptor_number << 1;
1998 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001999
2000 bool is_null_descriptor(int descriptor_number) {
2001 return PropertyDetails(GetDetails(descriptor_number)).type() ==
2002 NULL_DESCRIPTOR;
2003 }
2004 // Swap operation on FixedArray without using write barriers.
2005 static inline void fast_swap(FixedArray* array, int first, int second);
2006
2007 // Swap descriptor first and second.
2008 inline void Swap(int first, int second);
2009
2010 FixedArray* GetContentArray() {
2011 return FixedArray::cast(get(kContentArrayIndex));
2012 }
2013 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
2014};
2015
2016
2017// HashTable is a subclass of FixedArray that implements a hash table
2018// that uses open addressing and quadratic probing.
2019//
2020// In order for the quadratic probing to work, elements that have not
2021// yet been used and elements that have been deleted are
2022// distinguished. Probing continues when deleted elements are
2023// encountered and stops when unused elements are encountered.
2024//
2025// - Elements with key == undefined have not been used yet.
2026// - Elements with key == null have been deleted.
2027//
2028// The hash table class is parameterized with a Shape and a Key.
2029// Shape must be a class with the following interface:
2030// class ExampleShape {
2031// public:
2032// // Tells whether key matches other.
2033// static bool IsMatch(Key key, Object* other);
2034// // Returns the hash value for key.
2035// static uint32_t Hash(Key key);
2036// // Returns the hash value for object.
2037// static uint32_t HashForObject(Key key, Object* object);
2038// // Convert key to an object.
2039// static inline Object* AsObject(Key key);
2040// // The prefix size indicates number of elements in the beginning
2041// // of the backing storage.
2042// static const int kPrefixSize = ..;
2043// // The Element size indicates number of elements per entry.
2044// static const int kEntrySize = ..;
2045// };
Steve Block3ce2e202009-11-05 08:53:23 +00002046// The prefix size indicates an amount of memory in the
Steve Blocka7e24c12009-10-30 11:49:00 +00002047// beginning of the backing storage that can be used for non-element
2048// information by subclasses.
2049
2050template<typename Shape, typename Key>
2051class HashTable: public FixedArray {
2052 public:
Steve Block3ce2e202009-11-05 08:53:23 +00002053 // Returns the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002054 int NumberOfElements() {
2055 return Smi::cast(get(kNumberOfElementsIndex))->value();
2056 }
2057
Leon Clarkee46be812010-01-19 14:06:41 +00002058 // Returns the number of deleted elements in the hash table.
2059 int NumberOfDeletedElements() {
2060 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
2061 }
2062
Steve Block3ce2e202009-11-05 08:53:23 +00002063 // Returns the capacity of the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002064 int Capacity() {
2065 return Smi::cast(get(kCapacityIndex))->value();
2066 }
2067
2068 // ElementAdded should be called whenever an element is added to a
Steve Block3ce2e202009-11-05 08:53:23 +00002069 // hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002070 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
2071
2072 // ElementRemoved should be called whenever an element is removed from
Steve Block3ce2e202009-11-05 08:53:23 +00002073 // a hash table.
Leon Clarkee46be812010-01-19 14:06:41 +00002074 void ElementRemoved() {
2075 SetNumberOfElements(NumberOfElements() - 1);
2076 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
2077 }
2078 void ElementsRemoved(int n) {
2079 SetNumberOfElements(NumberOfElements() - n);
2080 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
2081 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002082
Steve Block3ce2e202009-11-05 08:53:23 +00002083 // Returns a new HashTable object. Might return Failure.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002084 MUST_USE_RESULT static Object* Allocate(
2085 int at_least_space_for,
2086 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002087
2088 // Returns the key at entry.
2089 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
2090
2091 // Tells whether k is a real key. Null and undefined are not allowed
2092 // as keys and can be used to indicate missing or deleted elements.
2093 bool IsKey(Object* k) {
2094 return !k->IsNull() && !k->IsUndefined();
2095 }
2096
2097 // Garbage collection support.
2098 void IteratePrefix(ObjectVisitor* visitor);
2099 void IterateElements(ObjectVisitor* visitor);
2100
2101 // Casting.
2102 static inline HashTable* cast(Object* obj);
2103
2104 // Compute the probe offset (quadratic probing).
2105 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
2106 return (n + n * n) >> 1;
2107 }
2108
2109 static const int kNumberOfElementsIndex = 0;
Leon Clarkee46be812010-01-19 14:06:41 +00002110 static const int kNumberOfDeletedElementsIndex = 1;
2111 static const int kCapacityIndex = 2;
2112 static const int kPrefixStartIndex = 3;
2113 static const int kElementsStartIndex =
Steve Blocka7e24c12009-10-30 11:49:00 +00002114 kPrefixStartIndex + Shape::kPrefixSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002115 static const int kEntrySize = Shape::kEntrySize;
2116 static const int kElementsStartOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00002117 kHeaderSize + kElementsStartIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01002118 static const int kCapacityOffset =
2119 kHeaderSize + kCapacityIndex * kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002120
2121 // Constant used for denoting a absent entry.
2122 static const int kNotFound = -1;
2123
Leon Clarkee46be812010-01-19 14:06:41 +00002124 // Maximal capacity of HashTable. Based on maximal length of underlying
2125 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
2126 // cannot overflow.
2127 static const int kMaxCapacity =
2128 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
2129
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002130 // Find entry for key otherwise return kNotFound.
Steve Blocka7e24c12009-10-30 11:49:00 +00002131 int FindEntry(Key key);
2132
2133 protected:
2134
2135 // Find the entry at which to insert element with the given key that
2136 // has the given hash value.
2137 uint32_t FindInsertionEntry(uint32_t hash);
2138
2139 // Returns the index for an entry (of the key)
2140 static inline int EntryToIndex(int entry) {
2141 return (entry * kEntrySize) + kElementsStartIndex;
2142 }
2143
Steve Block3ce2e202009-11-05 08:53:23 +00002144 // Update the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002145 void SetNumberOfElements(int nof) {
2146 fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
2147 }
2148
Leon Clarkee46be812010-01-19 14:06:41 +00002149 // Update the number of deleted elements in the hash table.
2150 void SetNumberOfDeletedElements(int nod) {
2151 fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
2152 }
2153
Steve Blocka7e24c12009-10-30 11:49:00 +00002154 // Sets the capacity of the hash table.
2155 void SetCapacity(int capacity) {
2156 // To scale a computed hash code to fit within the hash table, we
2157 // use bit-wise AND with a mask, so the capacity must be positive
2158 // and non-zero.
2159 ASSERT(capacity > 0);
Leon Clarkee46be812010-01-19 14:06:41 +00002160 ASSERT(capacity <= kMaxCapacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00002161 fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
2162 }
2163
2164
2165 // Returns probe entry.
2166 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
2167 ASSERT(IsPowerOf2(size));
2168 return (hash + GetProbeOffset(number)) & (size - 1);
2169 }
2170
Leon Clarkee46be812010-01-19 14:06:41 +00002171 static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
2172 return hash & (size - 1);
2173 }
2174
2175 static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
2176 return (last + number) & (size - 1);
2177 }
2178
Steve Blocka7e24c12009-10-30 11:49:00 +00002179 // Ensure enough space for n additional elements.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002180 MUST_USE_RESULT Object* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002181};
2182
2183
2184
2185// HashTableKey is an abstract superclass for virtual key behavior.
2186class HashTableKey {
2187 public:
2188 // Returns whether the other object matches this key.
2189 virtual bool IsMatch(Object* other) = 0;
2190 // Returns the hash value for this key.
2191 virtual uint32_t Hash() = 0;
2192 // Returns the hash value for object.
2193 virtual uint32_t HashForObject(Object* key) = 0;
Steve Block3ce2e202009-11-05 08:53:23 +00002194 // Returns the key object for storing into the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002195 // If allocations fails a failure object is returned.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002196 MUST_USE_RESULT virtual Object* AsObject() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002197 // Required.
2198 virtual ~HashTableKey() {}
2199};
2200
2201class SymbolTableShape {
2202 public:
2203 static bool IsMatch(HashTableKey* key, Object* value) {
2204 return key->IsMatch(value);
2205 }
2206 static uint32_t Hash(HashTableKey* key) {
2207 return key->Hash();
2208 }
2209 static uint32_t HashForObject(HashTableKey* key, Object* object) {
2210 return key->HashForObject(object);
2211 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002212 MUST_USE_RESULT static Object* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002213 return key->AsObject();
2214 }
2215
2216 static const int kPrefixSize = 0;
2217 static const int kEntrySize = 1;
2218};
2219
2220// SymbolTable.
2221//
2222// No special elements in the prefix and the element size is 1
2223// because only the symbol itself (the key) needs to be stored.
2224class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
2225 public:
2226 // Find symbol in the symbol table. If it is not there yet, it is
2227 // added. The return value is the symbol table which might have
2228 // been enlarged. If the return value is not a failure, the symbol
2229 // pointer *s is set to the symbol found.
2230 Object* LookupSymbol(Vector<const char> str, Object** s);
2231 Object* LookupString(String* key, Object** s);
2232
2233 // Looks up a symbol that is equal to the given string and returns
2234 // true if it is found, assigning the symbol to the given output
2235 // parameter.
2236 bool LookupSymbolIfExists(String* str, String** symbol);
Steve Blockd0582a62009-12-15 09:54:21 +00002237 bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002238
2239 // Casting.
2240 static inline SymbolTable* cast(Object* obj);
2241
2242 private:
2243 Object* LookupKey(HashTableKey* key, Object** s);
2244
2245 DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
2246};
2247
2248
2249class MapCacheShape {
2250 public:
2251 static bool IsMatch(HashTableKey* key, Object* value) {
2252 return key->IsMatch(value);
2253 }
2254 static uint32_t Hash(HashTableKey* key) {
2255 return key->Hash();
2256 }
2257
2258 static uint32_t HashForObject(HashTableKey* key, Object* object) {
2259 return key->HashForObject(object);
2260 }
2261
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002262 MUST_USE_RESULT static Object* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002263 return key->AsObject();
2264 }
2265
2266 static const int kPrefixSize = 0;
2267 static const int kEntrySize = 2;
2268};
2269
2270
2271// MapCache.
2272//
2273// Maps keys that are a fixed array of symbols to a map.
2274// Used for canonicalize maps for object literals.
2275class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
2276 public:
2277 // Find cached value for a string key, otherwise return null.
2278 Object* Lookup(FixedArray* key);
2279 Object* Put(FixedArray* key, Map* value);
2280 static inline MapCache* cast(Object* obj);
2281
2282 private:
2283 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
2284};
2285
2286
2287template <typename Shape, typename Key>
2288class Dictionary: public HashTable<Shape, Key> {
2289 public:
2290
2291 static inline Dictionary<Shape, Key>* cast(Object* obj) {
2292 return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
2293 }
2294
2295 // Returns the value at entry.
2296 Object* ValueAt(int entry) {
Steve Block6ded16b2010-05-10 14:33:55 +01002297 return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002298 }
2299
2300 // Set the value for entry.
2301 void ValueAtPut(int entry, Object* value) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002302 // Check that this value can actually be written.
2303 PropertyDetails details = DetailsAt(entry);
2304 // If a value has not been initilized we allow writing to it even if
2305 // it is read only (a declared const that has not been initialized).
2306 if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) return;
Steve Block6ded16b2010-05-10 14:33:55 +01002307 this->set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002308 }
2309
2310 // Returns the property details for the property at entry.
2311 PropertyDetails DetailsAt(int entry) {
2312 ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
2313 return PropertyDetails(
Steve Block6ded16b2010-05-10 14:33:55 +01002314 Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002315 }
2316
2317 // Set the details for entry.
2318 void DetailsAtPut(int entry, PropertyDetails value) {
Steve Block6ded16b2010-05-10 14:33:55 +01002319 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002320 }
2321
2322 // Sorting support
2323 void CopyValuesTo(FixedArray* elements);
2324
2325 // Delete a property from the dictionary.
2326 Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
2327
2328 // Returns the number of elements in the dictionary filtering out properties
2329 // with the specified attributes.
2330 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
2331
2332 // Returns the number of enumerable elements in the dictionary.
2333 int NumberOfEnumElements();
2334
2335 // Copies keys to preallocated fixed array.
2336 void CopyKeysTo(FixedArray* storage, PropertyAttributes filter);
2337 // Fill in details for properties into storage.
2338 void CopyKeysTo(FixedArray* storage);
2339
2340 // Accessors for next enumeration index.
2341 void SetNextEnumerationIndex(int index) {
Steve Block6ded16b2010-05-10 14:33:55 +01002342 this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00002343 }
2344
2345 int NextEnumerationIndex() {
2346 return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
2347 }
2348
2349 // Returns a new array for dictionary usage. Might return Failure.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002350 MUST_USE_RESULT static Object* Allocate(int at_least_space_for);
Steve Blocka7e24c12009-10-30 11:49:00 +00002351
2352 // Ensure enough space for n additional elements.
2353 Object* EnsureCapacity(int n, Key key);
2354
2355#ifdef DEBUG
2356 void Print();
2357#endif
2358 // Returns the key (slow).
2359 Object* SlowReverseLookup(Object* value);
2360
2361 // Sets the entry to (key, value) pair.
2362 inline void SetEntry(int entry,
2363 Object* key,
2364 Object* value,
2365 PropertyDetails details);
2366
2367 Object* Add(Key key, Object* value, PropertyDetails details);
2368
2369 protected:
2370 // Generic at put operation.
2371 Object* AtPut(Key key, Object* value);
2372
2373 // Add entry to dictionary.
2374 Object* AddEntry(Key key,
2375 Object* value,
2376 PropertyDetails details,
2377 uint32_t hash);
2378
2379 // Generate new enumeration indices to avoid enumeration index overflow.
2380 Object* GenerateNewEnumerationIndices();
2381 static const int kMaxNumberKeyIndex =
2382 HashTable<Shape, Key>::kPrefixStartIndex;
2383 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
2384};
2385
2386
2387class StringDictionaryShape {
2388 public:
2389 static inline bool IsMatch(String* key, Object* other);
2390 static inline uint32_t Hash(String* key);
2391 static inline uint32_t HashForObject(String* key, Object* object);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002392 MUST_USE_RESULT static inline Object* AsObject(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002393 static const int kPrefixSize = 2;
2394 static const int kEntrySize = 3;
2395 static const bool kIsEnumerable = true;
2396};
2397
2398
2399class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
2400 public:
2401 static inline StringDictionary* cast(Object* obj) {
2402 ASSERT(obj->IsDictionary());
2403 return reinterpret_cast<StringDictionary*>(obj);
2404 }
2405
2406 // Copies enumerable keys to preallocated fixed array.
2407 void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
2408
2409 // For transforming properties of a JSObject.
2410 Object* TransformPropertiesToFastFor(JSObject* obj,
2411 int unused_property_fields);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002412
2413 // Find entry for key otherwise return kNotFound. Optimzed version of
2414 // HashTable::FindEntry.
2415 int FindEntry(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002416};
2417
2418
2419class NumberDictionaryShape {
2420 public:
2421 static inline bool IsMatch(uint32_t key, Object* other);
2422 static inline uint32_t Hash(uint32_t key);
2423 static inline uint32_t HashForObject(uint32_t key, Object* object);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002424 MUST_USE_RESULT static inline Object* AsObject(uint32_t key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002425 static const int kPrefixSize = 2;
2426 static const int kEntrySize = 3;
2427 static const bool kIsEnumerable = false;
2428};
2429
2430
2431class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
2432 public:
2433 static NumberDictionary* cast(Object* obj) {
2434 ASSERT(obj->IsDictionary());
2435 return reinterpret_cast<NumberDictionary*>(obj);
2436 }
2437
2438 // Type specific at put (default NONE attributes is used when adding).
2439 Object* AtNumberPut(uint32_t key, Object* value);
2440 Object* AddNumberEntry(uint32_t key,
2441 Object* value,
2442 PropertyDetails details);
2443
2444 // Set an existing entry or add a new one if needed.
2445 Object* Set(uint32_t key, Object* value, PropertyDetails details);
2446
2447 void UpdateMaxNumberKey(uint32_t key);
2448
2449 // If slow elements are required we will never go back to fast-case
2450 // for the elements kept in this dictionary. We require slow
2451 // elements if an element has been added at an index larger than
2452 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
2453 // when defining a getter or setter with a number key.
2454 inline bool requires_slow_elements();
2455 inline void set_requires_slow_elements();
2456
2457 // Get the value of the max number key that has been added to this
2458 // dictionary. max_number_key can only be called if
2459 // requires_slow_elements returns false.
2460 inline uint32_t max_number_key();
2461
2462 // Remove all entries were key is a number and (from <= key && key < to).
2463 void RemoveNumberEntries(uint32_t from, uint32_t to);
2464
2465 // Bit masks.
2466 static const int kRequiresSlowElementsMask = 1;
2467 static const int kRequiresSlowElementsTagSize = 1;
2468 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
2469};
2470
2471
Steve Block6ded16b2010-05-10 14:33:55 +01002472// JSFunctionResultCache caches results of some JSFunction invocation.
2473// It is a fixed array with fixed structure:
2474// [0]: factory function
2475// [1]: finger index
2476// [2]: current cache size
2477// [3]: dummy field.
2478// The rest of array are key/value pairs.
2479class JSFunctionResultCache: public FixedArray {
2480 public:
2481 static const int kFactoryIndex = 0;
2482 static const int kFingerIndex = kFactoryIndex + 1;
2483 static const int kCacheSizeIndex = kFingerIndex + 1;
2484 static const int kDummyIndex = kCacheSizeIndex + 1;
2485 static const int kEntriesIndex = kDummyIndex + 1;
2486
2487 static const int kEntrySize = 2; // key + value
2488
Kristian Monsen25f61362010-05-21 11:50:48 +01002489 static const int kFactoryOffset = kHeaderSize;
2490 static const int kFingerOffset = kFactoryOffset + kPointerSize;
2491 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
2492
Steve Block6ded16b2010-05-10 14:33:55 +01002493 inline void MakeZeroSize();
2494 inline void Clear();
2495
2496 // Casting
2497 static inline JSFunctionResultCache* cast(Object* obj);
2498
2499#ifdef DEBUG
2500 void JSFunctionResultCacheVerify();
2501#endif
2502};
2503
2504
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002505// The cache for maps used by normalized (dictionary mode) objects.
2506// Such maps do not have property descriptors, so a typical program
2507// needs very limited number of distinct normalized maps.
2508class NormalizedMapCache: public FixedArray {
2509 public:
2510 static const int kEntries = 64;
2511
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002512 Object* Get(JSObject* object, PropertyNormalizationMode mode);
2513
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002514 void Clear();
2515
2516 // Casting
2517 static inline NormalizedMapCache* cast(Object* obj);
2518
2519#ifdef DEBUG
2520 void NormalizedMapCacheVerify();
2521#endif
2522
2523 private:
2524 static int Hash(Map* fast);
2525
2526 static bool CheckHit(Map* slow, Map* fast, PropertyNormalizationMode mode);
2527};
2528
2529
Steve Blocka7e24c12009-10-30 11:49:00 +00002530// ByteArray represents fixed sized byte arrays. Used by the outside world,
2531// such as PCRE, and also by the memory allocator and garbage collector to
2532// fill in free blocks in the heap.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002533class ByteArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002534 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002535 // [length]: length of the array.
2536 inline int length();
2537 inline void set_length(int value);
2538
Steve Blocka7e24c12009-10-30 11:49:00 +00002539 // Setter and getter.
2540 inline byte get(int index);
2541 inline void set(int index, byte value);
2542
2543 // Treat contents as an int array.
2544 inline int get_int(int index);
2545
2546 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002547 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
Steve Blocka7e24c12009-10-30 11:49:00 +00002548 }
2549 // We use byte arrays for free blocks in the heap. Given a desired size in
2550 // bytes that is a multiple of the word size and big enough to hold a byte
2551 // array, this function returns the number of elements a byte array should
2552 // have.
2553 static int LengthFor(int size_in_bytes) {
2554 ASSERT(IsAligned(size_in_bytes, kPointerSize));
2555 ASSERT(size_in_bytes >= kHeaderSize);
2556 return size_in_bytes - kHeaderSize;
2557 }
2558
2559 // Returns data start address.
2560 inline Address GetDataStartAddress();
2561
2562 // Returns a pointer to the ByteArray object for a given data start address.
2563 static inline ByteArray* FromDataStartAddress(Address address);
2564
2565 // Casting.
2566 static inline ByteArray* cast(Object* obj);
2567
2568 // Dispatched behavior.
Iain Merrick75681382010-08-19 15:07:18 +01002569 inline int ByteArraySize() {
2570 return SizeFor(this->length());
2571 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002572#ifdef DEBUG
2573 void ByteArrayPrint();
2574 void ByteArrayVerify();
2575#endif
2576
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002577 // Layout description.
2578 // Length is smi tagged when it is stored.
2579 static const int kLengthOffset = HeapObject::kHeaderSize;
2580 static const int kHeaderSize = kLengthOffset + kPointerSize;
2581
2582 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002583
Leon Clarkee46be812010-01-19 14:06:41 +00002584 // Maximal memory consumption for a single ByteArray.
2585 static const int kMaxSize = 512 * MB;
2586 // Maximal length of a single ByteArray.
2587 static const int kMaxLength = kMaxSize - kHeaderSize;
2588
Steve Blocka7e24c12009-10-30 11:49:00 +00002589 private:
2590 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
2591};
2592
2593
2594// A PixelArray represents a fixed-size byte array with special semantics
2595// used for implementing the CanvasPixelArray object. Please see the
2596// specification at:
2597// http://www.whatwg.org/specs/web-apps/current-work/
2598// multipage/the-canvas-element.html#canvaspixelarray
2599// In particular, write access clamps the value written to 0 or 255 if the
2600// value written is outside this range.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002601class PixelArray: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002602 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002603 // [length]: length of the array.
2604 inline int length();
2605 inline void set_length(int value);
2606
Steve Blocka7e24c12009-10-30 11:49:00 +00002607 // [external_pointer]: The pointer to the external memory area backing this
2608 // pixel array.
2609 DECL_ACCESSORS(external_pointer, uint8_t) // Pointer to the data store.
2610
2611 // Setter and getter.
2612 inline uint8_t get(int index);
2613 inline void set(int index, uint8_t value);
2614
2615 // This accessor applies the correct conversion from Smi, HeapNumber and
2616 // undefined and clamps the converted value between 0 and 255.
2617 Object* SetValue(uint32_t index, Object* value);
2618
2619 // Casting.
2620 static inline PixelArray* cast(Object* obj);
2621
2622#ifdef DEBUG
2623 void PixelArrayPrint();
2624 void PixelArrayVerify();
2625#endif // DEBUG
2626
Steve Block3ce2e202009-11-05 08:53:23 +00002627 // Maximal acceptable length for a pixel array.
2628 static const int kMaxLength = 0x3fffffff;
2629
Steve Blocka7e24c12009-10-30 11:49:00 +00002630 // PixelArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002631 static const int kLengthOffset = HeapObject::kHeaderSize;
2632 static const int kExternalPointerOffset =
2633 POINTER_SIZE_ALIGN(kLengthOffset + kIntSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002634 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002635 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002636
2637 private:
2638 DISALLOW_IMPLICIT_CONSTRUCTORS(PixelArray);
2639};
2640
2641
Steve Block3ce2e202009-11-05 08:53:23 +00002642// An ExternalArray represents a fixed-size array of primitive values
2643// which live outside the JavaScript heap. Its subclasses are used to
2644// implement the CanvasArray types being defined in the WebGL
2645// specification. As of this writing the first public draft is not yet
2646// available, but Khronos members can access the draft at:
2647// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
2648//
2649// The semantics of these arrays differ from CanvasPixelArray.
2650// Out-of-range values passed to the setter are converted via a C
2651// cast, not clamping. Out-of-range indices cause exceptions to be
2652// raised rather than being silently ignored.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002653class ExternalArray: public HeapObject {
Steve Block3ce2e202009-11-05 08:53:23 +00002654 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002655 // [length]: length of the array.
2656 inline int length();
2657 inline void set_length(int value);
2658
Steve Block3ce2e202009-11-05 08:53:23 +00002659 // [external_pointer]: The pointer to the external memory area backing this
2660 // external array.
2661 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
2662
2663 // Casting.
2664 static inline ExternalArray* cast(Object* obj);
2665
2666 // Maximal acceptable length for an external array.
2667 static const int kMaxLength = 0x3fffffff;
2668
2669 // ExternalArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002670 static const int kLengthOffset = HeapObject::kHeaderSize;
2671 static const int kExternalPointerOffset =
2672 POINTER_SIZE_ALIGN(kLengthOffset + kIntSize);
Steve Block3ce2e202009-11-05 08:53:23 +00002673 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002674 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Block3ce2e202009-11-05 08:53:23 +00002675
2676 private:
2677 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
2678};
2679
2680
2681class ExternalByteArray: public ExternalArray {
2682 public:
2683 // Setter and getter.
2684 inline int8_t get(int index);
2685 inline void set(int index, int8_t value);
2686
2687 // This accessor applies the correct conversion from Smi, HeapNumber
2688 // and undefined.
2689 Object* SetValue(uint32_t index, Object* value);
2690
2691 // Casting.
2692 static inline ExternalByteArray* cast(Object* obj);
2693
2694#ifdef DEBUG
2695 void ExternalByteArrayPrint();
2696 void ExternalByteArrayVerify();
2697#endif // DEBUG
2698
2699 private:
2700 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
2701};
2702
2703
2704class ExternalUnsignedByteArray: public ExternalArray {
2705 public:
2706 // Setter and getter.
2707 inline uint8_t get(int index);
2708 inline void set(int index, uint8_t value);
2709
2710 // This accessor applies the correct conversion from Smi, HeapNumber
2711 // and undefined.
2712 Object* SetValue(uint32_t index, Object* value);
2713
2714 // Casting.
2715 static inline ExternalUnsignedByteArray* cast(Object* obj);
2716
2717#ifdef DEBUG
2718 void ExternalUnsignedByteArrayPrint();
2719 void ExternalUnsignedByteArrayVerify();
2720#endif // DEBUG
2721
2722 private:
2723 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
2724};
2725
2726
2727class ExternalShortArray: public ExternalArray {
2728 public:
2729 // Setter and getter.
2730 inline int16_t get(int index);
2731 inline void set(int index, int16_t value);
2732
2733 // This accessor applies the correct conversion from Smi, HeapNumber
2734 // and undefined.
2735 Object* SetValue(uint32_t index, Object* value);
2736
2737 // Casting.
2738 static inline ExternalShortArray* cast(Object* obj);
2739
2740#ifdef DEBUG
2741 void ExternalShortArrayPrint();
2742 void ExternalShortArrayVerify();
2743#endif // DEBUG
2744
2745 private:
2746 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
2747};
2748
2749
2750class ExternalUnsignedShortArray: public ExternalArray {
2751 public:
2752 // Setter and getter.
2753 inline uint16_t get(int index);
2754 inline void set(int index, uint16_t value);
2755
2756 // This accessor applies the correct conversion from Smi, HeapNumber
2757 // and undefined.
2758 Object* SetValue(uint32_t index, Object* value);
2759
2760 // Casting.
2761 static inline ExternalUnsignedShortArray* cast(Object* obj);
2762
2763#ifdef DEBUG
2764 void ExternalUnsignedShortArrayPrint();
2765 void ExternalUnsignedShortArrayVerify();
2766#endif // DEBUG
2767
2768 private:
2769 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
2770};
2771
2772
2773class ExternalIntArray: public ExternalArray {
2774 public:
2775 // Setter and getter.
2776 inline int32_t get(int index);
2777 inline void set(int index, int32_t value);
2778
2779 // This accessor applies the correct conversion from Smi, HeapNumber
2780 // and undefined.
2781 Object* SetValue(uint32_t index, Object* value);
2782
2783 // Casting.
2784 static inline ExternalIntArray* cast(Object* obj);
2785
2786#ifdef DEBUG
2787 void ExternalIntArrayPrint();
2788 void ExternalIntArrayVerify();
2789#endif // DEBUG
2790
2791 private:
2792 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
2793};
2794
2795
2796class ExternalUnsignedIntArray: public ExternalArray {
2797 public:
2798 // Setter and getter.
2799 inline uint32_t get(int index);
2800 inline void set(int index, uint32_t value);
2801
2802 // This accessor applies the correct conversion from Smi, HeapNumber
2803 // and undefined.
2804 Object* SetValue(uint32_t index, Object* value);
2805
2806 // Casting.
2807 static inline ExternalUnsignedIntArray* cast(Object* obj);
2808
2809#ifdef DEBUG
2810 void ExternalUnsignedIntArrayPrint();
2811 void ExternalUnsignedIntArrayVerify();
2812#endif // DEBUG
2813
2814 private:
2815 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
2816};
2817
2818
2819class ExternalFloatArray: public ExternalArray {
2820 public:
2821 // Setter and getter.
2822 inline float get(int index);
2823 inline void set(int index, float value);
2824
2825 // This accessor applies the correct conversion from Smi, HeapNumber
2826 // and undefined.
2827 Object* SetValue(uint32_t index, Object* value);
2828
2829 // Casting.
2830 static inline ExternalFloatArray* cast(Object* obj);
2831
2832#ifdef DEBUG
2833 void ExternalFloatArrayPrint();
2834 void ExternalFloatArrayVerify();
2835#endif // DEBUG
2836
2837 private:
2838 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
2839};
2840
2841
Steve Blocka7e24c12009-10-30 11:49:00 +00002842// Code describes objects with on-the-fly generated machine code.
2843class Code: public HeapObject {
2844 public:
2845 // Opaque data type for encapsulating code flags like kind, inline
2846 // cache state, and arguments count.
Iain Merrick75681382010-08-19 15:07:18 +01002847 // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
2848 // enumeration type has correct value range (see Issue 830 for more details).
2849 enum Flags {
2850 FLAGS_MIN_VALUE = kMinInt,
2851 FLAGS_MAX_VALUE = kMaxInt
2852 };
Steve Blocka7e24c12009-10-30 11:49:00 +00002853
2854 enum Kind {
2855 FUNCTION,
2856 STUB,
2857 BUILTIN,
2858 LOAD_IC,
2859 KEYED_LOAD_IC,
2860 CALL_IC,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002861 KEYED_CALL_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00002862 STORE_IC,
2863 KEYED_STORE_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01002864 BINARY_OP_IC,
2865 // No more than 16 kinds. The value currently encoded in four bits in
Steve Blocka7e24c12009-10-30 11:49:00 +00002866 // Flags.
2867
2868 // Pseudo-kinds.
2869 REGEXP = BUILTIN,
2870 FIRST_IC_KIND = LOAD_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01002871 LAST_IC_KIND = BINARY_OP_IC
Steve Blocka7e24c12009-10-30 11:49:00 +00002872 };
2873
2874 enum {
Kristian Monsen50ef84f2010-07-29 15:18:00 +01002875 NUMBER_OF_KINDS = LAST_IC_KIND + 1
Steve Blocka7e24c12009-10-30 11:49:00 +00002876 };
2877
2878#ifdef ENABLE_DISASSEMBLER
2879 // Printing
2880 static const char* Kind2String(Kind kind);
2881 static const char* ICState2String(InlineCacheState state);
2882 static const char* PropertyType2String(PropertyType type);
2883 void Disassemble(const char* name);
2884#endif // ENABLE_DISASSEMBLER
2885
2886 // [instruction_size]: Size of the native instructions
2887 inline int instruction_size();
2888 inline void set_instruction_size(int value);
2889
Leon Clarkeac952652010-07-15 11:15:24 +01002890 // [relocation_info]: Code relocation information
2891 DECL_ACCESSORS(relocation_info, ByteArray)
2892
2893 // Unchecked accessor to be used during GC.
2894 inline ByteArray* unchecked_relocation_info();
2895
Steve Blocka7e24c12009-10-30 11:49:00 +00002896 inline int relocation_size();
Steve Blocka7e24c12009-10-30 11:49:00 +00002897
Steve Blocka7e24c12009-10-30 11:49:00 +00002898 // [flags]: Various code flags.
2899 inline Flags flags();
2900 inline void set_flags(Flags flags);
2901
2902 // [flags]: Access to specific code flags.
2903 inline Kind kind();
2904 inline InlineCacheState ic_state(); // Only valid for IC stubs.
2905 inline InLoopFlag ic_in_loop(); // Only valid for IC stubs.
2906 inline PropertyType type(); // Only valid for monomorphic IC stubs.
2907 inline int arguments_count(); // Only valid for call IC stubs.
2908
2909 // Testers for IC stub kinds.
2910 inline bool is_inline_cache_stub();
2911 inline bool is_load_stub() { return kind() == LOAD_IC; }
2912 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
2913 inline bool is_store_stub() { return kind() == STORE_IC; }
2914 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
2915 inline bool is_call_stub() { return kind() == CALL_IC; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002916 inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
Steve Blocka7e24c12009-10-30 11:49:00 +00002917
Steve Block6ded16b2010-05-10 14:33:55 +01002918 // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002919 inline int major_key();
2920 inline void set_major_key(int major);
Steve Blocka7e24c12009-10-30 11:49:00 +00002921
2922 // Flags operations.
2923 static inline Flags ComputeFlags(Kind kind,
2924 InLoopFlag in_loop = NOT_IN_LOOP,
2925 InlineCacheState ic_state = UNINITIALIZED,
2926 PropertyType type = NORMAL,
Steve Block8defd9f2010-07-08 12:39:36 +01002927 int argc = -1,
2928 InlineCacheHolderFlag holder = OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +00002929
2930 static inline Flags ComputeMonomorphicFlags(
2931 Kind kind,
2932 PropertyType type,
Steve Block8defd9f2010-07-08 12:39:36 +01002933 InlineCacheHolderFlag holder = OWN_MAP,
Steve Blocka7e24c12009-10-30 11:49:00 +00002934 InLoopFlag in_loop = NOT_IN_LOOP,
2935 int argc = -1);
2936
2937 static inline Kind ExtractKindFromFlags(Flags flags);
2938 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
2939 static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
2940 static inline PropertyType ExtractTypeFromFlags(Flags flags);
2941 static inline int ExtractArgumentsCountFromFlags(Flags flags);
Steve Block8defd9f2010-07-08 12:39:36 +01002942 static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00002943 static inline Flags RemoveTypeFromFlags(Flags flags);
2944
2945 // Convert a target address into a code object.
2946 static inline Code* GetCodeFromTargetAddress(Address address);
2947
Steve Block791712a2010-08-27 10:21:07 +01002948 // Convert an entry address into an object.
2949 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
2950
Steve Blocka7e24c12009-10-30 11:49:00 +00002951 // Returns the address of the first instruction.
2952 inline byte* instruction_start();
2953
Leon Clarkeac952652010-07-15 11:15:24 +01002954 // Returns the address right after the last instruction.
2955 inline byte* instruction_end();
2956
Steve Blocka7e24c12009-10-30 11:49:00 +00002957 // Returns the size of the instructions, padding, and relocation information.
2958 inline int body_size();
2959
2960 // Returns the address of the first relocation info (read backwards!).
2961 inline byte* relocation_start();
2962
2963 // Code entry point.
2964 inline byte* entry();
2965
2966 // Returns true if pc is inside this object's instructions.
2967 inline bool contains(byte* pc);
2968
Steve Blocka7e24c12009-10-30 11:49:00 +00002969 // Relocate the code by delta bytes. Called to signal that this code
2970 // object has been moved by delta bytes.
Steve Blockd0582a62009-12-15 09:54:21 +00002971 void Relocate(intptr_t delta);
Steve Blocka7e24c12009-10-30 11:49:00 +00002972
2973 // Migrate code described by desc.
2974 void CopyFrom(const CodeDesc& desc);
2975
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002976 // Returns the object size for a given body (used for allocation).
2977 static int SizeFor(int body_size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002978 ASSERT_SIZE_TAG_ALIGNED(body_size);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002979 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
Steve Blocka7e24c12009-10-30 11:49:00 +00002980 }
2981
2982 // Calculate the size of the code object to report for log events. This takes
2983 // the layout of the code object into account.
2984 int ExecutableSize() {
2985 // Check that the assumptions about the layout of the code object holds.
2986 ASSERT_EQ(static_cast<int>(instruction_start() - address()),
2987 Code::kHeaderSize);
2988 return instruction_size() + Code::kHeaderSize;
2989 }
2990
2991 // Locating source position.
2992 int SourcePosition(Address pc);
2993 int SourceStatementPosition(Address pc);
2994
2995 // Casting.
2996 static inline Code* cast(Object* obj);
2997
2998 // Dispatched behavior.
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002999 int CodeSize() { return SizeFor(body_size()); }
Iain Merrick75681382010-08-19 15:07:18 +01003000 inline void CodeIterateBody(ObjectVisitor* v);
3001
3002 template<typename StaticVisitor>
3003 inline void CodeIterateBody();
Steve Blocka7e24c12009-10-30 11:49:00 +00003004#ifdef DEBUG
3005 void CodePrint();
3006 void CodeVerify();
3007#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003008 // Layout description.
3009 static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
Leon Clarkeac952652010-07-15 11:15:24 +01003010 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003011 static const int kFlagsOffset = kRelocationInfoOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003012 static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
3013 // Add padding to align the instruction start following right after
3014 // the Code object header.
3015 static const int kHeaderSize =
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003016 CODE_POINTER_ALIGN(kKindSpecificFlagsOffset + kIntSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00003017
3018 // Byte offsets within kKindSpecificFlagsOffset.
3019 static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset + 1;
3020
3021 // Flags layout.
3022 static const int kFlagsICStateShift = 0;
3023 static const int kFlagsICInLoopShift = 3;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01003024 static const int kFlagsTypeShift = 4;
3025 static const int kFlagsKindShift = 7;
Steve Block8defd9f2010-07-08 12:39:36 +01003026 static const int kFlagsICHolderShift = 11;
3027 static const int kFlagsArgumentsCountShift = 12;
Steve Blocka7e24c12009-10-30 11:49:00 +00003028
Steve Block6ded16b2010-05-10 14:33:55 +01003029 static const int kFlagsICStateMask = 0x00000007; // 00000000111
3030 static const int kFlagsICInLoopMask = 0x00000008; // 00000001000
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01003031 static const int kFlagsTypeMask = 0x00000070; // 00001110000
3032 static const int kFlagsKindMask = 0x00000780; // 11110000000
Steve Block8defd9f2010-07-08 12:39:36 +01003033 static const int kFlagsCacheInPrototypeMapMask = 0x00000800;
3034 static const int kFlagsArgumentsCountMask = 0xFFFFF000;
Steve Blocka7e24c12009-10-30 11:49:00 +00003035
3036 static const int kFlagsNotUsedInLookup =
Steve Block8defd9f2010-07-08 12:39:36 +01003037 (kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
Steve Blocka7e24c12009-10-30 11:49:00 +00003038
3039 private:
3040 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
3041};
3042
3043
3044// All heap objects have a Map that describes their structure.
3045// A Map contains information about:
3046// - Size information about the object
3047// - How to iterate over an object (for garbage collection)
3048class Map: public HeapObject {
3049 public:
3050 // Instance size.
Steve Block791712a2010-08-27 10:21:07 +01003051 // Size in bytes or kVariableSizeSentinel if instances do not have
3052 // a fixed size.
Steve Blocka7e24c12009-10-30 11:49:00 +00003053 inline int instance_size();
3054 inline void set_instance_size(int value);
3055
3056 // Count of properties allocated in the object.
3057 inline int inobject_properties();
3058 inline void set_inobject_properties(int value);
3059
3060 // Count of property fields pre-allocated in the object when first allocated.
3061 inline int pre_allocated_property_fields();
3062 inline void set_pre_allocated_property_fields(int value);
3063
3064 // Instance type.
3065 inline InstanceType instance_type();
3066 inline void set_instance_type(InstanceType value);
3067
3068 // Tells how many unused property fields are available in the
3069 // instance (only used for JSObject in fast mode).
3070 inline int unused_property_fields();
3071 inline void set_unused_property_fields(int value);
3072
3073 // Bit field.
3074 inline byte bit_field();
3075 inline void set_bit_field(byte value);
3076
3077 // Bit field 2.
3078 inline byte bit_field2();
3079 inline void set_bit_field2(byte value);
3080
3081 // Tells whether the object in the prototype property will be used
3082 // for instances created from this function. If the prototype
3083 // property is set to a value that is not a JSObject, the prototype
3084 // property will not be used to create instances of the function.
3085 // See ECMA-262, 13.2.2.
3086 inline void set_non_instance_prototype(bool value);
3087 inline bool has_non_instance_prototype();
3088
Steve Block6ded16b2010-05-10 14:33:55 +01003089 // Tells whether function has special prototype property. If not, prototype
3090 // property will not be created when accessed (will return undefined),
3091 // and construction from this function will not be allowed.
3092 inline void set_function_with_prototype(bool value);
3093 inline bool function_with_prototype();
3094
Steve Blocka7e24c12009-10-30 11:49:00 +00003095 // Tells whether the instance with this map should be ignored by the
3096 // __proto__ accessor.
3097 inline void set_is_hidden_prototype() {
3098 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
3099 }
3100
3101 inline bool is_hidden_prototype() {
3102 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
3103 }
3104
3105 // Records and queries whether the instance has a named interceptor.
3106 inline void set_has_named_interceptor() {
3107 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
3108 }
3109
3110 inline bool has_named_interceptor() {
3111 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
3112 }
3113
3114 // Records and queries whether the instance has an indexed interceptor.
3115 inline void set_has_indexed_interceptor() {
3116 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
3117 }
3118
3119 inline bool has_indexed_interceptor() {
3120 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
3121 }
3122
3123 // Tells whether the instance is undetectable.
3124 // An undetectable object is a special class of JSObject: 'typeof' operator
3125 // returns undefined, ToBoolean returns false. Otherwise it behaves like
3126 // a normal JS object. It is useful for implementing undetectable
3127 // document.all in Firefox & Safari.
3128 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
3129 inline void set_is_undetectable() {
3130 set_bit_field(bit_field() | (1 << kIsUndetectable));
3131 }
3132
3133 inline bool is_undetectable() {
3134 return ((1 << kIsUndetectable) & bit_field()) != 0;
3135 }
3136
Steve Blocka7e24c12009-10-30 11:49:00 +00003137 // Tells whether the instance has a call-as-function handler.
3138 inline void set_has_instance_call_handler() {
3139 set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
3140 }
3141
3142 inline bool has_instance_call_handler() {
3143 return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
3144 }
3145
Steve Block8defd9f2010-07-08 12:39:36 +01003146 inline void set_is_extensible(bool value);
3147 inline bool is_extensible();
3148
3149 // Tells whether the instance has fast elements.
Iain Merrick75681382010-08-19 15:07:18 +01003150 // Equivalent to instance->GetElementsKind() == FAST_ELEMENTS.
3151 inline void set_has_fast_elements(bool value) {
Steve Block8defd9f2010-07-08 12:39:36 +01003152 if (value) {
3153 set_bit_field2(bit_field2() | (1 << kHasFastElements));
3154 } else {
3155 set_bit_field2(bit_field2() & ~(1 << kHasFastElements));
3156 }
Leon Clarkee46be812010-01-19 14:06:41 +00003157 }
3158
Iain Merrick75681382010-08-19 15:07:18 +01003159 inline bool has_fast_elements() {
Steve Block8defd9f2010-07-08 12:39:36 +01003160 return ((1 << kHasFastElements) & bit_field2()) != 0;
Leon Clarkee46be812010-01-19 14:06:41 +00003161 }
3162
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003163 // Tells whether the map is attached to SharedFunctionInfo
3164 // (for inobject slack tracking).
3165 inline void set_attached_to_shared_function_info(bool value);
3166
3167 inline bool attached_to_shared_function_info();
3168
3169 // Tells whether the map is shared between objects that may have different
3170 // behavior. If true, the map should never be modified, instead a clone
3171 // should be created and modified.
3172 inline void set_is_shared(bool value);
3173
3174 inline bool is_shared();
3175
Steve Blocka7e24c12009-10-30 11:49:00 +00003176 // Tells whether the instance needs security checks when accessing its
3177 // properties.
3178 inline void set_is_access_check_needed(bool access_check_needed);
3179 inline bool is_access_check_needed();
3180
3181 // [prototype]: implicit prototype object.
3182 DECL_ACCESSORS(prototype, Object)
3183
3184 // [constructor]: points back to the function responsible for this map.
3185 DECL_ACCESSORS(constructor, Object)
3186
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003187 inline JSFunction* unchecked_constructor();
3188
Steve Blocka7e24c12009-10-30 11:49:00 +00003189 // [instance descriptors]: describes the object.
3190 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
3191
3192 // [stub cache]: contains stubs compiled for this map.
Steve Block6ded16b2010-05-10 14:33:55 +01003193 DECL_ACCESSORS(code_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00003194
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003195 MUST_USE_RESULT Object* CopyDropDescriptors();
3196
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003197 MUST_USE_RESULT Object* CopyNormalized(PropertyNormalizationMode mode,
3198 NormalizedMapSharingMode sharing);
Steve Blocka7e24c12009-10-30 11:49:00 +00003199
3200 // Returns a copy of the map, with all transitions dropped from the
3201 // instance descriptors.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003202 MUST_USE_RESULT Object* CopyDropTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00003203
Steve Block8defd9f2010-07-08 12:39:36 +01003204 // Returns this map if it has the fast elements bit set, otherwise
3205 // returns a copy of the map, with all transitions dropped from the
3206 // descriptors and the fast elements bit set.
3207 inline Object* GetFastElementsMap();
3208
3209 // Returns this map if it has the fast elements bit cleared,
3210 // otherwise returns a copy of the map, with all transitions dropped
3211 // from the descriptors and the fast elements bit cleared.
3212 inline Object* GetSlowElementsMap();
3213
Steve Blocka7e24c12009-10-30 11:49:00 +00003214 // Returns the property index for name (only valid for FAST MODE).
3215 int PropertyIndexFor(String* name);
3216
3217 // Returns the next free property index (only valid for FAST MODE).
3218 int NextFreePropertyIndex();
3219
3220 // Returns the number of properties described in instance_descriptors.
3221 int NumberOfDescribedProperties();
3222
3223 // Casting.
3224 static inline Map* cast(Object* obj);
3225
3226 // Locate an accessor in the instance descriptor.
3227 AccessorDescriptor* FindAccessor(String* name);
3228
3229 // Code cache operations.
3230
3231 // Clears the code cache.
3232 inline void ClearCodeCache();
3233
3234 // Update code cache.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003235 MUST_USE_RESULT Object* UpdateCodeCache(String* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00003236
3237 // Returns the found code or undefined if absent.
3238 Object* FindInCodeCache(String* name, Code::Flags flags);
3239
3240 // Returns the non-negative index of the code object if it is in the
3241 // cache and -1 otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +01003242 int IndexInCodeCache(Object* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00003243
3244 // Removes a code object from the code cache at the given index.
Steve Block6ded16b2010-05-10 14:33:55 +01003245 void RemoveFromCodeCache(String* name, Code* code, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003246
3247 // For every transition in this map, makes the transition's
3248 // target's prototype pointer point back to this map.
3249 // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
3250 void CreateBackPointers();
3251
3252 // Set all map transitions from this map to dead maps to null.
3253 // Also, restore the original prototype on the targets of these
3254 // transitions, so that we do not process this map again while
3255 // following back pointers.
3256 void ClearNonLiveTransitions(Object* real_prototype);
3257
3258 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00003259#ifdef DEBUG
3260 void MapPrint();
3261 void MapVerify();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003262 void SharedMapVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00003263#endif
3264
Iain Merrick75681382010-08-19 15:07:18 +01003265 inline int visitor_id();
3266 inline void set_visitor_id(int visitor_id);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003267
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003268 typedef void (*TraverseCallback)(Map* map, void* data);
3269
3270 void TraverseTransitionTree(TraverseCallback callback, void* data);
3271
Steve Blocka7e24c12009-10-30 11:49:00 +00003272 static const int kMaxPreAllocatedPropertyFields = 255;
3273
3274 // Layout description.
3275 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
3276 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
3277 static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
3278 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
3279 static const int kInstanceDescriptorsOffset =
3280 kConstructorOffset + kPointerSize;
3281 static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
Iain Merrick9ac36c92010-09-13 15:29:50 +01003282 static const int kPadStart = kCodeCacheOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003283 static const int kSize = MAP_POINTER_ALIGN(kPadStart);
3284
3285 // Layout of pointer fields. Heap iteration code relies on them
3286 // being continiously allocated.
3287 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
3288 static const int kPointerFieldsEndOffset =
3289 Map::kCodeCacheOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003290
3291 // Byte offsets within kInstanceSizesOffset.
3292 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
3293 static const int kInObjectPropertiesByte = 1;
3294 static const int kInObjectPropertiesOffset =
3295 kInstanceSizesOffset + kInObjectPropertiesByte;
3296 static const int kPreAllocatedPropertyFieldsByte = 2;
3297 static const int kPreAllocatedPropertyFieldsOffset =
3298 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
Iain Merrick9ac36c92010-09-13 15:29:50 +01003299 static const int kVisitorIdByte = 3;
3300 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
Steve Blocka7e24c12009-10-30 11:49:00 +00003301
3302 // Byte offsets within kInstanceAttributesOffset attributes.
3303 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
3304 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
3305 static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
3306 static const int kBitField2Offset = kInstanceAttributesOffset + 3;
3307
3308 STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
3309
3310 // Bit positions for bit field.
3311 static const int kUnused = 0; // To be used for marking recently used maps.
3312 static const int kHasNonInstancePrototype = 1;
3313 static const int kIsHiddenPrototype = 2;
3314 static const int kHasNamedInterceptor = 3;
3315 static const int kHasIndexedInterceptor = 4;
3316 static const int kIsUndetectable = 5;
3317 static const int kHasInstanceCallHandler = 6;
3318 static const int kIsAccessCheckNeeded = 7;
3319
3320 // Bit positions for bit field 2
Andrei Popescu31002712010-02-23 13:46:05 +00003321 static const int kIsExtensible = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003322 static const int kFunctionWithPrototype = 1;
Steve Block8defd9f2010-07-08 12:39:36 +01003323 static const int kHasFastElements = 2;
Iain Merrick75681382010-08-19 15:07:18 +01003324 static const int kStringWrapperSafeForDefaultValueOf = 3;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003325 static const int kAttachedToSharedFunctionInfo = 4;
3326 static const int kIsShared = 5;
Steve Block6ded16b2010-05-10 14:33:55 +01003327
3328 // Layout of the default cache. It holds alternating name and code objects.
3329 static const int kCodeCacheEntrySize = 2;
3330 static const int kCodeCacheEntryNameOffset = 0;
3331 static const int kCodeCacheEntryCodeOffset = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00003332
Iain Merrick75681382010-08-19 15:07:18 +01003333 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
3334 kPointerFieldsEndOffset,
3335 kSize> BodyDescriptor;
3336
Steve Blocka7e24c12009-10-30 11:49:00 +00003337 private:
3338 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
3339};
3340
3341
3342// An abstract superclass, a marker class really, for simple structure classes.
3343// It doesn't carry much functionality but allows struct classes to me
3344// identified in the type system.
3345class Struct: public HeapObject {
3346 public:
3347 inline void InitializeBody(int object_size);
3348 static inline Struct* cast(Object* that);
3349};
3350
3351
3352// Script describes a script which has been added to the VM.
3353class Script: public Struct {
3354 public:
3355 // Script types.
3356 enum Type {
3357 TYPE_NATIVE = 0,
3358 TYPE_EXTENSION = 1,
3359 TYPE_NORMAL = 2
3360 };
3361
3362 // Script compilation types.
3363 enum CompilationType {
3364 COMPILATION_TYPE_HOST = 0,
3365 COMPILATION_TYPE_EVAL = 1,
3366 COMPILATION_TYPE_JSON = 2
3367 };
3368
3369 // [source]: the script source.
3370 DECL_ACCESSORS(source, Object)
3371
3372 // [name]: the script name.
3373 DECL_ACCESSORS(name, Object)
3374
3375 // [id]: the script id.
3376 DECL_ACCESSORS(id, Object)
3377
3378 // [line_offset]: script line offset in resource from where it was extracted.
3379 DECL_ACCESSORS(line_offset, Smi)
3380
3381 // [column_offset]: script column offset in resource from where it was
3382 // extracted.
3383 DECL_ACCESSORS(column_offset, Smi)
3384
3385 // [data]: additional data associated with this script.
3386 DECL_ACCESSORS(data, Object)
3387
3388 // [context_data]: context data for the context this script was compiled in.
3389 DECL_ACCESSORS(context_data, Object)
3390
3391 // [wrapper]: the wrapper cache.
3392 DECL_ACCESSORS(wrapper, Proxy)
3393
3394 // [type]: the script type.
3395 DECL_ACCESSORS(type, Smi)
3396
3397 // [compilation]: how the the script was compiled.
3398 DECL_ACCESSORS(compilation_type, Smi)
3399
Steve Blockd0582a62009-12-15 09:54:21 +00003400 // [line_ends]: FixedArray of line ends positions.
Steve Blocka7e24c12009-10-30 11:49:00 +00003401 DECL_ACCESSORS(line_ends, Object)
3402
Steve Blockd0582a62009-12-15 09:54:21 +00003403 // [eval_from_shared]: for eval scripts the shared funcion info for the
3404 // function from which eval was called.
3405 DECL_ACCESSORS(eval_from_shared, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00003406
3407 // [eval_from_instructions_offset]: the instruction offset in the code for the
3408 // function from which eval was called where eval was called.
3409 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
3410
3411 static inline Script* cast(Object* obj);
3412
Steve Block3ce2e202009-11-05 08:53:23 +00003413 // If script source is an external string, check that the underlying
3414 // resource is accessible. Otherwise, always return true.
3415 inline bool HasValidSource();
3416
Steve Blocka7e24c12009-10-30 11:49:00 +00003417#ifdef DEBUG
3418 void ScriptPrint();
3419 void ScriptVerify();
3420#endif
3421
3422 static const int kSourceOffset = HeapObject::kHeaderSize;
3423 static const int kNameOffset = kSourceOffset + kPointerSize;
3424 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
3425 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
3426 static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
3427 static const int kContextOffset = kDataOffset + kPointerSize;
3428 static const int kWrapperOffset = kContextOffset + kPointerSize;
3429 static const int kTypeOffset = kWrapperOffset + kPointerSize;
3430 static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
3431 static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
3432 static const int kIdOffset = kLineEndsOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00003433 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003434 static const int kEvalFrominstructionsOffsetOffset =
Steve Blockd0582a62009-12-15 09:54:21 +00003435 kEvalFromSharedOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003436 static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
3437
3438 private:
3439 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
3440};
3441
3442
3443// SharedFunctionInfo describes the JSFunction information that can be
3444// shared by multiple instances of the function.
3445class SharedFunctionInfo: public HeapObject {
3446 public:
3447 // [name]: Function name.
3448 DECL_ACCESSORS(name, Object)
3449
3450 // [code]: Function code.
3451 DECL_ACCESSORS(code, Code)
3452
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003453 // [scope_info]: Scope info.
3454 DECL_ACCESSORS(scope_info, SerializedScopeInfo)
3455
Steve Blocka7e24c12009-10-30 11:49:00 +00003456 // [construct stub]: Code stub for constructing instances of this function.
3457 DECL_ACCESSORS(construct_stub, Code)
3458
Iain Merrick75681382010-08-19 15:07:18 +01003459 inline Code* unchecked_code();
3460
Steve Blocka7e24c12009-10-30 11:49:00 +00003461 // Returns if this function has been compiled to native code yet.
3462 inline bool is_compiled();
3463
3464 // [length]: The function length - usually the number of declared parameters.
3465 // Use up to 2^30 parameters.
3466 inline int length();
3467 inline void set_length(int value);
3468
3469 // [formal parameter count]: The declared number of parameters.
3470 inline int formal_parameter_count();
3471 inline void set_formal_parameter_count(int value);
3472
3473 // Set the formal parameter count so the function code will be
3474 // called without using argument adaptor frames.
3475 inline void DontAdaptArguments();
3476
3477 // [expected_nof_properties]: Expected number of properties for the function.
3478 inline int expected_nof_properties();
3479 inline void set_expected_nof_properties(int value);
3480
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003481 // Inobject slack tracking is the way to reclaim unused inobject space.
3482 //
3483 // The instance size is initially determined by adding some slack to
3484 // expected_nof_properties (to allow for a few extra properties added
3485 // after the constructor). There is no guarantee that the extra space
3486 // will not be wasted.
3487 //
3488 // Here is the algorithm to reclaim the unused inobject space:
3489 // - Detect the first constructor call for this SharedFunctionInfo.
3490 // When it happens enter the "in progress" state: remember the
3491 // constructor's initial_map and install a special construct stub that
3492 // counts constructor calls.
3493 // - While the tracking is in progress create objects filled with
3494 // one_pointer_filler_map instead of undefined_value. This way they can be
3495 // resized quickly and safely.
3496 // - Once enough (kGenerousAllocationCount) objects have been created
3497 // compute the 'slack' (traverse the map transition tree starting from the
3498 // initial_map and find the lowest value of unused_property_fields).
3499 // - Traverse the transition tree again and decrease the instance size
3500 // of every map. Existing objects will resize automatically (they are
3501 // filled with one_pointer_filler_map). All further allocations will
3502 // use the adjusted instance size.
3503 // - Decrease expected_nof_properties so that an allocations made from
3504 // another context will use the adjusted instance size too.
3505 // - Exit "in progress" state by clearing the reference to the initial_map
3506 // and setting the regular construct stub (generic or inline).
3507 //
3508 // The above is the main event sequence. Some special cases are possible
3509 // while the tracking is in progress:
3510 //
3511 // - GC occurs.
3512 // Check if the initial_map is referenced by any live objects (except this
3513 // SharedFunctionInfo). If it is, continue tracking as usual.
3514 // If it is not, clear the reference and reset the tracking state. The
3515 // tracking will be initiated again on the next constructor call.
3516 //
3517 // - The constructor is called from another context.
3518 // Immediately complete the tracking, perform all the necessary changes
3519 // to maps. This is necessary because there is no efficient way to track
3520 // multiple initial_maps.
3521 // Proceed to create an object in the current context (with the adjusted
3522 // size).
3523 //
3524 // - A different constructor function sharing the same SharedFunctionInfo is
3525 // called in the same context. This could be another closure in the same
3526 // context, or the first function could have been disposed.
3527 // This is handled the same way as the previous case.
3528 //
3529 // Important: inobject slack tracking is not attempted during the snapshot
3530 // creation.
3531
Ben Murdochf87a2032010-10-22 12:50:53 +01003532 static const int kGenerousAllocationCount = 8;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003533
3534 // [construction_count]: Counter for constructor calls made during
3535 // the tracking phase.
3536 inline int construction_count();
3537 inline void set_construction_count(int value);
3538
3539 // [initial_map]: initial map of the first function called as a constructor.
3540 // Saved for the duration of the tracking phase.
3541 // This is a weak link (GC resets it to undefined_value if no other live
3542 // object reference this map).
3543 DECL_ACCESSORS(initial_map, Object)
3544
3545 // True if the initial_map is not undefined and the countdown stub is
3546 // installed.
3547 inline bool IsInobjectSlackTrackingInProgress();
3548
3549 // Starts the tracking.
3550 // Stores the initial map and installs the countdown stub.
3551 // IsInobjectSlackTrackingInProgress is normally true after this call,
3552 // except when tracking have not been started (e.g. the map has no unused
3553 // properties or the snapshot is being built).
3554 void StartInobjectSlackTracking(Map* map);
3555
3556 // Completes the tracking.
3557 // IsInobjectSlackTrackingInProgress is false after this call.
3558 void CompleteInobjectSlackTracking();
3559
3560 // Clears the initial_map before the GC marking phase to ensure the reference
3561 // is weak. IsInobjectSlackTrackingInProgress is false after this call.
3562 void DetachInitialMap();
3563
3564 // Restores the link to the initial map after the GC marking phase.
3565 // IsInobjectSlackTrackingInProgress is true after this call.
3566 void AttachInitialMap(Map* map);
3567
3568 // False if there are definitely no live objects created from this function.
3569 // True if live objects _may_ exist (existence not guaranteed).
3570 // May go back from true to false after GC.
3571 inline bool live_objects_may_exist();
3572
3573 inline void set_live_objects_may_exist(bool value);
3574
Steve Blocka7e24c12009-10-30 11:49:00 +00003575 // [instance class name]: class name for instances.
3576 DECL_ACCESSORS(instance_class_name, Object)
3577
Steve Block6ded16b2010-05-10 14:33:55 +01003578 // [function data]: This field holds some additional data for function.
3579 // Currently it either has FunctionTemplateInfo to make benefit the API
Kristian Monsen25f61362010-05-21 11:50:48 +01003580 // or Smi identifying a custom call generator.
Steve Blocka7e24c12009-10-30 11:49:00 +00003581 // In the long run we don't want all functions to have this field but
3582 // we can fix that when we have a better model for storing hidden data
3583 // on objects.
3584 DECL_ACCESSORS(function_data, Object)
3585
Steve Block6ded16b2010-05-10 14:33:55 +01003586 inline bool IsApiFunction();
3587 inline FunctionTemplateInfo* get_api_func_data();
3588 inline bool HasCustomCallGenerator();
Kristian Monsen25f61362010-05-21 11:50:48 +01003589 inline int custom_call_generator_id();
Steve Block6ded16b2010-05-10 14:33:55 +01003590
Steve Blocka7e24c12009-10-30 11:49:00 +00003591 // [script info]: Script from which the function originates.
3592 DECL_ACCESSORS(script, Object)
3593
Steve Block6ded16b2010-05-10 14:33:55 +01003594 // [num_literals]: Number of literals used by this function.
3595 inline int num_literals();
3596 inline void set_num_literals(int value);
3597
Steve Blocka7e24c12009-10-30 11:49:00 +00003598 // [start_position_and_type]: Field used to store both the source code
3599 // position, whether or not the function is a function expression,
3600 // and whether or not the function is a toplevel function. The two
3601 // least significants bit indicates whether the function is an
3602 // expression and the rest contains the source code position.
3603 inline int start_position_and_type();
3604 inline void set_start_position_and_type(int value);
3605
3606 // [debug info]: Debug information.
3607 DECL_ACCESSORS(debug_info, Object)
3608
3609 // [inferred name]: Name inferred from variable or property
3610 // assignment of this function. Used to facilitate debugging and
3611 // profiling of JavaScript code written in OO style, where almost
3612 // all functions are anonymous but are assigned to object
3613 // properties.
3614 DECL_ACCESSORS(inferred_name, String)
3615
Ben Murdochf87a2032010-10-22 12:50:53 +01003616 // The function's name if it is non-empty, otherwise the inferred name.
3617 String* DebugName();
3618
Steve Blocka7e24c12009-10-30 11:49:00 +00003619 // Position of the 'function' token in the script source.
3620 inline int function_token_position();
3621 inline void set_function_token_position(int function_token_position);
3622
3623 // Position of this function in the script source.
3624 inline int start_position();
3625 inline void set_start_position(int start_position);
3626
3627 // End position of this function in the script source.
3628 inline int end_position();
3629 inline void set_end_position(int end_position);
3630
3631 // Is this function a function expression in the source code.
3632 inline bool is_expression();
3633 inline void set_is_expression(bool value);
3634
3635 // Is this function a top-level function (scripts, evals).
3636 inline bool is_toplevel();
3637 inline void set_is_toplevel(bool value);
3638
3639 // Bit field containing various information collected by the compiler to
3640 // drive optimization.
3641 inline int compiler_hints();
3642 inline void set_compiler_hints(int value);
3643
3644 // Add information on assignments of the form this.x = ...;
3645 void SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +00003646 bool has_only_simple_this_property_assignments,
3647 FixedArray* this_property_assignments);
3648
3649 // Clear information on assignments of the form this.x = ...;
3650 void ClearThisPropertyAssignmentsInfo();
3651
3652 // Indicate that this function only consists of assignments of the form
Steve Blocka7e24c12009-10-30 11:49:00 +00003653 // this.x = y; where y is either a constant or refers to an argument.
3654 inline bool has_only_simple_this_property_assignments();
3655
Leon Clarked91b9f72010-01-27 17:25:45 +00003656 inline bool try_full_codegen();
3657 inline void set_try_full_codegen(bool flag);
Steve Blockd0582a62009-12-15 09:54:21 +00003658
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003659 // Indicates if this function can be lazy compiled.
3660 // This is used to determine if we can safely flush code from a function
3661 // when doing GC if we expect that the function will no longer be used.
3662 inline bool allows_lazy_compilation();
3663 inline void set_allows_lazy_compilation(bool flag);
3664
Iain Merrick75681382010-08-19 15:07:18 +01003665 // Indicates how many full GCs this function has survived with assigned
3666 // code object. Used to determine when it is relatively safe to flush
3667 // this code object and replace it with lazy compilation stub.
3668 // Age is reset when GC notices that the code object is referenced
3669 // from the stack or compilation cache.
3670 inline int code_age();
3671 inline void set_code_age(int age);
3672
3673
Andrei Popescu402d9372010-02-26 13:31:12 +00003674 // Check whether a inlined constructor can be generated with the given
3675 // prototype.
3676 bool CanGenerateInlineConstructor(Object* prototype);
3677
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003678 // Prevents further attempts to generate inline constructors.
3679 // To be called if generation failed for any reason.
3680 void ForbidInlineConstructor();
3681
Steve Blocka7e24c12009-10-30 11:49:00 +00003682 // For functions which only contains this property assignments this provides
3683 // access to the names for the properties assigned.
3684 DECL_ACCESSORS(this_property_assignments, Object)
3685 inline int this_property_assignments_count();
3686 inline void set_this_property_assignments_count(int value);
3687 String* GetThisPropertyAssignmentName(int index);
3688 bool IsThisPropertyAssignmentArgument(int index);
3689 int GetThisPropertyAssignmentArgument(int index);
3690 Object* GetThisPropertyAssignmentConstant(int index);
3691
3692 // [source code]: Source code for the function.
3693 bool HasSourceCode();
3694 Object* GetSourceCode();
3695
3696 // Calculate the instance size.
3697 int CalculateInstanceSize();
3698
3699 // Calculate the number of in-object properties.
3700 int CalculateInObjectProperties();
3701
3702 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00003703 // Set max_length to -1 for unlimited length.
3704 void SourceCodePrint(StringStream* accumulator, int max_length);
3705#ifdef DEBUG
3706 void SharedFunctionInfoPrint();
3707 void SharedFunctionInfoVerify();
3708#endif
3709
3710 // Casting.
3711 static inline SharedFunctionInfo* cast(Object* obj);
3712
3713 // Constants.
3714 static const int kDontAdaptArgumentsSentinel = -1;
3715
3716 // Layout description.
Steve Block6ded16b2010-05-10 14:33:55 +01003717 // Pointer fields.
Steve Blocka7e24c12009-10-30 11:49:00 +00003718 static const int kNameOffset = HeapObject::kHeaderSize;
3719 static const int kCodeOffset = kNameOffset + kPointerSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003720 static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
3721 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01003722 static const int kInstanceClassNameOffset =
3723 kConstructStubOffset + kPointerSize;
3724 static const int kFunctionDataOffset =
3725 kInstanceClassNameOffset + kPointerSize;
3726 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
3727 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
3728 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003729 static const int kInitialMapOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01003730 kInferredNameOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003731 static const int kThisPropertyAssignmentsOffset =
3732 kInitialMapOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003733#if V8_HOST_ARCH_32_BIT
3734 // Smi fields.
Steve Block6ded16b2010-05-10 14:33:55 +01003735 static const int kLengthOffset =
3736 kThisPropertyAssignmentsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003737 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
3738 static const int kExpectedNofPropertiesOffset =
3739 kFormalParameterCountOffset + kPointerSize;
3740 static const int kNumLiteralsOffset =
3741 kExpectedNofPropertiesOffset + kPointerSize;
3742 static const int kStartPositionAndTypeOffset =
3743 kNumLiteralsOffset + kPointerSize;
3744 static const int kEndPositionOffset =
3745 kStartPositionAndTypeOffset + kPointerSize;
3746 static const int kFunctionTokenPositionOffset =
3747 kEndPositionOffset + kPointerSize;
3748 static const int kCompilerHintsOffset =
3749 kFunctionTokenPositionOffset + kPointerSize;
3750 static const int kThisPropertyAssignmentsCountOffset =
3751 kCompilerHintsOffset + kPointerSize;
3752 // Total size.
3753 static const int kSize = kThisPropertyAssignmentsCountOffset + kPointerSize;
3754#else
3755 // The only reason to use smi fields instead of int fields
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003756 // is to allow iteration without maps decoding during
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003757 // garbage collections.
3758 // To avoid wasting space on 64-bit architectures we use
3759 // the following trick: we group integer fields into pairs
3760 // First integer in each pair is shifted left by 1.
3761 // By doing this we guarantee that LSB of each kPointerSize aligned
3762 // word is not set and thus this word cannot be treated as pointer
3763 // to HeapObject during old space traversal.
3764 static const int kLengthOffset =
3765 kThisPropertyAssignmentsOffset + kPointerSize;
3766 static const int kFormalParameterCountOffset =
3767 kLengthOffset + kIntSize;
3768
Steve Blocka7e24c12009-10-30 11:49:00 +00003769 static const int kExpectedNofPropertiesOffset =
3770 kFormalParameterCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003771 static const int kNumLiteralsOffset =
3772 kExpectedNofPropertiesOffset + kIntSize;
3773
3774 static const int kEndPositionOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01003775 kNumLiteralsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003776 static const int kStartPositionAndTypeOffset =
3777 kEndPositionOffset + kIntSize;
3778
3779 static const int kFunctionTokenPositionOffset =
3780 kStartPositionAndTypeOffset + kIntSize;
Steve Block6ded16b2010-05-10 14:33:55 +01003781 static const int kCompilerHintsOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00003782 kFunctionTokenPositionOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003783
Steve Blocka7e24c12009-10-30 11:49:00 +00003784 static const int kThisPropertyAssignmentsCountOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01003785 kCompilerHintsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003786
Steve Block6ded16b2010-05-10 14:33:55 +01003787 // Total size.
3788 static const int kSize = kThisPropertyAssignmentsCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003789
3790#endif
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003791
3792 // The construction counter for inobject slack tracking is stored in the
3793 // most significant byte of compiler_hints which is otherwise unused.
3794 // Its offset depends on the endian-ness of the architecture.
3795#if __BYTE_ORDER == __LITTLE_ENDIAN
3796 static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
3797#elif __BYTE_ORDER == __BIG_ENDIAN
3798 static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
3799#else
3800#error Unknown byte ordering
3801#endif
3802
Steve Block6ded16b2010-05-10 14:33:55 +01003803 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00003804
Iain Merrick75681382010-08-19 15:07:18 +01003805 typedef FixedBodyDescriptor<kNameOffset,
3806 kThisPropertyAssignmentsOffset + kPointerSize,
3807 kSize> BodyDescriptor;
3808
Steve Blocka7e24c12009-10-30 11:49:00 +00003809 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00003810 // Bit positions in start_position_and_type.
3811 // The source code start position is in the 30 most significant bits of
3812 // the start_position_and_type field.
3813 static const int kIsExpressionBit = 0;
3814 static const int kIsTopLevelBit = 1;
3815 static const int kStartPositionShift = 2;
3816 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
3817
3818 // Bit positions in compiler_hints.
Steve Blockd0582a62009-12-15 09:54:21 +00003819 static const int kHasOnlySimpleThisPropertyAssignments = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +00003820 static const int kTryFullCodegen = 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003821 static const int kAllowLazyCompilation = 2;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003822 static const int kLiveObjectsMayExist = 3;
3823 static const int kCodeAgeShift = 4;
Iain Merrick75681382010-08-19 15:07:18 +01003824 static const int kCodeAgeMask = 7;
Steve Blocka7e24c12009-10-30 11:49:00 +00003825
3826 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
3827};
3828
3829
3830// JSFunction describes JavaScript functions.
3831class JSFunction: public JSObject {
3832 public:
3833 // [prototype_or_initial_map]:
3834 DECL_ACCESSORS(prototype_or_initial_map, Object)
3835
3836 // [shared_function_info]: The information about the function that
3837 // can be shared by instances.
3838 DECL_ACCESSORS(shared, SharedFunctionInfo)
3839
Iain Merrick75681382010-08-19 15:07:18 +01003840 inline SharedFunctionInfo* unchecked_shared();
3841
Steve Blocka7e24c12009-10-30 11:49:00 +00003842 // [context]: The context for this function.
3843 inline Context* context();
3844 inline Object* unchecked_context();
3845 inline void set_context(Object* context);
3846
3847 // [code]: The generated code object for this function. Executed
3848 // when the function is invoked, e.g. foo() or new foo(). See
3849 // [[Call]] and [[Construct]] description in ECMA-262, section
3850 // 8.6.2, page 27.
3851 inline Code* code();
3852 inline void set_code(Code* value);
3853
Iain Merrick75681382010-08-19 15:07:18 +01003854 inline Code* unchecked_code();
3855
Steve Blocka7e24c12009-10-30 11:49:00 +00003856 // Tells whether this function is builtin.
3857 inline bool IsBuiltin();
3858
3859 // [literals]: Fixed array holding the materialized literals.
3860 //
3861 // If the function contains object, regexp or array literals, the
3862 // literals array prefix contains the object, regexp, and array
3863 // function to be used when creating these literals. This is
3864 // necessary so that we do not dynamically lookup the object, regexp
3865 // or array functions. Performing a dynamic lookup, we might end up
3866 // using the functions from a new context that we should not have
3867 // access to.
3868 DECL_ACCESSORS(literals, FixedArray)
3869
3870 // The initial map for an object created by this constructor.
3871 inline Map* initial_map();
3872 inline void set_initial_map(Map* value);
3873 inline bool has_initial_map();
3874
3875 // Get and set the prototype property on a JSFunction. If the
3876 // function has an initial map the prototype is set on the initial
3877 // map. Otherwise, the prototype is put in the initial map field
3878 // until an initial map is needed.
3879 inline bool has_prototype();
3880 inline bool has_instance_prototype();
3881 inline Object* prototype();
3882 inline Object* instance_prototype();
3883 Object* SetInstancePrototype(Object* value);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003884 MUST_USE_RESULT Object* SetPrototype(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003885
Steve Block6ded16b2010-05-10 14:33:55 +01003886 // After prototype is removed, it will not be created when accessed, and
3887 // [[Construct]] from this function will not be allowed.
3888 Object* RemovePrototype();
3889 inline bool should_have_prototype();
3890
Steve Blocka7e24c12009-10-30 11:49:00 +00003891 // Accessor for this function's initial map's [[class]]
3892 // property. This is primarily used by ECMA native functions. This
3893 // method sets the class_name field of this function's initial map
3894 // to a given value. It creates an initial map if this function does
3895 // not have one. Note that this method does not copy the initial map
3896 // if it has one already, but simply replaces it with the new value.
3897 // Instances created afterwards will have a map whose [[class]] is
3898 // set to 'value', but there is no guarantees on instances created
3899 // before.
3900 Object* SetInstanceClassName(String* name);
3901
3902 // Returns if this function has been compiled to native code yet.
3903 inline bool is_compiled();
3904
3905 // Casting.
3906 static inline JSFunction* cast(Object* obj);
3907
Steve Block791712a2010-08-27 10:21:07 +01003908 // Iterates the objects, including code objects indirectly referenced
3909 // through pointers to the first instruction in the code object.
3910 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
3911
Steve Blocka7e24c12009-10-30 11:49:00 +00003912 // Dispatched behavior.
3913#ifdef DEBUG
3914 void JSFunctionPrint();
3915 void JSFunctionVerify();
3916#endif
3917
3918 // Returns the number of allocated literals.
3919 inline int NumberOfLiterals();
3920
3921 // Retrieve the global context from a function's literal array.
3922 static Context* GlobalContextFromLiterals(FixedArray* literals);
3923
3924 // Layout descriptors.
Steve Block791712a2010-08-27 10:21:07 +01003925 static const int kCodeEntryOffset = JSObject::kHeaderSize;
Iain Merrick75681382010-08-19 15:07:18 +01003926 static const int kPrototypeOrInitialMapOffset =
Steve Block791712a2010-08-27 10:21:07 +01003927 kCodeEntryOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003928 static const int kSharedFunctionInfoOffset =
3929 kPrototypeOrInitialMapOffset + kPointerSize;
3930 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
3931 static const int kLiteralsOffset = kContextOffset + kPointerSize;
3932 static const int kSize = kLiteralsOffset + kPointerSize;
3933
3934 // Layout of the literals array.
3935 static const int kLiteralsPrefixSize = 1;
3936 static const int kLiteralGlobalContextIndex = 0;
3937 private:
3938 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
3939};
3940
3941
3942// JSGlobalProxy's prototype must be a JSGlobalObject or null,
3943// and the prototype is hidden. JSGlobalProxy always delegates
3944// property accesses to its prototype if the prototype is not null.
3945//
3946// A JSGlobalProxy can be reinitialized which will preserve its identity.
3947//
3948// Accessing a JSGlobalProxy requires security check.
3949
3950class JSGlobalProxy : public JSObject {
3951 public:
3952 // [context]: the owner global context of this proxy object.
3953 // It is null value if this object is not used by any context.
3954 DECL_ACCESSORS(context, Object)
3955
3956 // Casting.
3957 static inline JSGlobalProxy* cast(Object* obj);
3958
3959 // Dispatched behavior.
3960#ifdef DEBUG
3961 void JSGlobalProxyPrint();
3962 void JSGlobalProxyVerify();
3963#endif
3964
3965 // Layout description.
3966 static const int kContextOffset = JSObject::kHeaderSize;
3967 static const int kSize = kContextOffset + kPointerSize;
3968
3969 private:
3970
3971 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
3972};
3973
3974
3975// Forward declaration.
3976class JSBuiltinsObject;
3977
3978// Common super class for JavaScript global objects and the special
3979// builtins global objects.
3980class GlobalObject: public JSObject {
3981 public:
3982 // [builtins]: the object holding the runtime routines written in JS.
3983 DECL_ACCESSORS(builtins, JSBuiltinsObject)
3984
3985 // [global context]: the global context corresponding to this global object.
3986 DECL_ACCESSORS(global_context, Context)
3987
3988 // [global receiver]: the global receiver object of the context
3989 DECL_ACCESSORS(global_receiver, JSObject)
3990
3991 // Retrieve the property cell used to store a property.
3992 Object* GetPropertyCell(LookupResult* result);
3993
3994 // Ensure that the global object has a cell for the given property name.
3995 Object* EnsurePropertyCell(String* name);
3996
3997 // Casting.
3998 static inline GlobalObject* cast(Object* obj);
3999
4000 // Layout description.
4001 static const int kBuiltinsOffset = JSObject::kHeaderSize;
4002 static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
4003 static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
4004 static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
4005
4006 private:
4007 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
4008
4009 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
4010};
4011
4012
4013// JavaScript global object.
4014class JSGlobalObject: public GlobalObject {
4015 public:
4016
4017 // Casting.
4018 static inline JSGlobalObject* cast(Object* obj);
4019
4020 // Dispatched behavior.
4021#ifdef DEBUG
4022 void JSGlobalObjectPrint();
4023 void JSGlobalObjectVerify();
4024#endif
4025
4026 // Layout description.
4027 static const int kSize = GlobalObject::kHeaderSize;
4028
4029 private:
4030 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
4031};
4032
4033
4034// Builtins global object which holds the runtime routines written in
4035// JavaScript.
4036class JSBuiltinsObject: public GlobalObject {
4037 public:
4038 // Accessors for the runtime routines written in JavaScript.
4039 inline Object* javascript_builtin(Builtins::JavaScript id);
4040 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
4041
Steve Block6ded16b2010-05-10 14:33:55 +01004042 // Accessors for code of the runtime routines written in JavaScript.
4043 inline Code* javascript_builtin_code(Builtins::JavaScript id);
4044 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
4045
Steve Blocka7e24c12009-10-30 11:49:00 +00004046 // Casting.
4047 static inline JSBuiltinsObject* cast(Object* obj);
4048
4049 // Dispatched behavior.
4050#ifdef DEBUG
4051 void JSBuiltinsObjectPrint();
4052 void JSBuiltinsObjectVerify();
4053#endif
4054
4055 // Layout description. The size of the builtins object includes
Steve Block6ded16b2010-05-10 14:33:55 +01004056 // room for two pointers per runtime routine written in javascript
4057 // (function and code object).
Steve Blocka7e24c12009-10-30 11:49:00 +00004058 static const int kJSBuiltinsCount = Builtins::id_count;
4059 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004060 static const int kJSBuiltinsCodeOffset =
4061 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004062 static const int kSize =
Steve Block6ded16b2010-05-10 14:33:55 +01004063 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
4064
4065 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
4066 return kJSBuiltinsOffset + id * kPointerSize;
4067 }
4068
4069 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
4070 return kJSBuiltinsCodeOffset + id * kPointerSize;
4071 }
4072
Steve Blocka7e24c12009-10-30 11:49:00 +00004073 private:
4074 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
4075};
4076
4077
4078// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
4079class JSValue: public JSObject {
4080 public:
4081 // [value]: the object being wrapped.
4082 DECL_ACCESSORS(value, Object)
4083
4084 // Casting.
4085 static inline JSValue* cast(Object* obj);
4086
4087 // Dispatched behavior.
4088#ifdef DEBUG
4089 void JSValuePrint();
4090 void JSValueVerify();
4091#endif
4092
4093 // Layout description.
4094 static const int kValueOffset = JSObject::kHeaderSize;
4095 static const int kSize = kValueOffset + kPointerSize;
4096
4097 private:
4098 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
4099};
4100
4101// Regular expressions
4102// The regular expression holds a single reference to a FixedArray in
4103// the kDataOffset field.
4104// The FixedArray contains the following data:
4105// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
4106// - reference to the original source string
4107// - reference to the original flag string
4108// If it is an atom regexp
4109// - a reference to a literal string to search for
4110// If it is an irregexp regexp:
4111// - a reference to code for ASCII inputs (bytecode or compiled).
4112// - a reference to code for UC16 inputs (bytecode or compiled).
4113// - max number of registers used by irregexp implementations.
4114// - number of capture registers (output values) of the regexp.
4115class JSRegExp: public JSObject {
4116 public:
4117 // Meaning of Type:
4118 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
4119 // ATOM: A simple string to match against using an indexOf operation.
4120 // IRREGEXP: Compiled with Irregexp.
4121 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
4122 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
4123 enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
4124
4125 class Flags {
4126 public:
4127 explicit Flags(uint32_t value) : value_(value) { }
4128 bool is_global() { return (value_ & GLOBAL) != 0; }
4129 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
4130 bool is_multiline() { return (value_ & MULTILINE) != 0; }
4131 uint32_t value() { return value_; }
4132 private:
4133 uint32_t value_;
4134 };
4135
4136 DECL_ACCESSORS(data, Object)
4137
4138 inline Type TypeTag();
4139 inline int CaptureCount();
4140 inline Flags GetFlags();
4141 inline String* Pattern();
4142 inline Object* DataAt(int index);
4143 // Set implementation data after the object has been prepared.
4144 inline void SetDataAt(int index, Object* value);
4145 static int code_index(bool is_ascii) {
4146 if (is_ascii) {
4147 return kIrregexpASCIICodeIndex;
4148 } else {
4149 return kIrregexpUC16CodeIndex;
4150 }
4151 }
4152
4153 static inline JSRegExp* cast(Object* obj);
4154
4155 // Dispatched behavior.
4156#ifdef DEBUG
4157 void JSRegExpVerify();
4158#endif
4159
4160 static const int kDataOffset = JSObject::kHeaderSize;
4161 static const int kSize = kDataOffset + kPointerSize;
4162
4163 // Indices in the data array.
4164 static const int kTagIndex = 0;
4165 static const int kSourceIndex = kTagIndex + 1;
4166 static const int kFlagsIndex = kSourceIndex + 1;
4167 static const int kDataIndex = kFlagsIndex + 1;
4168 // The data fields are used in different ways depending on the
4169 // value of the tag.
4170 // Atom regexps (literal strings).
4171 static const int kAtomPatternIndex = kDataIndex;
4172
4173 static const int kAtomDataSize = kAtomPatternIndex + 1;
4174
4175 // Irregexp compiled code or bytecode for ASCII. If compilation
4176 // fails, this fields hold an exception object that should be
4177 // thrown if the regexp is used again.
4178 static const int kIrregexpASCIICodeIndex = kDataIndex;
4179 // Irregexp compiled code or bytecode for UC16. If compilation
4180 // fails, this fields hold an exception object that should be
4181 // thrown if the regexp is used again.
4182 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
4183 // Maximal number of registers used by either ASCII or UC16.
4184 // Only used to check that there is enough stack space
4185 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 2;
4186 // Number of captures in the compiled regexp.
4187 static const int kIrregexpCaptureCountIndex = kDataIndex + 3;
4188
4189 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
Leon Clarkee46be812010-01-19 14:06:41 +00004190
4191 // Offsets directly into the data fixed array.
4192 static const int kDataTagOffset =
4193 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
4194 static const int kDataAsciiCodeOffset =
4195 FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +00004196 static const int kDataUC16CodeOffset =
4197 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00004198 static const int kIrregexpCaptureCountOffset =
4199 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004200
4201 // In-object fields.
4202 static const int kSourceFieldIndex = 0;
4203 static const int kGlobalFieldIndex = 1;
4204 static const int kIgnoreCaseFieldIndex = 2;
4205 static const int kMultilineFieldIndex = 3;
4206 static const int kLastIndexFieldIndex = 4;
Ben Murdochbb769b22010-08-11 14:56:33 +01004207 static const int kInObjectFieldCount = 5;
Steve Blocka7e24c12009-10-30 11:49:00 +00004208};
4209
4210
4211class CompilationCacheShape {
4212 public:
4213 static inline bool IsMatch(HashTableKey* key, Object* value) {
4214 return key->IsMatch(value);
4215 }
4216
4217 static inline uint32_t Hash(HashTableKey* key) {
4218 return key->Hash();
4219 }
4220
4221 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
4222 return key->HashForObject(object);
4223 }
4224
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004225 MUST_USE_RESULT static Object* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004226 return key->AsObject();
4227 }
4228
4229 static const int kPrefixSize = 0;
4230 static const int kEntrySize = 2;
4231};
4232
Steve Block3ce2e202009-11-05 08:53:23 +00004233
Steve Blocka7e24c12009-10-30 11:49:00 +00004234class CompilationCacheTable: public HashTable<CompilationCacheShape,
4235 HashTableKey*> {
4236 public:
4237 // Find cached value for a string key, otherwise return null.
4238 Object* Lookup(String* src);
4239 Object* LookupEval(String* src, Context* context);
4240 Object* LookupRegExp(String* source, JSRegExp::Flags flags);
4241 Object* Put(String* src, Object* value);
4242 Object* PutEval(String* src, Context* context, Object* value);
4243 Object* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
4244
4245 static inline CompilationCacheTable* cast(Object* obj);
4246
4247 private:
4248 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
4249};
4250
4251
Steve Block6ded16b2010-05-10 14:33:55 +01004252class CodeCache: public Struct {
4253 public:
4254 DECL_ACCESSORS(default_cache, FixedArray)
4255 DECL_ACCESSORS(normal_type_cache, Object)
4256
4257 // Add the code object to the cache.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004258 MUST_USE_RESULT Object* Update(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01004259
4260 // Lookup code object in the cache. Returns code object if found and undefined
4261 // if not.
4262 Object* Lookup(String* name, Code::Flags flags);
4263
4264 // Get the internal index of a code object in the cache. Returns -1 if the
4265 // code object is not in that cache. This index can be used to later call
4266 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
4267 // RemoveByIndex.
4268 int GetIndex(Object* name, Code* code);
4269
4270 // Remove an object from the cache with the provided internal index.
4271 void RemoveByIndex(Object* name, Code* code, int index);
4272
4273 static inline CodeCache* cast(Object* obj);
4274
4275#ifdef DEBUG
4276 void CodeCachePrint();
4277 void CodeCacheVerify();
4278#endif
4279
4280 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
4281 static const int kNormalTypeCacheOffset =
4282 kDefaultCacheOffset + kPointerSize;
4283 static const int kSize = kNormalTypeCacheOffset + kPointerSize;
4284
4285 private:
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004286 MUST_USE_RESULT Object* UpdateDefaultCache(String* name, Code* code);
4287 MUST_USE_RESULT Object* UpdateNormalTypeCache(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01004288 Object* LookupDefaultCache(String* name, Code::Flags flags);
4289 Object* LookupNormalTypeCache(String* name, Code::Flags flags);
4290
4291 // Code cache layout of the default cache. Elements are alternating name and
4292 // code objects for non normal load/store/call IC's.
4293 static const int kCodeCacheEntrySize = 2;
4294 static const int kCodeCacheEntryNameOffset = 0;
4295 static const int kCodeCacheEntryCodeOffset = 1;
4296
4297 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
4298};
4299
4300
4301class CodeCacheHashTableShape {
4302 public:
4303 static inline bool IsMatch(HashTableKey* key, Object* value) {
4304 return key->IsMatch(value);
4305 }
4306
4307 static inline uint32_t Hash(HashTableKey* key) {
4308 return key->Hash();
4309 }
4310
4311 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
4312 return key->HashForObject(object);
4313 }
4314
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004315 MUST_USE_RESULT static Object* AsObject(HashTableKey* key) {
Steve Block6ded16b2010-05-10 14:33:55 +01004316 return key->AsObject();
4317 }
4318
4319 static const int kPrefixSize = 0;
4320 static const int kEntrySize = 2;
4321};
4322
4323
4324class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
4325 HashTableKey*> {
4326 public:
4327 Object* Lookup(String* name, Code::Flags flags);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004328 MUST_USE_RESULT Object* Put(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01004329
4330 int GetIndex(String* name, Code::Flags flags);
4331 void RemoveByIndex(int index);
4332
4333 static inline CodeCacheHashTable* cast(Object* obj);
4334
4335 // Initial size of the fixed array backing the hash table.
4336 static const int kInitialSize = 64;
4337
4338 private:
4339 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
4340};
4341
4342
Steve Blocka7e24c12009-10-30 11:49:00 +00004343enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
4344enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
4345
4346
4347class StringHasher {
4348 public:
4349 inline StringHasher(int length);
4350
4351 // Returns true if the hash of this string can be computed without
4352 // looking at the contents.
4353 inline bool has_trivial_hash();
4354
4355 // Add a character to the hash and update the array index calculation.
4356 inline void AddCharacter(uc32 c);
4357
4358 // Adds a character to the hash but does not update the array index
4359 // calculation. This can only be called when it has been verified
4360 // that the input is not an array index.
4361 inline void AddCharacterNoIndex(uc32 c);
4362
4363 // Returns the value to store in the hash field of a string with
4364 // the given length and contents.
4365 uint32_t GetHashField();
4366
4367 // Returns true if the characters seen so far make up a legal array
4368 // index.
4369 bool is_array_index() { return is_array_index_; }
4370
4371 bool is_valid() { return is_valid_; }
4372
4373 void invalidate() { is_valid_ = false; }
4374
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004375 // Calculated hash value for a string consisting of 1 to
4376 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
4377 // value is represented decimal value.
Iain Merrick9ac36c92010-09-13 15:29:50 +01004378 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004379
Steve Blocka7e24c12009-10-30 11:49:00 +00004380 private:
4381
4382 uint32_t array_index() {
4383 ASSERT(is_array_index());
4384 return array_index_;
4385 }
4386
4387 inline uint32_t GetHash();
4388
4389 int length_;
4390 uint32_t raw_running_hash_;
4391 uint32_t array_index_;
4392 bool is_array_index_;
4393 bool is_first_char_;
4394 bool is_valid_;
Steve Blockd0582a62009-12-15 09:54:21 +00004395 friend class TwoCharHashTableKey;
Steve Blocka7e24c12009-10-30 11:49:00 +00004396};
4397
4398
4399// The characteristics of a string are stored in its map. Retrieving these
4400// few bits of information is moderately expensive, involving two memory
4401// loads where the second is dependent on the first. To improve efficiency
4402// the shape of the string is given its own class so that it can be retrieved
4403// once and used for several string operations. A StringShape is small enough
4404// to be passed by value and is immutable, but be aware that flattening a
4405// string can potentially alter its shape. Also be aware that a GC caused by
4406// something else can alter the shape of a string due to ConsString
4407// shortcutting. Keeping these restrictions in mind has proven to be error-
4408// prone and so we no longer put StringShapes in variables unless there is a
4409// concrete performance benefit at that particular point in the code.
4410class StringShape BASE_EMBEDDED {
4411 public:
4412 inline explicit StringShape(String* s);
4413 inline explicit StringShape(Map* s);
4414 inline explicit StringShape(InstanceType t);
4415 inline bool IsSequential();
4416 inline bool IsExternal();
4417 inline bool IsCons();
Steve Blocka7e24c12009-10-30 11:49:00 +00004418 inline bool IsExternalAscii();
4419 inline bool IsExternalTwoByte();
4420 inline bool IsSequentialAscii();
4421 inline bool IsSequentialTwoByte();
4422 inline bool IsSymbol();
4423 inline StringRepresentationTag representation_tag();
4424 inline uint32_t full_representation_tag();
4425 inline uint32_t size_tag();
4426#ifdef DEBUG
4427 inline uint32_t type() { return type_; }
4428 inline void invalidate() { valid_ = false; }
4429 inline bool valid() { return valid_; }
4430#else
4431 inline void invalidate() { }
4432#endif
4433 private:
4434 uint32_t type_;
4435#ifdef DEBUG
4436 inline void set_valid() { valid_ = true; }
4437 bool valid_;
4438#else
4439 inline void set_valid() { }
4440#endif
4441};
4442
4443
4444// The String abstract class captures JavaScript string values:
4445//
4446// Ecma-262:
4447// 4.3.16 String Value
4448// A string value is a member of the type String and is a finite
4449// ordered sequence of zero or more 16-bit unsigned integer values.
4450//
4451// All string values have a length field.
4452class String: public HeapObject {
4453 public:
4454 // Get and set the length of the string.
4455 inline int length();
4456 inline void set_length(int value);
4457
Steve Blockd0582a62009-12-15 09:54:21 +00004458 // Get and set the hash field of the string.
4459 inline uint32_t hash_field();
4460 inline void set_hash_field(uint32_t value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004461
4462 inline bool IsAsciiRepresentation();
4463 inline bool IsTwoByteRepresentation();
4464
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004465 // Returns whether this string has ascii chars, i.e. all of them can
4466 // be ascii encoded. This might be the case even if the string is
4467 // two-byte. Such strings may appear when the embedder prefers
4468 // two-byte external representations even for ascii data.
Steve Block6ded16b2010-05-10 14:33:55 +01004469 //
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004470 // NOTE: this should be considered only a hint. False negatives are
4471 // possible.
4472 inline bool HasOnlyAsciiChars();
Steve Block6ded16b2010-05-10 14:33:55 +01004473
Steve Blocka7e24c12009-10-30 11:49:00 +00004474 // Get and set individual two byte chars in the string.
4475 inline void Set(int index, uint16_t value);
4476 // Get individual two byte char in the string. Repeated calls
4477 // to this method are not efficient unless the string is flat.
4478 inline uint16_t Get(int index);
4479
Leon Clarkef7060e22010-06-03 12:02:55 +01004480 // Try to flatten the string. Checks first inline to see if it is
4481 // necessary. Does nothing if the string is not a cons string.
4482 // Flattening allocates a sequential string with the same data as
4483 // the given string and mutates the cons string to a degenerate
4484 // form, where the first component is the new sequential string and
4485 // the second component is the empty string. If allocation fails,
4486 // this function returns a failure. If flattening succeeds, this
4487 // function returns the sequential string that is now the first
4488 // component of the cons string.
4489 //
4490 // Degenerate cons strings are handled specially by the garbage
4491 // collector (see IsShortcutCandidate).
4492 //
4493 // Use FlattenString from Handles.cc to flatten even in case an
4494 // allocation failure happens.
Steve Block6ded16b2010-05-10 14:33:55 +01004495 inline Object* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004496
Leon Clarkef7060e22010-06-03 12:02:55 +01004497 // Convenience function. Has exactly the same behavior as
4498 // TryFlatten(), except in the case of failure returns the original
4499 // string.
4500 inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
4501
Steve Blocka7e24c12009-10-30 11:49:00 +00004502 Vector<const char> ToAsciiVector();
4503 Vector<const uc16> ToUC16Vector();
4504
4505 // Mark the string as an undetectable object. It only applies to
4506 // ascii and two byte string types.
4507 bool MarkAsUndetectable();
4508
Steve Blockd0582a62009-12-15 09:54:21 +00004509 // Return a substring.
Steve Block6ded16b2010-05-10 14:33:55 +01004510 Object* SubString(int from, int to, PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004511
4512 // String equality operations.
4513 inline bool Equals(String* other);
4514 bool IsEqualTo(Vector<const char> str);
4515
4516 // Return a UTF8 representation of the string. The string is null
4517 // terminated but may optionally contain nulls. Length is returned
4518 // in length_output if length_output is not a null pointer The string
4519 // should be nearly flat, otherwise the performance of this method may
4520 // be very slow (quadratic in the length). Setting robustness_flag to
4521 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
4522 // handles unexpected data without causing assert failures and it does not
4523 // do any heap allocations. This is useful when printing stack traces.
4524 SmartPointer<char> ToCString(AllowNullsFlag allow_nulls,
4525 RobustnessFlag robustness_flag,
4526 int offset,
4527 int length,
4528 int* length_output = 0);
4529 SmartPointer<char> ToCString(
4530 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
4531 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
4532 int* length_output = 0);
4533
4534 int Utf8Length();
4535
4536 // Return a 16 bit Unicode representation of the string.
4537 // The string should be nearly flat, otherwise the performance of
4538 // of this method may be very bad. Setting robustness_flag to
4539 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
4540 // handles unexpected data without causing assert failures and it does not
4541 // do any heap allocations. This is useful when printing stack traces.
4542 SmartPointer<uc16> ToWideCString(
4543 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
4544
4545 // Tells whether the hash code has been computed.
4546 inline bool HasHashCode();
4547
4548 // Returns a hash value used for the property table
4549 inline uint32_t Hash();
4550
Steve Blockd0582a62009-12-15 09:54:21 +00004551 static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
4552 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00004553
4554 static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
4555 uint32_t* index,
4556 int length);
4557
4558 // Externalization.
4559 bool MakeExternal(v8::String::ExternalStringResource* resource);
4560 bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
4561
4562 // Conversion.
4563 inline bool AsArrayIndex(uint32_t* index);
4564
4565 // Casting.
4566 static inline String* cast(Object* obj);
4567
4568 void PrintOn(FILE* out);
4569
4570 // For use during stack traces. Performs rudimentary sanity check.
4571 bool LooksValid();
4572
4573 // Dispatched behavior.
4574 void StringShortPrint(StringStream* accumulator);
4575#ifdef DEBUG
4576 void StringPrint();
4577 void StringVerify();
4578#endif
4579 inline bool IsFlat();
4580
4581 // Layout description.
4582 static const int kLengthOffset = HeapObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01004583 static const int kHashFieldOffset = kLengthOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004584 static const int kSize = kHashFieldOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004585
Steve Blockd0582a62009-12-15 09:54:21 +00004586 // Maximum number of characters to consider when trying to convert a string
4587 // value into an array index.
Steve Blocka7e24c12009-10-30 11:49:00 +00004588 static const int kMaxArrayIndexSize = 10;
4589
4590 // Max ascii char code.
4591 static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
4592 static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
4593 static const int kMaxUC16CharCode = 0xffff;
4594
Steve Blockd0582a62009-12-15 09:54:21 +00004595 // Minimum length for a cons string.
Steve Blocka7e24c12009-10-30 11:49:00 +00004596 static const int kMinNonFlatLength = 13;
4597
4598 // Mask constant for checking if a string has a computed hash code
4599 // and if it is an array index. The least significant bit indicates
4600 // whether a hash code has been computed. If the hash code has been
4601 // computed the 2nd bit tells whether the string can be used as an
4602 // array index.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004603 static const int kHashNotComputedMask = 1;
4604 static const int kIsNotArrayIndexMask = 1 << 1;
4605 static const int kNofHashBitFields = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +00004606
Steve Blockd0582a62009-12-15 09:54:21 +00004607 // Shift constant retrieving hash code from hash field.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004608 static const int kHashShift = kNofHashBitFields;
Steve Blockd0582a62009-12-15 09:54:21 +00004609
Steve Blocka7e24c12009-10-30 11:49:00 +00004610 // Array index strings this short can keep their index in the hash
4611 // field.
4612 static const int kMaxCachedArrayIndexLength = 7;
4613
Steve Blockd0582a62009-12-15 09:54:21 +00004614 // For strings which are array indexes the hash value has the string length
4615 // mixed into the hash, mainly to avoid a hash value of zero which would be
4616 // the case for the string '0'. 24 bits are used for the array index value.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004617 static const int kArrayIndexValueBits = 24;
4618 static const int kArrayIndexLengthBits =
4619 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
4620
4621 STATIC_CHECK((kArrayIndexLengthBits > 0));
Iain Merrick9ac36c92010-09-13 15:29:50 +01004622 STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004623
4624 static const int kArrayIndexHashLengthShift =
4625 kArrayIndexValueBits + kNofHashBitFields;
4626
Steve Blockd0582a62009-12-15 09:54:21 +00004627 static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004628
4629 static const int kArrayIndexValueMask =
4630 ((1 << kArrayIndexValueBits) - 1) << kHashShift;
4631
4632 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
4633 // could use a mask to test if the length of string is less than or equal to
4634 // kMaxCachedArrayIndexLength.
4635 STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
4636
4637 static const int kContainsCachedArrayIndexMask =
4638 (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
4639 kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00004640
4641 // Value of empty hash field indicating that the hash is not computed.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004642 static const int kEmptyHashField =
4643 kIsNotArrayIndexMask | kHashNotComputedMask;
4644
4645 // Value of hash field containing computed hash equal to zero.
4646 static const int kZeroHash = kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00004647
4648 // Maximal string length.
4649 static const int kMaxLength = (1 << (32 - 2)) - 1;
4650
4651 // Max length for computing hash. For strings longer than this limit the
4652 // string length is used as the hash value.
4653 static const int kMaxHashCalcLength = 16383;
Steve Blocka7e24c12009-10-30 11:49:00 +00004654
4655 // Limit for truncation in short printing.
4656 static const int kMaxShortPrintLength = 1024;
4657
4658 // Support for regular expressions.
4659 const uc16* GetTwoByteData();
4660 const uc16* GetTwoByteData(unsigned start);
4661
4662 // Support for StringInputBuffer
4663 static const unibrow::byte* ReadBlock(String* input,
4664 unibrow::byte* util_buffer,
4665 unsigned capacity,
4666 unsigned* remaining,
4667 unsigned* offset);
4668 static const unibrow::byte* ReadBlock(String** input,
4669 unibrow::byte* util_buffer,
4670 unsigned capacity,
4671 unsigned* remaining,
4672 unsigned* offset);
4673
4674 // Helper function for flattening strings.
4675 template <typename sinkchar>
4676 static void WriteToFlat(String* source,
4677 sinkchar* sink,
4678 int from,
4679 int to);
4680
4681 protected:
4682 class ReadBlockBuffer {
4683 public:
4684 ReadBlockBuffer(unibrow::byte* util_buffer_,
4685 unsigned cursor_,
4686 unsigned capacity_,
4687 unsigned remaining_) :
4688 util_buffer(util_buffer_),
4689 cursor(cursor_),
4690 capacity(capacity_),
4691 remaining(remaining_) {
4692 }
4693 unibrow::byte* util_buffer;
4694 unsigned cursor;
4695 unsigned capacity;
4696 unsigned remaining;
4697 };
4698
Steve Blocka7e24c12009-10-30 11:49:00 +00004699 static inline const unibrow::byte* ReadBlock(String* input,
4700 ReadBlockBuffer* buffer,
4701 unsigned* offset,
4702 unsigned max_chars);
4703 static void ReadBlockIntoBuffer(String* input,
4704 ReadBlockBuffer* buffer,
4705 unsigned* offset_ptr,
4706 unsigned max_chars);
4707
4708 private:
Leon Clarkef7060e22010-06-03 12:02:55 +01004709 // Try to flatten the top level ConsString that is hiding behind this
4710 // string. This is a no-op unless the string is a ConsString. Flatten
4711 // mutates the ConsString and might return a failure.
4712 Object* SlowTryFlatten(PretenureFlag pretenure);
4713
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004714 static inline bool IsHashFieldComputed(uint32_t field);
4715
Steve Blocka7e24c12009-10-30 11:49:00 +00004716 // Slow case of String::Equals. This implementation works on any strings
4717 // but it is most efficient on strings that are almost flat.
4718 bool SlowEquals(String* other);
4719
4720 // Slow case of AsArrayIndex.
4721 bool SlowAsArrayIndex(uint32_t* index);
4722
4723 // Compute and set the hash code.
4724 uint32_t ComputeAndSetHash();
4725
4726 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
4727};
4728
4729
4730// The SeqString abstract class captures sequential string values.
4731class SeqString: public String {
4732 public:
4733
4734 // Casting.
4735 static inline SeqString* cast(Object* obj);
4736
Steve Blocka7e24c12009-10-30 11:49:00 +00004737 private:
4738 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
4739};
4740
4741
4742// The AsciiString class captures sequential ascii string objects.
4743// Each character in the AsciiString is an ascii character.
4744class SeqAsciiString: public SeqString {
4745 public:
Leon Clarkeac952652010-07-15 11:15:24 +01004746 static const bool kHasAsciiEncoding = true;
4747
Steve Blocka7e24c12009-10-30 11:49:00 +00004748 // Dispatched behavior.
4749 inline uint16_t SeqAsciiStringGet(int index);
4750 inline void SeqAsciiStringSet(int index, uint16_t value);
4751
4752 // Get the address of the characters in this string.
4753 inline Address GetCharsAddress();
4754
4755 inline char* GetChars();
4756
4757 // Casting
4758 static inline SeqAsciiString* cast(Object* obj);
4759
4760 // Garbage collection support. This method is called by the
4761 // garbage collector to compute the actual size of an AsciiString
4762 // instance.
4763 inline int SeqAsciiStringSize(InstanceType instance_type);
4764
4765 // Computes the size for an AsciiString instance of a given length.
4766 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004767 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004768 }
4769
4770 // Layout description.
4771 static const int kHeaderSize = String::kSize;
4772 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
4773
Leon Clarkee46be812010-01-19 14:06:41 +00004774 // Maximal memory usage for a single sequential ASCII string.
4775 static const int kMaxSize = 512 * MB;
4776 // Maximal length of a single sequential ASCII string.
4777 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
4778 static const int kMaxLength = (kMaxSize - kHeaderSize);
4779
Steve Blocka7e24c12009-10-30 11:49:00 +00004780 // Support for StringInputBuffer.
4781 inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
4782 unsigned* offset,
4783 unsigned chars);
4784 inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
4785 unsigned* offset,
4786 unsigned chars);
4787
4788 private:
4789 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
4790};
4791
4792
4793// The TwoByteString class captures sequential unicode string objects.
4794// Each character in the TwoByteString is a two-byte uint16_t.
4795class SeqTwoByteString: public SeqString {
4796 public:
Leon Clarkeac952652010-07-15 11:15:24 +01004797 static const bool kHasAsciiEncoding = false;
4798
Steve Blocka7e24c12009-10-30 11:49:00 +00004799 // Dispatched behavior.
4800 inline uint16_t SeqTwoByteStringGet(int index);
4801 inline void SeqTwoByteStringSet(int index, uint16_t value);
4802
4803 // Get the address of the characters in this string.
4804 inline Address GetCharsAddress();
4805
4806 inline uc16* GetChars();
4807
4808 // For regexp code.
4809 const uint16_t* SeqTwoByteStringGetData(unsigned start);
4810
4811 // Casting
4812 static inline SeqTwoByteString* cast(Object* obj);
4813
4814 // Garbage collection support. This method is called by the
4815 // garbage collector to compute the actual size of a TwoByteString
4816 // instance.
4817 inline int SeqTwoByteStringSize(InstanceType instance_type);
4818
4819 // Computes the size for a TwoByteString instance of a given length.
4820 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004821 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004822 }
4823
4824 // Layout description.
4825 static const int kHeaderSize = String::kSize;
4826 static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
4827
Leon Clarkee46be812010-01-19 14:06:41 +00004828 // Maximal memory usage for a single sequential two-byte string.
4829 static const int kMaxSize = 512 * MB;
4830 // Maximal length of a single sequential two-byte string.
4831 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
4832 static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
4833
Steve Blocka7e24c12009-10-30 11:49:00 +00004834 // Support for StringInputBuffer.
4835 inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
4836 unsigned* offset_ptr,
4837 unsigned chars);
4838
4839 private:
4840 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
4841};
4842
4843
4844// The ConsString class describes string values built by using the
4845// addition operator on strings. A ConsString is a pair where the
4846// first and second components are pointers to other string values.
4847// One or both components of a ConsString can be pointers to other
4848// ConsStrings, creating a binary tree of ConsStrings where the leaves
4849// are non-ConsString string values. The string value represented by
4850// a ConsString can be obtained by concatenating the leaf string
4851// values in a left-to-right depth-first traversal of the tree.
4852class ConsString: public String {
4853 public:
4854 // First string of the cons cell.
4855 inline String* first();
4856 // Doesn't check that the result is a string, even in debug mode. This is
4857 // useful during GC where the mark bits confuse the checks.
4858 inline Object* unchecked_first();
4859 inline void set_first(String* first,
4860 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
4861
4862 // Second string of the cons cell.
4863 inline String* second();
4864 // Doesn't check that the result is a string, even in debug mode. This is
4865 // useful during GC where the mark bits confuse the checks.
4866 inline Object* unchecked_second();
4867 inline void set_second(String* second,
4868 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
4869
4870 // Dispatched behavior.
4871 uint16_t ConsStringGet(int index);
4872
4873 // Casting.
4874 static inline ConsString* cast(Object* obj);
4875
Steve Blocka7e24c12009-10-30 11:49:00 +00004876 // Layout description.
4877 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
4878 static const int kSecondOffset = kFirstOffset + kPointerSize;
4879 static const int kSize = kSecondOffset + kPointerSize;
4880
4881 // Support for StringInputBuffer.
4882 inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
4883 unsigned* offset_ptr,
4884 unsigned chars);
4885 inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
4886 unsigned* offset_ptr,
4887 unsigned chars);
4888
4889 // Minimum length for a cons string.
4890 static const int kMinLength = 13;
4891
Iain Merrick75681382010-08-19 15:07:18 +01004892 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
4893 BodyDescriptor;
4894
Steve Blocka7e24c12009-10-30 11:49:00 +00004895 private:
4896 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
4897};
4898
4899
Steve Blocka7e24c12009-10-30 11:49:00 +00004900// The ExternalString class describes string values that are backed by
4901// a string resource that lies outside the V8 heap. ExternalStrings
4902// consist of the length field common to all strings, a pointer to the
4903// external resource. It is important to ensure (externally) that the
4904// resource is not deallocated while the ExternalString is live in the
4905// V8 heap.
4906//
4907// The API expects that all ExternalStrings are created through the
4908// API. Therefore, ExternalStrings should not be used internally.
4909class ExternalString: public String {
4910 public:
4911 // Casting
4912 static inline ExternalString* cast(Object* obj);
4913
4914 // Layout description.
4915 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
4916 static const int kSize = kResourceOffset + kPointerSize;
4917
4918 STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
4919
4920 private:
4921 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
4922};
4923
4924
4925// The ExternalAsciiString class is an external string backed by an
4926// ASCII string.
4927class ExternalAsciiString: public ExternalString {
4928 public:
Leon Clarkeac952652010-07-15 11:15:24 +01004929 static const bool kHasAsciiEncoding = true;
4930
Steve Blocka7e24c12009-10-30 11:49:00 +00004931 typedef v8::String::ExternalAsciiStringResource Resource;
4932
4933 // The underlying resource.
4934 inline Resource* resource();
4935 inline void set_resource(Resource* buffer);
4936
4937 // Dispatched behavior.
4938 uint16_t ExternalAsciiStringGet(int index);
4939
4940 // Casting.
4941 static inline ExternalAsciiString* cast(Object* obj);
4942
Steve Blockd0582a62009-12-15 09:54:21 +00004943 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01004944 inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
4945
4946 template<typename StaticVisitor>
4947 inline void ExternalAsciiStringIterateBody();
Steve Blockd0582a62009-12-15 09:54:21 +00004948
Steve Blocka7e24c12009-10-30 11:49:00 +00004949 // Support for StringInputBuffer.
4950 const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
4951 unsigned* offset,
4952 unsigned chars);
4953 inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
4954 unsigned* offset,
4955 unsigned chars);
4956
Steve Blocka7e24c12009-10-30 11:49:00 +00004957 private:
4958 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
4959};
4960
4961
4962// The ExternalTwoByteString class is an external string backed by a UTF-16
4963// encoded string.
4964class ExternalTwoByteString: public ExternalString {
4965 public:
Leon Clarkeac952652010-07-15 11:15:24 +01004966 static const bool kHasAsciiEncoding = false;
4967
Steve Blocka7e24c12009-10-30 11:49:00 +00004968 typedef v8::String::ExternalStringResource Resource;
4969
4970 // The underlying string resource.
4971 inline Resource* resource();
4972 inline void set_resource(Resource* buffer);
4973
4974 // Dispatched behavior.
4975 uint16_t ExternalTwoByteStringGet(int index);
4976
4977 // For regexp code.
4978 const uint16_t* ExternalTwoByteStringGetData(unsigned start);
4979
4980 // Casting.
4981 static inline ExternalTwoByteString* cast(Object* obj);
4982
Steve Blockd0582a62009-12-15 09:54:21 +00004983 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01004984 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
4985
4986 template<typename StaticVisitor>
4987 inline void ExternalTwoByteStringIterateBody();
4988
Steve Blockd0582a62009-12-15 09:54:21 +00004989
Steve Blocka7e24c12009-10-30 11:49:00 +00004990 // Support for StringInputBuffer.
4991 void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
4992 unsigned* offset_ptr,
4993 unsigned chars);
4994
Steve Blocka7e24c12009-10-30 11:49:00 +00004995 private:
4996 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
4997};
4998
4999
5000// Utility superclass for stack-allocated objects that must be updated
5001// on gc. It provides two ways for the gc to update instances, either
5002// iterating or updating after gc.
5003class Relocatable BASE_EMBEDDED {
5004 public:
5005 inline Relocatable() : prev_(top_) { top_ = this; }
5006 virtual ~Relocatable() {
5007 ASSERT_EQ(top_, this);
5008 top_ = prev_;
5009 }
5010 virtual void IterateInstance(ObjectVisitor* v) { }
5011 virtual void PostGarbageCollection() { }
5012
5013 static void PostGarbageCollectionProcessing();
5014 static int ArchiveSpacePerThread();
5015 static char* ArchiveState(char* to);
5016 static char* RestoreState(char* from);
5017 static void Iterate(ObjectVisitor* v);
5018 static void Iterate(ObjectVisitor* v, Relocatable* top);
5019 static char* Iterate(ObjectVisitor* v, char* t);
5020 private:
5021 static Relocatable* top_;
5022 Relocatable* prev_;
5023};
5024
5025
5026// A flat string reader provides random access to the contents of a
5027// string independent of the character width of the string. The handle
5028// must be valid as long as the reader is being used.
5029class FlatStringReader : public Relocatable {
5030 public:
5031 explicit FlatStringReader(Handle<String> str);
5032 explicit FlatStringReader(Vector<const char> input);
5033 void PostGarbageCollection();
5034 inline uc32 Get(int index);
5035 int length() { return length_; }
5036 private:
5037 String** str_;
5038 bool is_ascii_;
5039 int length_;
5040 const void* start_;
5041};
5042
5043
5044// Note that StringInputBuffers are not valid across a GC! To fix this
5045// it would have to store a String Handle instead of a String* and
5046// AsciiStringReadBlock would have to be modified to use memcpy.
5047//
5048// StringInputBuffer is able to traverse any string regardless of how
5049// deeply nested a sequence of ConsStrings it is made of. However,
5050// performance will be better if deep strings are flattened before they
5051// are traversed. Since flattening requires memory allocation this is
5052// not always desirable, however (esp. in debugging situations).
5053class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
5054 public:
5055 virtual void Seek(unsigned pos);
5056 inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
5057 inline StringInputBuffer(String* backing):
5058 unibrow::InputBuffer<String, String*, 1024>(backing) {}
5059};
5060
5061
5062class SafeStringInputBuffer
5063 : public unibrow::InputBuffer<String, String**, 256> {
5064 public:
5065 virtual void Seek(unsigned pos);
5066 inline SafeStringInputBuffer()
5067 : unibrow::InputBuffer<String, String**, 256>() {}
5068 inline SafeStringInputBuffer(String** backing)
5069 : unibrow::InputBuffer<String, String**, 256>(backing) {}
5070};
5071
5072
5073template <typename T>
5074class VectorIterator {
5075 public:
5076 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
5077 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
5078 T GetNext() { return data_[index_++]; }
5079 bool has_more() { return index_ < data_.length(); }
5080 private:
5081 Vector<const T> data_;
5082 int index_;
5083};
5084
5085
5086// The Oddball describes objects null, undefined, true, and false.
5087class Oddball: public HeapObject {
5088 public:
5089 // [to_string]: Cached to_string computed at startup.
5090 DECL_ACCESSORS(to_string, String)
5091
5092 // [to_number]: Cached to_number computed at startup.
5093 DECL_ACCESSORS(to_number, Object)
5094
5095 // Casting.
5096 static inline Oddball* cast(Object* obj);
5097
5098 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00005099#ifdef DEBUG
5100 void OddballVerify();
5101#endif
5102
5103 // Initialize the fields.
5104 Object* Initialize(const char* to_string, Object* to_number);
5105
5106 // Layout description.
5107 static const int kToStringOffset = HeapObject::kHeaderSize;
5108 static const int kToNumberOffset = kToStringOffset + kPointerSize;
5109 static const int kSize = kToNumberOffset + kPointerSize;
5110
Iain Merrick75681382010-08-19 15:07:18 +01005111 typedef FixedBodyDescriptor<kToStringOffset,
5112 kToNumberOffset + kPointerSize,
5113 kSize> BodyDescriptor;
5114
Steve Blocka7e24c12009-10-30 11:49:00 +00005115 private:
5116 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
5117};
5118
5119
5120class JSGlobalPropertyCell: public HeapObject {
5121 public:
5122 // [value]: value of the global property.
5123 DECL_ACCESSORS(value, Object)
5124
5125 // Casting.
5126 static inline JSGlobalPropertyCell* cast(Object* obj);
5127
Steve Blocka7e24c12009-10-30 11:49:00 +00005128#ifdef DEBUG
5129 void JSGlobalPropertyCellVerify();
5130 void JSGlobalPropertyCellPrint();
5131#endif
5132
5133 // Layout description.
5134 static const int kValueOffset = HeapObject::kHeaderSize;
5135 static const int kSize = kValueOffset + kPointerSize;
5136
Iain Merrick75681382010-08-19 15:07:18 +01005137 typedef FixedBodyDescriptor<kValueOffset,
5138 kValueOffset + kPointerSize,
5139 kSize> BodyDescriptor;
5140
Steve Blocka7e24c12009-10-30 11:49:00 +00005141 private:
5142 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
5143};
5144
5145
5146
5147// Proxy describes objects pointing from JavaScript to C structures.
5148// Since they cannot contain references to JS HeapObjects they can be
5149// placed in old_data_space.
5150class Proxy: public HeapObject {
5151 public:
5152 // [proxy]: field containing the address.
5153 inline Address proxy();
5154 inline void set_proxy(Address value);
5155
5156 // Casting.
5157 static inline Proxy* cast(Object* obj);
5158
5159 // Dispatched behavior.
5160 inline void ProxyIterateBody(ObjectVisitor* v);
Iain Merrick75681382010-08-19 15:07:18 +01005161
5162 template<typename StaticVisitor>
5163 inline void ProxyIterateBody();
5164
Steve Blocka7e24c12009-10-30 11:49:00 +00005165#ifdef DEBUG
5166 void ProxyPrint();
5167 void ProxyVerify();
5168#endif
5169
5170 // Layout description.
5171
5172 static const int kProxyOffset = HeapObject::kHeaderSize;
5173 static const int kSize = kProxyOffset + kPointerSize;
5174
5175 STATIC_CHECK(kProxyOffset == Internals::kProxyProxyOffset);
5176
5177 private:
5178 DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
5179};
5180
5181
5182// The JSArray describes JavaScript Arrays
5183// Such an array can be in one of two modes:
5184// - fast, backing storage is a FixedArray and length <= elements.length();
5185// Please note: push and pop can be used to grow and shrink the array.
5186// - slow, backing storage is a HashTable with numbers as keys.
5187class JSArray: public JSObject {
5188 public:
5189 // [length]: The length property.
5190 DECL_ACCESSORS(length, Object)
5191
Leon Clarke4515c472010-02-03 11:58:03 +00005192 // Overload the length setter to skip write barrier when the length
5193 // is set to a smi. This matches the set function on FixedArray.
5194 inline void set_length(Smi* length);
5195
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005196 MUST_USE_RESULT Object* JSArrayUpdateLengthFromIndex(uint32_t index,
5197 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005198
5199 // Initialize the array with the given capacity. The function may
5200 // fail due to out-of-memory situations, but only if the requested
5201 // capacity is non-zero.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005202 MUST_USE_RESULT Object* Initialize(int capacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00005203
5204 // Set the content of the array to the content of storage.
5205 inline void SetContent(FixedArray* storage);
5206
5207 // Casting.
5208 static inline JSArray* cast(Object* obj);
5209
5210 // Uses handles. Ensures that the fixed array backing the JSArray has at
5211 // least the stated size.
5212 inline void EnsureSize(int minimum_size_of_backing_fixed_array);
5213
5214 // Dispatched behavior.
5215#ifdef DEBUG
5216 void JSArrayPrint();
5217 void JSArrayVerify();
5218#endif
5219
5220 // Number of element slots to pre-allocate for an empty array.
5221 static const int kPreallocatedArrayElements = 4;
5222
5223 // Layout description.
5224 static const int kLengthOffset = JSObject::kHeaderSize;
5225 static const int kSize = kLengthOffset + kPointerSize;
5226
5227 private:
5228 // Expand the fixed array backing of a fast-case JSArray to at least
5229 // the requested size.
5230 void Expand(int minimum_size_of_backing_fixed_array);
5231
5232 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
5233};
5234
5235
Steve Block6ded16b2010-05-10 14:33:55 +01005236// JSRegExpResult is just a JSArray with a specific initial map.
5237// This initial map adds in-object properties for "index" and "input"
5238// properties, as assigned by RegExp.prototype.exec, which allows
5239// faster creation of RegExp exec results.
5240// This class just holds constants used when creating the result.
5241// After creation the result must be treated as a JSArray in all regards.
5242class JSRegExpResult: public JSArray {
5243 public:
5244 // Offsets of object fields.
5245 static const int kIndexOffset = JSArray::kSize;
5246 static const int kInputOffset = kIndexOffset + kPointerSize;
5247 static const int kSize = kInputOffset + kPointerSize;
5248 // Indices of in-object properties.
5249 static const int kIndexIndex = 0;
5250 static const int kInputIndex = 1;
5251 private:
5252 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
5253};
5254
5255
Steve Blocka7e24c12009-10-30 11:49:00 +00005256// An accessor must have a getter, but can have no setter.
5257//
5258// When setting a property, V8 searches accessors in prototypes.
5259// If an accessor was found and it does not have a setter,
5260// the request is ignored.
5261//
5262// If the accessor in the prototype has the READ_ONLY property attribute, then
5263// a new value is added to the local object when the property is set.
5264// This shadows the accessor in the prototype.
5265class AccessorInfo: public Struct {
5266 public:
5267 DECL_ACCESSORS(getter, Object)
5268 DECL_ACCESSORS(setter, Object)
5269 DECL_ACCESSORS(data, Object)
5270 DECL_ACCESSORS(name, Object)
5271 DECL_ACCESSORS(flag, Smi)
Steve Blockd0582a62009-12-15 09:54:21 +00005272 DECL_ACCESSORS(load_stub_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00005273
5274 inline bool all_can_read();
5275 inline void set_all_can_read(bool value);
5276
5277 inline bool all_can_write();
5278 inline void set_all_can_write(bool value);
5279
5280 inline bool prohibits_overwriting();
5281 inline void set_prohibits_overwriting(bool value);
5282
5283 inline PropertyAttributes property_attributes();
5284 inline void set_property_attributes(PropertyAttributes attributes);
5285
5286 static inline AccessorInfo* cast(Object* obj);
5287
5288#ifdef DEBUG
5289 void AccessorInfoPrint();
5290 void AccessorInfoVerify();
5291#endif
5292
5293 static const int kGetterOffset = HeapObject::kHeaderSize;
5294 static const int kSetterOffset = kGetterOffset + kPointerSize;
5295 static const int kDataOffset = kSetterOffset + kPointerSize;
5296 static const int kNameOffset = kDataOffset + kPointerSize;
5297 static const int kFlagOffset = kNameOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00005298 static const int kLoadStubCacheOffset = kFlagOffset + kPointerSize;
5299 static const int kSize = kLoadStubCacheOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005300
5301 private:
5302 // Bit positions in flag.
5303 static const int kAllCanReadBit = 0;
5304 static const int kAllCanWriteBit = 1;
5305 static const int kProhibitsOverwritingBit = 2;
5306 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
5307
5308 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
5309};
5310
5311
5312class AccessCheckInfo: public Struct {
5313 public:
5314 DECL_ACCESSORS(named_callback, Object)
5315 DECL_ACCESSORS(indexed_callback, Object)
5316 DECL_ACCESSORS(data, Object)
5317
5318 static inline AccessCheckInfo* cast(Object* obj);
5319
5320#ifdef DEBUG
5321 void AccessCheckInfoPrint();
5322 void AccessCheckInfoVerify();
5323#endif
5324
5325 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
5326 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
5327 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
5328 static const int kSize = kDataOffset + kPointerSize;
5329
5330 private:
5331 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
5332};
5333
5334
5335class InterceptorInfo: public Struct {
5336 public:
5337 DECL_ACCESSORS(getter, Object)
5338 DECL_ACCESSORS(setter, Object)
5339 DECL_ACCESSORS(query, Object)
5340 DECL_ACCESSORS(deleter, Object)
5341 DECL_ACCESSORS(enumerator, Object)
5342 DECL_ACCESSORS(data, Object)
5343
5344 static inline InterceptorInfo* cast(Object* obj);
5345
5346#ifdef DEBUG
5347 void InterceptorInfoPrint();
5348 void InterceptorInfoVerify();
5349#endif
5350
5351 static const int kGetterOffset = HeapObject::kHeaderSize;
5352 static const int kSetterOffset = kGetterOffset + kPointerSize;
5353 static const int kQueryOffset = kSetterOffset + kPointerSize;
5354 static const int kDeleterOffset = kQueryOffset + kPointerSize;
5355 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
5356 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
5357 static const int kSize = kDataOffset + kPointerSize;
5358
5359 private:
5360 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
5361};
5362
5363
5364class CallHandlerInfo: public Struct {
5365 public:
5366 DECL_ACCESSORS(callback, Object)
5367 DECL_ACCESSORS(data, Object)
5368
5369 static inline CallHandlerInfo* cast(Object* obj);
5370
5371#ifdef DEBUG
5372 void CallHandlerInfoPrint();
5373 void CallHandlerInfoVerify();
5374#endif
5375
5376 static const int kCallbackOffset = HeapObject::kHeaderSize;
5377 static const int kDataOffset = kCallbackOffset + kPointerSize;
5378 static const int kSize = kDataOffset + kPointerSize;
5379
5380 private:
5381 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
5382};
5383
5384
5385class TemplateInfo: public Struct {
5386 public:
5387 DECL_ACCESSORS(tag, Object)
5388 DECL_ACCESSORS(property_list, Object)
5389
5390#ifdef DEBUG
5391 void TemplateInfoVerify();
5392#endif
5393
5394 static const int kTagOffset = HeapObject::kHeaderSize;
5395 static const int kPropertyListOffset = kTagOffset + kPointerSize;
5396 static const int kHeaderSize = kPropertyListOffset + kPointerSize;
5397 protected:
5398 friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
5399 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
5400};
5401
5402
5403class FunctionTemplateInfo: public TemplateInfo {
5404 public:
5405 DECL_ACCESSORS(serial_number, Object)
5406 DECL_ACCESSORS(call_code, Object)
5407 DECL_ACCESSORS(property_accessors, Object)
5408 DECL_ACCESSORS(prototype_template, Object)
5409 DECL_ACCESSORS(parent_template, Object)
5410 DECL_ACCESSORS(named_property_handler, Object)
5411 DECL_ACCESSORS(indexed_property_handler, Object)
5412 DECL_ACCESSORS(instance_template, Object)
5413 DECL_ACCESSORS(class_name, Object)
5414 DECL_ACCESSORS(signature, Object)
5415 DECL_ACCESSORS(instance_call_handler, Object)
5416 DECL_ACCESSORS(access_check_info, Object)
5417 DECL_ACCESSORS(flag, Smi)
5418
5419 // Following properties use flag bits.
5420 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
5421 DECL_BOOLEAN_ACCESSORS(undetectable)
5422 // If the bit is set, object instances created by this function
5423 // requires access check.
5424 DECL_BOOLEAN_ACCESSORS(needs_access_check)
5425
5426 static inline FunctionTemplateInfo* cast(Object* obj);
5427
5428#ifdef DEBUG
5429 void FunctionTemplateInfoPrint();
5430 void FunctionTemplateInfoVerify();
5431#endif
5432
5433 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
5434 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
5435 static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
5436 static const int kPrototypeTemplateOffset =
5437 kPropertyAccessorsOffset + kPointerSize;
5438 static const int kParentTemplateOffset =
5439 kPrototypeTemplateOffset + kPointerSize;
5440 static const int kNamedPropertyHandlerOffset =
5441 kParentTemplateOffset + kPointerSize;
5442 static const int kIndexedPropertyHandlerOffset =
5443 kNamedPropertyHandlerOffset + kPointerSize;
5444 static const int kInstanceTemplateOffset =
5445 kIndexedPropertyHandlerOffset + kPointerSize;
5446 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
5447 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
5448 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
5449 static const int kAccessCheckInfoOffset =
5450 kInstanceCallHandlerOffset + kPointerSize;
5451 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
5452 static const int kSize = kFlagOffset + kPointerSize;
5453
5454 private:
5455 // Bit position in the flag, from least significant bit position.
5456 static const int kHiddenPrototypeBit = 0;
5457 static const int kUndetectableBit = 1;
5458 static const int kNeedsAccessCheckBit = 2;
5459
5460 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
5461};
5462
5463
5464class ObjectTemplateInfo: public TemplateInfo {
5465 public:
5466 DECL_ACCESSORS(constructor, Object)
5467 DECL_ACCESSORS(internal_field_count, Object)
5468
5469 static inline ObjectTemplateInfo* cast(Object* obj);
5470
5471#ifdef DEBUG
5472 void ObjectTemplateInfoPrint();
5473 void ObjectTemplateInfoVerify();
5474#endif
5475
5476 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
5477 static const int kInternalFieldCountOffset =
5478 kConstructorOffset + kPointerSize;
5479 static const int kSize = kInternalFieldCountOffset + kPointerSize;
5480};
5481
5482
5483class SignatureInfo: public Struct {
5484 public:
5485 DECL_ACCESSORS(receiver, Object)
5486 DECL_ACCESSORS(args, Object)
5487
5488 static inline SignatureInfo* cast(Object* obj);
5489
5490#ifdef DEBUG
5491 void SignatureInfoPrint();
5492 void SignatureInfoVerify();
5493#endif
5494
5495 static const int kReceiverOffset = Struct::kHeaderSize;
5496 static const int kArgsOffset = kReceiverOffset + kPointerSize;
5497 static const int kSize = kArgsOffset + kPointerSize;
5498
5499 private:
5500 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
5501};
5502
5503
5504class TypeSwitchInfo: public Struct {
5505 public:
5506 DECL_ACCESSORS(types, Object)
5507
5508 static inline TypeSwitchInfo* cast(Object* obj);
5509
5510#ifdef DEBUG
5511 void TypeSwitchInfoPrint();
5512 void TypeSwitchInfoVerify();
5513#endif
5514
5515 static const int kTypesOffset = Struct::kHeaderSize;
5516 static const int kSize = kTypesOffset + kPointerSize;
5517};
5518
5519
5520#ifdef ENABLE_DEBUGGER_SUPPORT
5521// The DebugInfo class holds additional information for a function being
5522// debugged.
5523class DebugInfo: public Struct {
5524 public:
5525 // The shared function info for the source being debugged.
5526 DECL_ACCESSORS(shared, SharedFunctionInfo)
5527 // Code object for the original code.
5528 DECL_ACCESSORS(original_code, Code)
5529 // Code object for the patched code. This code object is the code object
5530 // currently active for the function.
5531 DECL_ACCESSORS(code, Code)
5532 // Fixed array holding status information for each active break point.
5533 DECL_ACCESSORS(break_points, FixedArray)
5534
5535 // Check if there is a break point at a code position.
5536 bool HasBreakPoint(int code_position);
5537 // Get the break point info object for a code position.
5538 Object* GetBreakPointInfo(int code_position);
5539 // Clear a break point.
5540 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
5541 int code_position,
5542 Handle<Object> break_point_object);
5543 // Set a break point.
5544 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
5545 int source_position, int statement_position,
5546 Handle<Object> break_point_object);
5547 // Get the break point objects for a code position.
5548 Object* GetBreakPointObjects(int code_position);
5549 // Find the break point info holding this break point object.
5550 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
5551 Handle<Object> break_point_object);
5552 // Get the number of break points for this function.
5553 int GetBreakPointCount();
5554
5555 static inline DebugInfo* cast(Object* obj);
5556
5557#ifdef DEBUG
5558 void DebugInfoPrint();
5559 void DebugInfoVerify();
5560#endif
5561
5562 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
5563 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
5564 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
5565 static const int kActiveBreakPointsCountIndex =
5566 kPatchedCodeIndex + kPointerSize;
5567 static const int kBreakPointsStateIndex =
5568 kActiveBreakPointsCountIndex + kPointerSize;
5569 static const int kSize = kBreakPointsStateIndex + kPointerSize;
5570
5571 private:
5572 static const int kNoBreakPointInfo = -1;
5573
5574 // Lookup the index in the break_points array for a code position.
5575 int GetBreakPointInfoIndex(int code_position);
5576
5577 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
5578};
5579
5580
5581// The BreakPointInfo class holds information for break points set in a
5582// function. The DebugInfo object holds a BreakPointInfo object for each code
5583// position with one or more break points.
5584class BreakPointInfo: public Struct {
5585 public:
5586 // The position in the code for the break point.
5587 DECL_ACCESSORS(code_position, Smi)
5588 // The position in the source for the break position.
5589 DECL_ACCESSORS(source_position, Smi)
5590 // The position in the source for the last statement before this break
5591 // position.
5592 DECL_ACCESSORS(statement_position, Smi)
5593 // List of related JavaScript break points.
5594 DECL_ACCESSORS(break_point_objects, Object)
5595
5596 // Removes a break point.
5597 static void ClearBreakPoint(Handle<BreakPointInfo> info,
5598 Handle<Object> break_point_object);
5599 // Set a break point.
5600 static void SetBreakPoint(Handle<BreakPointInfo> info,
5601 Handle<Object> break_point_object);
5602 // Check if break point info has this break point object.
5603 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
5604 Handle<Object> break_point_object);
5605 // Get the number of break points for this code position.
5606 int GetBreakPointCount();
5607
5608 static inline BreakPointInfo* cast(Object* obj);
5609
5610#ifdef DEBUG
5611 void BreakPointInfoPrint();
5612 void BreakPointInfoVerify();
5613#endif
5614
5615 static const int kCodePositionIndex = Struct::kHeaderSize;
5616 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
5617 static const int kStatementPositionIndex =
5618 kSourcePositionIndex + kPointerSize;
5619 static const int kBreakPointObjectsIndex =
5620 kStatementPositionIndex + kPointerSize;
5621 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
5622
5623 private:
5624 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
5625};
5626#endif // ENABLE_DEBUGGER_SUPPORT
5627
5628
5629#undef DECL_BOOLEAN_ACCESSORS
5630#undef DECL_ACCESSORS
5631
5632
5633// Abstract base class for visiting, and optionally modifying, the
5634// pointers contained in Objects. Used in GC and serialization/deserialization.
5635class ObjectVisitor BASE_EMBEDDED {
5636 public:
5637 virtual ~ObjectVisitor() {}
5638
5639 // Visits a contiguous arrays of pointers in the half-open range
5640 // [start, end). Any or all of the values may be modified on return.
5641 virtual void VisitPointers(Object** start, Object** end) = 0;
5642
5643 // To allow lazy clearing of inline caches the visitor has
5644 // a rich interface for iterating over Code objects..
5645
5646 // Visits a code target in the instruction stream.
5647 virtual void VisitCodeTarget(RelocInfo* rinfo);
5648
Steve Block791712a2010-08-27 10:21:07 +01005649 // Visits a code entry in a JS function.
5650 virtual void VisitCodeEntry(Address entry_address);
5651
Steve Blocka7e24c12009-10-30 11:49:00 +00005652 // Visits a runtime entry in the instruction stream.
5653 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
5654
Steve Blockd0582a62009-12-15 09:54:21 +00005655 // Visits the resource of an ASCII or two-byte string.
5656 virtual void VisitExternalAsciiString(
5657 v8::String::ExternalAsciiStringResource** resource) {}
5658 virtual void VisitExternalTwoByteString(
5659 v8::String::ExternalStringResource** resource) {}
5660
Steve Blocka7e24c12009-10-30 11:49:00 +00005661 // Visits a debug call target in the instruction stream.
5662 virtual void VisitDebugTarget(RelocInfo* rinfo);
5663
5664 // Handy shorthand for visiting a single pointer.
5665 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
5666
5667 // Visits a contiguous arrays of external references (references to the C++
5668 // heap) in the half-open range [start, end). Any or all of the values
5669 // may be modified on return.
5670 virtual void VisitExternalReferences(Address* start, Address* end) {}
5671
5672 inline void VisitExternalReference(Address* p) {
5673 VisitExternalReferences(p, p + 1);
5674 }
5675
5676#ifdef DEBUG
5677 // Intended for serialization/deserialization checking: insert, or
5678 // check for the presence of, a tag at this position in the stream.
5679 virtual void Synchronize(const char* tag) {}
Steve Blockd0582a62009-12-15 09:54:21 +00005680#else
5681 inline void Synchronize(const char* tag) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00005682#endif
5683};
5684
5685
Iain Merrick75681382010-08-19 15:07:18 +01005686class StructBodyDescriptor : public
5687 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
5688 public:
5689 static inline int SizeOf(Map* map, HeapObject* object) {
5690 return map->instance_size();
5691 }
5692};
5693
5694
Steve Blocka7e24c12009-10-30 11:49:00 +00005695// BooleanBit is a helper class for setting and getting a bit in an
5696// integer or Smi.
5697class BooleanBit : public AllStatic {
5698 public:
5699 static inline bool get(Smi* smi, int bit_position) {
5700 return get(smi->value(), bit_position);
5701 }
5702
5703 static inline bool get(int value, int bit_position) {
5704 return (value & (1 << bit_position)) != 0;
5705 }
5706
5707 static inline Smi* set(Smi* smi, int bit_position, bool v) {
5708 return Smi::FromInt(set(smi->value(), bit_position, v));
5709 }
5710
5711 static inline int set(int value, int bit_position, bool v) {
5712 if (v) {
5713 value |= (1 << bit_position);
5714 } else {
5715 value &= ~(1 << bit_position);
5716 }
5717 return value;
5718 }
5719};
5720
5721} } // namespace v8::internal
5722
5723#endif // V8_OBJECTS_H_