blob: d6d1057327436e8e373392b23568fc3d6cc95096 [file] [log] [blame]
Ben Murdochc7cc0282012-03-05 14:35:55 +00001// Copyright 2012 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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "builtins.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000033#include "list.h"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000034#include "property-details.h"
Ben Murdoch589d6972011-11-30 16:04:58 +000035#include "smart-array-pointer.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036#include "unicode-inl.h"
Steve Block3ce2e202009-11-05 08:53:23 +000037#if V8_TARGET_ARCH_ARM
38#include "arm/constants-arm.h"
Andrei Popescu31002712010-02-23 13:46:05 +000039#elif V8_TARGET_ARCH_MIPS
40#include "mips/constants-mips.h"
Steve Block3ce2e202009-11-05 08:53:23 +000041#endif
Ben Murdoch592a9fc2012-03-05 11:04:45 +000042#include "v8checks.h"
43
Steve Blocka7e24c12009-10-30 11:49:00 +000044
45//
Kristian Monsen50ef84f2010-07-29 15:18:00 +010046// Most object types in the V8 JavaScript are described in this file.
Steve Blocka7e24c12009-10-30 11:49:00 +000047//
48// Inheritance hierarchy:
John Reck59135872010-11-02 12:39:01 -070049// - MaybeObject (an object or a failure)
50// - Failure (immediate for marking failed operation)
Steve Blocka7e24c12009-10-30 11:49:00 +000051// - Object
52// - Smi (immediate small integer)
Steve Blocka7e24c12009-10-30 11:49:00 +000053// - HeapObject (superclass for everything allocated in the heap)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000054// - JSReceiver (suitable for property access)
55// - JSObject
56// - JSArray
Ben Murdoch592a9fc2012-03-05 11:04:45 +000057// - JSSet
58// - JSMap
Ben Murdoch69a99ed2011-11-30 16:03:39 +000059// - JSWeakMap
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000060// - JSRegExp
61// - JSFunction
62// - GlobalObject
63// - JSGlobalObject
64// - JSBuiltinsObject
65// - JSGlobalProxy
66// - JSValue
67// - JSMessageObject
68// - JSProxy
69// - JSFunctionProxy
Ben Murdoch69a99ed2011-11-30 16:03:39 +000070// - FixedArrayBase
71// - ByteArray
72// - FixedArray
73// - DescriptorArray
74// - HashTable
75// - Dictionary
76// - SymbolTable
77// - CompilationCacheTable
78// - CodeCacheHashTable
79// - MapCache
80// - Context
81// - JSFunctionResultCache
Ben Murdoch592a9fc2012-03-05 11:04:45 +000082// - ScopeInfo
Ben Murdoch69a99ed2011-11-30 16:03:39 +000083// - FixedDoubleArray
84// - ExternalArray
85// - ExternalPixelArray
86// - ExternalByteArray
87// - ExternalUnsignedByteArray
88// - ExternalShortArray
89// - ExternalUnsignedShortArray
90// - ExternalIntArray
91// - ExternalUnsignedIntArray
92// - ExternalFloatArray
Steve Blocka7e24c12009-10-30 11:49:00 +000093// - String
94// - SeqString
95// - SeqAsciiString
96// - SeqTwoByteString
Ben Murdoch69a99ed2011-11-30 16:03:39 +000097// - SlicedString
Steve Blocka7e24c12009-10-30 11:49:00 +000098// - ConsString
Steve Blocka7e24c12009-10-30 11:49:00 +000099// - ExternalString
100// - ExternalAsciiString
101// - ExternalTwoByteString
102// - HeapNumber
103// - Code
104// - Map
105// - Oddball
Ben Murdoch257744e2011-11-30 15:57:28 +0000106// - Foreign
Steve Blocka7e24c12009-10-30 11:49:00 +0000107// - SharedFunctionInfo
108// - Struct
109// - AccessorInfo
Ben Murdochc7cc0282012-03-05 14:35:55 +0000110// - AccessorPair
Steve Blocka7e24c12009-10-30 11:49:00 +0000111// - AccessCheckInfo
112// - InterceptorInfo
113// - CallHandlerInfo
114// - TemplateInfo
115// - FunctionTemplateInfo
116// - ObjectTemplateInfo
117// - Script
118// - SignatureInfo
119// - TypeSwitchInfo
120// - DebugInfo
121// - BreakPointInfo
Steve Block6ded16b2010-05-10 14:33:55 +0100122// - CodeCache
Steve Blocka7e24c12009-10-30 11:49:00 +0000123//
124// Formats of Object*:
125// Smi: [31 bit signed int] 0
126// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
127// Failure: [30 bit signed int] 11
128
Steve Blocka7e24c12009-10-30 11:49:00 +0000129namespace v8 {
130namespace internal {
131
Ben Murdoch589d6972011-11-30 16:04:58 +0000132enum ElementsKind {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000133 // The "fast" kind for elements that only contain SMI values. Must be first
134 // to make it possible to efficiently check maps for this kind.
135 FAST_SMI_ONLY_ELEMENTS,
136
137 // The "fast" kind for tagged values. Must be second to make it possible to
138 // efficiently check maps for this and the FAST_SMI_ONLY_ELEMENTS kind
139 // together at once.
Ben Murdoch589d6972011-11-30 16:04:58 +0000140 FAST_ELEMENTS,
141
142 // The "fast" kind for unwrapped, non-tagged double values.
143 FAST_DOUBLE_ELEMENTS,
144
145 // The "slow" kind.
146 DICTIONARY_ELEMENTS,
147 NON_STRICT_ARGUMENTS_ELEMENTS,
148 // The "fast" kind for external arrays
149 EXTERNAL_BYTE_ELEMENTS,
150 EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
151 EXTERNAL_SHORT_ELEMENTS,
152 EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
153 EXTERNAL_INT_ELEMENTS,
154 EXTERNAL_UNSIGNED_INT_ELEMENTS,
155 EXTERNAL_FLOAT_ELEMENTS,
156 EXTERNAL_DOUBLE_ELEMENTS,
157 EXTERNAL_PIXEL_ELEMENTS,
158
159 // Derived constants from ElementsKind
160 FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_BYTE_ELEMENTS,
161 LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000162 FIRST_ELEMENTS_KIND = FAST_SMI_ONLY_ELEMENTS,
Ben Murdoch589d6972011-11-30 16:04:58 +0000163 LAST_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS
164};
165
Ben Murdochc7cc0282012-03-05 14:35:55 +0000166enum CompareMapMode {
167 REQUIRE_EXACT_MAP,
168 ALLOW_ELEMENT_TRANSITION_MAPS
169};
170
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000171const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000172
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000173void PrintElementsKind(FILE* out, ElementsKind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000174
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000175inline bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
176 ElementsKind to_kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000177
178// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
179enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
180
181
182// PropertyNormalizationMode is used to specify whether to keep
183// inobject properties when normalizing properties of a JSObject.
184enum PropertyNormalizationMode {
185 CLEAR_INOBJECT_PROPERTIES,
186 KEEP_INOBJECT_PROPERTIES
187};
188
189
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100190// NormalizedMapSharingMode is used to specify whether a map may be shared
191// by different objects with normalized properties.
192enum NormalizedMapSharingMode {
193 UNIQUE_NORMALIZED_MAP,
194 SHARED_NORMALIZED_MAP
195};
196
197
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000198// Indicates whether a get method should implicitly create the object looked up.
199enum CreationFlag {
200 ALLOW_CREATION,
201 OMIT_CREATION
202};
203
204
Steve Block791712a2010-08-27 10:21:07 +0100205// Instance size sentinel for objects of variable size.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000206const int kVariableSizeSentinel = 0;
Steve Block791712a2010-08-27 10:21:07 +0100207
208
Steve Blocka7e24c12009-10-30 11:49:00 +0000209// All Maps have a field instance_type containing a InstanceType.
210// It describes the type of the instances.
211//
212// As an example, a JavaScript object is a heap object and its map
213// instance_type is JS_OBJECT_TYPE.
214//
215// The names of the string instance types are intended to systematically
Leon Clarkee46be812010-01-19 14:06:41 +0000216// mirror their encoding in the instance_type field of the map. The default
217// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
218// encoding is mentioned explicitly in the name. Likewise, the default
219// representation is considered sequential. It is not mentioned in the
Ben Murdochc7cc0282012-03-05 14:35:55 +0000220// name. The other representations (e.g. CONS, EXTERNAL) are explicitly
Leon Clarkee46be812010-01-19 14:06:41 +0000221// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
222// symbol) or a STRING_TYPE (if it is not a symbol).
Steve Blocka7e24c12009-10-30 11:49:00 +0000223//
224// NOTE: The following things are some that depend on the string types having
225// instance_types that are less than those of all other types:
226// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
227// Object::IsString.
228//
229// NOTE: Everything following JS_VALUE_TYPE is considered a
230// JSObject for GC purposes. The first four entries here have typeof
231// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
Steve Blockd0582a62009-12-15 09:54:21 +0000232#define INSTANCE_TYPE_LIST_ALL(V) \
233 V(SYMBOL_TYPE) \
234 V(ASCII_SYMBOL_TYPE) \
235 V(CONS_SYMBOL_TYPE) \
236 V(CONS_ASCII_SYMBOL_TYPE) \
237 V(EXTERNAL_SYMBOL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100238 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000239 V(EXTERNAL_ASCII_SYMBOL_TYPE) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000240 V(SHORT_EXTERNAL_SYMBOL_TYPE) \
241 V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
242 V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000243 V(STRING_TYPE) \
244 V(ASCII_STRING_TYPE) \
245 V(CONS_STRING_TYPE) \
246 V(CONS_ASCII_STRING_TYPE) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000247 V(SLICED_STRING_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000248 V(EXTERNAL_STRING_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100249 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000250 V(EXTERNAL_ASCII_STRING_TYPE) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000251 V(SHORT_EXTERNAL_STRING_TYPE) \
252 V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
253 V(SHORT_EXTERNAL_ASCII_STRING_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000254 V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
255 \
256 V(MAP_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000257 V(CODE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000258 V(ODDBALL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100259 V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
Leon Clarkee46be812010-01-19 14:06:41 +0000260 \
261 V(HEAP_NUMBER_TYPE) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000262 V(FOREIGN_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000263 V(BYTE_ARRAY_TYPE) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000264 V(FREE_SPACE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000265 /* Note: the order of these external array */ \
266 /* types is relied upon in */ \
267 /* Object::IsExternalArray(). */ \
268 V(EXTERNAL_BYTE_ARRAY_TYPE) \
269 V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
270 V(EXTERNAL_SHORT_ARRAY_TYPE) \
271 V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
272 V(EXTERNAL_INT_ARRAY_TYPE) \
273 V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
274 V(EXTERNAL_FLOAT_ARRAY_TYPE) \
Steve Block44f0eee2011-05-26 01:26:41 +0100275 V(EXTERNAL_PIXEL_ARRAY_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000276 V(FILLER_TYPE) \
277 \
278 V(ACCESSOR_INFO_TYPE) \
Ben Murdochc7cc0282012-03-05 14:35:55 +0000279 V(ACCESSOR_PAIR_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000280 V(ACCESS_CHECK_INFO_TYPE) \
281 V(INTERCEPTOR_INFO_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000282 V(CALL_HANDLER_INFO_TYPE) \
283 V(FUNCTION_TEMPLATE_INFO_TYPE) \
284 V(OBJECT_TEMPLATE_INFO_TYPE) \
285 V(SIGNATURE_INFO_TYPE) \
286 V(TYPE_SWITCH_INFO_TYPE) \
287 V(SCRIPT_TYPE) \
Steve Block6ded16b2010-05-10 14:33:55 +0100288 V(CODE_CACHE_TYPE) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000289 V(POLYMORPHIC_CODE_CACHE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000290 \
Iain Merrick75681382010-08-19 15:07:18 +0100291 V(FIXED_ARRAY_TYPE) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000292 V(FIXED_DOUBLE_ARRAY_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100293 V(SHARED_FUNCTION_INFO_TYPE) \
294 \
Steve Block1e0659c2011-05-24 12:43:12 +0100295 V(JS_MESSAGE_OBJECT_TYPE) \
296 \
Steve Blockd0582a62009-12-15 09:54:21 +0000297 V(JS_VALUE_TYPE) \
298 V(JS_OBJECT_TYPE) \
299 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
300 V(JS_GLOBAL_OBJECT_TYPE) \
301 V(JS_BUILTINS_OBJECT_TYPE) \
302 V(JS_GLOBAL_PROXY_TYPE) \
303 V(JS_ARRAY_TYPE) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000304 V(JS_PROXY_TYPE) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000305 V(JS_WEAK_MAP_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000306 V(JS_REGEXP_TYPE) \
307 \
308 V(JS_FUNCTION_TYPE) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000309 V(JS_FUNCTION_PROXY_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000310
311#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000312#define INSTANCE_TYPE_LIST_DEBUGGER(V) \
313 V(DEBUG_INFO_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 V(BREAK_POINT_INFO_TYPE)
315#else
316#define INSTANCE_TYPE_LIST_DEBUGGER(V)
317#endif
318
Steve Blockd0582a62009-12-15 09:54:21 +0000319#define INSTANCE_TYPE_LIST(V) \
320 INSTANCE_TYPE_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000321 INSTANCE_TYPE_LIST_DEBUGGER(V)
322
323
324// Since string types are not consecutive, this macro is used to
325// iterate over them.
326#define STRING_TYPE_LIST(V) \
Steve Blockd0582a62009-12-15 09:54:21 +0000327 V(SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100328 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000329 symbol, \
330 Symbol) \
331 V(ASCII_SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100332 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000333 ascii_symbol, \
334 AsciiSymbol) \
335 V(CONS_SYMBOL_TYPE, \
336 ConsString::kSize, \
337 cons_symbol, \
338 ConsSymbol) \
339 V(CONS_ASCII_SYMBOL_TYPE, \
340 ConsString::kSize, \
341 cons_ascii_symbol, \
342 ConsAsciiSymbol) \
343 V(EXTERNAL_SYMBOL_TYPE, \
344 ExternalTwoByteString::kSize, \
345 external_symbol, \
346 ExternalSymbol) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100347 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
348 ExternalTwoByteString::kSize, \
349 external_symbol_with_ascii_data, \
350 ExternalSymbolWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000351 V(EXTERNAL_ASCII_SYMBOL_TYPE, \
352 ExternalAsciiString::kSize, \
353 external_ascii_symbol, \
354 ExternalAsciiSymbol) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000355 V(SHORT_EXTERNAL_SYMBOL_TYPE, \
356 ExternalTwoByteString::kShortSize, \
357 short_external_symbol, \
358 ShortExternalSymbol) \
359 V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
360 ExternalTwoByteString::kShortSize, \
361 short_external_symbol_with_ascii_data, \
362 ShortExternalSymbolWithAsciiData) \
363 V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE, \
364 ExternalAsciiString::kShortSize, \
365 short_external_ascii_symbol, \
366 ShortExternalAsciiSymbol) \
Steve Blockd0582a62009-12-15 09:54:21 +0000367 V(STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100368 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000369 string, \
370 String) \
371 V(ASCII_STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100372 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000373 ascii_string, \
374 AsciiString) \
375 V(CONS_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000377 cons_string, \
378 ConsString) \
379 V(CONS_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000380 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000381 cons_ascii_string, \
382 ConsAsciiString) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000383 V(SLICED_STRING_TYPE, \
384 SlicedString::kSize, \
385 sliced_string, \
386 SlicedString) \
387 V(SLICED_ASCII_STRING_TYPE, \
388 SlicedString::kSize, \
389 sliced_ascii_string, \
390 SlicedAsciiString) \
Steve Blockd0582a62009-12-15 09:54:21 +0000391 V(EXTERNAL_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 ExternalTwoByteString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000393 external_string, \
394 ExternalString) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100395 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
396 ExternalTwoByteString::kSize, \
397 external_string_with_ascii_data, \
398 ExternalStringWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000399 V(EXTERNAL_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 ExternalAsciiString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000401 external_ascii_string, \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000402 ExternalAsciiString) \
403 V(SHORT_EXTERNAL_STRING_TYPE, \
404 ExternalTwoByteString::kShortSize, \
405 short_external_string, \
406 ShortExternalString) \
407 V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
408 ExternalTwoByteString::kShortSize, \
409 short_external_string_with_ascii_data, \
410 ShortExternalStringWithAsciiData) \
411 V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
412 ExternalAsciiString::kShortSize, \
413 short_external_ascii_string, \
414 ShortExternalAsciiString)
Steve Blocka7e24c12009-10-30 11:49:00 +0000415
416// A struct is a simple object a set of object-valued fields. Including an
417// object type in this causes the compiler to generate most of the boilerplate
418// code for the class including allocation and garbage collection routines,
419// casts and predicates. All you need to define is the class, methods and
420// object verification routines. Easy, no?
421//
422// Note that for subtle reasons related to the ordering or numerical values of
423// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
424// manually.
Steve Blockd0582a62009-12-15 09:54:21 +0000425#define STRUCT_LIST_ALL(V) \
426 V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
Ben Murdochc7cc0282012-03-05 14:35:55 +0000427 V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \
Steve Blockd0582a62009-12-15 09:54:21 +0000428 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
429 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
430 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
431 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
432 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
433 V(SIGNATURE_INFO, SignatureInfo, signature_info) \
434 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
Steve Block6ded16b2010-05-10 14:33:55 +0100435 V(SCRIPT, Script, script) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000436 V(CODE_CACHE, CodeCache, code_cache) \
437 V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache)
Steve Blocka7e24c12009-10-30 11:49:00 +0000438
439#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000440#define STRUCT_LIST_DEBUGGER(V) \
441 V(DEBUG_INFO, DebugInfo, debug_info) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
443#else
444#define STRUCT_LIST_DEBUGGER(V)
445#endif
446
Steve Blockd0582a62009-12-15 09:54:21 +0000447#define STRUCT_LIST(V) \
448 STRUCT_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 STRUCT_LIST_DEBUGGER(V)
450
451// We use the full 8 bits of the instance_type field to encode heap object
452// instance types. The high-order bit (bit 7) is set if the object is not a
453// string, and cleared if it is a string.
454const uint32_t kIsNotStringMask = 0x80;
455const uint32_t kStringTag = 0x0;
456const uint32_t kNotStringTag = 0x80;
457
Leon Clarkee46be812010-01-19 14:06:41 +0000458// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
459// There are not enough types that the non-string types (with bit 7 set) can
460// have bit 6 set too.
461const uint32_t kIsSymbolMask = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000462const uint32_t kNotSymbolTag = 0x0;
Leon Clarkee46be812010-01-19 14:06:41 +0000463const uint32_t kSymbolTag = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000464
Steve Blocka7e24c12009-10-30 11:49:00 +0000465// If bit 7 is clear then bit 2 indicates whether the string consists of
466// two-byte characters or one-byte characters.
467const uint32_t kStringEncodingMask = 0x4;
468const uint32_t kTwoByteStringTag = 0x0;
469const uint32_t kAsciiStringTag = 0x4;
470
471// If bit 7 is clear, the low-order 2 bits indicate the representation
472// of the string.
473const uint32_t kStringRepresentationMask = 0x03;
474enum StringRepresentationTag {
475 kSeqStringTag = 0x0,
476 kConsStringTag = 0x1,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000477 kExternalStringTag = 0x2,
478 kSlicedStringTag = 0x3
Steve Blocka7e24c12009-10-30 11:49:00 +0000479};
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000480const uint32_t kIsIndirectStringMask = 0x1;
481const uint32_t kIsIndirectStringTag = 0x1;
482STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0);
483STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0);
484STATIC_ASSERT(
485 (kConsStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
486STATIC_ASSERT(
487 (kSlicedStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
488
489// Use this mask to distinguish between cons and slice only after making
490// sure that the string is one of the two (an indirect string).
491const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
492STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000493
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100494// If bit 7 is clear, then bit 3 indicates whether this two-byte
Ben Murdochc7cc0282012-03-05 14:35:55 +0000495// string actually contains ASCII data.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100496const uint32_t kAsciiDataHintMask = 0x08;
497const uint32_t kAsciiDataHintTag = 0x08;
498
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000499// If bit 7 is clear and string representation indicates an external string,
500// then bit 4 indicates whether the data pointer is cached.
501const uint32_t kShortExternalStringMask = 0x10;
502const uint32_t kShortExternalStringTag = 0x10;
503
Steve Blocka7e24c12009-10-30 11:49:00 +0000504
505// A ConsString with an empty string as the right side is a candidate
506// for being shortcut by the garbage collector unless it is a
507// symbol. It's not common to have non-flat symbols, so we do not
508// shortcut them thereby avoiding turning symbols into strings. See
509// heap.cc and mark-compact.cc.
510const uint32_t kShortcutTypeMask =
511 kIsNotStringMask |
512 kIsSymbolMask |
513 kStringRepresentationMask;
514const uint32_t kShortcutTypeTag = kConsStringTag;
515
516
517enum InstanceType {
Leon Clarkee46be812010-01-19 14:06:41 +0000518 // String types.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100519 SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000520 ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100521 CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000522 CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000523 SHORT_EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag |
524 kExternalStringTag | kShortExternalStringTag,
525 SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
526 kTwoByteStringTag | kSymbolTag | kExternalStringTag |
527 kAsciiDataHintTag | kShortExternalStringTag,
528 SHORT_EXTERNAL_ASCII_SYMBOL_TYPE = kAsciiStringTag | kExternalStringTag |
529 kSymbolTag | kShortExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100530 EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
531 EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
532 kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000533 EXTERNAL_ASCII_SYMBOL_TYPE =
534 kAsciiStringTag | kSymbolTag | kExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100535 STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000536 ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100537 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000538 CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000539 SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
540 SLICED_ASCII_STRING_TYPE = kAsciiStringTag | kSlicedStringTag,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000541 SHORT_EXTERNAL_STRING_TYPE =
542 kTwoByteStringTag | kExternalStringTag | kShortExternalStringTag,
543 SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
544 kTwoByteStringTag | kExternalStringTag |
545 kAsciiDataHintTag | kShortExternalStringTag,
546 SHORT_EXTERNAL_ASCII_STRING_TYPE =
547 kAsciiStringTag | kExternalStringTag | kShortExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100548 EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
549 EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
550 kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
Steve Block1e0659c2011-05-24 12:43:12 +0100551 // LAST_STRING_TYPE
Steve Blockd0582a62009-12-15 09:54:21 +0000552 EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
553 PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000554
Leon Clarkee46be812010-01-19 14:06:41 +0000555 // Objects allocated in their own spaces (never in new space).
556 MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000557 CODE_TYPE,
558 ODDBALL_TYPE,
559 JS_GLOBAL_PROPERTY_CELL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000560
561 // "Data", objects that cannot contain non-map-word pointers to heap
562 // objects.
563 HEAP_NUMBER_TYPE,
Ben Murdoch257744e2011-11-30 15:57:28 +0000564 FOREIGN_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 BYTE_ARRAY_TYPE,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000566 FREE_SPACE_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000567 EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
Steve Block3ce2e202009-11-05 08:53:23 +0000568 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
569 EXTERNAL_SHORT_ARRAY_TYPE,
570 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
571 EXTERNAL_INT_ARRAY_TYPE,
572 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100573 EXTERNAL_FLOAT_ARRAY_TYPE,
Ben Murdoch257744e2011-11-30 15:57:28 +0000574 EXTERNAL_DOUBLE_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100575 EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000576 FIXED_DOUBLE_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000577 FILLER_TYPE, // LAST_DATA_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000578
Leon Clarkee46be812010-01-19 14:06:41 +0000579 // Structs.
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 ACCESSOR_INFO_TYPE,
Ben Murdochc7cc0282012-03-05 14:35:55 +0000581 ACCESSOR_PAIR_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000582 ACCESS_CHECK_INFO_TYPE,
583 INTERCEPTOR_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000584 CALL_HANDLER_INFO_TYPE,
585 FUNCTION_TEMPLATE_INFO_TYPE,
586 OBJECT_TEMPLATE_INFO_TYPE,
587 SIGNATURE_INFO_TYPE,
588 TYPE_SWITCH_INFO_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000589 SCRIPT_TYPE,
Steve Block6ded16b2010-05-10 14:33:55 +0100590 CODE_CACHE_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000591 POLYMORPHIC_CODE_CACHE_TYPE,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100592 // The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
593 // is defined. However as include/v8.h contain some of the instance type
594 // constants always having them avoids them getting different numbers
595 // depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
Steve Blocka7e24c12009-10-30 11:49:00 +0000596 DEBUG_INFO_TYPE,
597 BREAK_POINT_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000598
Leon Clarkee46be812010-01-19 14:06:41 +0000599 FIXED_ARRAY_TYPE,
600 SHARED_FUNCTION_INFO_TYPE,
601
Steve Block1e0659c2011-05-24 12:43:12 +0100602 JS_MESSAGE_OBJECT_TYPE,
603
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000604 // All the following types are subtypes of JSReceiver, which corresponds to
605 // objects in the JS sense. The first and the last type in this range are
606 // the two forms of function. This organization enables using the same
607 // compares for checking the JS_RECEIVER/SPEC_OBJECT range and the
608 // NONCALLABLE_JS_OBJECT range.
609 JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE
610 JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE
611
612 JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000613 JS_OBJECT_TYPE,
614 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
615 JS_GLOBAL_OBJECT_TYPE,
616 JS_BUILTINS_OBJECT_TYPE,
617 JS_GLOBAL_PROXY_TYPE,
618 JS_ARRAY_TYPE,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000619 JS_SET_TYPE,
620 JS_MAP_TYPE,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000621 JS_WEAK_MAP_TYPE,
Steve Block1e0659c2011-05-24 12:43:12 +0100622
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000623 JS_REGEXP_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000625 JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000626
627 // Pseudo-types
Steve Blocka7e24c12009-10-30 11:49:00 +0000628 FIRST_TYPE = 0x0,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000629 LAST_TYPE = JS_FUNCTION_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000630 INVALID_TYPE = FIRST_TYPE - 1,
631 FIRST_NONSTRING_TYPE = MAP_TYPE,
632 // Boundaries for testing for an external array.
633 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100634 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000635 // Boundary for promotion to old data space/old pointer space.
636 LAST_DATA_TYPE = FILLER_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000637 // Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
638 // Note that there is no range for JSObject or JSProxy, since their subtypes
639 // are not continuous in this enum! The enum ranges instead reflect the
640 // external class names, where proxies are treated as either ordinary objects,
641 // or functions.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000642 FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000643 LAST_JS_RECEIVER_TYPE = LAST_TYPE,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000644 // Boundaries for testing the types represented as JSObject
645 FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
646 LAST_JS_OBJECT_TYPE = LAST_TYPE,
647 // Boundaries for testing the types represented as JSProxy
648 FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE,
649 LAST_JS_PROXY_TYPE = JS_PROXY_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000650 // Boundaries for testing whether the type is a JavaScript object.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000651 FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE,
652 LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE,
653 // Boundaries for testing the types for which typeof is "object".
654 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE,
655 LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE,
656 // Note that the types for which typeof is "function" are not continuous.
657 // Define this so that we can put assertions on discrete checks.
658 NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2
Steve Blocka7e24c12009-10-30 11:49:00 +0000659};
660
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000661const int kExternalArrayTypeCount =
662 LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000663
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100664STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
665STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
Ben Murdoch257744e2011-11-30 15:57:28 +0000666STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100667
668
Steve Blocka7e24c12009-10-30 11:49:00 +0000669enum CompareResult {
670 LESS = -1,
671 EQUAL = 0,
672 GREATER = 1,
673
674 NOT_EQUAL = GREATER
675};
676
677
678#define DECL_BOOLEAN_ACCESSORS(name) \
679 inline bool name(); \
680 inline void set_##name(bool value); \
681
682
683#define DECL_ACCESSORS(name, type) \
684 inline type* name(); \
685 inline void set_##name(type* value, \
686 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
687
688
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000689class DictionaryElementsAccessor;
690class ElementsAccessor;
691class FixedArrayBase;
Steve Blocka7e24c12009-10-30 11:49:00 +0000692class ObjectVisitor;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000693class StringStream;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000694class Failure;
Steve Blocka7e24c12009-10-30 11:49:00 +0000695
696struct ValueInfo : public Malloced {
697 ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
698 InstanceType type;
699 Object* ptr;
700 const char* str;
701 double number;
702};
703
704
705// A template-ized version of the IsXXX functions.
706template <class C> static inline bool Is(Object* obj);
707
Ben Murdochb0fe1622011-05-05 13:52:32 +0100708
John Reck59135872010-11-02 12:39:01 -0700709class MaybeObject BASE_EMBEDDED {
710 public:
711 inline bool IsFailure();
712 inline bool IsRetryAfterGC();
713 inline bool IsOutOfMemory();
714 inline bool IsException();
715 INLINE(bool IsTheHole());
716 inline bool ToObject(Object** obj) {
717 if (IsFailure()) return false;
718 *obj = reinterpret_cast<Object*>(this);
719 return true;
720 }
Steve Block053d10c2011-06-13 19:13:29 +0100721 inline Failure* ToFailureUnchecked() {
722 ASSERT(IsFailure());
723 return reinterpret_cast<Failure*>(this);
724 }
John Reck59135872010-11-02 12:39:01 -0700725 inline Object* ToObjectUnchecked() {
726 ASSERT(!IsFailure());
727 return reinterpret_cast<Object*>(this);
728 }
729 inline Object* ToObjectChecked() {
730 CHECK(!IsFailure());
731 return reinterpret_cast<Object*>(this);
732 }
733
Steve Block053d10c2011-06-13 19:13:29 +0100734 template<typename T>
735 inline bool To(T** obj) {
736 if (IsFailure()) return false;
737 *obj = T::cast(reinterpret_cast<Object*>(this));
738 return true;
739 }
740
Ben Murdochb0fe1622011-05-05 13:52:32 +0100741#ifdef OBJECT_PRINT
John Reck59135872010-11-02 12:39:01 -0700742 // Prints this object with details.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100743 inline void Print() {
744 Print(stdout);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000745 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100746 inline void PrintLn() {
747 PrintLn(stdout);
748 }
749 void Print(FILE* out);
750 void PrintLn(FILE* out);
751#endif
752#ifdef DEBUG
John Reck59135872010-11-02 12:39:01 -0700753 // Verifies the object.
754 void Verify();
755#endif
756};
Steve Blocka7e24c12009-10-30 11:49:00 +0000757
Ben Murdochb8e0da22011-05-16 14:20:40 +0100758
759#define OBJECT_TYPE_LIST(V) \
760 V(Smi) \
761 V(HeapObject) \
762 V(Number) \
763
764#define HEAP_OBJECT_TYPE_LIST(V) \
765 V(HeapNumber) \
766 V(String) \
767 V(Symbol) \
768 V(SeqString) \
769 V(ExternalString) \
770 V(ConsString) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000771 V(SlicedString) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100772 V(ExternalTwoByteString) \
773 V(ExternalAsciiString) \
774 V(SeqTwoByteString) \
775 V(SeqAsciiString) \
776 \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100777 V(ExternalArray) \
778 V(ExternalByteArray) \
779 V(ExternalUnsignedByteArray) \
780 V(ExternalShortArray) \
781 V(ExternalUnsignedShortArray) \
782 V(ExternalIntArray) \
783 V(ExternalUnsignedIntArray) \
784 V(ExternalFloatArray) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000785 V(ExternalDoubleArray) \
Steve Block44f0eee2011-05-26 01:26:41 +0100786 V(ExternalPixelArray) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100787 V(ByteArray) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000788 V(FreeSpace) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000789 V(JSReceiver) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100790 V(JSObject) \
791 V(JSContextExtensionObject) \
792 V(Map) \
793 V(DescriptorArray) \
794 V(DeoptimizationInputData) \
795 V(DeoptimizationOutputData) \
796 V(FixedArray) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000797 V(FixedDoubleArray) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100798 V(Context) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100799 V(GlobalContext) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000800 V(ScopeInfo) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100801 V(JSFunction) \
802 V(Code) \
803 V(Oddball) \
804 V(SharedFunctionInfo) \
805 V(JSValue) \
Steve Block1e0659c2011-05-24 12:43:12 +0100806 V(JSMessageObject) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100807 V(StringWrapper) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000808 V(Foreign) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100809 V(Boolean) \
810 V(JSArray) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000811 V(JSProxy) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000812 V(JSFunctionProxy) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000813 V(JSSet) \
814 V(JSMap) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000815 V(JSWeakMap) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100816 V(JSRegExp) \
817 V(HashTable) \
818 V(Dictionary) \
819 V(SymbolTable) \
820 V(JSFunctionResultCache) \
821 V(NormalizedMapCache) \
822 V(CompilationCacheTable) \
823 V(CodeCacheHashTable) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000824 V(PolymorphicCodeCacheHashTable) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100825 V(MapCache) \
826 V(Primitive) \
827 V(GlobalObject) \
828 V(JSGlobalObject) \
829 V(JSBuiltinsObject) \
830 V(JSGlobalProxy) \
831 V(UndetectableObject) \
832 V(AccessCheckNeeded) \
833 V(JSGlobalPropertyCell) \
834
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000835
836class JSReceiver;
837
Steve Blocka7e24c12009-10-30 11:49:00 +0000838// Object is the abstract superclass for all classes in the
839// object hierarchy.
840// Object does not use any virtual functions to avoid the
841// allocation of the C++ vtable.
842// Since Smi and Failure are subclasses of Object no
843// data members can be present in Object.
John Reck59135872010-11-02 12:39:01 -0700844class Object : public MaybeObject {
Steve Blocka7e24c12009-10-30 11:49:00 +0000845 public:
846 // Type testing.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100847#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
848 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
849 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
850#undef IS_TYPE_FUNCTION_DECL
Steve Blocka7e24c12009-10-30 11:49:00 +0000851
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000852 inline bool IsFixedArrayBase();
853
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 // Returns true if this object is an instance of the specified
855 // function template.
856 inline bool IsInstanceOf(FunctionTemplateInfo* type);
857
858 inline bool IsStruct();
859#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
860 STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
861#undef DECLARE_STRUCT_PREDICATE
862
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000863 INLINE(bool IsSpecObject());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000864 INLINE(bool IsSpecFunction());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000865
Steve Blocka7e24c12009-10-30 11:49:00 +0000866 // Oddball testing.
867 INLINE(bool IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 INLINE(bool IsNull());
Steve Block44f0eee2011-05-26 01:26:41 +0100869 INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
Steve Blocka7e24c12009-10-30 11:49:00 +0000870 INLINE(bool IsTrue());
871 INLINE(bool IsFalse());
Ben Murdoch086aeea2011-05-13 15:57:08 +0100872 inline bool IsArgumentsMarker();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000873 inline bool NonFailureIsHeapObject();
874
875 // Filler objects (fillers and free space objects).
876 inline bool IsFiller();
Steve Blocka7e24c12009-10-30 11:49:00 +0000877
878 // Extract the number.
879 inline double Number();
880
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000881 // Returns true if the object is of the correct type to be used as a
882 // implementation of a JSObject's elements.
883 inline bool HasValidElements();
884
Steve Blocka7e24c12009-10-30 11:49:00 +0000885 inline bool HasSpecificClassOf(String* name);
886
John Reck59135872010-11-02 12:39:01 -0700887 MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9.
888 Object* ToBoolean(); // ECMA-262 9.2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000889
890 // Convert to a JSObject if needed.
891 // global_context is used when creating wrapper object.
John Reck59135872010-11-02 12:39:01 -0700892 MUST_USE_RESULT MaybeObject* ToObject(Context* global_context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000893
894 // Converts this to a Smi if possible.
895 // Failure is returned otherwise.
John Reck59135872010-11-02 12:39:01 -0700896 MUST_USE_RESULT inline MaybeObject* ToSmi();
Steve Blocka7e24c12009-10-30 11:49:00 +0000897
898 void Lookup(String* name, LookupResult* result);
899
900 // Property access.
John Reck59135872010-11-02 12:39:01 -0700901 MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
902 MUST_USE_RESULT inline MaybeObject* GetProperty(
903 String* key,
904 PropertyAttributes* attributes);
905 MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
906 Object* receiver,
907 String* key,
908 PropertyAttributes* attributes);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000909
910 static Handle<Object> GetProperty(Handle<Object> object,
911 Handle<Object> receiver,
912 LookupResult* result,
913 Handle<String> key,
914 PropertyAttributes* attributes);
915
John Reck59135872010-11-02 12:39:01 -0700916 MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
917 LookupResult* result,
918 String* key,
919 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000920
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000921 MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
922 JSReceiver* getter);
923
924 static Handle<Object> GetElement(Handle<Object> object, uint32_t index);
John Reck59135872010-11-02 12:39:01 -0700925 inline MaybeObject* GetElement(uint32_t index);
926 // For use when we know that no exception can be thrown.
927 inline Object* GetElementNoExceptionThrown(uint32_t index);
928 MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000929
930 // Return the object's prototype (might be Heap::null_value()).
931 Object* GetPrototype();
932
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000933 // Returns the permanent hash code associated with this object depending on
934 // the actual object type. Might return a failure in case no hash was
935 // created yet or GC was caused by creation.
936 MUST_USE_RESULT MaybeObject* GetHash(CreationFlag flag);
937
938 // Checks whether this object has the same value as the given one. This
939 // function is implemented according to ES5, section 9.12 and can be used
940 // to implement the Harmony "egal" function.
941 bool SameValue(Object* other);
942
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100943 // Tries to convert an object to an array index. Returns true and sets
944 // the output parameter if it succeeds.
945 inline bool ToArrayIndex(uint32_t* index);
946
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 // Returns true if this is a JSValue containing a string and the index is
948 // < the length of the string. Used to implement [] on strings.
949 inline bool IsStringObjectWithCharacterAt(uint32_t index);
950
951#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000952 // Verify a pointer is a valid object pointer.
953 static void VerifyPointer(Object* p);
954#endif
955
956 // Prints this object without details.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100957 inline void ShortPrint() {
958 ShortPrint(stdout);
959 }
960 void ShortPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000961
962 // Prints this object without details to a message accumulator.
963 void ShortPrint(StringStream* accumulator);
964
965 // Casting: This cast is only needed to satisfy macros in objects-inl.h.
966 static Object* cast(Object* value) { return value; }
967
968 // Layout description.
969 static const int kHeaderSize = 0; // Object does not take up any space.
970
971 private:
972 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
973};
974
975
976// Smi represents integer Numbers that can be stored in 31 bits.
977// Smis are immediate which means they are NOT allocated in the heap.
Steve Blocka7e24c12009-10-30 11:49:00 +0000978// The this pointer has the following format: [31 bit signed int] 0
Steve Block3ce2e202009-11-05 08:53:23 +0000979// For long smis it has the following format:
980// [32 bit signed int] [31 bits zero padding] 0
981// Smi stands for small integer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000982class Smi: public Object {
983 public:
984 // Returns the integer value.
985 inline int value();
986
987 // Convert a value to a Smi object.
988 static inline Smi* FromInt(int value);
989
990 static inline Smi* FromIntptr(intptr_t value);
991
992 // Returns whether value can be represented in a Smi.
993 static inline bool IsValid(intptr_t value);
994
Steve Blocka7e24c12009-10-30 11:49:00 +0000995 // Casting.
996 static inline Smi* cast(Object* object);
997
998 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100999 inline void SmiPrint() {
1000 SmiPrint(stdout);
1001 }
1002 void SmiPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001003 void SmiPrint(StringStream* accumulator);
1004#ifdef DEBUG
1005 void SmiVerify();
1006#endif
1007
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001008 static const int kMinValue =
1009 (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
Steve Block3ce2e202009-11-05 08:53:23 +00001010 static const int kMaxValue = -(kMinValue + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001011
1012 private:
1013 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
1014};
1015
1016
1017// Failure is used for reporting out of memory situations and
1018// propagating exceptions through the runtime system. Failure objects
1019// are transient and cannot occur as part of the object graph.
1020//
1021// Failures are a single word, encoded as follows:
1022// +-------------------------+---+--+--+
Ben Murdochf87a2032010-10-22 12:50:53 +01001023// |.........unused..........|sss|tt|11|
Steve Blocka7e24c12009-10-30 11:49:00 +00001024// +-------------------------+---+--+--+
Steve Block3ce2e202009-11-05 08:53:23 +00001025// 7 6 4 32 10
1026//
Steve Blocka7e24c12009-10-30 11:49:00 +00001027//
1028// The low two bits, 0-1, are the failure tag, 11. The next two bits,
1029// 2-3, are a failure type tag 'tt' with possible values:
1030// 00 RETRY_AFTER_GC
1031// 01 EXCEPTION
1032// 10 INTERNAL_ERROR
1033// 11 OUT_OF_MEMORY_EXCEPTION
1034//
1035// The next three bits, 4-6, are an allocation space tag 'sss'. The
1036// allocation space tag is 000 for all failure types except
1037// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
1038// allocation spaces (the encoding is found in globals.h).
Steve Blocka7e24c12009-10-30 11:49:00 +00001039
1040// Failure type tag info.
1041const int kFailureTypeTagSize = 2;
1042const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
1043
John Reck59135872010-11-02 12:39:01 -07001044class Failure: public MaybeObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 public:
1046 // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
1047 enum Type {
1048 RETRY_AFTER_GC = 0,
1049 EXCEPTION = 1, // Returning this marker tells the real exception
Steve Block44f0eee2011-05-26 01:26:41 +01001050 // is in Isolate::pending_exception.
Steve Blocka7e24c12009-10-30 11:49:00 +00001051 INTERNAL_ERROR = 2,
1052 OUT_OF_MEMORY_EXCEPTION = 3
1053 };
1054
1055 inline Type type() const;
1056
1057 // Returns the space that needs to be collected for RetryAfterGC failures.
1058 inline AllocationSpace allocation_space() const;
1059
Steve Blocka7e24c12009-10-30 11:49:00 +00001060 inline bool IsInternalError() const;
1061 inline bool IsOutOfMemoryException() const;
1062
Ben Murdochf87a2032010-10-22 12:50:53 +01001063 static inline Failure* RetryAfterGC(AllocationSpace space);
1064 static inline Failure* RetryAfterGC(); // NEW_SPACE
Steve Blocka7e24c12009-10-30 11:49:00 +00001065 static inline Failure* Exception();
1066 static inline Failure* InternalError();
1067 static inline Failure* OutOfMemoryException();
1068 // Casting.
John Reck59135872010-11-02 12:39:01 -07001069 static inline Failure* cast(MaybeObject* object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001070
1071 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001072 inline void FailurePrint() {
1073 FailurePrint(stdout);
1074 }
1075 void FailurePrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 void FailurePrint(StringStream* accumulator);
1077#ifdef DEBUG
1078 void FailureVerify();
1079#endif
1080
1081 private:
Steve Block3ce2e202009-11-05 08:53:23 +00001082 inline intptr_t value() const;
1083 static inline Failure* Construct(Type type, intptr_t value = 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001084
1085 DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
1086};
1087
1088
1089// Heap objects typically have a map pointer in their first word. However,
Ben Murdochc7cc0282012-03-05 14:35:55 +00001090// during GC other data (e.g. mark bits, forwarding addresses) is sometimes
Steve Blocka7e24c12009-10-30 11:49:00 +00001091// encoded in the first word. The class MapWord is an abstraction of the
1092// value in a heap object's first word.
1093class MapWord BASE_EMBEDDED {
1094 public:
1095 // Normal state: the map word contains a map pointer.
1096
1097 // Create a map word from a map pointer.
1098 static inline MapWord FromMap(Map* map);
1099
1100 // View this map word as a map pointer.
1101 inline Map* ToMap();
1102
1103
1104 // Scavenge collection: the map word of live objects in the from space
1105 // contains a forwarding address (a heap object pointer in the to space).
1106
1107 // True if this map word is a forwarding address for a scavenge
1108 // collection. Only valid during a scavenge collection (specifically,
Ben Murdochc7cc0282012-03-05 14:35:55 +00001109 // when all map words are heap object pointers, i.e. not during a full GC).
Steve Blocka7e24c12009-10-30 11:49:00 +00001110 inline bool IsForwardingAddress();
1111
1112 // Create a map word from a forwarding address.
1113 static inline MapWord FromForwardingAddress(HeapObject* object);
1114
1115 // View this map word as a forwarding address.
1116 inline HeapObject* ToForwardingAddress();
1117
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001118 static inline MapWord FromRawValue(uintptr_t value) {
1119 return MapWord(value);
1120 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001121
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001122 inline uintptr_t ToRawValue() {
1123 return value_;
1124 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001125
1126 private:
1127 // HeapObject calls the private constructor and directly reads the value.
1128 friend class HeapObject;
1129
1130 explicit MapWord(uintptr_t value) : value_(value) {}
1131
1132 uintptr_t value_;
1133};
1134
1135
1136// HeapObject is the superclass for all classes describing heap allocated
1137// objects.
1138class HeapObject: public Object {
1139 public:
1140 // [map]: Contains a map which contains the object's reflective
1141 // information.
1142 inline Map* map();
1143 inline void set_map(Map* value);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001144 // The no-write-barrier version. This is OK if the object is white and in
1145 // new space, or if the value is an immortal immutable object, like the maps
1146 // of primitive (non-JS) objects like strings, heap numbers etc.
1147 inline void set_map_no_write_barrier(Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001148
1149 // During garbage collection, the map word of a heap object does not
1150 // necessarily contain a map pointer.
1151 inline MapWord map_word();
1152 inline void set_map_word(MapWord map_word);
1153
Steve Block44f0eee2011-05-26 01:26:41 +01001154 // The Heap the object was allocated in. Used also to access Isolate.
Steve Block44f0eee2011-05-26 01:26:41 +01001155 inline Heap* GetHeap();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001156
Steve Block44f0eee2011-05-26 01:26:41 +01001157 // Convenience method to get current isolate. This method can be
1158 // accessed only when its result is the same as
1159 // Isolate::Current(), it ASSERTs this. See also comment for GetHeap.
1160 inline Isolate* GetIsolate();
1161
Steve Blocka7e24c12009-10-30 11:49:00 +00001162 // Converts an address to a HeapObject pointer.
1163 static inline HeapObject* FromAddress(Address address);
1164
1165 // Returns the address of this HeapObject.
1166 inline Address address();
1167
1168 // Iterates over pointers contained in the object (including the Map)
1169 void Iterate(ObjectVisitor* v);
1170
1171 // Iterates over all pointers contained in the object except the
1172 // first map pointer. The object type is given in the first
1173 // parameter. This function does not access the map pointer in the
1174 // object, and so is safe to call while the map pointer is modified.
1175 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
1176
Steve Blocka7e24c12009-10-30 11:49:00 +00001177 // Returns the heap object's size in bytes
1178 inline int Size();
1179
1180 // Given a heap object's map pointer, returns the heap size in bytes
1181 // Useful when the map pointer field is used for other purposes.
1182 // GC internal.
1183 inline int SizeFromMap(Map* map);
1184
Steve Blocka7e24c12009-10-30 11:49:00 +00001185 // Returns the field at offset in obj, as a read/write Object* reference.
1186 // Does no checking, and is safe to use during GC, while maps are invalid.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001187 // Does not invoke write barrier, so should only be assigned to
Steve Blocka7e24c12009-10-30 11:49:00 +00001188 // during marking GC.
1189 static inline Object** RawField(HeapObject* obj, int offset);
1190
1191 // Casting.
1192 static inline HeapObject* cast(Object* obj);
1193
Leon Clarke4515c472010-02-03 11:58:03 +00001194 // Return the write barrier mode for this. Callers of this function
1195 // must be able to present a reference to an AssertNoAllocation
1196 // object as a sign that they are not going to use this function
1197 // from code that allocates and thus invalidates the returned write
1198 // barrier mode.
1199 inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
Steve Blocka7e24c12009-10-30 11:49:00 +00001200
1201 // Dispatched behavior.
1202 void HeapObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001203#ifdef OBJECT_PRINT
1204 inline void HeapObjectPrint() {
1205 HeapObjectPrint(stdout);
1206 }
1207 void HeapObjectPrint(FILE* out);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001208 void PrintHeader(FILE* out, const char* id);
1209#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001210
Ben Murdochb0fe1622011-05-05 13:52:32 +01001211#ifdef DEBUG
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001212 void HeapObjectVerify();
1213 inline void VerifyObjectField(int offset);
1214 inline void VerifySmiField(int offset);
1215
Steve Blocka7e24c12009-10-30 11:49:00 +00001216 // Verify a pointer is a valid HeapObject pointer that points to object
1217 // areas in the heap.
1218 static void VerifyHeapPointer(Object* p);
1219#endif
1220
1221 // Layout description.
1222 // First field in a heap object is map.
1223 static const int kMapOffset = Object::kHeaderSize;
1224 static const int kHeaderSize = kMapOffset + kPointerSize;
1225
1226 STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
1227
1228 protected:
1229 // helpers for calling an ObjectVisitor to iterate over pointers in the
1230 // half-open range [start, end) specified as integer offsets
1231 inline void IteratePointers(ObjectVisitor* v, int start, int end);
1232 // as above, for the single element at "offset"
1233 inline void IteratePointer(ObjectVisitor* v, int offset);
1234
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 private:
1236 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
1237};
1238
1239
Iain Merrick75681382010-08-19 15:07:18 +01001240#define SLOT_ADDR(obj, offset) \
1241 reinterpret_cast<Object**>((obj)->address() + offset)
1242
1243// This class describes a body of an object of a fixed size
1244// in which all pointer fields are located in the [start_offset, end_offset)
1245// interval.
1246template<int start_offset, int end_offset, int size>
1247class FixedBodyDescriptor {
1248 public:
1249 static const int kStartOffset = start_offset;
1250 static const int kEndOffset = end_offset;
1251 static const int kSize = size;
1252
1253 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
1254
1255 template<typename StaticVisitor>
1256 static inline void IterateBody(HeapObject* obj) {
1257 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1258 SLOT_ADDR(obj, end_offset));
1259 }
1260};
1261
1262
1263// This class describes a body of an object of a variable size
1264// in which all pointer fields are located in the [start_offset, object_size)
1265// interval.
1266template<int start_offset>
1267class FlexibleBodyDescriptor {
1268 public:
1269 static const int kStartOffset = start_offset;
1270
1271 static inline void IterateBody(HeapObject* obj,
1272 int object_size,
1273 ObjectVisitor* v);
1274
1275 template<typename StaticVisitor>
1276 static inline void IterateBody(HeapObject* obj, int object_size) {
1277 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1278 SLOT_ADDR(obj, object_size));
1279 }
1280};
1281
1282#undef SLOT_ADDR
1283
1284
Steve Blocka7e24c12009-10-30 11:49:00 +00001285// The HeapNumber class describes heap allocated numbers that cannot be
1286// represented in a Smi (small integer)
1287class HeapNumber: public HeapObject {
1288 public:
1289 // [value]: number value.
1290 inline double value();
1291 inline void set_value(double value);
1292
1293 // Casting.
1294 static inline HeapNumber* cast(Object* obj);
1295
1296 // Dispatched behavior.
1297 Object* HeapNumberToBoolean();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001298 inline void HeapNumberPrint() {
1299 HeapNumberPrint(stdout);
1300 }
1301 void HeapNumberPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001302 void HeapNumberPrint(StringStream* accumulator);
1303#ifdef DEBUG
1304 void HeapNumberVerify();
1305#endif
1306
Steve Block6ded16b2010-05-10 14:33:55 +01001307 inline int get_exponent();
1308 inline int get_sign();
1309
Steve Blocka7e24c12009-10-30 11:49:00 +00001310 // Layout description.
1311 static const int kValueOffset = HeapObject::kHeaderSize;
1312 // IEEE doubles are two 32 bit words. The first is just mantissa, the second
1313 // is a mixture of sign, exponent and mantissa. Our current platforms are all
1314 // little endian apart from non-EABI arm which is little endian with big
1315 // endian floating point word ordering!
Steve Blocka7e24c12009-10-30 11:49:00 +00001316 static const int kMantissaOffset = kValueOffset;
1317 static const int kExponentOffset = kValueOffset + 4;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001318
Steve Blocka7e24c12009-10-30 11:49:00 +00001319 static const int kSize = kValueOffset + kDoubleSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001320 static const uint32_t kSignMask = 0x80000000u;
1321 static const uint32_t kExponentMask = 0x7ff00000u;
1322 static const uint32_t kMantissaMask = 0xfffffu;
Steve Block6ded16b2010-05-10 14:33:55 +01001323 static const int kMantissaBits = 52;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001324 static const int kExponentBits = 11;
Steve Blocka7e24c12009-10-30 11:49:00 +00001325 static const int kExponentBias = 1023;
1326 static const int kExponentShift = 20;
1327 static const int kMantissaBitsInTopWord = 20;
1328 static const int kNonMantissaBitsInTopWord = 12;
1329
1330 private:
1331 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1332};
1333
1334
Ben Murdochc7cc0282012-03-05 14:35:55 +00001335enum EnsureElementsMode {
1336 DONT_ALLOW_DOUBLE_ELEMENTS,
1337 ALLOW_COPIED_DOUBLE_ELEMENTS,
1338 ALLOW_CONVERTED_DOUBLE_ELEMENTS
1339};
1340
1341
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001342// JSReceiver includes types on which properties can be defined, i.e.,
1343// JSObject and JSProxy.
1344class JSReceiver: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001345 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001346 enum DeleteMode {
1347 NORMAL_DELETION,
1348 STRICT_DELETION,
1349 FORCE_DELETION
1350 };
1351
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001352 // Casting.
1353 static inline JSReceiver* cast(Object* obj);
1354
Ben Murdochc7cc0282012-03-05 14:35:55 +00001355 static Handle<Object> SetProperty(Handle<JSReceiver> object,
1356 Handle<String> key,
1357 Handle<Object> value,
1358 PropertyAttributes attributes,
1359 StrictModeFlag strict_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001360 // Can cause GC.
1361 MUST_USE_RESULT MaybeObject* SetProperty(String* key,
1362 Object* value,
1363 PropertyAttributes attributes,
1364 StrictModeFlag strict_mode);
1365 MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
1366 String* key,
1367 Object* value,
1368 PropertyAttributes attributes,
1369 StrictModeFlag strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001370 MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
1371 Object* value);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001372
1373 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001374 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
1375
1376 // Set the index'th array element.
1377 // Can cause GC, or return failure if GC is required.
1378 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1379 Object* value,
1380 StrictModeFlag strict_mode,
1381 bool check_prototype);
1382
1383 // Tests for the fast common case for property enumeration.
1384 bool IsSimpleEnum();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001385
1386 // Returns the class name ([[Class]] property in the specification).
1387 String* class_name();
1388
1389 // Returns the constructor name (the name (possibly, inferred name) of the
1390 // function that was used to instantiate the object).
1391 String* constructor_name();
1392
1393 inline PropertyAttributes GetPropertyAttribute(String* name);
1394 PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
1395 String* name);
1396 PropertyAttributes GetLocalPropertyAttribute(String* name);
1397
1398 // Can cause a GC.
1399 inline bool HasProperty(String* name);
1400 inline bool HasLocalProperty(String* name);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001401 inline bool HasElement(uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001402
1403 // Return the object's prototype (might be Heap::null_value()).
1404 inline Object* GetPrototype();
1405
1406 // Set the object's prototype (only JSReceiver and null are allowed).
1407 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
1408 bool skip_hidden_prototypes);
1409
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001410 // Retrieves a permanent object identity hash code. The undefined value might
1411 // be returned in case no hash was created yet and OMIT_CREATION was used.
1412 inline MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
1413
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001414 // Lookup a property. If found, the result is valid and has
1415 // detailed information.
1416 void LocalLookup(String* name, LookupResult* result);
1417 void Lookup(String* name, LookupResult* result);
1418
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001419 protected:
1420 Smi* GenerateIdentityHash();
1421
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001422 private:
1423 PropertyAttributes GetPropertyAttribute(JSReceiver* receiver,
1424 LookupResult* result,
1425 String* name,
1426 bool continue_search);
1427
1428 DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
1429};
1430
1431// The JSObject describes real heap allocated JavaScript objects with
1432// properties.
1433// Note that the map of JSObject changes during execution to enable inline
1434// caching.
1435class JSObject: public JSReceiver {
1436 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00001437 // [properties]: Backing storage for properties.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001438 // properties is a FixedArray in the fast case and a Dictionary in the
Steve Blocka7e24c12009-10-30 11:49:00 +00001439 // slow case.
1440 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
1441 inline void initialize_properties();
1442 inline bool HasFastProperties();
1443 inline StringDictionary* property_dictionary(); // Gets slow properties.
1444
1445 // [elements]: The elements (properties with names that are integers).
Iain Merrick75681382010-08-19 15:07:18 +01001446 //
1447 // Elements can be in two general modes: fast and slow. Each mode
1448 // corrensponds to a set of object representations of elements that
1449 // have something in common.
1450 //
1451 // In the fast mode elements is a FixedArray and so each element can
1452 // be quickly accessed. This fact is used in the generated code. The
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001453 // elements array can have one of three maps in this mode:
1454 // fixed_array_map, non_strict_arguments_elements_map or
1455 // fixed_cow_array_map (for copy-on-write arrays). In the latter case
1456 // the elements array may be shared by a few objects and so before
1457 // writing to any element the array must be copied. Use
1458 // EnsureWritableFastElements in this case.
Iain Merrick75681382010-08-19 15:07:18 +01001459 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001460 // In the slow mode the elements is either a NumberDictionary, an
1461 // ExternalArray, or a FixedArray parameter map for a (non-strict)
1462 // arguments object.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001463 DECL_ACCESSORS(elements, FixedArrayBase)
Steve Blocka7e24c12009-10-30 11:49:00 +00001464 inline void initialize_elements();
John Reck59135872010-11-02 12:39:01 -07001465 MUST_USE_RESULT inline MaybeObject* ResetElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 inline ElementsKind GetElementsKind();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001467 inline ElementsAccessor* GetElementsAccessor();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001468 inline bool HasFastSmiOnlyElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001469 inline bool HasFastElements();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001470 // Returns if an object has either FAST_ELEMENT or FAST_SMI_ONLY_ELEMENT
1471 // elements. TODO(danno): Rename HasFastTypeElements to HasFastElements() and
1472 // HasFastElements to HasFastObjectElements.
1473 inline bool HasFastTypeElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001474 inline bool HasFastDoubleElements();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001475 inline bool HasNonStrictArgumentsElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001476 inline bool HasDictionaryElements();
Steve Block44f0eee2011-05-26 01:26:41 +01001477 inline bool HasExternalPixelElements();
Steve Block3ce2e202009-11-05 08:53:23 +00001478 inline bool HasExternalArrayElements();
1479 inline bool HasExternalByteElements();
1480 inline bool HasExternalUnsignedByteElements();
1481 inline bool HasExternalShortElements();
1482 inline bool HasExternalUnsignedShortElements();
1483 inline bool HasExternalIntElements();
1484 inline bool HasExternalUnsignedIntElements();
1485 inline bool HasExternalFloatElements();
Ben Murdoch257744e2011-11-30 15:57:28 +00001486 inline bool HasExternalDoubleElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001487 bool HasFastArgumentsElements();
1488 bool HasDictionaryArgumentsElements();
Ben Murdochc7cc0282012-03-05 14:35:55 +00001489 inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
1490
1491 inline void set_map_and_elements(
1492 Map* map,
1493 FixedArrayBase* value,
1494 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001495
1496 // Requires: HasFastElements().
John Reck59135872010-11-02 12:39:01 -07001497 MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001498
1499 // Collects elements starting at index 0.
1500 // Undefined values are placed after non-undefined values.
1501 // Returns the number of non-undefined values.
John Reck59135872010-11-02 12:39:01 -07001502 MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001503 // As PrepareElementsForSort, but only on objects where elements is
1504 // a dictionary, and it will stay a dictionary.
John Reck59135872010-11-02 12:39:01 -07001505 MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001506
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001507 MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
1508 Object* structure,
1509 String* name);
1510
1511 // Can cause GC.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001512 MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
John Reck59135872010-11-02 12:39:01 -07001513 String* key,
1514 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001515 PropertyAttributes attributes,
1516 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001517 MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
1518 LookupResult* result,
1519 String* name,
Ben Murdoch086aeea2011-05-13 15:57:08 +01001520 Object* value,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001521 bool check_prototype,
1522 StrictModeFlag strict_mode);
1523 MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
1524 Object* structure,
1525 String* name,
1526 Object* value,
1527 JSObject* holder,
1528 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001529 MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
1530 String* name,
1531 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001532 PropertyAttributes attributes,
1533 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001534 MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
1535 String* name,
1536 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001537 PropertyAttributes attributes,
1538 StrictModeFlag strict_mode);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001539
1540 static Handle<Object> SetLocalPropertyIgnoreAttributes(
1541 Handle<JSObject> object,
1542 Handle<String> key,
1543 Handle<Object> value,
1544 PropertyAttributes attributes);
1545
1546 // Can cause GC.
Ben Murdoch086aeea2011-05-13 15:57:08 +01001547 MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
John Reck59135872010-11-02 12:39:01 -07001548 String* key,
1549 Object* value,
1550 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001551
1552 // Retrieve a value in a normalized object given a lookup result.
1553 // Handles the special representation of JS global objects.
1554 Object* GetNormalizedProperty(LookupResult* result);
1555
1556 // Sets the property value in a normalized object given a lookup result.
1557 // Handles the special representation of JS global objects.
1558 Object* SetNormalizedProperty(LookupResult* result, Object* value);
1559
1560 // Sets the property value in a normalized object given (key, value, details).
1561 // Handles the special representation of JS global objects.
Ben Murdochc7cc0282012-03-05 14:35:55 +00001562 static Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
1563 Handle<String> key,
1564 Handle<Object> value,
1565 PropertyDetails details);
1566
John Reck59135872010-11-02 12:39:01 -07001567 MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
1568 Object* value,
1569 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00001570
1571 // Deletes the named property in a normalized object.
John Reck59135872010-11-02 12:39:01 -07001572 MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
1573 DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001574
Steve Blocka7e24c12009-10-30 11:49:00 +00001575 // Retrieve interceptors.
1576 InterceptorInfo* GetNamedInterceptor();
1577 InterceptorInfo* GetIndexedInterceptor();
1578
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001579 // Used from JSReceiver.
1580 PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
1581 String* name,
1582 bool continue_search);
1583 PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
1584 String* name,
1585 bool continue_search);
1586 PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
1587 Object* receiver,
1588 LookupResult* result,
1589 String* name,
1590 bool continue_search);
Steve Blocka7e24c12009-10-30 11:49:00 +00001591
John Reck59135872010-11-02 12:39:01 -07001592 MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
1593 bool is_getter,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001594 Object* fun,
John Reck59135872010-11-02 12:39:01 -07001595 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001596 Object* LookupAccessor(String* name, bool is_getter);
1597
John Reck59135872010-11-02 12:39:01 -07001598 MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
Leon Clarkef7060e22010-06-03 12:02:55 +01001599
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 // Used from Object::GetProperty().
John Reck59135872010-11-02 12:39:01 -07001601 MaybeObject* GetPropertyWithFailedAccessCheck(
1602 Object* receiver,
1603 LookupResult* result,
1604 String* name,
1605 PropertyAttributes* attributes);
1606 MaybeObject* GetPropertyWithInterceptor(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001607 JSReceiver* receiver,
John Reck59135872010-11-02 12:39:01 -07001608 String* name,
1609 PropertyAttributes* attributes);
1610 MaybeObject* GetPropertyPostInterceptor(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001611 JSReceiver* receiver,
John Reck59135872010-11-02 12:39:01 -07001612 String* name,
1613 PropertyAttributes* attributes);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001614 MaybeObject* GetLocalPropertyPostInterceptor(JSReceiver* receiver,
John Reck59135872010-11-02 12:39:01 -07001615 String* name,
1616 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001617
1618 // Returns true if this is an instance of an api function and has
1619 // been modified since it was created. May give false positives.
1620 bool IsDirty();
1621
Steve Blockd0582a62009-12-15 09:54:21 +00001622 // If the receiver is a JSGlobalProxy this method will return its prototype,
1623 // otherwise the result is the receiver itself.
1624 inline Object* BypassGlobalProxy();
1625
1626 // Accessors for hidden properties object.
1627 //
1628 // Hidden properties are not local properties of the object itself.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001629 // Instead they are stored in an auxiliary structure kept as a local
Steve Blockd0582a62009-12-15 09:54:21 +00001630 // property with a special name Heap::hidden_symbol(). But if the
1631 // receiver is a JSGlobalProxy then the auxiliary object is a property
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001632 // of its prototype, and if it's a detached proxy, then you can't have
1633 // hidden properties.
Steve Blockd0582a62009-12-15 09:54:21 +00001634
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001635 // Sets a hidden property on this object. Returns this object if successful,
Ben Murdochc7cc0282012-03-05 14:35:55 +00001636 // undefined if called on a detached proxy.
1637 static Handle<Object> SetHiddenProperty(Handle<JSObject> obj,
1638 Handle<String> key,
1639 Handle<Object> value);
1640 // Returns a failure if a GC is required.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001641 MaybeObject* SetHiddenProperty(String* key, Object* value);
1642 // Gets the value of a hidden property with the given key. Returns undefined
1643 // if the property doesn't exist (or if called on a detached proxy),
1644 // otherwise returns the value set for the key.
1645 Object* GetHiddenProperty(String* key);
1646 // Deletes a hidden property. Deleting a non-existing property is
1647 // considered successful.
1648 void DeleteHiddenProperty(String* key);
1649 // Returns true if the object has a property with the hidden symbol as name.
1650 bool HasHiddenProperties();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001651
Ben Murdochc7cc0282012-03-05 14:35:55 +00001652 static int GetIdentityHash(Handle<JSObject> obj);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001653 MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
1654 MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag flag);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001655
Ben Murdochc7cc0282012-03-05 14:35:55 +00001656 static Handle<Object> DeleteProperty(Handle<JSObject> obj,
1657 Handle<String> name);
John Reck59135872010-11-02 12:39:01 -07001658 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001659
1660 static Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
John Reck59135872010-11-02 12:39:01 -07001661 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001662
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001663 inline void ValidateSmiOnlyElements();
1664
Ben Murdochc7cc0282012-03-05 14:35:55 +00001665 // Makes sure that this object can contain HeapObject as elements.
1666 inline MaybeObject* EnsureCanContainHeapObjectElements();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001667
1668 // Makes sure that this object can contain the specified elements.
1669 inline MaybeObject* EnsureCanContainElements(Object** elements,
Ben Murdochc7cc0282012-03-05 14:35:55 +00001670 uint32_t count,
1671 EnsureElementsMode mode);
1672 inline MaybeObject* EnsureCanContainElements(FixedArrayBase* elements,
1673 EnsureElementsMode mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001674 MaybeObject* EnsureCanContainElements(Arguments* arguments,
1675 uint32_t first_arg,
Ben Murdochc7cc0282012-03-05 14:35:55 +00001676 uint32_t arg_count,
1677 EnsureElementsMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001678
1679 // Do we want to keep the elements in fast case when increasing the
1680 // capacity?
1681 bool ShouldConvertToSlowElements(int new_capacity);
1682 // Returns true if the backing storage for the slow-case elements of
1683 // this object takes up nearly as much space as a fast-case backing
1684 // storage would. In that case the JSObject should have fast
1685 // elements.
1686 bool ShouldConvertToFastElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001687 // Returns true if the elements of JSObject contains only values that can be
Ben Murdochc7cc0282012-03-05 14:35:55 +00001688 // represented in a FixedDoubleArray and has at least one value that can only
1689 // be represented as a double and not a Smi.
1690 bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements);
Andrei Popescu402d9372010-02-26 13:31:12 +00001691
Steve Blocka7e24c12009-10-30 11:49:00 +00001692 // Tells whether the index'th element is present.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001693 bool HasElementWithReceiver(JSReceiver* receiver, uint32_t index);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001694
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001695 // Computes the new capacity when expanding the elements of a JSObject.
1696 static int NewElementsCapacity(int old_capacity) {
1697 // (old_capacity + 50%) + 16
1698 return old_capacity + (old_capacity >> 1) + 16;
1699 }
1700
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001701 // Tells whether the index'th element is present and how it is stored.
1702 enum LocalElementType {
1703 // There is no element with given index.
1704 UNDEFINED_ELEMENT,
1705
1706 // Element with given index is handled by interceptor.
1707 INTERCEPTED_ELEMENT,
1708
1709 // Element with given index is character in string.
1710 STRING_CHARACTER_ELEMENT,
1711
1712 // Element with given index is stored in fast backing store.
1713 FAST_ELEMENT,
1714
1715 // Element with given index is stored in slow backing store.
1716 DICTIONARY_ELEMENT
1717 };
1718
1719 LocalElementType HasLocalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001720
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001721 bool HasElementWithInterceptor(JSReceiver* receiver, uint32_t index);
1722 bool HasElementPostInterceptor(JSReceiver* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001723
Steve Block9fac8402011-05-12 15:51:54 +01001724 MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
1725 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001726 StrictModeFlag strict_mode,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001727 bool check_prototype);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001728
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001729 MUST_USE_RESULT MaybeObject* SetDictionaryElement(uint32_t index,
1730 Object* value,
1731 StrictModeFlag strict_mode,
1732 bool check_prototype);
1733
1734 MUST_USE_RESULT MaybeObject* SetFastDoubleElement(
1735 uint32_t index,
1736 Object* value,
1737 StrictModeFlag strict_mode,
1738 bool check_prototype = true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001739
Ben Murdochc7cc0282012-03-05 14:35:55 +00001740
1741 static Handle<Object> SetOwnElement(Handle<JSObject> object,
1742 uint32_t index,
1743 Handle<Object> value,
1744 StrictModeFlag strict_mode);
1745
1746 // Empty handle is returned if the element cannot be set to the given value.
1747 static MUST_USE_RESULT Handle<Object> SetElement(Handle<JSObject> object,
1748 uint32_t index,
1749 Handle<Object> value,
1750 StrictModeFlag strict_mode);
1751
Steve Blocka7e24c12009-10-30 11:49:00 +00001752 // A Failure object is returned if GC is needed.
Steve Block9fac8402011-05-12 15:51:54 +01001753 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1754 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001755 StrictModeFlag strict_mode,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001756 bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00001757
1758 // Returns the index'th element.
1759 // The undefined object if index is out of bounds.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001760 MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
1761
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001762 enum SetFastElementsCapacityMode {
1763 kAllowSmiOnlyElements,
Ben Murdochc7cc0282012-03-05 14:35:55 +00001764 kForceSmiOnlyElements,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001765 kDontAllowSmiOnlyElements
1766 };
1767
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001768 // Replace the elements' backing store with fast elements of the given
1769 // capacity. Update the length for JSArrays. Returns the new backing
1770 // store.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001771 MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(
1772 int capacity,
1773 int length,
1774 SetFastElementsCapacityMode set_capacity_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001775 MUST_USE_RESULT MaybeObject* SetFastDoubleElementsCapacityAndLength(
1776 int capacity,
1777 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001778
1779 // Lookup interceptors are used for handling properties controlled by host
1780 // objects.
1781 inline bool HasNamedInterceptor();
1782 inline bool HasIndexedInterceptor();
1783
1784 // Support functions for v8 api (needed for correct interceptor behavior).
1785 bool HasRealNamedProperty(String* key);
1786 bool HasRealElementProperty(uint32_t index);
1787 bool HasRealNamedCallbackProperty(String* key);
1788
Steve Blocka7e24c12009-10-30 11:49:00 +00001789 // Get the header size for a JSObject. Used to compute the index of
1790 // internal fields as well as the number of internal fields.
1791 inline int GetHeaderSize();
1792
1793 inline int GetInternalFieldCount();
Steve Block44f0eee2011-05-26 01:26:41 +01001794 inline int GetInternalFieldOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001795 inline Object* GetInternalField(int index);
1796 inline void SetInternalField(int index, Object* value);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001797 inline void SetInternalField(int index, Smi* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001798
1799 // The following lookup functions skip interceptors.
1800 void LocalLookupRealNamedProperty(String* name, LookupResult* result);
1801 void LookupRealNamedProperty(String* name, LookupResult* result);
1802 void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
1803 void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
Steve Block1e0659c2011-05-24 12:43:12 +01001804 MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001805 uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001806 void LookupCallback(String* name, LookupResult* result);
1807
1808 // Returns the number of properties on this object filtering out properties
1809 // with the specified attributes (ignoring interceptors).
1810 int NumberOfLocalProperties(PropertyAttributes filter);
1811 // Returns the number of enumerable properties (ignoring interceptors).
1812 int NumberOfEnumProperties();
1813 // Fill in details for properties into storage starting at the specified
1814 // index.
1815 void GetLocalPropertyNames(FixedArray* storage, int index);
1816
1817 // Returns the number of properties on this object filtering out properties
1818 // with the specified attributes (ignoring interceptors).
1819 int NumberOfLocalElements(PropertyAttributes filter);
1820 // Returns the number of enumerable elements (ignoring interceptors).
1821 int NumberOfEnumElements();
1822 // Returns the number of elements on this object filtering out elements
1823 // with the specified attributes (ignoring interceptors).
1824 int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
1825 // Count and fill in the enumerable elements into storage.
1826 // (storage->length() == NumberOfEnumElements()).
1827 // If storage is NULL, will count the elements without adding
1828 // them to any storage.
1829 // Returns the number of enumerable elements.
1830 int GetEnumElementKeys(FixedArray* storage);
1831
1832 // Add a property to a fast-case object using a map transition to
1833 // new_map.
John Reck59135872010-11-02 12:39:01 -07001834 MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
1835 String* name,
1836 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001837
1838 // Add a constant function property to a fast-case object.
1839 // This leaves a CONSTANT_TRANSITION in the old map, and
1840 // if it is called on a second object with this map, a
1841 // normal property is added instead, with a map transition.
1842 // This avoids the creation of many maps with the same constant
1843 // function, all orphaned.
John Reck59135872010-11-02 12:39:01 -07001844 MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
1845 String* name,
1846 JSFunction* function,
1847 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001848
John Reck59135872010-11-02 12:39:01 -07001849 MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
1850 String* name,
1851 Object* value,
1852 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001853
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001854 // Returns a new map with all transitions dropped from the object's current
1855 // map and the ElementsKind set.
1856 static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
1857 ElementsKind to_kind);
1858 MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
1859 ElementsKind elements_kind);
1860
Ben Murdochc7cc0282012-03-05 14:35:55 +00001861 static Handle<Object> TransitionElementsKind(Handle<JSObject> object,
1862 ElementsKind to_kind);
1863
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001864 MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
1865
Steve Blocka7e24c12009-10-30 11:49:00 +00001866 // Converts a descriptor of any other type to a real field,
1867 // backed by the properties array. Descriptors of visible
1868 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1869 // Converts the descriptor on the original object's map to a
1870 // map transition, and the the new field is on the object's new map.
John Reck59135872010-11-02 12:39:01 -07001871 MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
Steve Blocka7e24c12009-10-30 11:49:00 +00001872 String* name,
1873 Object* new_value,
1874 PropertyAttributes attributes);
1875
1876 // Converts a descriptor of any other type to a real field,
1877 // backed by the properties array. Descriptors of visible
1878 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
John Reck59135872010-11-02 12:39:01 -07001879 MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
1880 String* name,
1881 Object* new_value,
1882 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001883
1884 // Add a property to a fast-case object.
John Reck59135872010-11-02 12:39:01 -07001885 MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
1886 Object* value,
1887 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001888
1889 // Add a property to a slow-case object.
John Reck59135872010-11-02 12:39:01 -07001890 MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
1891 Object* value,
1892 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001893
1894 // Add a property to an object.
John Reck59135872010-11-02 12:39:01 -07001895 MUST_USE_RESULT MaybeObject* AddProperty(String* name,
1896 Object* value,
Steve Block44f0eee2011-05-26 01:26:41 +01001897 PropertyAttributes attributes,
1898 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001899
1900 // Convert the object to use the canonical dictionary
1901 // representation. If the object is expected to have additional properties
1902 // added this number can be indicated to have the backing store allocated to
1903 // an initial capacity for holding these properties.
Ben Murdochc7cc0282012-03-05 14:35:55 +00001904 static void NormalizeProperties(Handle<JSObject> object,
1905 PropertyNormalizationMode mode,
1906 int expected_additional_properties);
1907
John Reck59135872010-11-02 12:39:01 -07001908 MUST_USE_RESULT MaybeObject* NormalizeProperties(
1909 PropertyNormalizationMode mode,
1910 int expected_additional_properties);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001911
Ben Murdochc7cc0282012-03-05 14:35:55 +00001912 // Convert and update the elements backing store to be a
1913 // SeededNumberDictionary dictionary. Returns the backing after conversion.
1914 static Handle<SeededNumberDictionary> NormalizeElements(
1915 Handle<JSObject> object);
1916
John Reck59135872010-11-02 12:39:01 -07001917 MUST_USE_RESULT MaybeObject* NormalizeElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001918
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001919 static void UpdateMapCodeCache(Handle<JSObject> object,
1920 Handle<String> name,
1921 Handle<Code> code);
1922
John Reck59135872010-11-02 12:39:01 -07001923 MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001924
Steve Blocka7e24c12009-10-30 11:49:00 +00001925 // Transform slow named properties to fast variants.
1926 // Returns failure if allocation failed.
Ben Murdochc7cc0282012-03-05 14:35:55 +00001927 static void TransformToFastProperties(Handle<JSObject> object,
1928 int unused_property_fields);
1929
John Reck59135872010-11-02 12:39:01 -07001930 MUST_USE_RESULT MaybeObject* TransformToFastProperties(
1931 int unused_property_fields);
Steve Blocka7e24c12009-10-30 11:49:00 +00001932
1933 // Access fast-case object properties at index.
1934 inline Object* FastPropertyAt(int index);
1935 inline Object* FastPropertyAtPut(int index, Object* value);
1936
1937 // Access to in object properties.
Steve Block44f0eee2011-05-26 01:26:41 +01001938 inline int GetInObjectPropertyOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001939 inline Object* InObjectPropertyAt(int index);
1940 inline Object* InObjectPropertyAtPut(int index,
1941 Object* value,
1942 WriteBarrierMode mode
1943 = UPDATE_WRITE_BARRIER);
1944
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001945 // Initializes the body after properties slot, properties slot is
1946 // initialized by set_properties. Fill the pre-allocated fields with
1947 // pre_allocated_value and the rest with filler_value.
1948 // Note: this call does not update write barrier, the caller is responsible
1949 // to ensure that |filler_value| can be collected without WB here.
1950 inline void InitializeBody(Map* map,
1951 Object* pre_allocated_value,
1952 Object* filler_value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001953
1954 // Check whether this object references another object
1955 bool ReferencesObject(Object* obj);
1956
1957 // Casting.
1958 static inline JSObject* cast(Object* obj);
1959
Steve Block8defd9f2010-07-08 12:39:36 +01001960 // Disalow further properties to be added to the object.
Ben Murdochc7cc0282012-03-05 14:35:55 +00001961 static Handle<Object> PreventExtensions(Handle<JSObject> object);
John Reck59135872010-11-02 12:39:01 -07001962 MUST_USE_RESULT MaybeObject* PreventExtensions();
Steve Block8defd9f2010-07-08 12:39:36 +01001963
1964
Steve Blocka7e24c12009-10-30 11:49:00 +00001965 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00001966 void JSObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001967#ifdef OBJECT_PRINT
1968 inline void JSObjectPrint() {
1969 JSObjectPrint(stdout);
1970 }
1971 void JSObjectPrint(FILE* out);
1972#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001973#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001974 void JSObjectVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001975#endif
1976#ifdef OBJECT_PRINT
1977 inline void PrintProperties() {
1978 PrintProperties(stdout);
1979 }
1980 void PrintProperties(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001981
Ben Murdochb0fe1622011-05-05 13:52:32 +01001982 inline void PrintElements() {
1983 PrintElements(stdout);
1984 }
1985 void PrintElements(FILE* out);
1986#endif
1987
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001988 void PrintElementsTransition(
1989 FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
1990 ElementsKind to_kind, FixedArrayBase* to_elements);
1991
Ben Murdochb0fe1622011-05-05 13:52:32 +01001992#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001993 // Structure for collecting spill information about JSObjects.
1994 class SpillInformation {
1995 public:
1996 void Clear();
1997 void Print();
1998 int number_of_objects_;
1999 int number_of_objects_with_fast_properties_;
2000 int number_of_objects_with_fast_elements_;
2001 int number_of_fast_used_fields_;
2002 int number_of_fast_unused_fields_;
2003 int number_of_slow_used_properties_;
2004 int number_of_slow_unused_properties_;
2005 int number_of_fast_used_elements_;
2006 int number_of_fast_unused_elements_;
2007 int number_of_slow_used_elements_;
2008 int number_of_slow_unused_elements_;
2009 };
2010
2011 void IncrementSpillStatistics(SpillInformation* info);
2012#endif
2013 Object* SlowReverseLookup(Object* value);
2014
Steve Block8defd9f2010-07-08 12:39:36 +01002015 // Maximal number of fast properties for the JSObject. Used to
2016 // restrict the number of map transitions to avoid an explosion in
2017 // the number of maps for objects used as dictionaries.
2018 inline int MaxFastProperties();
2019
Leon Clarkee46be812010-01-19 14:06:41 +00002020 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
2021 // Also maximal value of JSArray's length property.
2022 static const uint32_t kMaxElementCount = 0xffffffffu;
2023
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002024 // Constants for heuristics controlling conversion of fast elements
2025 // to slow elements.
2026
2027 // Maximal gap that can be introduced by adding an element beyond
2028 // the current elements length.
Steve Blocka7e24c12009-10-30 11:49:00 +00002029 static const uint32_t kMaxGap = 1024;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002030
2031 // Maximal length of fast elements array that won't be checked for
2032 // being dense enough on expansion.
2033 static const int kMaxUncheckedFastElementsLength = 5000;
2034
2035 // Same as above but for old arrays. This limit is more strict. We
2036 // don't want to be wasteful with long lived objects.
2037 static const int kMaxUncheckedOldFastElementsLength = 500;
2038
Steve Blocka7e24c12009-10-30 11:49:00 +00002039 static const int kInitialMaxFastElementArray = 100000;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002040 static const int kMaxFastProperties = 12;
Steve Blocka7e24c12009-10-30 11:49:00 +00002041 static const int kMaxInstanceSize = 255 * kPointerSize;
2042 // When extending the backing storage for property values, we increase
2043 // its size by more than the 1 entry necessary, so sequentially adding fields
2044 // to the same object requires fewer allocations and copies.
2045 static const int kFieldsAdded = 3;
2046
2047 // Layout description.
2048 static const int kPropertiesOffset = HeapObject::kHeaderSize;
2049 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
2050 static const int kHeaderSize = kElementsOffset + kPointerSize;
2051
2052 STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
2053
Iain Merrick75681382010-08-19 15:07:18 +01002054 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
2055 public:
2056 static inline int SizeOf(Map* map, HeapObject* object);
2057 };
2058
Steve Blocka7e24c12009-10-30 11:49:00 +00002059 private:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002060 friend class DictionaryElementsAccessor;
2061
John Reck59135872010-11-02 12:39:01 -07002062 MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
2063 Object* structure,
2064 uint32_t index,
2065 Object* holder);
2066 MaybeObject* SetElementWithCallback(Object* structure,
2067 uint32_t index,
2068 Object* value,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002069 JSObject* holder,
2070 StrictModeFlag strict_mode);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002071 MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
2072 uint32_t index,
2073 Object* value,
2074 StrictModeFlag strict_mode,
2075 bool check_prototype);
Steve Block9fac8402011-05-12 15:51:54 +01002076 MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
2077 uint32_t index,
2078 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002079 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01002080 bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00002081
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002082 // Searches the prototype chain for a callback setter and sets the property
2083 // with the setter if it finds one. The '*found' flag indicates whether
2084 // a setter was found or not.
2085 // This function can cause GC and can return a failure result with
2086 // '*found==true'.
2087 MUST_USE_RESULT MaybeObject* SetPropertyWithCallbackSetterInPrototypes(
2088 String* name,
2089 Object* value,
2090 PropertyAttributes attributes,
2091 bool* found,
2092 StrictModeFlag strict_mode);
2093
John Reck59135872010-11-02 12:39:01 -07002094 MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
2095 DeleteMode mode);
2096 MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002097
John Reck59135872010-11-02 12:39:01 -07002098 MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002099
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002100 MUST_USE_RESULT MaybeObject* DeleteFastElement(uint32_t index);
2101 MUST_USE_RESULT MaybeObject* DeleteDictionaryElement(uint32_t index,
2102 DeleteMode mode);
2103
2104 bool ReferencesObjectFromElements(FixedArray* elements,
2105 ElementsKind kind,
2106 Object* object);
2107 bool HasElementInElements(FixedArray* elements,
2108 ElementsKind kind,
2109 uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002110
2111 // Returns true if most of the elements backing storage is used.
2112 bool HasDenseElements();
2113
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002114 // Gets the current elements capacity and the number of used elements.
2115 void GetElementsCapacityAndUsage(int* capacity, int* used);
2116
Leon Clarkef7060e22010-06-03 12:02:55 +01002117 bool CanSetCallback(String* name);
John Reck59135872010-11-02 12:39:01 -07002118 MUST_USE_RESULT MaybeObject* SetElementCallback(
2119 uint32_t index,
2120 Object* structure,
2121 PropertyAttributes attributes);
2122 MUST_USE_RESULT MaybeObject* SetPropertyCallback(
2123 String* name,
2124 Object* structure,
2125 PropertyAttributes attributes);
2126 MUST_USE_RESULT MaybeObject* DefineGetterSetter(
2127 String* name,
2128 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00002129
2130 void LookupInDescriptor(String* name, LookupResult* result);
2131
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002132 // Returns the hidden properties backing store object, currently
2133 // a StringDictionary, stored on this object.
2134 // If no hidden properties object has been put on this object,
2135 // return undefined, unless create_if_absent is true, in which case
2136 // a new dictionary is created, added to this object, and returned.
2137 MaybeObject* GetHiddenPropertiesDictionary(bool create_if_absent);
2138 // Updates the existing hidden properties dictionary.
2139 MaybeObject* SetHiddenPropertiesDictionary(StringDictionary* dictionary);
2140
Steve Blocka7e24c12009-10-30 11:49:00 +00002141 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
2142};
2143
2144
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002145// Common superclass for FixedArrays that allow implementations to share
2146// common accessors and some code paths.
2147class FixedArrayBase: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002148 public:
2149 // [length]: length of the array.
2150 inline int length();
2151 inline void set_length(int value);
2152
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002153 inline static FixedArrayBase* cast(Object* object);
2154
2155 // Layout description.
2156 // Length is smi tagged when it is stored.
2157 static const int kLengthOffset = HeapObject::kHeaderSize;
2158 static const int kHeaderSize = kLengthOffset + kPointerSize;
2159};
2160
2161
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002162class FixedDoubleArray;
2163
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002164// FixedArray describes fixed-sized arrays with element type Object*.
2165class FixedArray: public FixedArrayBase {
2166 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00002167 // Setter and getter for elements.
2168 inline Object* get(int index);
2169 // Setter that uses write barrier.
2170 inline void set(int index, Object* value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002171 inline bool is_the_hole(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002172
2173 // Setter that doesn't need write barrier).
2174 inline void set(int index, Smi* value);
2175 // Setter with explicit barrier mode.
2176 inline void set(int index, Object* value, WriteBarrierMode mode);
2177
2178 // Setters for frequently used oddballs located in old space.
2179 inline void set_undefined(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01002180 // TODO(isolates): duplicate.
2181 inline void set_undefined(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002182 inline void set_null(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01002183 // TODO(isolates): duplicate.
2184 inline void set_null(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002185 inline void set_the_hole(int index);
2186
Iain Merrick75681382010-08-19 15:07:18 +01002187 // Setters with less debug checks for the GC to use.
2188 inline void set_unchecked(int index, Smi* value);
Steve Block44f0eee2011-05-26 01:26:41 +01002189 inline void set_null_unchecked(Heap* heap, int index);
2190 inline void set_unchecked(Heap* heap, int index, Object* value,
2191 WriteBarrierMode mode);
Iain Merrick75681382010-08-19 15:07:18 +01002192
Steve Block6ded16b2010-05-10 14:33:55 +01002193 // Gives access to raw memory which stores the array's data.
2194 inline Object** data_start();
2195
Ben Murdochc7cc0282012-03-05 14:35:55 +00002196 inline Object** GetFirstElementAddress();
2197 inline bool ContainsOnlySmisOrHoles();
2198
Steve Blocka7e24c12009-10-30 11:49:00 +00002199 // Copy operations.
John Reck59135872010-11-02 12:39:01 -07002200 MUST_USE_RESULT inline MaybeObject* Copy();
2201 MUST_USE_RESULT MaybeObject* CopySize(int new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +00002202
2203 // Add the elements of a JSArray to this FixedArray.
John Reck59135872010-11-02 12:39:01 -07002204 MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
Steve Blocka7e24c12009-10-30 11:49:00 +00002205
2206 // Compute the union of this and other.
John Reck59135872010-11-02 12:39:01 -07002207 MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
Steve Blocka7e24c12009-10-30 11:49:00 +00002208
2209 // Copy a sub array from the receiver to dest.
2210 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
2211
2212 // Garbage collection support.
2213 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
2214
2215 // Code Generation support.
2216 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2217
2218 // Casting.
2219 static inline FixedArray* cast(Object* obj);
2220
Leon Clarkee46be812010-01-19 14:06:41 +00002221 // Maximal allowed size, in bytes, of a single FixedArray.
2222 // Prevents overflowing size computations, as well as extreme memory
2223 // consumption.
Ben Murdoch692be652012-01-10 18:47:50 +00002224 static const int kMaxSize = 128 * MB * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002225 // Maximally allowed length of a FixedArray.
2226 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002227
2228 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002229#ifdef OBJECT_PRINT
2230 inline void FixedArrayPrint() {
2231 FixedArrayPrint(stdout);
2232 }
2233 void FixedArrayPrint(FILE* out);
2234#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002235#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002236 void FixedArrayVerify();
2237 // Checks if two FixedArrays have identical contents.
2238 bool IsEqualTo(FixedArray* other);
2239#endif
2240
2241 // Swap two elements in a pair of arrays. If this array and the
2242 // numbers array are the same object, the elements are only swapped
2243 // once.
2244 void SwapPairs(FixedArray* numbers, int i, int j);
2245
2246 // Sort prefix of this array and the numbers array as pairs wrt. the
2247 // numbers. If the numbers array and the this array are the same
2248 // object, the prefix of this array is sorted.
2249 void SortPairs(FixedArray* numbers, uint32_t len);
2250
Iain Merrick75681382010-08-19 15:07:18 +01002251 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
2252 public:
2253 static inline int SizeOf(Map* map, HeapObject* object) {
2254 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
2255 }
2256 };
2257
Steve Blocka7e24c12009-10-30 11:49:00 +00002258 protected:
Leon Clarke4515c472010-02-03 11:58:03 +00002259 // Set operation on FixedArray without using write barriers. Can
2260 // only be used for storing old space objects or smis.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002261 static inline void NoWriteBarrierSet(FixedArray* array,
2262 int index,
2263 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002264
Ben Murdochc7cc0282012-03-05 14:35:55 +00002265 // Set operation on FixedArray without incremental write barrier. Can
2266 // only be used if the object is guaranteed to be white (whiteness witness
2267 // is present).
2268 static inline void NoIncrementalWriteBarrierSet(FixedArray* array,
2269 int index,
2270 Object* value);
2271
Steve Blocka7e24c12009-10-30 11:49:00 +00002272 private:
2273 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
2274};
2275
2276
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002277// FixedDoubleArray describes fixed-sized arrays with element type double.
2278class FixedDoubleArray: public FixedArrayBase {
2279 public:
2280 inline void Initialize(FixedArray* from);
2281 inline void Initialize(FixedDoubleArray* from);
Ben Murdochc7cc0282012-03-05 14:35:55 +00002282 inline void Initialize(SeededNumberDictionary* from);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002283
2284 // Setter and getter for elements.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002285 inline double get_scalar(int index);
2286 inline MaybeObject* get(int index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002287 inline void set(int index, double value);
2288 inline void set_the_hole(int index);
2289
2290 // Checking for the hole.
2291 inline bool is_the_hole(int index);
2292
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002293 // Copy operations
2294 MUST_USE_RESULT inline MaybeObject* Copy();
2295
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002296 // Garbage collection support.
2297 inline static int SizeFor(int length) {
2298 return kHeaderSize + length * kDoubleSize;
2299 }
2300
2301 // Code Generation support.
2302 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2303
2304 inline static bool is_the_hole_nan(double value);
2305 inline static double hole_nan_as_double();
2306 inline static double canonical_not_the_hole_nan_as_double();
2307
2308 // Casting.
2309 static inline FixedDoubleArray* cast(Object* obj);
2310
2311 // Maximal allowed size, in bytes, of a single FixedDoubleArray.
2312 // Prevents overflowing size computations, as well as extreme memory
2313 // consumption.
2314 static const int kMaxSize = 512 * MB;
2315 // Maximally allowed length of a FixedArray.
2316 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
2317
2318 // Dispatched behavior.
2319#ifdef OBJECT_PRINT
2320 inline void FixedDoubleArrayPrint() {
2321 FixedDoubleArrayPrint(stdout);
2322 }
2323 void FixedDoubleArrayPrint(FILE* out);
2324#endif
2325
2326#ifdef DEBUG
2327 void FixedDoubleArrayVerify();
2328#endif
2329
2330 private:
2331 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
2332};
2333
2334
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002335class IncrementalMarking;
2336
2337
Steve Blocka7e24c12009-10-30 11:49:00 +00002338// DescriptorArrays are fixed arrays used to hold instance descriptors.
2339// The format of the these objects is:
Ben Murdoch257744e2011-11-30 15:57:28 +00002340// TODO(1399): It should be possible to make room for bit_field3 in the map
2341// without overloading the instance descriptors field in the map
2342// (and storing it in the DescriptorArray when the map has one).
2343// [0]: storage for bit_field3 for Map owning this object (Smi)
2344// [1]: point to a fixed array with (value, detail) pairs.
2345// [2]: next enumeration index (Smi), or pointer to small fixed array:
Steve Blocka7e24c12009-10-30 11:49:00 +00002346// [0]: next enumeration index (Smi)
2347// [1]: pointer to fixed array with enum cache
Ben Murdoch257744e2011-11-30 15:57:28 +00002348// [3]: first key
Steve Blocka7e24c12009-10-30 11:49:00 +00002349// [length() - 1]: last key
2350//
2351class DescriptorArray: public FixedArray {
2352 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00002353 // Returns true for both shared empty_descriptor_array and for smis, which the
2354 // map uses to encode additional bit fields when the descriptor array is not
2355 // yet used.
Steve Blocka7e24c12009-10-30 11:49:00 +00002356 inline bool IsEmpty();
Leon Clarkee46be812010-01-19 14:06:41 +00002357
Steve Blocka7e24c12009-10-30 11:49:00 +00002358 // Returns the number of descriptors in the array.
2359 int number_of_descriptors() {
Steve Block44f0eee2011-05-26 01:26:41 +01002360 ASSERT(length() > kFirstIndex || IsEmpty());
2361 int len = length();
2362 return len <= kFirstIndex ? 0 : len - kFirstIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00002363 }
2364
2365 int NextEnumerationIndex() {
2366 if (IsEmpty()) return PropertyDetails::kInitialIndex;
2367 Object* obj = get(kEnumerationIndexIndex);
2368 if (obj->IsSmi()) {
2369 return Smi::cast(obj)->value();
2370 } else {
2371 Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
2372 return Smi::cast(index)->value();
2373 }
2374 }
2375
2376 // Set next enumeration index and flush any enum cache.
2377 void SetNextEnumerationIndex(int value) {
2378 if (!IsEmpty()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002379 set(kEnumerationIndexIndex, Smi::FromInt(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002380 }
2381 }
2382 bool HasEnumCache() {
2383 return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
2384 }
2385
2386 Object* GetEnumCache() {
2387 ASSERT(HasEnumCache());
2388 FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
2389 return bridge->get(kEnumCacheBridgeCacheIndex);
2390 }
2391
Ben Murdoch257744e2011-11-30 15:57:28 +00002392 // TODO(1399): It should be possible to make room for bit_field3 in the map
2393 // without overloading the instance descriptors field in the map
2394 // (and storing it in the DescriptorArray when the map has one).
2395 inline int bit_field3_storage();
2396 inline void set_bit_field3_storage(int value);
2397
Steve Blocka7e24c12009-10-30 11:49:00 +00002398 // Initialize or change the enum cache,
2399 // using the supplied storage for the small "bridge".
2400 void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
2401
2402 // Accessors for fetching instance descriptor at descriptor number.
2403 inline String* GetKey(int descriptor_number);
2404 inline Object* GetValue(int descriptor_number);
2405 inline Smi* GetDetails(int descriptor_number);
2406 inline PropertyType GetType(int descriptor_number);
2407 inline int GetFieldIndex(int descriptor_number);
2408 inline JSFunction* GetConstantFunction(int descriptor_number);
2409 inline Object* GetCallbacksObject(int descriptor_number);
2410 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
2411 inline bool IsProperty(int descriptor_number);
2412 inline bool IsTransition(int descriptor_number);
2413 inline bool IsNullDescriptor(int descriptor_number);
2414 inline bool IsDontEnum(int descriptor_number);
2415
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002416 class WhitenessWitness {
2417 public:
2418 inline explicit WhitenessWitness(DescriptorArray* array);
2419 inline ~WhitenessWitness();
2420
2421 private:
2422 IncrementalMarking* marking_;
2423 };
2424
Steve Blocka7e24c12009-10-30 11:49:00 +00002425 // Accessor for complete descriptor.
2426 inline void Get(int descriptor_number, Descriptor* desc);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002427 inline void Set(int descriptor_number,
2428 Descriptor* desc,
2429 const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00002430
2431 // Transfer complete descriptor from another descriptor array to
2432 // this one.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002433 inline void CopyFrom(int index,
2434 DescriptorArray* src,
2435 int src_index,
2436 const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00002437
2438 // Copy the descriptor array, insert a new descriptor and optionally
2439 // remove map transitions. If the descriptor is already present, it is
2440 // replaced. If a replaced descriptor is a real property (not a transition
2441 // or null), its enumeration index is kept as is.
2442 // If adding a real property, map transitions must be removed. If adding
2443 // a transition, they must not be removed. All null descriptors are removed.
John Reck59135872010-11-02 12:39:01 -07002444 MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
2445 TransitionFlag transition_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +00002446
2447 // Remove all transitions. Return a copy of the array with all transitions
2448 // removed, or a Failure object if the new array could not be allocated.
John Reck59135872010-11-02 12:39:01 -07002449 MUST_USE_RESULT MaybeObject* RemoveTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002450
2451 // Sort the instance descriptors by the hash codes of their keys.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002452 // Does not check for duplicates.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002453 void SortUnchecked(const WhitenessWitness&);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002454
2455 // Sort the instance descriptors by the hash codes of their keys.
2456 // Checks the result for duplicates.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002457 void Sort(const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00002458
2459 // Search the instance descriptors for given name.
2460 inline int Search(String* name);
2461
Iain Merrick75681382010-08-19 15:07:18 +01002462 // As the above, but uses DescriptorLookupCache and updates it when
2463 // necessary.
2464 inline int SearchWithCache(String* name);
2465
Steve Blocka7e24c12009-10-30 11:49:00 +00002466 // Tells whether the name is present int the array.
2467 bool Contains(String* name) { return kNotFound != Search(name); }
2468
2469 // Perform a binary search in the instance descriptors represented
2470 // by this fixed array. low and high are descriptor indices. If there
2471 // are three instance descriptors in this array it should be called
2472 // with low=0 and high=2.
2473 int BinarySearch(String* name, int low, int high);
2474
2475 // Perform a linear search in the instance descriptors represented
2476 // by this fixed array. len is the number of descriptor indices that are
2477 // valid. Does not require the descriptors to be sorted.
2478 int LinearSearch(String* name, int len);
2479
2480 // Allocates a DescriptorArray, but returns the singleton
2481 // empty descriptor array object if number_of_descriptors is 0.
John Reck59135872010-11-02 12:39:01 -07002482 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
Steve Blocka7e24c12009-10-30 11:49:00 +00002483
2484 // Casting.
2485 static inline DescriptorArray* cast(Object* obj);
2486
2487 // Constant for denoting key was not found.
2488 static const int kNotFound = -1;
2489
Ben Murdoch257744e2011-11-30 15:57:28 +00002490 static const int kBitField3StorageIndex = 0;
2491 static const int kContentArrayIndex = 1;
2492 static const int kEnumerationIndexIndex = 2;
2493 static const int kFirstIndex = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +00002494
2495 // The length of the "bridge" to the enum cache.
2496 static const int kEnumCacheBridgeLength = 2;
2497 static const int kEnumCacheBridgeEnumIndex = 0;
2498 static const int kEnumCacheBridgeCacheIndex = 1;
2499
2500 // Layout description.
Ben Murdoch257744e2011-11-30 15:57:28 +00002501 static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
2502 static const int kContentArrayOffset = kBitField3StorageOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002503 static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
2504 static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
2505
2506 // Layout description for the bridge array.
2507 static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
2508 static const int kEnumCacheBridgeCacheOffset =
2509 kEnumCacheBridgeEnumOffset + kPointerSize;
2510
Ben Murdochb0fe1622011-05-05 13:52:32 +01002511#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +00002512 // Print all the descriptors.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002513 inline void PrintDescriptors() {
2514 PrintDescriptors(stdout);
2515 }
2516 void PrintDescriptors(FILE* out);
2517#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002518
Ben Murdochb0fe1622011-05-05 13:52:32 +01002519#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002520 // Is the descriptor array sorted and without duplicates?
2521 bool IsSortedNoDuplicates();
2522
2523 // Are two DescriptorArrays equal?
2524 bool IsEqualTo(DescriptorArray* other);
2525#endif
2526
2527 // The maximum number of descriptors we want in a descriptor array (should
2528 // fit in a page).
2529 static const int kMaxNumberOfDescriptors = 1024 + 512;
2530
2531 private:
2532 // Conversion from descriptor number to array indices.
2533 static int ToKeyIndex(int descriptor_number) {
2534 return descriptor_number+kFirstIndex;
2535 }
Leon Clarkee46be812010-01-19 14:06:41 +00002536
2537 static int ToDetailsIndex(int descriptor_number) {
2538 return (descriptor_number << 1) + 1;
2539 }
2540
Steve Blocka7e24c12009-10-30 11:49:00 +00002541 static int ToValueIndex(int descriptor_number) {
2542 return descriptor_number << 1;
2543 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002544
2545 bool is_null_descriptor(int descriptor_number) {
2546 return PropertyDetails(GetDetails(descriptor_number)).type() ==
2547 NULL_DESCRIPTOR;
2548 }
2549 // Swap operation on FixedArray without using write barriers.
Ben Murdochc7cc0282012-03-05 14:35:55 +00002550 static inline void NoIncrementalWriteBarrierSwap(
2551 FixedArray* array, int first, int second);
Steve Blocka7e24c12009-10-30 11:49:00 +00002552
2553 // Swap descriptor first and second.
Ben Murdochc7cc0282012-03-05 14:35:55 +00002554 inline void NoIncrementalWriteBarrierSwapDescriptors(
2555 int first, int second);
Steve Blocka7e24c12009-10-30 11:49:00 +00002556
2557 FixedArray* GetContentArray() {
2558 return FixedArray::cast(get(kContentArrayIndex));
2559 }
2560 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
2561};
2562
2563
2564// HashTable is a subclass of FixedArray that implements a hash table
2565// that uses open addressing and quadratic probing.
2566//
2567// In order for the quadratic probing to work, elements that have not
2568// yet been used and elements that have been deleted are
2569// distinguished. Probing continues when deleted elements are
2570// encountered and stops when unused elements are encountered.
2571//
2572// - Elements with key == undefined have not been used yet.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002573// - Elements with key == the_hole have been deleted.
Steve Blocka7e24c12009-10-30 11:49:00 +00002574//
2575// The hash table class is parameterized with a Shape and a Key.
2576// Shape must be a class with the following interface:
2577// class ExampleShape {
2578// public:
2579// // Tells whether key matches other.
2580// static bool IsMatch(Key key, Object* other);
2581// // Returns the hash value for key.
2582// static uint32_t Hash(Key key);
2583// // Returns the hash value for object.
2584// static uint32_t HashForObject(Key key, Object* object);
2585// // Convert key to an object.
2586// static inline Object* AsObject(Key key);
2587// // The prefix size indicates number of elements in the beginning
2588// // of the backing storage.
2589// static const int kPrefixSize = ..;
2590// // The Element size indicates number of elements per entry.
2591// static const int kEntrySize = ..;
2592// };
Steve Block3ce2e202009-11-05 08:53:23 +00002593// The prefix size indicates an amount of memory in the
Steve Blocka7e24c12009-10-30 11:49:00 +00002594// beginning of the backing storage that can be used for non-element
2595// information by subclasses.
2596
Ben Murdochc7cc0282012-03-05 14:35:55 +00002597template<typename Key>
2598class BaseShape {
2599 public:
2600 static const bool UsesSeed = false;
2601 static uint32_t Hash(Key key) { return 0; }
2602 static uint32_t SeededHash(Key key, uint32_t seed) {
2603 ASSERT(UsesSeed);
2604 return Hash(key);
2605 }
2606 static uint32_t HashForObject(Key key, Object* object) { return 0; }
2607 static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) {
2608 ASSERT(UsesSeed);
2609 return HashForObject(key, object);
2610 }
2611};
2612
Steve Blocka7e24c12009-10-30 11:49:00 +00002613template<typename Shape, typename Key>
2614class HashTable: public FixedArray {
2615 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +00002616 // Wrapper methods
2617 inline uint32_t Hash(Key key) {
2618 if (Shape::UsesSeed) {
2619 return Shape::SeededHash(key,
2620 GetHeap()->HashSeed());
2621 } else {
2622 return Shape::Hash(key);
2623 }
2624 }
2625
2626 inline uint32_t HashForObject(Key key, Object* object) {
2627 if (Shape::UsesSeed) {
2628 return Shape::SeededHashForObject(key,
2629 GetHeap()->HashSeed(), object);
2630 } else {
2631 return Shape::HashForObject(key, object);
2632 }
2633 }
2634
Steve Block3ce2e202009-11-05 08:53:23 +00002635 // Returns the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002636 int NumberOfElements() {
2637 return Smi::cast(get(kNumberOfElementsIndex))->value();
2638 }
2639
Leon Clarkee46be812010-01-19 14:06:41 +00002640 // Returns the number of deleted elements in the hash table.
2641 int NumberOfDeletedElements() {
2642 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
2643 }
2644
Steve Block3ce2e202009-11-05 08:53:23 +00002645 // Returns the capacity of the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002646 int Capacity() {
2647 return Smi::cast(get(kCapacityIndex))->value();
2648 }
2649
2650 // ElementAdded should be called whenever an element is added to a
Steve Block3ce2e202009-11-05 08:53:23 +00002651 // hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002652 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
2653
2654 // ElementRemoved should be called whenever an element is removed from
Steve Block3ce2e202009-11-05 08:53:23 +00002655 // a hash table.
Leon Clarkee46be812010-01-19 14:06:41 +00002656 void ElementRemoved() {
2657 SetNumberOfElements(NumberOfElements() - 1);
2658 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
2659 }
2660 void ElementsRemoved(int n) {
2661 SetNumberOfElements(NumberOfElements() - n);
2662 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
2663 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002664
Steve Block3ce2e202009-11-05 08:53:23 +00002665 // Returns a new HashTable object. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002666 MUST_USE_RESULT static MaybeObject* Allocate(
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002667 int at_least_space_for,
2668 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002669
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002670 // Computes the required capacity for a table holding the given
2671 // number of elements. May be more than HashTable::kMaxCapacity.
2672 static int ComputeCapacity(int at_least_space_for);
2673
Steve Blocka7e24c12009-10-30 11:49:00 +00002674 // Returns the key at entry.
2675 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
2676
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002677 // Tells whether k is a real key. The hole and undefined are not allowed
Steve Blocka7e24c12009-10-30 11:49:00 +00002678 // as keys and can be used to indicate missing or deleted elements.
2679 bool IsKey(Object* k) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002680 return !k->IsTheHole() && !k->IsUndefined();
Steve Blocka7e24c12009-10-30 11:49:00 +00002681 }
2682
2683 // Garbage collection support.
2684 void IteratePrefix(ObjectVisitor* visitor);
2685 void IterateElements(ObjectVisitor* visitor);
2686
2687 // Casting.
2688 static inline HashTable* cast(Object* obj);
2689
2690 // Compute the probe offset (quadratic probing).
2691 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
2692 return (n + n * n) >> 1;
2693 }
2694
2695 static const int kNumberOfElementsIndex = 0;
Leon Clarkee46be812010-01-19 14:06:41 +00002696 static const int kNumberOfDeletedElementsIndex = 1;
2697 static const int kCapacityIndex = 2;
2698 static const int kPrefixStartIndex = 3;
2699 static const int kElementsStartIndex =
Steve Blocka7e24c12009-10-30 11:49:00 +00002700 kPrefixStartIndex + Shape::kPrefixSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002701 static const int kEntrySize = Shape::kEntrySize;
2702 static const int kElementsStartOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00002703 kHeaderSize + kElementsStartIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01002704 static const int kCapacityOffset =
2705 kHeaderSize + kCapacityIndex * kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002706
2707 // Constant used for denoting a absent entry.
2708 static const int kNotFound = -1;
2709
Leon Clarkee46be812010-01-19 14:06:41 +00002710 // Maximal capacity of HashTable. Based on maximal length of underlying
2711 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
2712 // cannot overflow.
2713 static const int kMaxCapacity =
2714 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
2715
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002716 // Find entry for key otherwise return kNotFound.
Steve Block44f0eee2011-05-26 01:26:41 +01002717 inline int FindEntry(Key key);
2718 int FindEntry(Isolate* isolate, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002719
2720 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +00002721 // Find the entry at which to insert element with the given key that
2722 // has the given hash value.
2723 uint32_t FindInsertionEntry(uint32_t hash);
2724
2725 // Returns the index for an entry (of the key)
2726 static inline int EntryToIndex(int entry) {
2727 return (entry * kEntrySize) + kElementsStartIndex;
2728 }
2729
Steve Block3ce2e202009-11-05 08:53:23 +00002730 // Update the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002731 void SetNumberOfElements(int nof) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002732 set(kNumberOfElementsIndex, Smi::FromInt(nof));
Steve Blocka7e24c12009-10-30 11:49:00 +00002733 }
2734
Leon Clarkee46be812010-01-19 14:06:41 +00002735 // Update the number of deleted elements in the hash table.
2736 void SetNumberOfDeletedElements(int nod) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002737 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
Leon Clarkee46be812010-01-19 14:06:41 +00002738 }
2739
Steve Blocka7e24c12009-10-30 11:49:00 +00002740 // Sets the capacity of the hash table.
2741 void SetCapacity(int capacity) {
2742 // To scale a computed hash code to fit within the hash table, we
2743 // use bit-wise AND with a mask, so the capacity must be positive
2744 // and non-zero.
2745 ASSERT(capacity > 0);
Leon Clarkee46be812010-01-19 14:06:41 +00002746 ASSERT(capacity <= kMaxCapacity);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002747 set(kCapacityIndex, Smi::FromInt(capacity));
Steve Blocka7e24c12009-10-30 11:49:00 +00002748 }
2749
2750
2751 // Returns probe entry.
2752 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
2753 ASSERT(IsPowerOf2(size));
2754 return (hash + GetProbeOffset(number)) & (size - 1);
2755 }
2756
Leon Clarkee46be812010-01-19 14:06:41 +00002757 static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
2758 return hash & (size - 1);
2759 }
2760
2761 static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
2762 return (last + number) & (size - 1);
2763 }
2764
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002765 // Rehashes this hash-table into the new table.
2766 MUST_USE_RESULT MaybeObject* Rehash(HashTable* new_table, Key key);
2767
2768 // Attempt to shrink hash table after removal of key.
2769 MUST_USE_RESULT MaybeObject* Shrink(Key key);
2770
Steve Blocka7e24c12009-10-30 11:49:00 +00002771 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002772 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002773};
2774
2775
Steve Blocka7e24c12009-10-30 11:49:00 +00002776// HashTableKey is an abstract superclass for virtual key behavior.
2777class HashTableKey {
2778 public:
2779 // Returns whether the other object matches this key.
2780 virtual bool IsMatch(Object* other) = 0;
2781 // Returns the hash value for this key.
2782 virtual uint32_t Hash() = 0;
2783 // Returns the hash value for object.
2784 virtual uint32_t HashForObject(Object* key) = 0;
Steve Block3ce2e202009-11-05 08:53:23 +00002785 // Returns the key object for storing into the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002786 // If allocations fails a failure object is returned.
John Reck59135872010-11-02 12:39:01 -07002787 MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002788 // Required.
2789 virtual ~HashTableKey() {}
2790};
2791
Ben Murdochc7cc0282012-03-05 14:35:55 +00002792
2793class SymbolTableShape : public BaseShape<HashTableKey*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00002794 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002795 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002796 return key->IsMatch(value);
2797 }
Steve Block44f0eee2011-05-26 01:26:41 +01002798 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002799 return key->Hash();
2800 }
Steve Block44f0eee2011-05-26 01:26:41 +01002801 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002802 return key->HashForObject(object);
2803 }
Steve Block44f0eee2011-05-26 01:26:41 +01002804 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002805 return key->AsObject();
2806 }
2807
2808 static const int kPrefixSize = 0;
2809 static const int kEntrySize = 1;
2810};
2811
Ben Murdoch257744e2011-11-30 15:57:28 +00002812class SeqAsciiString;
2813
Steve Blocka7e24c12009-10-30 11:49:00 +00002814// SymbolTable.
2815//
2816// No special elements in the prefix and the element size is 1
2817// because only the symbol itself (the key) needs to be stored.
2818class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
2819 public:
2820 // Find symbol in the symbol table. If it is not there yet, it is
2821 // added. The return value is the symbol table which might have
2822 // been enlarged. If the return value is not a failure, the symbol
2823 // pointer *s is set to the symbol found.
John Reck59135872010-11-02 12:39:01 -07002824 MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
Steve Block9fac8402011-05-12 15:51:54 +01002825 MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
2826 Object** s);
Ben Murdoch257744e2011-11-30 15:57:28 +00002827 MUST_USE_RESULT MaybeObject* LookupSubStringAsciiSymbol(
2828 Handle<SeqAsciiString> str,
2829 int from,
2830 int length,
2831 Object** s);
Steve Block9fac8402011-05-12 15:51:54 +01002832 MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
2833 Object** s);
John Reck59135872010-11-02 12:39:01 -07002834 MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002835
2836 // Looks up a symbol that is equal to the given string and returns
2837 // true if it is found, assigning the symbol to the given output
2838 // parameter.
2839 bool LookupSymbolIfExists(String* str, String** symbol);
Steve Blockd0582a62009-12-15 09:54:21 +00002840 bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002841
2842 // Casting.
2843 static inline SymbolTable* cast(Object* obj);
2844
2845 private:
John Reck59135872010-11-02 12:39:01 -07002846 MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002847
2848 DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
2849};
2850
2851
Ben Murdochc7cc0282012-03-05 14:35:55 +00002852class MapCacheShape : public BaseShape<HashTableKey*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00002853 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002854 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002855 return key->IsMatch(value);
2856 }
Steve Block44f0eee2011-05-26 01:26:41 +01002857 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002858 return key->Hash();
2859 }
2860
Steve Block44f0eee2011-05-26 01:26:41 +01002861 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002862 return key->HashForObject(object);
2863 }
2864
Steve Block44f0eee2011-05-26 01:26:41 +01002865 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002866 return key->AsObject();
2867 }
2868
2869 static const int kPrefixSize = 0;
2870 static const int kEntrySize = 2;
2871};
2872
2873
2874// MapCache.
2875//
2876// Maps keys that are a fixed array of symbols to a map.
2877// Used for canonicalize maps for object literals.
2878class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
2879 public:
2880 // Find cached value for a string key, otherwise return null.
2881 Object* Lookup(FixedArray* key);
John Reck59135872010-11-02 12:39:01 -07002882 MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002883 static inline MapCache* cast(Object* obj);
2884
2885 private:
2886 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
2887};
2888
2889
2890template <typename Shape, typename Key>
2891class Dictionary: public HashTable<Shape, Key> {
2892 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00002893 static inline Dictionary<Shape, Key>* cast(Object* obj) {
2894 return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
2895 }
2896
2897 // Returns the value at entry.
2898 Object* ValueAt(int entry) {
Steve Block6ded16b2010-05-10 14:33:55 +01002899 return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002900 }
2901
2902 // Set the value for entry.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002903 // Returns false if the put wasn't performed due to property being read only.
2904 // Returns true on successful put.
2905 bool ValueAtPut(int entry, Object* value) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002906 // Check that this value can actually be written.
2907 PropertyDetails details = DetailsAt(entry);
2908 // If a value has not been initilized we allow writing to it even if
2909 // it is read only (a declared const that has not been initialized).
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002910 if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
2911 return false;
2912 }
2913 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
2914 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002915 }
2916
2917 // Returns the property details for the property at entry.
2918 PropertyDetails DetailsAt(int entry) {
2919 ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
2920 return PropertyDetails(
Steve Block6ded16b2010-05-10 14:33:55 +01002921 Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002922 }
2923
2924 // Set the details for entry.
2925 void DetailsAtPut(int entry, PropertyDetails value) {
Steve Block6ded16b2010-05-10 14:33:55 +01002926 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002927 }
2928
2929 // Sorting support
2930 void CopyValuesTo(FixedArray* elements);
2931
2932 // Delete a property from the dictionary.
2933 Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
2934
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002935 // Attempt to shrink the dictionary after deletion of key.
2936 MUST_USE_RESULT MaybeObject* Shrink(Key key);
2937
Steve Blocka7e24c12009-10-30 11:49:00 +00002938 // Returns the number of elements in the dictionary filtering out properties
2939 // with the specified attributes.
2940 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
2941
2942 // Returns the number of enumerable elements in the dictionary.
2943 int NumberOfEnumElements();
2944
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002945 enum SortMode { UNSORTED, SORTED };
Steve Blocka7e24c12009-10-30 11:49:00 +00002946 // Copies keys to preallocated fixed array.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002947 void CopyKeysTo(FixedArray* storage,
2948 PropertyAttributes filter,
2949 SortMode sort_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002950 // Fill in details for properties into storage.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002951 void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002952
2953 // Accessors for next enumeration index.
2954 void SetNextEnumerationIndex(int index) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002955 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00002956 }
2957
2958 int NextEnumerationIndex() {
2959 return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
2960 }
2961
2962 // Returns a new array for dictionary usage. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002963 MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
Steve Blocka7e24c12009-10-30 11:49:00 +00002964
2965 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002966 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002967
Ben Murdochb0fe1622011-05-05 13:52:32 +01002968#ifdef OBJECT_PRINT
2969 inline void Print() {
2970 Print(stdout);
2971 }
2972 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00002973#endif
2974 // Returns the key (slow).
2975 Object* SlowReverseLookup(Object* value);
2976
2977 // Sets the entry to (key, value) pair.
2978 inline void SetEntry(int entry,
2979 Object* key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002980 Object* value);
2981 inline void SetEntry(int entry,
2982 Object* key,
Steve Blocka7e24c12009-10-30 11:49:00 +00002983 Object* value,
2984 PropertyDetails details);
2985
John Reck59135872010-11-02 12:39:01 -07002986 MUST_USE_RESULT MaybeObject* Add(Key key,
2987 Object* value,
2988 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002989
2990 protected:
2991 // Generic at put operation.
John Reck59135872010-11-02 12:39:01 -07002992 MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002993
2994 // Add entry to dictionary.
John Reck59135872010-11-02 12:39:01 -07002995 MUST_USE_RESULT MaybeObject* AddEntry(Key key,
2996 Object* value,
2997 PropertyDetails details,
2998 uint32_t hash);
Steve Blocka7e24c12009-10-30 11:49:00 +00002999
3000 // Generate new enumeration indices to avoid enumeration index overflow.
John Reck59135872010-11-02 12:39:01 -07003001 MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
Steve Blocka7e24c12009-10-30 11:49:00 +00003002 static const int kMaxNumberKeyIndex =
3003 HashTable<Shape, Key>::kPrefixStartIndex;
3004 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
3005};
3006
3007
Ben Murdochc7cc0282012-03-05 14:35:55 +00003008class StringDictionaryShape : public BaseShape<String*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00003009 public:
3010 static inline bool IsMatch(String* key, Object* other);
3011 static inline uint32_t Hash(String* key);
3012 static inline uint32_t HashForObject(String* key, Object* object);
John Reck59135872010-11-02 12:39:01 -07003013 MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003014 static const int kPrefixSize = 2;
3015 static const int kEntrySize = 3;
3016 static const bool kIsEnumerable = true;
3017};
3018
3019
3020class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
3021 public:
3022 static inline StringDictionary* cast(Object* obj) {
3023 ASSERT(obj->IsDictionary());
3024 return reinterpret_cast<StringDictionary*>(obj);
3025 }
3026
3027 // Copies enumerable keys to preallocated fixed array.
3028 void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
3029
3030 // For transforming properties of a JSObject.
John Reck59135872010-11-02 12:39:01 -07003031 MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
3032 JSObject* obj,
3033 int unused_property_fields);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003034
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003035 // Find entry for key, otherwise return kNotFound. Optimized version of
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003036 // HashTable::FindEntry.
3037 int FindEntry(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003038};
3039
3040
Ben Murdochc7cc0282012-03-05 14:35:55 +00003041class NumberDictionaryShape : public BaseShape<uint32_t> {
Steve Blocka7e24c12009-10-30 11:49:00 +00003042 public:
3043 static inline bool IsMatch(uint32_t key, Object* other);
John Reck59135872010-11-02 12:39:01 -07003044 MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003045 static const int kEntrySize = 3;
3046 static const bool kIsEnumerable = false;
3047};
3048
3049
Ben Murdochc7cc0282012-03-05 14:35:55 +00003050class SeededNumberDictionaryShape : public NumberDictionaryShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00003051 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +00003052 static const bool UsesSeed = true;
3053 static const int kPrefixSize = 2;
3054
3055 static inline uint32_t SeededHash(uint32_t key, uint32_t seed);
3056 static inline uint32_t SeededHashForObject(uint32_t key,
3057 uint32_t seed,
3058 Object* object);
3059};
3060
3061
3062class UnseededNumberDictionaryShape : public NumberDictionaryShape {
3063 public:
3064 static const int kPrefixSize = 0;
3065
3066 static inline uint32_t Hash(uint32_t key);
3067 static inline uint32_t HashForObject(uint32_t key, Object* object);
3068};
3069
3070
3071class SeededNumberDictionary
3072 : public Dictionary<SeededNumberDictionaryShape, uint32_t> {
3073 public:
3074 static SeededNumberDictionary* cast(Object* obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003075 ASSERT(obj->IsDictionary());
Ben Murdochc7cc0282012-03-05 14:35:55 +00003076 return reinterpret_cast<SeededNumberDictionary*>(obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003077 }
3078
3079 // Type specific at put (default NONE attributes is used when adding).
John Reck59135872010-11-02 12:39:01 -07003080 MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
3081 MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
3082 Object* value,
3083 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00003084
3085 // Set an existing entry or add a new one if needed.
Ben Murdochc7cc0282012-03-05 14:35:55 +00003086 // Return the updated dictionary.
3087 MUST_USE_RESULT static Handle<SeededNumberDictionary> Set(
3088 Handle<SeededNumberDictionary> dictionary,
3089 uint32_t index,
3090 Handle<Object> value,
3091 PropertyDetails details);
3092
John Reck59135872010-11-02 12:39:01 -07003093 MUST_USE_RESULT MaybeObject* Set(uint32_t key,
3094 Object* value,
3095 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00003096
3097 void UpdateMaxNumberKey(uint32_t key);
3098
3099 // If slow elements are required we will never go back to fast-case
3100 // for the elements kept in this dictionary. We require slow
3101 // elements if an element has been added at an index larger than
3102 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
3103 // when defining a getter or setter with a number key.
3104 inline bool requires_slow_elements();
3105 inline void set_requires_slow_elements();
3106
3107 // Get the value of the max number key that has been added to this
3108 // dictionary. max_number_key can only be called if
3109 // requires_slow_elements returns false.
3110 inline uint32_t max_number_key();
3111
Steve Blocka7e24c12009-10-30 11:49:00 +00003112 // Bit masks.
3113 static const int kRequiresSlowElementsMask = 1;
3114 static const int kRequiresSlowElementsTagSize = 1;
3115 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
3116};
3117
3118
Ben Murdochc7cc0282012-03-05 14:35:55 +00003119class UnseededNumberDictionary
3120 : public Dictionary<UnseededNumberDictionaryShape, uint32_t> {
3121 public:
3122 static UnseededNumberDictionary* cast(Object* obj) {
3123 ASSERT(obj->IsDictionary());
3124 return reinterpret_cast<UnseededNumberDictionary*>(obj);
3125 }
3126
3127 // Type specific at put (default NONE attributes is used when adding).
3128 MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
3129 MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key, Object* value);
3130
3131 // Set an existing entry or add a new one if needed.
3132 // Return the updated dictionary.
3133 MUST_USE_RESULT static Handle<UnseededNumberDictionary> Set(
3134 Handle<UnseededNumberDictionary> dictionary,
3135 uint32_t index,
3136 Handle<Object> value);
3137
3138 MUST_USE_RESULT MaybeObject* Set(uint32_t key, Object* value);
3139};
3140
3141
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003142template <int entrysize>
Ben Murdochc7cc0282012-03-05 14:35:55 +00003143class ObjectHashTableShape : public BaseShape<Object*> {
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003144 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003145 static inline bool IsMatch(Object* key, Object* other);
3146 static inline uint32_t Hash(Object* key);
3147 static inline uint32_t HashForObject(Object* key, Object* object);
3148 MUST_USE_RESULT static inline MaybeObject* AsObject(Object* key);
3149 static const int kPrefixSize = 0;
3150 static const int kEntrySize = entrysize;
3151};
3152
3153
3154// ObjectHashSet holds keys that are arbitrary objects by using the identity
3155// hash of the key for hashing purposes.
3156class ObjectHashSet: public HashTable<ObjectHashTableShape<1>, Object*> {
3157 public:
3158 static inline ObjectHashSet* cast(Object* obj) {
3159 ASSERT(obj->IsHashTable());
3160 return reinterpret_cast<ObjectHashSet*>(obj);
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003161 }
3162
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003163 // Looks up whether the given key is part of this hash set.
3164 bool Contains(Object* key);
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003165
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003166 // Adds the given key to this hash set.
3167 MUST_USE_RESULT MaybeObject* Add(Object* key);
3168
3169 // Removes the given key from this hash set.
3170 MUST_USE_RESULT MaybeObject* Remove(Object* key);
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003171};
3172
3173
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003174// ObjectHashTable maps keys that are arbitrary objects to object values by
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003175// using the identity hash of the key for hashing purposes.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003176class ObjectHashTable: public HashTable<ObjectHashTableShape<2>, Object*> {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003177 public:
3178 static inline ObjectHashTable* cast(Object* obj) {
3179 ASSERT(obj->IsHashTable());
3180 return reinterpret_cast<ObjectHashTable*>(obj);
3181 }
3182
3183 // Looks up the value associated with the given key. The undefined value is
3184 // returned in case the key is not present.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003185 Object* Lookup(Object* key);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003186
3187 // Adds (or overwrites) the value associated with the given key. Mapping a
3188 // key to the undefined value causes removal of the whole entry.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003189 MUST_USE_RESULT MaybeObject* Put(Object* key, Object* value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003190
3191 private:
3192 friend class MarkCompactCollector;
3193
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003194 void AddEntry(int entry, Object* key, Object* value);
3195 void RemoveEntry(int entry);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003196
3197 // Returns the index to the value of an entry.
3198 static inline int EntryToValueIndex(int entry) {
3199 return EntryToIndex(entry) + 1;
3200 }
3201};
3202
3203
Steve Block6ded16b2010-05-10 14:33:55 +01003204// JSFunctionResultCache caches results of some JSFunction invocation.
3205// It is a fixed array with fixed structure:
3206// [0]: factory function
3207// [1]: finger index
3208// [2]: current cache size
3209// [3]: dummy field.
3210// The rest of array are key/value pairs.
3211class JSFunctionResultCache: public FixedArray {
3212 public:
3213 static const int kFactoryIndex = 0;
3214 static const int kFingerIndex = kFactoryIndex + 1;
3215 static const int kCacheSizeIndex = kFingerIndex + 1;
3216 static const int kDummyIndex = kCacheSizeIndex + 1;
3217 static const int kEntriesIndex = kDummyIndex + 1;
3218
3219 static const int kEntrySize = 2; // key + value
3220
Kristian Monsen25f61362010-05-21 11:50:48 +01003221 static const int kFactoryOffset = kHeaderSize;
3222 static const int kFingerOffset = kFactoryOffset + kPointerSize;
3223 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
3224
Steve Block6ded16b2010-05-10 14:33:55 +01003225 inline void MakeZeroSize();
3226 inline void Clear();
3227
Ben Murdochb8e0da22011-05-16 14:20:40 +01003228 inline int size();
3229 inline void set_size(int size);
3230 inline int finger_index();
3231 inline void set_finger_index(int finger_index);
3232
Steve Block6ded16b2010-05-10 14:33:55 +01003233 // Casting
3234 static inline JSFunctionResultCache* cast(Object* obj);
3235
3236#ifdef DEBUG
3237 void JSFunctionResultCacheVerify();
3238#endif
3239};
3240
3241
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003242// ScopeInfo represents information about different scopes of a source
3243// program and the allocation of the scope's variables. Scope information
3244// is stored in a compressed form in ScopeInfo objects and is used
3245// at runtime (stack dumps, deoptimization, etc.).
3246
3247// This object provides quick access to scope info details for runtime
3248// routines.
3249class ScopeInfo : public FixedArray {
3250 public:
3251 static inline ScopeInfo* cast(Object* object);
3252
3253 // Return the type of this scope.
3254 ScopeType Type();
3255
3256 // Does this scope call eval?
3257 bool CallsEval();
3258
3259 // Return the language mode of this scope.
3260 LanguageMode language_mode();
3261
3262 // Does this scope make a non-strict eval call?
3263 bool CallsNonStrictEval() {
3264 return CallsEval() && (language_mode() == CLASSIC_MODE);
3265 }
3266
3267 // Return the total number of locals allocated on the stack and in the
3268 // context. This includes the parameters that are allocated in the context.
3269 int LocalCount();
3270
3271 // Return the number of stack slots for code. This number consists of two
3272 // parts:
3273 // 1. One stack slot per stack allocated local.
3274 // 2. One stack slot for the function name if it is stack allocated.
3275 int StackSlotCount();
3276
3277 // Return the number of context slots for code if a context is allocated. This
3278 // number consists of three parts:
3279 // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS
3280 // 2. One context slot per context allocated local.
3281 // 3. One context slot for the function name if it is context allocated.
3282 // Parameters allocated in the context count as context allocated locals. If
3283 // no contexts are allocated for this scope ContextLength returns 0.
3284 int ContextLength();
3285
3286 // Is this scope the scope of a named function expression?
3287 bool HasFunctionName();
3288
3289 // Return if this has context allocated locals.
3290 bool HasHeapAllocatedLocals();
3291
3292 // Return if contexts are allocated for this scope.
3293 bool HasContext();
3294
3295 // Return the function_name if present.
3296 String* FunctionName();
3297
3298 // Return the name of the given parameter.
3299 String* ParameterName(int var);
3300
3301 // Return the name of the given local.
3302 String* LocalName(int var);
3303
3304 // Return the name of the given stack local.
3305 String* StackLocalName(int var);
3306
3307 // Return the name of the given context local.
3308 String* ContextLocalName(int var);
3309
3310 // Return the mode of the given context local.
3311 VariableMode ContextLocalMode(int var);
3312
3313 // Return the initialization flag of the given context local.
3314 InitializationFlag ContextLocalInitFlag(int var);
3315
3316 // Lookup support for serialized scope info. Returns the
3317 // the stack slot index for a given slot name if the slot is
3318 // present; otherwise returns a value < 0. The name must be a symbol
3319 // (canonicalized).
3320 int StackSlotIndex(String* name);
3321
3322 // Lookup support for serialized scope info. Returns the
3323 // context slot index for a given slot name if the slot is present; otherwise
3324 // returns a value < 0. The name must be a symbol (canonicalized).
3325 // If the slot is present and mode != NULL, sets *mode to the corresponding
3326 // mode for that variable.
3327 int ContextSlotIndex(String* name,
3328 VariableMode* mode,
3329 InitializationFlag* init_flag);
3330
3331 // Lookup support for serialized scope info. Returns the
3332 // parameter index for a given parameter name if the parameter is present;
3333 // otherwise returns a value < 0. The name must be a symbol (canonicalized).
3334 int ParameterIndex(String* name);
3335
3336 // Lookup support for serialized scope info. Returns the
3337 // function context slot index if the function name is present (named
3338 // function expressions, only), otherwise returns a value < 0. The name
3339 // must be a symbol (canonicalized).
3340 int FunctionContextSlotIndex(String* name, VariableMode* mode);
3341
3342 static Handle<ScopeInfo> Create(Scope* scope);
3343
3344 // Serializes empty scope info.
3345 static ScopeInfo* Empty();
3346
3347#ifdef DEBUG
3348 void Print();
3349#endif
3350
3351 // The layout of the static part of a ScopeInfo is as follows. Each entry is
3352 // numeric and occupies one array slot.
3353 // 1. A set of properties of the scope
3354 // 2. The number of parameters. This only applies to function scopes. For
3355 // non-function scopes this is 0.
3356 // 3. The number of non-parameter variables allocated on the stack.
3357 // 4. The number of non-parameter and parameter variables allocated in the
3358 // context.
3359#define FOR_EACH_NUMERIC_FIELD(V) \
3360 V(Flags) \
3361 V(ParameterCount) \
3362 V(StackLocalCount) \
3363 V(ContextLocalCount)
3364
3365#define FIELD_ACCESSORS(name) \
3366 void Set##name(int value) { \
3367 set(k##name, Smi::FromInt(value)); \
3368 } \
3369 int name() { \
3370 if (length() > 0) { \
3371 return Smi::cast(get(k##name))->value(); \
3372 } else { \
3373 return 0; \
3374 } \
3375 }
3376 FOR_EACH_NUMERIC_FIELD(FIELD_ACCESSORS)
3377#undef FIELD_ACCESSORS
3378
3379 private:
3380 enum {
3381#define DECL_INDEX(name) k##name,
3382 FOR_EACH_NUMERIC_FIELD(DECL_INDEX)
3383#undef DECL_INDEX
3384#undef FOR_EACH_NUMERIC_FIELD
3385 kVariablePartIndex
3386 };
3387
3388 // The layout of the variable part of a ScopeInfo is as follows:
3389 // 1. ParameterEntries:
3390 // This part stores the names of the parameters for function scopes. One
3391 // slot is used per parameter, so in total this part occupies
3392 // ParameterCount() slots in the array. For other scopes than function
3393 // scopes ParameterCount() is 0.
3394 // 2. StackLocalEntries:
3395 // Contains the names of local variables that are allocated on the stack,
3396 // in increasing order of the stack slot index. One slot is used per stack
3397 // local, so in total this part occupies StackLocalCount() slots in the
3398 // array.
3399 // 3. ContextLocalNameEntries:
3400 // Contains the names of local variables and parameters that are allocated
3401 // in the context. They are stored in increasing order of the context slot
3402 // index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
3403 // context local, so in total this part occupies ContextLocalCount() slots
3404 // in the array.
3405 // 4. ContextLocalInfoEntries:
3406 // Contains the variable modes and initialization flags corresponding to
3407 // the context locals in ContextLocalNameEntries. One slot is used per
3408 // context local, so in total this part occupies ContextLocalCount()
3409 // slots in the array.
3410 // 5. FunctionNameEntryIndex:
3411 // If the scope belongs to a named function expression this part contains
3412 // information about the function variable. It always occupies two array
3413 // slots: a. The name of the function variable.
3414 // b. The context or stack slot index for the variable.
3415 int ParameterEntriesIndex();
3416 int StackLocalEntriesIndex();
3417 int ContextLocalNameEntriesIndex();
3418 int ContextLocalInfoEntriesIndex();
3419 int FunctionNameEntryIndex();
3420
3421 // Location of the function variable for named function expressions.
3422 enum FunctionVariableInfo {
3423 NONE, // No function name present.
3424 STACK, // Function
3425 CONTEXT,
3426 UNUSED
3427 };
3428
3429 // Properties of scopes.
3430 class TypeField: public BitField<ScopeType, 0, 3> {};
3431 class CallsEvalField: public BitField<bool, 3, 1> {};
3432 class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
3433 class FunctionVariableField: public BitField<FunctionVariableInfo, 6, 2> {};
3434 class FunctionVariableMode: public BitField<VariableMode, 8, 3> {};
3435
3436 // BitFields representing the encoded information for context locals in the
3437 // ContextLocalInfoEntries part.
3438 class ContextLocalMode: public BitField<VariableMode, 0, 3> {};
3439 class ContextLocalInitFlag: public BitField<InitializationFlag, 3, 1> {};
3440};
3441
3442
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003443// The cache for maps used by normalized (dictionary mode) objects.
3444// Such maps do not have property descriptors, so a typical program
3445// needs very limited number of distinct normalized maps.
3446class NormalizedMapCache: public FixedArray {
3447 public:
3448 static const int kEntries = 64;
3449
John Reck59135872010-11-02 12:39:01 -07003450 MUST_USE_RESULT MaybeObject* Get(JSObject* object,
3451 PropertyNormalizationMode mode);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003452
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003453 void Clear();
3454
3455 // Casting
3456 static inline NormalizedMapCache* cast(Object* obj);
3457
3458#ifdef DEBUG
3459 void NormalizedMapCacheVerify();
3460#endif
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003461};
3462
3463
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003464// ByteArray represents fixed sized byte arrays. Used for the relocation info
3465// that is attached to code objects.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003466class ByteArray: public FixedArrayBase {
Steve Blocka7e24c12009-10-30 11:49:00 +00003467 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003468 inline int Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
3469
Steve Blocka7e24c12009-10-30 11:49:00 +00003470 // Setter and getter.
3471 inline byte get(int index);
3472 inline void set(int index, byte value);
3473
3474 // Treat contents as an int array.
3475 inline int get_int(int index);
3476
3477 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003478 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
Steve Blocka7e24c12009-10-30 11:49:00 +00003479 }
3480 // We use byte arrays for free blocks in the heap. Given a desired size in
3481 // bytes that is a multiple of the word size and big enough to hold a byte
3482 // array, this function returns the number of elements a byte array should
3483 // have.
3484 static int LengthFor(int size_in_bytes) {
3485 ASSERT(IsAligned(size_in_bytes, kPointerSize));
3486 ASSERT(size_in_bytes >= kHeaderSize);
3487 return size_in_bytes - kHeaderSize;
3488 }
3489
3490 // Returns data start address.
3491 inline Address GetDataStartAddress();
3492
3493 // Returns a pointer to the ByteArray object for a given data start address.
3494 static inline ByteArray* FromDataStartAddress(Address address);
3495
3496 // Casting.
3497 static inline ByteArray* cast(Object* obj);
3498
3499 // Dispatched behavior.
Iain Merrick75681382010-08-19 15:07:18 +01003500 inline int ByteArraySize() {
3501 return SizeFor(this->length());
3502 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003503#ifdef OBJECT_PRINT
3504 inline void ByteArrayPrint() {
3505 ByteArrayPrint(stdout);
3506 }
3507 void ByteArrayPrint(FILE* out);
3508#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003509#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003510 void ByteArrayVerify();
3511#endif
3512
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003513 // Layout description.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003514 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00003515
Leon Clarkee46be812010-01-19 14:06:41 +00003516 // Maximal memory consumption for a single ByteArray.
3517 static const int kMaxSize = 512 * MB;
3518 // Maximal length of a single ByteArray.
3519 static const int kMaxLength = kMaxSize - kHeaderSize;
3520
Steve Blocka7e24c12009-10-30 11:49:00 +00003521 private:
3522 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
3523};
3524
3525
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003526// FreeSpace represents fixed sized areas of the heap that are not currently in
3527// use. Used by the heap and GC.
3528class FreeSpace: public HeapObject {
3529 public:
3530 // [size]: size of the free space including the header.
3531 inline int size();
3532 inline void set_size(int value);
3533
3534 inline int Size() { return size(); }
3535
3536 // Casting.
3537 static inline FreeSpace* cast(Object* obj);
3538
3539#ifdef OBJECT_PRINT
3540 inline void FreeSpacePrint() {
3541 FreeSpacePrint(stdout);
3542 }
3543 void FreeSpacePrint(FILE* out);
3544#endif
3545#ifdef DEBUG
3546 void FreeSpaceVerify();
3547#endif
3548
3549 // Layout description.
3550 // Size is smi tagged when it is stored.
3551 static const int kSizeOffset = HeapObject::kHeaderSize;
3552 static const int kHeaderSize = kSizeOffset + kPointerSize;
3553
3554 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
3555
3556 private:
3557 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace);
3558};
3559
3560
Steve Block3ce2e202009-11-05 08:53:23 +00003561// An ExternalArray represents a fixed-size array of primitive values
3562// which live outside the JavaScript heap. Its subclasses are used to
3563// implement the CanvasArray types being defined in the WebGL
3564// specification. As of this writing the first public draft is not yet
3565// available, but Khronos members can access the draft at:
3566// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
3567//
3568// The semantics of these arrays differ from CanvasPixelArray.
3569// Out-of-range values passed to the setter are converted via a C
3570// cast, not clamping. Out-of-range indices cause exceptions to be
3571// raised rather than being silently ignored.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003572class ExternalArray: public FixedArrayBase {
Steve Block3ce2e202009-11-05 08:53:23 +00003573 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003574 inline bool is_the_hole(int index) { return false; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003575
Steve Block3ce2e202009-11-05 08:53:23 +00003576 // [external_pointer]: The pointer to the external memory area backing this
3577 // external array.
3578 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
3579
3580 // Casting.
3581 static inline ExternalArray* cast(Object* obj);
3582
3583 // Maximal acceptable length for an external array.
3584 static const int kMaxLength = 0x3fffffff;
3585
3586 // ExternalArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003587 static const int kExternalPointerOffset =
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003588 POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize);
Steve Block3ce2e202009-11-05 08:53:23 +00003589 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003590 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Block3ce2e202009-11-05 08:53:23 +00003591
3592 private:
3593 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
3594};
3595
3596
Steve Block44f0eee2011-05-26 01:26:41 +01003597// A ExternalPixelArray represents a fixed-size byte array with special
3598// semantics used for implementing the CanvasPixelArray object. Please see the
3599// specification at:
3600
3601// http://www.whatwg.org/specs/web-apps/current-work/
3602// multipage/the-canvas-element.html#canvaspixelarray
3603// In particular, write access clamps the value written to 0 or 255 if the
3604// value written is outside this range.
3605class ExternalPixelArray: public ExternalArray {
3606 public:
3607 inline uint8_t* external_pixel_pointer();
3608
3609 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003610 inline uint8_t get_scalar(int index);
3611 inline MaybeObject* get(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01003612 inline void set(int index, uint8_t value);
3613
3614 // This accessor applies the correct conversion from Smi, HeapNumber and
3615 // undefined and clamps the converted value between 0 and 255.
3616 Object* SetValue(uint32_t index, Object* value);
3617
3618 // Casting.
3619 static inline ExternalPixelArray* cast(Object* obj);
3620
3621#ifdef OBJECT_PRINT
3622 inline void ExternalPixelArrayPrint() {
3623 ExternalPixelArrayPrint(stdout);
3624 }
3625 void ExternalPixelArrayPrint(FILE* out);
3626#endif
3627#ifdef DEBUG
3628 void ExternalPixelArrayVerify();
3629#endif // DEBUG
3630
3631 private:
3632 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
3633};
3634
3635
Steve Block3ce2e202009-11-05 08:53:23 +00003636class ExternalByteArray: public ExternalArray {
3637 public:
3638 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003639 inline int8_t get_scalar(int index);
3640 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003641 inline void set(int index, int8_t value);
3642
3643 // This accessor applies the correct conversion from Smi, HeapNumber
3644 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003645 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003646
3647 // Casting.
3648 static inline ExternalByteArray* cast(Object* obj);
3649
Ben Murdochb0fe1622011-05-05 13:52:32 +01003650#ifdef OBJECT_PRINT
3651 inline void ExternalByteArrayPrint() {
3652 ExternalByteArrayPrint(stdout);
3653 }
3654 void ExternalByteArrayPrint(FILE* out);
3655#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003656#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003657 void ExternalByteArrayVerify();
3658#endif // DEBUG
3659
3660 private:
3661 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
3662};
3663
3664
3665class ExternalUnsignedByteArray: public ExternalArray {
3666 public:
3667 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003668 inline uint8_t get_scalar(int index);
3669 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003670 inline void set(int index, uint8_t value);
3671
3672 // This accessor applies the correct conversion from Smi, HeapNumber
3673 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003674 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003675
3676 // Casting.
3677 static inline ExternalUnsignedByteArray* cast(Object* obj);
3678
Ben Murdochb0fe1622011-05-05 13:52:32 +01003679#ifdef OBJECT_PRINT
3680 inline void ExternalUnsignedByteArrayPrint() {
3681 ExternalUnsignedByteArrayPrint(stdout);
3682 }
3683 void ExternalUnsignedByteArrayPrint(FILE* out);
3684#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003685#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003686 void ExternalUnsignedByteArrayVerify();
3687#endif // DEBUG
3688
3689 private:
3690 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
3691};
3692
3693
3694class ExternalShortArray: public ExternalArray {
3695 public:
3696 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003697 inline int16_t get_scalar(int index);
3698 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003699 inline void set(int index, int16_t value);
3700
3701 // This accessor applies the correct conversion from Smi, HeapNumber
3702 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003703 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003704
3705 // Casting.
3706 static inline ExternalShortArray* cast(Object* obj);
3707
Ben Murdochb0fe1622011-05-05 13:52:32 +01003708#ifdef OBJECT_PRINT
3709 inline void ExternalShortArrayPrint() {
3710 ExternalShortArrayPrint(stdout);
3711 }
3712 void ExternalShortArrayPrint(FILE* out);
3713#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003714#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003715 void ExternalShortArrayVerify();
3716#endif // DEBUG
3717
3718 private:
3719 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
3720};
3721
3722
3723class ExternalUnsignedShortArray: public ExternalArray {
3724 public:
3725 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003726 inline uint16_t get_scalar(int index);
3727 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003728 inline void set(int index, uint16_t value);
3729
3730 // This accessor applies the correct conversion from Smi, HeapNumber
3731 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003732 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003733
3734 // Casting.
3735 static inline ExternalUnsignedShortArray* cast(Object* obj);
3736
Ben Murdochb0fe1622011-05-05 13:52:32 +01003737#ifdef OBJECT_PRINT
3738 inline void ExternalUnsignedShortArrayPrint() {
3739 ExternalUnsignedShortArrayPrint(stdout);
3740 }
3741 void ExternalUnsignedShortArrayPrint(FILE* out);
3742#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003743#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003744 void ExternalUnsignedShortArrayVerify();
3745#endif // DEBUG
3746
3747 private:
3748 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
3749};
3750
3751
3752class ExternalIntArray: public ExternalArray {
3753 public:
3754 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003755 inline int32_t get_scalar(int index);
3756 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003757 inline void set(int index, int32_t value);
3758
3759 // This accessor applies the correct conversion from Smi, HeapNumber
3760 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003761 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003762
3763 // Casting.
3764 static inline ExternalIntArray* cast(Object* obj);
3765
Ben Murdochb0fe1622011-05-05 13:52:32 +01003766#ifdef OBJECT_PRINT
3767 inline void ExternalIntArrayPrint() {
3768 ExternalIntArrayPrint(stdout);
3769 }
3770 void ExternalIntArrayPrint(FILE* out);
3771#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003772#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003773 void ExternalIntArrayVerify();
3774#endif // DEBUG
3775
3776 private:
3777 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
3778};
3779
3780
3781class ExternalUnsignedIntArray: public ExternalArray {
3782 public:
3783 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003784 inline uint32_t get_scalar(int index);
3785 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003786 inline void set(int index, uint32_t value);
3787
3788 // This accessor applies the correct conversion from Smi, HeapNumber
3789 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003790 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003791
3792 // Casting.
3793 static inline ExternalUnsignedIntArray* cast(Object* obj);
3794
Ben Murdochb0fe1622011-05-05 13:52:32 +01003795#ifdef OBJECT_PRINT
3796 inline void ExternalUnsignedIntArrayPrint() {
3797 ExternalUnsignedIntArrayPrint(stdout);
3798 }
3799 void ExternalUnsignedIntArrayPrint(FILE* out);
3800#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003801#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003802 void ExternalUnsignedIntArrayVerify();
3803#endif // DEBUG
3804
3805 private:
3806 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
3807};
3808
3809
3810class ExternalFloatArray: public ExternalArray {
3811 public:
3812 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003813 inline float get_scalar(int index);
3814 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003815 inline void set(int index, float value);
3816
3817 // This accessor applies the correct conversion from Smi, HeapNumber
3818 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003819 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003820
3821 // Casting.
3822 static inline ExternalFloatArray* cast(Object* obj);
3823
Ben Murdochb0fe1622011-05-05 13:52:32 +01003824#ifdef OBJECT_PRINT
3825 inline void ExternalFloatArrayPrint() {
3826 ExternalFloatArrayPrint(stdout);
3827 }
3828 void ExternalFloatArrayPrint(FILE* out);
3829#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003830#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003831 void ExternalFloatArrayVerify();
3832#endif // DEBUG
3833
3834 private:
3835 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
3836};
3837
3838
Ben Murdoch257744e2011-11-30 15:57:28 +00003839class ExternalDoubleArray: public ExternalArray {
3840 public:
3841 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003842 inline double get_scalar(int index);
3843 inline MaybeObject* get(int index);
Ben Murdoch257744e2011-11-30 15:57:28 +00003844 inline void set(int index, double value);
3845
3846 // This accessor applies the correct conversion from Smi, HeapNumber
3847 // and undefined.
3848 MaybeObject* SetValue(uint32_t index, Object* value);
3849
3850 // Casting.
3851 static inline ExternalDoubleArray* cast(Object* obj);
3852
3853#ifdef OBJECT_PRINT
3854 inline void ExternalDoubleArrayPrint() {
3855 ExternalDoubleArrayPrint(stdout);
3856 }
3857 void ExternalDoubleArrayPrint(FILE* out);
3858#endif // OBJECT_PRINT
3859#ifdef DEBUG
3860 void ExternalDoubleArrayVerify();
3861#endif // DEBUG
3862
3863 private:
3864 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalDoubleArray);
3865};
3866
3867
Ben Murdochb0fe1622011-05-05 13:52:32 +01003868// DeoptimizationInputData is a fixed array used to hold the deoptimization
3869// data for code generated by the Hydrogen/Lithium compiler. It also
3870// contains information about functions that were inlined. If N different
3871// functions were inlined then first N elements of the literal array will
3872// contain these functions.
3873//
3874// It can be empty.
3875class DeoptimizationInputData: public FixedArray {
3876 public:
3877 // Layout description. Indices in the array.
3878 static const int kTranslationByteArrayIndex = 0;
3879 static const int kInlinedFunctionCountIndex = 1;
3880 static const int kLiteralArrayIndex = 2;
3881 static const int kOsrAstIdIndex = 3;
3882 static const int kOsrPcOffsetIndex = 4;
3883 static const int kFirstDeoptEntryIndex = 5;
3884
3885 // Offsets of deopt entry elements relative to the start of the entry.
3886 static const int kAstIdOffset = 0;
3887 static const int kTranslationIndexOffset = 1;
3888 static const int kArgumentsStackHeightOffset = 2;
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003889 static const int kPcOffset = 3;
3890 static const int kDeoptEntrySize = 4;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003891
3892 // Simple element accessors.
3893#define DEFINE_ELEMENT_ACCESSORS(name, type) \
3894 type* name() { \
3895 return type::cast(get(k##name##Index)); \
3896 } \
3897 void Set##name(type* value) { \
3898 set(k##name##Index, value); \
3899 }
3900
3901 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
3902 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
3903 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
3904 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
3905 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
3906
Ben Murdochb0fe1622011-05-05 13:52:32 +01003907#undef DEFINE_ELEMENT_ACCESSORS
3908
3909 // Accessors for elements of the ith deoptimization entry.
3910#define DEFINE_ENTRY_ACCESSORS(name, type) \
3911 type* name(int i) { \
3912 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
3913 } \
3914 void Set##name(int i, type* value) { \
3915 set(IndexForEntry(i) + k##name##Offset, value); \
3916 }
3917
3918 DEFINE_ENTRY_ACCESSORS(AstId, Smi)
3919 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
3920 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003921 DEFINE_ENTRY_ACCESSORS(Pc, Smi)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003922
3923#undef DEFINE_ENTRY_ACCESSORS
3924
3925 int DeoptCount() {
3926 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
3927 }
3928
3929 // Allocates a DeoptimizationInputData.
3930 MUST_USE_RESULT static MaybeObject* Allocate(int deopt_entry_count,
3931 PretenureFlag pretenure);
3932
3933 // Casting.
3934 static inline DeoptimizationInputData* cast(Object* obj);
3935
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003936#ifdef ENABLE_DISASSEMBLER
Ben Murdochb0fe1622011-05-05 13:52:32 +01003937 void DeoptimizationInputDataPrint(FILE* out);
3938#endif
3939
3940 private:
3941 static int IndexForEntry(int i) {
3942 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
3943 }
3944
3945 static int LengthFor(int entry_count) {
3946 return IndexForEntry(entry_count);
3947 }
3948};
3949
3950
3951// DeoptimizationOutputData is a fixed array used to hold the deoptimization
3952// data for code generated by the full compiler.
3953// The format of the these objects is
3954// [i * 2]: Ast ID for ith deoptimization.
3955// [i * 2 + 1]: PC and state of ith deoptimization
3956class DeoptimizationOutputData: public FixedArray {
3957 public:
3958 int DeoptPoints() { return length() / 2; }
3959 Smi* AstId(int index) { return Smi::cast(get(index * 2)); }
3960 void SetAstId(int index, Smi* id) { set(index * 2, id); }
3961 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
3962 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
3963
3964 static int LengthOfFixedArray(int deopt_points) {
3965 return deopt_points * 2;
3966 }
3967
3968 // Allocates a DeoptimizationOutputData.
3969 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_deopt_points,
3970 PretenureFlag pretenure);
3971
3972 // Casting.
3973 static inline DeoptimizationOutputData* cast(Object* obj);
3974
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003975#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003976 void DeoptimizationOutputDataPrint(FILE* out);
3977#endif
3978};
3979
3980
Ben Murdochb8e0da22011-05-16 14:20:40 +01003981class SafepointEntry;
3982
3983
Steve Blocka7e24c12009-10-30 11:49:00 +00003984// Code describes objects with on-the-fly generated machine code.
3985class Code: public HeapObject {
3986 public:
3987 // Opaque data type for encapsulating code flags like kind, inline
3988 // cache state, and arguments count.
Iain Merrick75681382010-08-19 15:07:18 +01003989 // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
3990 // enumeration type has correct value range (see Issue 830 for more details).
3991 enum Flags {
3992 FLAGS_MIN_VALUE = kMinInt,
3993 FLAGS_MAX_VALUE = kMaxInt
3994 };
Steve Blocka7e24c12009-10-30 11:49:00 +00003995
3996 enum Kind {
3997 FUNCTION,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003998 OPTIMIZED_FUNCTION,
Steve Blocka7e24c12009-10-30 11:49:00 +00003999 STUB,
4000 BUILTIN,
4001 LOAD_IC,
4002 KEYED_LOAD_IC,
4003 CALL_IC,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004004 KEYED_CALL_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00004005 STORE_IC,
4006 KEYED_STORE_IC,
Ben Murdoch257744e2011-11-30 15:57:28 +00004007 UNARY_OP_IC,
4008 BINARY_OP_IC,
Ben Murdochb0fe1622011-05-05 13:52:32 +01004009 COMPARE_IC,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004010 TO_BOOLEAN_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01004011 // No more than 16 kinds. The value currently encoded in four bits in
Steve Blocka7e24c12009-10-30 11:49:00 +00004012 // Flags.
4013
4014 // Pseudo-kinds.
4015 REGEXP = BUILTIN,
4016 FIRST_IC_KIND = LOAD_IC,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004017 LAST_IC_KIND = TO_BOOLEAN_IC
Steve Blocka7e24c12009-10-30 11:49:00 +00004018 };
4019
4020 enum {
Kristian Monsen50ef84f2010-07-29 15:18:00 +01004021 NUMBER_OF_KINDS = LAST_IC_KIND + 1
Steve Blocka7e24c12009-10-30 11:49:00 +00004022 };
4023
Ben Murdochb8e0da22011-05-16 14:20:40 +01004024 typedef int ExtraICState;
4025
4026 static const ExtraICState kNoExtraICState = 0;
4027
Steve Blocka7e24c12009-10-30 11:49:00 +00004028#ifdef ENABLE_DISASSEMBLER
4029 // Printing
4030 static const char* Kind2String(Kind kind);
4031 static const char* ICState2String(InlineCacheState state);
4032 static const char* PropertyType2String(PropertyType type);
Steve Block1e0659c2011-05-24 12:43:12 +01004033 static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004034 inline void Disassemble(const char* name) {
4035 Disassemble(name, stdout);
4036 }
4037 void Disassemble(const char* name, FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00004038#endif // ENABLE_DISASSEMBLER
4039
4040 // [instruction_size]: Size of the native instructions
4041 inline int instruction_size();
4042 inline void set_instruction_size(int value);
4043
Leon Clarkeac952652010-07-15 11:15:24 +01004044 // [relocation_info]: Code relocation information
4045 DECL_ACCESSORS(relocation_info, ByteArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004046 void InvalidateRelocation();
Leon Clarkeac952652010-07-15 11:15:24 +01004047
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004048 // [handler_table]: Fixed array containing offsets of exception handlers.
4049 DECL_ACCESSORS(handler_table, FixedArray)
4050
Ben Murdochb0fe1622011-05-05 13:52:32 +01004051 // [deoptimization_data]: Array containing data for deopt.
4052 DECL_ACCESSORS(deoptimization_data, FixedArray)
4053
Ben Murdochc7cc0282012-03-05 14:35:55 +00004054 // [gc_metadata]: Field used to hold GC related metadata. The contents of this
Ben Murdoch257744e2011-11-30 15:57:28 +00004055 // field does not have to be traced during garbage collection since
4056 // it is only used by the garbage collector itself.
Ben Murdochc7cc0282012-03-05 14:35:55 +00004057 DECL_ACCESSORS(gc_metadata, Object)
Ben Murdoch257744e2011-11-30 15:57:28 +00004058
Ben Murdochb0fe1622011-05-05 13:52:32 +01004059 // Unchecked accessors to be used during GC.
Leon Clarkeac952652010-07-15 11:15:24 +01004060 inline ByteArray* unchecked_relocation_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004061 inline FixedArray* unchecked_deoptimization_data();
Leon Clarkeac952652010-07-15 11:15:24 +01004062
Steve Blocka7e24c12009-10-30 11:49:00 +00004063 inline int relocation_size();
Steve Blocka7e24c12009-10-30 11:49:00 +00004064
Steve Blocka7e24c12009-10-30 11:49:00 +00004065 // [flags]: Various code flags.
4066 inline Flags flags();
4067 inline void set_flags(Flags flags);
4068
4069 // [flags]: Access to specific code flags.
4070 inline Kind kind();
4071 inline InlineCacheState ic_state(); // Only valid for IC stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01004072 inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
Steve Blocka7e24c12009-10-30 11:49:00 +00004073 inline PropertyType type(); // Only valid for monomorphic IC stubs.
4074 inline int arguments_count(); // Only valid for call IC stubs.
4075
4076 // Testers for IC stub kinds.
4077 inline bool is_inline_cache_stub();
4078 inline bool is_load_stub() { return kind() == LOAD_IC; }
4079 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
4080 inline bool is_store_stub() { return kind() == STORE_IC; }
4081 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
4082 inline bool is_call_stub() { return kind() == CALL_IC; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004083 inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004084 inline bool is_unary_op_stub() { return kind() == UNARY_OP_IC; }
4085 inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004086 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004087 inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
Steve Blocka7e24c12009-10-30 11:49:00 +00004088
Steve Block6ded16b2010-05-10 14:33:55 +01004089 // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004090 inline int major_key();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004091 inline void set_major_key(int value);
4092
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004093 // For stubs, tells whether they should always exist, so that they can be
4094 // called from other stubs.
4095 inline bool is_pregenerated();
4096 inline void set_is_pregenerated(bool value);
4097
Ben Murdochb0fe1622011-05-05 13:52:32 +01004098 // [optimizable]: For FUNCTION kind, tells if it is optimizable.
4099 inline bool optimizable();
4100 inline void set_optimizable(bool value);
4101
4102 // [has_deoptimization_support]: For FUNCTION kind, tells if it has
4103 // deoptimization support.
4104 inline bool has_deoptimization_support();
4105 inline void set_has_deoptimization_support(bool value);
4106
Ben Murdoch589d6972011-11-30 16:04:58 +00004107 // [has_debug_break_slots]: For FUNCTION kind, tells if it has
4108 // been compiled with debug break slots.
4109 inline bool has_debug_break_slots();
4110 inline void set_has_debug_break_slots(bool value);
4111
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004112 // [compiled_with_optimizing]: For FUNCTION kind, tells if it has
4113 // been compiled with IsOptimizing set to true.
4114 inline bool is_compiled_optimizable();
4115 inline void set_compiled_optimizable(bool value);
4116
Ben Murdochb0fe1622011-05-05 13:52:32 +01004117 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
4118 // how long the function has been marked for OSR and therefore which
4119 // level of loop nesting we are willing to do on-stack replacement
4120 // for.
4121 inline void set_allow_osr_at_loop_nesting_level(int level);
4122 inline int allow_osr_at_loop_nesting_level();
4123
4124 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
4125 // reserved in the code prologue.
4126 inline unsigned stack_slots();
4127 inline void set_stack_slots(unsigned slots);
4128
4129 // [safepoint_table_start]: For kind OPTIMIZED_CODE, the offset in
4130 // the instruction stream where the safepoint table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01004131 inline unsigned safepoint_table_offset();
4132 inline void set_safepoint_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004133
4134 // [stack_check_table_start]: For kind FUNCTION, the offset in the
4135 // instruction stream where the stack check table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01004136 inline unsigned stack_check_table_offset();
4137 inline void set_stack_check_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004138
4139 // [check type]: For kind CALL_IC, tells how to check if the
4140 // receiver is valid for the given call.
4141 inline CheckType check_type();
4142 inline void set_check_type(CheckType value);
4143
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004144 // [type-recording unary op type]: For kind UNARY_OP_IC.
Ben Murdoch257744e2011-11-30 15:57:28 +00004145 inline byte unary_op_type();
4146 inline void set_unary_op_type(byte value);
4147
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004148 // [type-recording binary op type]: For kind BINARY_OP_IC.
Ben Murdoch257744e2011-11-30 15:57:28 +00004149 inline byte binary_op_type();
4150 inline void set_binary_op_type(byte value);
4151 inline byte binary_op_result_type();
4152 inline void set_binary_op_result_type(byte value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004153
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004154 // [compare state]: For kind COMPARE_IC, tells what state the stub is in.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004155 inline byte compare_state();
4156 inline void set_compare_state(byte value);
4157
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004158 // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
4159 inline byte to_boolean_state();
4160 inline void set_to_boolean_state(byte value);
4161
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004162 // For kind STUB, major_key == CallFunction, tells whether there is
4163 // a function cache in the instruction stream.
4164 inline bool has_function_cache();
4165 inline void set_has_function_cache(bool flag);
4166
Ben Murdochb8e0da22011-05-16 14:20:40 +01004167 // Get the safepoint entry for the given pc.
4168 SafepointEntry GetSafepointEntry(Address pc);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004169
4170 // Mark this code object as not having a stack check table. Assumes kind
4171 // is FUNCTION.
4172 void SetNoStackCheckTable();
4173
4174 // Find the first map in an IC stub.
4175 Map* FindFirstMap();
Steve Blocka7e24c12009-10-30 11:49:00 +00004176
4177 // Flags operations.
Ben Murdochb8e0da22011-05-16 14:20:40 +01004178 static inline Flags ComputeFlags(
4179 Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01004180 InlineCacheState ic_state = UNINITIALIZED,
4181 ExtraICState extra_ic_state = kNoExtraICState,
4182 PropertyType type = NORMAL,
4183 int argc = -1,
4184 InlineCacheHolderFlag holder = OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +00004185
4186 static inline Flags ComputeMonomorphicFlags(
4187 Kind kind,
4188 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01004189 ExtraICState extra_ic_state = kNoExtraICState,
Steve Block8defd9f2010-07-08 12:39:36 +01004190 InlineCacheHolderFlag holder = OWN_MAP,
Steve Blocka7e24c12009-10-30 11:49:00 +00004191 int argc = -1);
4192
Steve Blocka7e24c12009-10-30 11:49:00 +00004193 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00004194 static inline PropertyType ExtractTypeFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00004195 static inline Kind ExtractKindFromFlags(Flags flags);
Steve Block8defd9f2010-07-08 12:39:36 +01004196 static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00004197 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
4198 static inline int ExtractArgumentsCountFromFlags(Flags flags);
4199
Steve Blocka7e24c12009-10-30 11:49:00 +00004200 static inline Flags RemoveTypeFromFlags(Flags flags);
4201
4202 // Convert a target address into a code object.
4203 static inline Code* GetCodeFromTargetAddress(Address address);
4204
Steve Block791712a2010-08-27 10:21:07 +01004205 // Convert an entry address into an object.
4206 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
4207
Steve Blocka7e24c12009-10-30 11:49:00 +00004208 // Returns the address of the first instruction.
4209 inline byte* instruction_start();
4210
Leon Clarkeac952652010-07-15 11:15:24 +01004211 // Returns the address right after the last instruction.
4212 inline byte* instruction_end();
4213
Steve Blocka7e24c12009-10-30 11:49:00 +00004214 // Returns the size of the instructions, padding, and relocation information.
4215 inline int body_size();
4216
4217 // Returns the address of the first relocation info (read backwards!).
4218 inline byte* relocation_start();
4219
4220 // Code entry point.
4221 inline byte* entry();
4222
4223 // Returns true if pc is inside this object's instructions.
4224 inline bool contains(byte* pc);
4225
Steve Blocka7e24c12009-10-30 11:49:00 +00004226 // Relocate the code by delta bytes. Called to signal that this code
4227 // object has been moved by delta bytes.
Steve Blockd0582a62009-12-15 09:54:21 +00004228 void Relocate(intptr_t delta);
Steve Blocka7e24c12009-10-30 11:49:00 +00004229
4230 // Migrate code described by desc.
4231 void CopyFrom(const CodeDesc& desc);
4232
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004233 // Returns the object size for a given body (used for allocation).
4234 static int SizeFor(int body_size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004235 ASSERT_SIZE_TAG_ALIGNED(body_size);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004236 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
Steve Blocka7e24c12009-10-30 11:49:00 +00004237 }
4238
4239 // Calculate the size of the code object to report for log events. This takes
4240 // the layout of the code object into account.
4241 int ExecutableSize() {
4242 // Check that the assumptions about the layout of the code object holds.
4243 ASSERT_EQ(static_cast<int>(instruction_start() - address()),
4244 Code::kHeaderSize);
4245 return instruction_size() + Code::kHeaderSize;
4246 }
4247
4248 // Locating source position.
4249 int SourcePosition(Address pc);
4250 int SourceStatementPosition(Address pc);
4251
4252 // Casting.
4253 static inline Code* cast(Object* obj);
4254
4255 // Dispatched behavior.
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004256 int CodeSize() { return SizeFor(body_size()); }
Iain Merrick75681382010-08-19 15:07:18 +01004257 inline void CodeIterateBody(ObjectVisitor* v);
4258
4259 template<typename StaticVisitor>
Steve Block44f0eee2011-05-26 01:26:41 +01004260 inline void CodeIterateBody(Heap* heap);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004261#ifdef OBJECT_PRINT
4262 inline void CodePrint() {
4263 CodePrint(stdout);
4264 }
4265 void CodePrint(FILE* out);
4266#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004267#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004268 void CodeVerify();
4269#endif
Ben Murdochb0fe1622011-05-05 13:52:32 +01004270
4271 // Max loop nesting marker used to postpose OSR. We don't take loop
4272 // nesting that is deeper than 5 levels into account.
4273 static const int kMaxLoopNestingMarker = 6;
4274
Steve Blocka7e24c12009-10-30 11:49:00 +00004275 // Layout description.
4276 static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
Leon Clarkeac952652010-07-15 11:15:24 +01004277 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004278 static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004279 static const int kDeoptimizationDataOffset =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004280 kHandlerTableOffset + kPointerSize;
Ben Murdochc7cc0282012-03-05 14:35:55 +00004281 static const int kGCMetadataOffset = kDeoptimizationDataOffset + kPointerSize;
4282 static const int kFlagsOffset = kGCMetadataOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004283
Ben Murdoch257744e2011-11-30 15:57:28 +00004284 static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004285 static const int kKindSpecificFlagsSize = 2 * kIntSize;
4286
4287 static const int kHeaderPaddingStart = kKindSpecificFlagsOffset +
4288 kKindSpecificFlagsSize;
4289
Steve Blocka7e24c12009-10-30 11:49:00 +00004290 // Add padding to align the instruction start following right after
4291 // the Code object header.
4292 static const int kHeaderSize =
Ben Murdochb0fe1622011-05-05 13:52:32 +01004293 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00004294
4295 // Byte offsets within kKindSpecificFlagsOffset.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004296 static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset;
4297 static const int kOptimizableOffset = kKindSpecificFlagsOffset;
4298 static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
4299 static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
4300
Ben Murdoch257744e2011-11-30 15:57:28 +00004301 static const int kUnaryOpTypeOffset = kStubMajorKeyOffset + 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004302 static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004303 static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
4304 static const int kToBooleanTypeOffset = kStubMajorKeyOffset + 1;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004305 static const int kHasFunctionCacheOffset = kStubMajorKeyOffset + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00004306
4307 static const int kFullCodeFlags = kOptimizableOffset + 1;
4308 class FullCodeFlagsHasDeoptimizationSupportField:
4309 public BitField<bool, 0, 1> {}; // NOLINT
4310 class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004311 class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
Ben Murdochb0fe1622011-05-05 13:52:32 +01004312
4313 static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00004314
4315 static const int kAllowOSRAtLoopNestingLevelOffset = kFullCodeFlags + 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004316
Steve Block1e0659c2011-05-24 12:43:12 +01004317 static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
4318 static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004319
Ben Murdoch589d6972011-11-30 16:04:58 +00004320 // Flags layout. BitField<type, shift, size>.
4321 class ICStateField: public BitField<InlineCacheState, 0, 3> {};
4322 class TypeField: public BitField<PropertyType, 3, 4> {};
4323 class KindField: public BitField<Kind, 7, 4> {};
4324 class CacheHolderField: public BitField<InlineCacheHolderFlag, 11, 1> {};
4325 class ExtraICStateField: public BitField<ExtraICState, 12, 2> {};
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004326 class IsPregeneratedField: public BitField<bool, 14, 1> {};
Steve Blocka7e24c12009-10-30 11:49:00 +00004327
Ben Murdoch589d6972011-11-30 16:04:58 +00004328 // Signed field cannot be encoded using the BitField class.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004329 static const int kArgumentsCountShift = 15;
Ben Murdoch589d6972011-11-30 16:04:58 +00004330 static const int kArgumentsCountMask = ~((1 << kArgumentsCountShift) - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00004331
4332 static const int kFlagsNotUsedInLookup =
Ben Murdoch589d6972011-11-30 16:04:58 +00004333 TypeField::kMask | CacheHolderField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00004334
4335 private:
4336 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
4337};
4338
4339
4340// All heap objects have a Map that describes their structure.
4341// A Map contains information about:
4342// - Size information about the object
4343// - How to iterate over an object (for garbage collection)
4344class Map: public HeapObject {
4345 public:
4346 // Instance size.
Steve Block791712a2010-08-27 10:21:07 +01004347 // Size in bytes or kVariableSizeSentinel if instances do not have
4348 // a fixed size.
Steve Blocka7e24c12009-10-30 11:49:00 +00004349 inline int instance_size();
4350 inline void set_instance_size(int value);
4351
4352 // Count of properties allocated in the object.
4353 inline int inobject_properties();
4354 inline void set_inobject_properties(int value);
4355
4356 // Count of property fields pre-allocated in the object when first allocated.
4357 inline int pre_allocated_property_fields();
4358 inline void set_pre_allocated_property_fields(int value);
4359
4360 // Instance type.
4361 inline InstanceType instance_type();
4362 inline void set_instance_type(InstanceType value);
4363
4364 // Tells how many unused property fields are available in the
4365 // instance (only used for JSObject in fast mode).
4366 inline int unused_property_fields();
4367 inline void set_unused_property_fields(int value);
4368
4369 // Bit field.
4370 inline byte bit_field();
4371 inline void set_bit_field(byte value);
4372
4373 // Bit field 2.
4374 inline byte bit_field2();
4375 inline void set_bit_field2(byte value);
4376
Ben Murdoch257744e2011-11-30 15:57:28 +00004377 // Bit field 3.
4378 // TODO(1399): It should be possible to make room for bit_field3 in the map
4379 // without overloading the instance descriptors field (and storing it in the
4380 // DescriptorArray when the map has one).
4381 inline int bit_field3();
4382 inline void set_bit_field3(int value);
4383
Steve Blocka7e24c12009-10-30 11:49:00 +00004384 // Tells whether the object in the prototype property will be used
4385 // for instances created from this function. If the prototype
4386 // property is set to a value that is not a JSObject, the prototype
4387 // property will not be used to create instances of the function.
4388 // See ECMA-262, 13.2.2.
4389 inline void set_non_instance_prototype(bool value);
4390 inline bool has_non_instance_prototype();
4391
Steve Block6ded16b2010-05-10 14:33:55 +01004392 // Tells whether function has special prototype property. If not, prototype
4393 // property will not be created when accessed (will return undefined),
4394 // and construction from this function will not be allowed.
4395 inline void set_function_with_prototype(bool value);
4396 inline bool function_with_prototype();
4397
Steve Blocka7e24c12009-10-30 11:49:00 +00004398 // Tells whether the instance with this map should be ignored by the
4399 // __proto__ accessor.
4400 inline void set_is_hidden_prototype() {
4401 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
4402 }
4403
4404 inline bool is_hidden_prototype() {
4405 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
4406 }
4407
4408 // Records and queries whether the instance has a named interceptor.
4409 inline void set_has_named_interceptor() {
4410 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
4411 }
4412
4413 inline bool has_named_interceptor() {
4414 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
4415 }
4416
4417 // Records and queries whether the instance has an indexed interceptor.
4418 inline void set_has_indexed_interceptor() {
4419 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
4420 }
4421
4422 inline bool has_indexed_interceptor() {
4423 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
4424 }
4425
4426 // Tells whether the instance is undetectable.
4427 // An undetectable object is a special class of JSObject: 'typeof' operator
4428 // returns undefined, ToBoolean returns false. Otherwise it behaves like
4429 // a normal JS object. It is useful for implementing undetectable
4430 // document.all in Firefox & Safari.
4431 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
4432 inline void set_is_undetectable() {
4433 set_bit_field(bit_field() | (1 << kIsUndetectable));
4434 }
4435
4436 inline bool is_undetectable() {
4437 return ((1 << kIsUndetectable) & bit_field()) != 0;
4438 }
4439
Steve Blocka7e24c12009-10-30 11:49:00 +00004440 // Tells whether the instance has a call-as-function handler.
4441 inline void set_has_instance_call_handler() {
4442 set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
4443 }
4444
4445 inline bool has_instance_call_handler() {
4446 return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
4447 }
4448
Steve Block8defd9f2010-07-08 12:39:36 +01004449 inline void set_is_extensible(bool value);
4450 inline bool is_extensible();
4451
Ben Murdoch589d6972011-11-30 16:04:58 +00004452 inline void set_elements_kind(ElementsKind elements_kind) {
4453 ASSERT(elements_kind < kElementsKindCount);
4454 ASSERT(kElementsKindCount <= (1 << kElementsKindBitCount));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004455 set_bit_field2((bit_field2() & ~kElementsKindMask) |
4456 (elements_kind << kElementsKindShift));
4457 ASSERT(this->elements_kind() == elements_kind);
4458 }
4459
Ben Murdoch589d6972011-11-30 16:04:58 +00004460 inline ElementsKind elements_kind() {
4461 return static_cast<ElementsKind>(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004462 (bit_field2() & kElementsKindMask) >> kElementsKindShift);
4463 }
4464
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004465 // Tells whether the instance has fast elements that are only Smis.
4466 inline bool has_fast_smi_only_elements() {
4467 return elements_kind() == FAST_SMI_ONLY_ELEMENTS;
4468 }
4469
Steve Block8defd9f2010-07-08 12:39:36 +01004470 // Tells whether the instance has fast elements.
Iain Merrick75681382010-08-19 15:07:18 +01004471 inline bool has_fast_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004472 return elements_kind() == FAST_ELEMENTS;
Leon Clarkee46be812010-01-19 14:06:41 +00004473 }
4474
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004475 inline bool has_fast_double_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004476 return elements_kind() == FAST_DOUBLE_ELEMENTS;
Steve Block1e0659c2011-05-24 12:43:12 +01004477 }
4478
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004479 inline bool has_non_strict_arguments_elements() {
4480 return elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4481 }
4482
Steve Block44f0eee2011-05-26 01:26:41 +01004483 inline bool has_external_array_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004484 ElementsKind kind(elements_kind());
4485 return kind >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
4486 kind <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004487 }
4488
4489 inline bool has_dictionary_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004490 return elements_kind() == DICTIONARY_ELEMENTS;
Steve Block1e0659c2011-05-24 12:43:12 +01004491 }
4492
Ben Murdochc7cc0282012-03-05 14:35:55 +00004493 inline bool has_slow_elements_kind() {
4494 return elements_kind() == DICTIONARY_ELEMENTS
4495 || elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4496 }
4497
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004498 static bool IsValidElementsTransition(ElementsKind from_kind,
4499 ElementsKind to_kind);
4500
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004501 // Tells whether the map is attached to SharedFunctionInfo
4502 // (for inobject slack tracking).
4503 inline void set_attached_to_shared_function_info(bool value);
4504
4505 inline bool attached_to_shared_function_info();
4506
4507 // Tells whether the map is shared between objects that may have different
4508 // behavior. If true, the map should never be modified, instead a clone
4509 // should be created and modified.
4510 inline void set_is_shared(bool value);
4511
4512 inline bool is_shared();
4513
Steve Blocka7e24c12009-10-30 11:49:00 +00004514 // Tells whether the instance needs security checks when accessing its
4515 // properties.
4516 inline void set_is_access_check_needed(bool access_check_needed);
4517 inline bool is_access_check_needed();
4518
4519 // [prototype]: implicit prototype object.
4520 DECL_ACCESSORS(prototype, Object)
4521
4522 // [constructor]: points back to the function responsible for this map.
4523 DECL_ACCESSORS(constructor, Object)
4524
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004525 inline JSFunction* unchecked_constructor();
4526
Ben Murdoch257744e2011-11-30 15:57:28 +00004527 // Should only be called by the code that initializes map to set initial valid
4528 // value of the instance descriptor member.
4529 inline void init_instance_descriptors();
4530
Steve Blocka7e24c12009-10-30 11:49:00 +00004531 // [instance descriptors]: describes the object.
4532 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
4533
Ben Murdoch257744e2011-11-30 15:57:28 +00004534 // Sets the instance descriptor array for the map to be an empty descriptor
4535 // array.
4536 inline void clear_instance_descriptors();
4537
Steve Blocka7e24c12009-10-30 11:49:00 +00004538 // [stub cache]: contains stubs compiled for this map.
Steve Block6ded16b2010-05-10 14:33:55 +01004539 DECL_ACCESSORS(code_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00004540
Steve Block053d10c2011-06-13 19:13:29 +01004541 // [prototype transitions]: cache of prototype transitions.
4542 // Prototype transition is a transition that happens
4543 // when we change object's prototype to a new one.
4544 // Cache format:
4545 // 0: finger - index of the first free cell in the cache
4546 // 1 + 2 * i: prototype
4547 // 2 + 2 * i: target map
4548 DECL_ACCESSORS(prototype_transitions, FixedArray)
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004549
Steve Block053d10c2011-06-13 19:13:29 +01004550 inline FixedArray* unchecked_prototype_transitions();
4551
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004552 static const int kProtoTransitionHeaderSize = 1;
4553 static const int kProtoTransitionNumberOfEntriesOffset = 0;
4554 static const int kProtoTransitionElementsPerEntry = 2;
4555 static const int kProtoTransitionPrototypeOffset = 0;
4556 static const int kProtoTransitionMapOffset = 1;
4557
4558 inline int NumberOfProtoTransitions() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004559 FixedArray* cache = prototype_transitions();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004560 if (cache->length() == 0) return 0;
4561 return
4562 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
4563 }
4564
4565 inline void SetNumberOfProtoTransitions(int value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004566 FixedArray* cache = prototype_transitions();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004567 ASSERT(cache->length() != 0);
4568 cache->set_unchecked(kProtoTransitionNumberOfEntriesOffset,
4569 Smi::FromInt(value));
4570 }
4571
Ben Murdochb0fe1622011-05-05 13:52:32 +01004572 // Lookup in the map's instance descriptors and fill out the result
4573 // with the given holder if the name is found. The holder may be
4574 // NULL when this function is used from the compiler.
4575 void LookupInDescriptors(JSObject* holder,
4576 String* name,
4577 LookupResult* result);
4578
John Reck59135872010-11-02 12:39:01 -07004579 MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004580
John Reck59135872010-11-02 12:39:01 -07004581 MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
4582 NormalizedMapSharingMode sharing);
Steve Blocka7e24c12009-10-30 11:49:00 +00004583
4584 // Returns a copy of the map, with all transitions dropped from the
4585 // instance descriptors.
John Reck59135872010-11-02 12:39:01 -07004586 MUST_USE_RESULT MaybeObject* CopyDropTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00004587
4588 // Returns the property index for name (only valid for FAST MODE).
4589 int PropertyIndexFor(String* name);
4590
4591 // Returns the next free property index (only valid for FAST MODE).
4592 int NextFreePropertyIndex();
4593
4594 // Returns the number of properties described in instance_descriptors.
4595 int NumberOfDescribedProperties();
4596
4597 // Casting.
4598 static inline Map* cast(Object* obj);
4599
4600 // Locate an accessor in the instance descriptor.
4601 AccessorDescriptor* FindAccessor(String* name);
4602
4603 // Code cache operations.
4604
4605 // Clears the code cache.
Steve Block44f0eee2011-05-26 01:26:41 +01004606 inline void ClearCodeCache(Heap* heap);
Steve Blocka7e24c12009-10-30 11:49:00 +00004607
4608 // Update code cache.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004609 static void UpdateCodeCache(Handle<Map> map,
4610 Handle<String> name,
4611 Handle<Code> code);
John Reck59135872010-11-02 12:39:01 -07004612 MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00004613
4614 // Returns the found code or undefined if absent.
4615 Object* FindInCodeCache(String* name, Code::Flags flags);
4616
4617 // Returns the non-negative index of the code object if it is in the
4618 // cache and -1 otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +01004619 int IndexInCodeCache(Object* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00004620
4621 // Removes a code object from the code cache at the given index.
Steve Block6ded16b2010-05-10 14:33:55 +01004622 void RemoveFromCodeCache(String* name, Code* code, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004623
4624 // For every transition in this map, makes the transition's
4625 // target's prototype pointer point back to this map.
4626 // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
4627 void CreateBackPointers();
4628
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004629 void CreateOneBackPointer(Map* transition_target);
4630
Steve Blocka7e24c12009-10-30 11:49:00 +00004631 // Set all map transitions from this map to dead maps to null.
4632 // Also, restore the original prototype on the targets of these
4633 // transitions, so that we do not process this map again while
4634 // following back pointers.
Steve Block44f0eee2011-05-26 01:26:41 +01004635 void ClearNonLiveTransitions(Heap* heap, Object* real_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00004636
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004637 // Computes a hash value for this map, to be used in HashTables and such.
4638 int Hash();
4639
4640 // Compares this map to another to see if they describe equivalent objects.
4641 // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if
4642 // it had exactly zero inobject properties.
4643 // The "shared" flags of both this map and |other| are ignored.
4644 bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode);
4645
4646 // Returns true if this map and |other| describe equivalent objects.
4647 // The "shared" flags of both this map and |other| are ignored.
4648 bool EquivalentTo(Map* other) {
4649 return EquivalentToForNormalization(other, KEEP_INOBJECT_PROPERTIES);
4650 }
4651
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004652 // Returns the contents of this map's descriptor array for the given string.
4653 // May return NULL. |safe_to_add_transition| is set to false and NULL
4654 // is returned if adding transitions is not allowed.
4655 Object* GetDescriptorContents(String* sentinel_name,
4656 bool* safe_to_add_transitions);
4657
4658 // Returns the map that this map transitions to if its elements_kind
4659 // is changed to |elements_kind|, or NULL if no such map is cached yet.
4660 // |safe_to_add_transitions| is set to false if adding transitions is not
4661 // allowed.
4662 Map* LookupElementsTransitionMap(ElementsKind elements_kind,
4663 bool* safe_to_add_transition);
4664
4665 // Adds an entry to this map's descriptor array for a transition to
4666 // |transitioned_map| when its elements_kind is changed to |elements_kind|.
4667 MaybeObject* AddElementsTransition(ElementsKind elements_kind,
4668 Map* transitioned_map);
4669
4670 // Returns the transitioned map for this map with the most generic
4671 // elements_kind that's found in |candidates|, or null handle if no match is
4672 // found at all.
4673 Handle<Map> FindTransitionedMap(MapHandleList* candidates);
4674 Map* FindTransitionedMap(MapList* candidates);
4675
4676
Steve Blocka7e24c12009-10-30 11:49:00 +00004677 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004678#ifdef OBJECT_PRINT
4679 inline void MapPrint() {
4680 MapPrint(stdout);
4681 }
4682 void MapPrint(FILE* out);
4683#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004684#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004685 void MapVerify();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004686 void SharedMapVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00004687#endif
4688
Iain Merrick75681382010-08-19 15:07:18 +01004689 inline int visitor_id();
4690 inline void set_visitor_id(int visitor_id);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004691
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004692 typedef void (*TraverseCallback)(Map* map, void* data);
4693
4694 void TraverseTransitionTree(TraverseCallback callback, void* data);
4695
Steve Block053d10c2011-06-13 19:13:29 +01004696 static const int kMaxCachedPrototypeTransitions = 256;
4697
4698 Object* GetPrototypeTransition(Object* prototype);
4699
4700 MaybeObject* PutPrototypeTransition(Object* prototype, Map* map);
4701
Steve Blocka7e24c12009-10-30 11:49:00 +00004702 static const int kMaxPreAllocatedPropertyFields = 255;
4703
4704 // Layout description.
4705 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
4706 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
4707 static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
4708 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00004709 // Storage for instance descriptors is overloaded to also contain additional
4710 // map flags when unused (bit_field3). When the map has instance descriptors,
4711 // the flags are transferred to the instance descriptor array and accessed
4712 // through an extra indirection.
4713 // TODO(1399): It should be possible to make room for bit_field3 in the map
4714 // without overloading the instance descriptors field, but the map is
4715 // currently perfectly aligned to 32 bytes and extending it at all would
4716 // double its size. After the increment GC work lands, this size restriction
4717 // could be loosened and bit_field3 moved directly back in the map.
4718 static const int kInstanceDescriptorsOrBitField3Offset =
Steve Blocka7e24c12009-10-30 11:49:00 +00004719 kConstructorOffset + kPointerSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00004720 static const int kCodeCacheOffset =
4721 kInstanceDescriptorsOrBitField3Offset + kPointerSize;
Steve Block053d10c2011-06-13 19:13:29 +01004722 static const int kPrototypeTransitionsOffset =
4723 kCodeCacheOffset + kPointerSize;
4724 static const int kPadStart = kPrototypeTransitionsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004725 static const int kSize = MAP_POINTER_ALIGN(kPadStart);
4726
4727 // Layout of pointer fields. Heap iteration code relies on them
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004728 // being continuously allocated.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004729 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
4730 static const int kPointerFieldsEndOffset =
Steve Block053d10c2011-06-13 19:13:29 +01004731 Map::kPrototypeTransitionsOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004732
4733 // Byte offsets within kInstanceSizesOffset.
4734 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
4735 static const int kInObjectPropertiesByte = 1;
4736 static const int kInObjectPropertiesOffset =
4737 kInstanceSizesOffset + kInObjectPropertiesByte;
4738 static const int kPreAllocatedPropertyFieldsByte = 2;
4739 static const int kPreAllocatedPropertyFieldsOffset =
4740 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
Iain Merrick9ac36c92010-09-13 15:29:50 +01004741 static const int kVisitorIdByte = 3;
4742 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
Steve Blocka7e24c12009-10-30 11:49:00 +00004743
4744 // Byte offsets within kInstanceAttributesOffset attributes.
4745 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
4746 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
4747 static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
4748 static const int kBitField2Offset = kInstanceAttributesOffset + 3;
4749
4750 STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
4751
4752 // Bit positions for bit field.
4753 static const int kUnused = 0; // To be used for marking recently used maps.
4754 static const int kHasNonInstancePrototype = 1;
4755 static const int kIsHiddenPrototype = 2;
4756 static const int kHasNamedInterceptor = 3;
4757 static const int kHasIndexedInterceptor = 4;
4758 static const int kIsUndetectable = 5;
4759 static const int kHasInstanceCallHandler = 6;
4760 static const int kIsAccessCheckNeeded = 7;
4761
4762 // Bit positions for bit field 2
Andrei Popescu31002712010-02-23 13:46:05 +00004763 static const int kIsExtensible = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01004764 static const int kFunctionWithPrototype = 1;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004765 static const int kStringWrapperSafeForDefaultValueOf = 2;
4766 static const int kAttachedToSharedFunctionInfo = 3;
4767 // No bits can be used after kElementsKindFirstBit, they are all reserved for
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004768 // storing ElementKind.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004769 static const int kElementsKindShift = 4;
4770 static const int kElementsKindBitCount = 4;
4771
4772 // Derived values from bit field 2
4773 static const int kElementsKindMask = (-1 << kElementsKindShift) &
4774 ((1 << (kElementsKindShift + kElementsKindBitCount)) - 1);
4775 static const int8_t kMaximumBitField2FastElementValue = static_cast<int8_t>(
Ben Murdoch589d6972011-11-30 16:04:58 +00004776 (FAST_ELEMENTS + 1) << Map::kElementsKindShift) - 1;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004777 static const int8_t kMaximumBitField2FastSmiOnlyElementValue =
4778 static_cast<int8_t>((FAST_SMI_ONLY_ELEMENTS + 1) <<
4779 Map::kElementsKindShift) - 1;
Ben Murdoch257744e2011-11-30 15:57:28 +00004780
4781 // Bit positions for bit field 3
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004782 static const int kIsShared = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01004783
4784 // Layout of the default cache. It holds alternating name and code objects.
4785 static const int kCodeCacheEntrySize = 2;
4786 static const int kCodeCacheEntryNameOffset = 0;
4787 static const int kCodeCacheEntryCodeOffset = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00004788
Iain Merrick75681382010-08-19 15:07:18 +01004789 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
4790 kPointerFieldsEndOffset,
4791 kSize> BodyDescriptor;
4792
Steve Blocka7e24c12009-10-30 11:49:00 +00004793 private:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004794 String* elements_transition_sentinel_name();
Steve Blocka7e24c12009-10-30 11:49:00 +00004795 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
4796};
4797
4798
4799// An abstract superclass, a marker class really, for simple structure classes.
Ben Murdoch257744e2011-11-30 15:57:28 +00004800// It doesn't carry much functionality but allows struct classes to be
Steve Blocka7e24c12009-10-30 11:49:00 +00004801// identified in the type system.
4802class Struct: public HeapObject {
4803 public:
4804 inline void InitializeBody(int object_size);
4805 static inline Struct* cast(Object* that);
4806};
4807
4808
4809// Script describes a script which has been added to the VM.
4810class Script: public Struct {
4811 public:
4812 // Script types.
4813 enum Type {
4814 TYPE_NATIVE = 0,
4815 TYPE_EXTENSION = 1,
4816 TYPE_NORMAL = 2
4817 };
4818
4819 // Script compilation types.
4820 enum CompilationType {
4821 COMPILATION_TYPE_HOST = 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004822 COMPILATION_TYPE_EVAL = 1
Steve Blocka7e24c12009-10-30 11:49:00 +00004823 };
4824
4825 // [source]: the script source.
4826 DECL_ACCESSORS(source, Object)
4827
4828 // [name]: the script name.
4829 DECL_ACCESSORS(name, Object)
4830
4831 // [id]: the script id.
4832 DECL_ACCESSORS(id, Object)
4833
4834 // [line_offset]: script line offset in resource from where it was extracted.
4835 DECL_ACCESSORS(line_offset, Smi)
4836
4837 // [column_offset]: script column offset in resource from where it was
4838 // extracted.
4839 DECL_ACCESSORS(column_offset, Smi)
4840
4841 // [data]: additional data associated with this script.
4842 DECL_ACCESSORS(data, Object)
4843
4844 // [context_data]: context data for the context this script was compiled in.
4845 DECL_ACCESSORS(context_data, Object)
4846
4847 // [wrapper]: the wrapper cache.
Ben Murdoch257744e2011-11-30 15:57:28 +00004848 DECL_ACCESSORS(wrapper, Foreign)
Steve Blocka7e24c12009-10-30 11:49:00 +00004849
4850 // [type]: the script type.
4851 DECL_ACCESSORS(type, Smi)
4852
4853 // [compilation]: how the the script was compiled.
4854 DECL_ACCESSORS(compilation_type, Smi)
4855
Steve Blockd0582a62009-12-15 09:54:21 +00004856 // [line_ends]: FixedArray of line ends positions.
Steve Blocka7e24c12009-10-30 11:49:00 +00004857 DECL_ACCESSORS(line_ends, Object)
4858
Steve Blockd0582a62009-12-15 09:54:21 +00004859 // [eval_from_shared]: for eval scripts the shared funcion info for the
4860 // function from which eval was called.
4861 DECL_ACCESSORS(eval_from_shared, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00004862
4863 // [eval_from_instructions_offset]: the instruction offset in the code for the
4864 // function from which eval was called where eval was called.
4865 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
4866
4867 static inline Script* cast(Object* obj);
4868
Steve Block3ce2e202009-11-05 08:53:23 +00004869 // If script source is an external string, check that the underlying
4870 // resource is accessible. Otherwise, always return true.
4871 inline bool HasValidSource();
4872
Ben Murdochb0fe1622011-05-05 13:52:32 +01004873#ifdef OBJECT_PRINT
4874 inline void ScriptPrint() {
4875 ScriptPrint(stdout);
4876 }
4877 void ScriptPrint(FILE* out);
4878#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004879#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004880 void ScriptVerify();
4881#endif
4882
4883 static const int kSourceOffset = HeapObject::kHeaderSize;
4884 static const int kNameOffset = kSourceOffset + kPointerSize;
4885 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
4886 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
4887 static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
4888 static const int kContextOffset = kDataOffset + kPointerSize;
4889 static const int kWrapperOffset = kContextOffset + kPointerSize;
4890 static const int kTypeOffset = kWrapperOffset + kPointerSize;
4891 static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
4892 static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
4893 static const int kIdOffset = kLineEndsOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00004894 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004895 static const int kEvalFrominstructionsOffsetOffset =
Steve Blockd0582a62009-12-15 09:54:21 +00004896 kEvalFromSharedOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004897 static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
4898
4899 private:
4900 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
4901};
4902
4903
Ben Murdochb0fe1622011-05-05 13:52:32 +01004904// List of builtin functions we want to identify to improve code
4905// generation.
4906//
4907// Each entry has a name of a global object property holding an object
4908// optionally followed by ".prototype", a name of a builtin function
4909// on the object (the one the id is set for), and a label.
4910//
4911// Installation of ids for the selected builtin functions is handled
4912// by the bootstrapper.
4913//
4914// NOTE: Order is important: math functions should be at the end of
4915// the list and MathFloor should be the first math function.
4916#define FUNCTIONS_WITH_ID_LIST(V) \
4917 V(Array.prototype, push, ArrayPush) \
4918 V(Array.prototype, pop, ArrayPop) \
Ben Murdoch42effa52011-08-19 16:40:31 +01004919 V(Function.prototype, apply, FunctionApply) \
Ben Murdochb0fe1622011-05-05 13:52:32 +01004920 V(String.prototype, charCodeAt, StringCharCodeAt) \
4921 V(String.prototype, charAt, StringCharAt) \
4922 V(String, fromCharCode, StringFromCharCode) \
4923 V(Math, floor, MathFloor) \
4924 V(Math, round, MathRound) \
4925 V(Math, ceil, MathCeil) \
4926 V(Math, abs, MathAbs) \
4927 V(Math, log, MathLog) \
4928 V(Math, sin, MathSin) \
4929 V(Math, cos, MathCos) \
4930 V(Math, tan, MathTan) \
4931 V(Math, asin, MathASin) \
4932 V(Math, acos, MathACos) \
4933 V(Math, atan, MathATan) \
4934 V(Math, exp, MathExp) \
4935 V(Math, sqrt, MathSqrt) \
Ben Murdochc7cc0282012-03-05 14:35:55 +00004936 V(Math, pow, MathPow) \
4937 V(Math, random, MathRandom) \
4938 V(Math, max, MathMax) \
4939 V(Math, min, MathMin)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004940
4941
4942enum BuiltinFunctionId {
4943#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
4944 k##name,
4945 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
4946#undef DECLARE_FUNCTION_ID
4947 // Fake id for a special case of Math.pow. Note, it continues the
4948 // list of math functions.
4949 kMathPowHalf,
4950 kFirstMathFunctionId = kMathFloor
4951};
4952
4953
Steve Blocka7e24c12009-10-30 11:49:00 +00004954// SharedFunctionInfo describes the JSFunction information that can be
4955// shared by multiple instances of the function.
4956class SharedFunctionInfo: public HeapObject {
4957 public:
4958 // [name]: Function name.
4959 DECL_ACCESSORS(name, Object)
4960
4961 // [code]: Function code.
4962 DECL_ACCESSORS(code, Code)
4963
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004964 // [scope_info]: Scope info.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004965 DECL_ACCESSORS(scope_info, ScopeInfo)
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004966
Steve Blocka7e24c12009-10-30 11:49:00 +00004967 // [construct stub]: Code stub for constructing instances of this function.
4968 DECL_ACCESSORS(construct_stub, Code)
4969
Iain Merrick75681382010-08-19 15:07:18 +01004970 inline Code* unchecked_code();
4971
Steve Blocka7e24c12009-10-30 11:49:00 +00004972 // Returns if this function has been compiled to native code yet.
4973 inline bool is_compiled();
4974
4975 // [length]: The function length - usually the number of declared parameters.
4976 // Use up to 2^30 parameters.
4977 inline int length();
4978 inline void set_length(int value);
4979
4980 // [formal parameter count]: The declared number of parameters.
4981 inline int formal_parameter_count();
4982 inline void set_formal_parameter_count(int value);
4983
4984 // Set the formal parameter count so the function code will be
4985 // called without using argument adaptor frames.
4986 inline void DontAdaptArguments();
4987
4988 // [expected_nof_properties]: Expected number of properties for the function.
4989 inline int expected_nof_properties();
4990 inline void set_expected_nof_properties(int value);
4991
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004992 // Inobject slack tracking is the way to reclaim unused inobject space.
4993 //
4994 // The instance size is initially determined by adding some slack to
4995 // expected_nof_properties (to allow for a few extra properties added
4996 // after the constructor). There is no guarantee that the extra space
4997 // will not be wasted.
4998 //
4999 // Here is the algorithm to reclaim the unused inobject space:
5000 // - Detect the first constructor call for this SharedFunctionInfo.
5001 // When it happens enter the "in progress" state: remember the
5002 // constructor's initial_map and install a special construct stub that
5003 // counts constructor calls.
5004 // - While the tracking is in progress create objects filled with
5005 // one_pointer_filler_map instead of undefined_value. This way they can be
5006 // resized quickly and safely.
5007 // - Once enough (kGenerousAllocationCount) objects have been created
5008 // compute the 'slack' (traverse the map transition tree starting from the
5009 // initial_map and find the lowest value of unused_property_fields).
5010 // - Traverse the transition tree again and decrease the instance size
5011 // of every map. Existing objects will resize automatically (they are
5012 // filled with one_pointer_filler_map). All further allocations will
5013 // use the adjusted instance size.
5014 // - Decrease expected_nof_properties so that an allocations made from
5015 // another context will use the adjusted instance size too.
5016 // - Exit "in progress" state by clearing the reference to the initial_map
5017 // and setting the regular construct stub (generic or inline).
5018 //
5019 // The above is the main event sequence. Some special cases are possible
5020 // while the tracking is in progress:
5021 //
5022 // - GC occurs.
5023 // Check if the initial_map is referenced by any live objects (except this
5024 // SharedFunctionInfo). If it is, continue tracking as usual.
5025 // If it is not, clear the reference and reset the tracking state. The
5026 // tracking will be initiated again on the next constructor call.
5027 //
5028 // - The constructor is called from another context.
5029 // Immediately complete the tracking, perform all the necessary changes
5030 // to maps. This is necessary because there is no efficient way to track
5031 // multiple initial_maps.
5032 // Proceed to create an object in the current context (with the adjusted
5033 // size).
5034 //
5035 // - A different constructor function sharing the same SharedFunctionInfo is
5036 // called in the same context. This could be another closure in the same
5037 // context, or the first function could have been disposed.
5038 // This is handled the same way as the previous case.
5039 //
5040 // Important: inobject slack tracking is not attempted during the snapshot
5041 // creation.
5042
Ben Murdochf87a2032010-10-22 12:50:53 +01005043 static const int kGenerousAllocationCount = 8;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005044
5045 // [construction_count]: Counter for constructor calls made during
5046 // the tracking phase.
5047 inline int construction_count();
5048 inline void set_construction_count(int value);
5049
5050 // [initial_map]: initial map of the first function called as a constructor.
5051 // Saved for the duration of the tracking phase.
5052 // This is a weak link (GC resets it to undefined_value if no other live
5053 // object reference this map).
5054 DECL_ACCESSORS(initial_map, Object)
5055
5056 // True if the initial_map is not undefined and the countdown stub is
5057 // installed.
5058 inline bool IsInobjectSlackTrackingInProgress();
5059
5060 // Starts the tracking.
5061 // Stores the initial map and installs the countdown stub.
5062 // IsInobjectSlackTrackingInProgress is normally true after this call,
5063 // except when tracking have not been started (e.g. the map has no unused
5064 // properties or the snapshot is being built).
5065 void StartInobjectSlackTracking(Map* map);
5066
5067 // Completes the tracking.
5068 // IsInobjectSlackTrackingInProgress is false after this call.
5069 void CompleteInobjectSlackTracking();
5070
5071 // Clears the initial_map before the GC marking phase to ensure the reference
5072 // is weak. IsInobjectSlackTrackingInProgress is false after this call.
5073 void DetachInitialMap();
5074
5075 // Restores the link to the initial map after the GC marking phase.
5076 // IsInobjectSlackTrackingInProgress is true after this call.
5077 void AttachInitialMap(Map* map);
5078
5079 // False if there are definitely no live objects created from this function.
5080 // True if live objects _may_ exist (existence not guaranteed).
5081 // May go back from true to false after GC.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005082 DECL_BOOLEAN_ACCESSORS(live_objects_may_exist)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005083
Steve Blocka7e24c12009-10-30 11:49:00 +00005084 // [instance class name]: class name for instances.
5085 DECL_ACCESSORS(instance_class_name, Object)
5086
Steve Block6ded16b2010-05-10 14:33:55 +01005087 // [function data]: This field holds some additional data for function.
5088 // Currently it either has FunctionTemplateInfo to make benefit the API
Ben Murdochb0fe1622011-05-05 13:52:32 +01005089 // or Smi identifying a builtin function.
Steve Blocka7e24c12009-10-30 11:49:00 +00005090 // In the long run we don't want all functions to have this field but
5091 // we can fix that when we have a better model for storing hidden data
5092 // on objects.
5093 DECL_ACCESSORS(function_data, Object)
5094
Steve Block6ded16b2010-05-10 14:33:55 +01005095 inline bool IsApiFunction();
5096 inline FunctionTemplateInfo* get_api_func_data();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005097 inline bool HasBuiltinFunctionId();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005098 inline BuiltinFunctionId builtin_function_id();
Steve Block6ded16b2010-05-10 14:33:55 +01005099
Steve Blocka7e24c12009-10-30 11:49:00 +00005100 // [script info]: Script from which the function originates.
5101 DECL_ACCESSORS(script, Object)
5102
Steve Block6ded16b2010-05-10 14:33:55 +01005103 // [num_literals]: Number of literals used by this function.
5104 inline int num_literals();
5105 inline void set_num_literals(int value);
5106
Steve Blocka7e24c12009-10-30 11:49:00 +00005107 // [start_position_and_type]: Field used to store both the source code
5108 // position, whether or not the function is a function expression,
5109 // and whether or not the function is a toplevel function. The two
5110 // least significants bit indicates whether the function is an
5111 // expression and the rest contains the source code position.
5112 inline int start_position_and_type();
5113 inline void set_start_position_and_type(int value);
5114
5115 // [debug info]: Debug information.
5116 DECL_ACCESSORS(debug_info, Object)
5117
5118 // [inferred name]: Name inferred from variable or property
5119 // assignment of this function. Used to facilitate debugging and
5120 // profiling of JavaScript code written in OO style, where almost
5121 // all functions are anonymous but are assigned to object
5122 // properties.
5123 DECL_ACCESSORS(inferred_name, String)
5124
Ben Murdochf87a2032010-10-22 12:50:53 +01005125 // The function's name if it is non-empty, otherwise the inferred name.
5126 String* DebugName();
5127
Steve Blocka7e24c12009-10-30 11:49:00 +00005128 // Position of the 'function' token in the script source.
5129 inline int function_token_position();
5130 inline void set_function_token_position(int function_token_position);
5131
5132 // Position of this function in the script source.
5133 inline int start_position();
5134 inline void set_start_position(int start_position);
5135
5136 // End position of this function in the script source.
5137 inline int end_position();
5138 inline void set_end_position(int end_position);
5139
5140 // Is this function a function expression in the source code.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005141 DECL_BOOLEAN_ACCESSORS(is_expression)
Steve Blocka7e24c12009-10-30 11:49:00 +00005142
5143 // Is this function a top-level function (scripts, evals).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005144 DECL_BOOLEAN_ACCESSORS(is_toplevel)
Steve Blocka7e24c12009-10-30 11:49:00 +00005145
5146 // Bit field containing various information collected by the compiler to
5147 // drive optimization.
5148 inline int compiler_hints();
5149 inline void set_compiler_hints(int value);
5150
Ben Murdochb0fe1622011-05-05 13:52:32 +01005151 // A counter used to determine when to stress the deoptimizer with a
5152 // deopt.
5153 inline Smi* deopt_counter();
5154 inline void set_deopt_counter(Smi* counter);
5155
Steve Blocka7e24c12009-10-30 11:49:00 +00005156 // Add information on assignments of the form this.x = ...;
5157 void SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +00005158 bool has_only_simple_this_property_assignments,
5159 FixedArray* this_property_assignments);
5160
5161 // Clear information on assignments of the form this.x = ...;
5162 void ClearThisPropertyAssignmentsInfo();
5163
5164 // Indicate that this function only consists of assignments of the form
Steve Blocka7e24c12009-10-30 11:49:00 +00005165 // this.x = y; where y is either a constant or refers to an argument.
5166 inline bool has_only_simple_this_property_assignments();
5167
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005168 // Indicates if this function can be lazy compiled.
5169 // This is used to determine if we can safely flush code from a function
5170 // when doing GC if we expect that the function will no longer be used.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005171 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005172
Iain Merrick75681382010-08-19 15:07:18 +01005173 // Indicates how many full GCs this function has survived with assigned
5174 // code object. Used to determine when it is relatively safe to flush
5175 // this code object and replace it with lazy compilation stub.
5176 // Age is reset when GC notices that the code object is referenced
5177 // from the stack or compilation cache.
5178 inline int code_age();
5179 inline void set_code_age(int age);
5180
Ben Murdochb0fe1622011-05-05 13:52:32 +01005181 // Indicates whether optimizations have been disabled for this
5182 // shared function info. If a function is repeatedly optimized or if
5183 // we cannot optimize the function we disable optimization to avoid
5184 // spending time attempting to optimize it again.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005185 DECL_BOOLEAN_ACCESSORS(optimization_disabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01005186
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005187 // Indicates the language mode of the function's code as defined by the
5188 // current harmony drafts for the next ES language standard. Possible
5189 // values are:
5190 // 1. CLASSIC_MODE - Unrestricted syntax and semantics, same as in ES5.
5191 // 2. STRICT_MODE - Restricted syntax and semantics, same as in ES5.
5192 // 3. EXTENDED_MODE - Only available under the harmony flag, not part of ES5.
5193 inline LanguageMode language_mode();
5194 inline void set_language_mode(LanguageMode language_mode);
5195
5196 // Indicates whether the language mode of this function is CLASSIC_MODE.
5197 inline bool is_classic_mode();
5198
5199 // Indicates whether the language mode of this function is EXTENDED_MODE.
5200 inline bool is_extended_mode();
Steve Block1e0659c2011-05-24 12:43:12 +01005201
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005202 // False if the function definitely does not allocate an arguments object.
5203 DECL_BOOLEAN_ACCESSORS(uses_arguments)
5204
5205 // True if the function has any duplicated parameter names.
5206 DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters)
5207
5208 // Indicates whether the function is a native function.
Ben Murdoch589d6972011-11-30 16:04:58 +00005209 // These needs special treatment in .call and .apply since
Ben Murdoch257744e2011-11-30 15:57:28 +00005210 // null passed as the receiver should not be translated to the
5211 // global object.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005212 DECL_BOOLEAN_ACCESSORS(native)
5213
5214 // Indicates that the function was created by the Function function.
5215 // Though it's anonymous, toString should treat it as if it had the name
5216 // "anonymous". We don't set the name itself so that the system does not
5217 // see a binding for it.
5218 DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
5219
5220 // Indicates whether the function is a bound function created using
5221 // the bind function.
5222 DECL_BOOLEAN_ACCESSORS(bound)
5223
5224 // Indicates that the function is anonymous (the name field can be set
5225 // through the API, which does not change this flag).
5226 DECL_BOOLEAN_ACCESSORS(is_anonymous)
Ben Murdoch257744e2011-11-30 15:57:28 +00005227
Ben Murdochb0fe1622011-05-05 13:52:32 +01005228 // Indicates whether or not the code in the shared function support
5229 // deoptimization.
5230 inline bool has_deoptimization_support();
5231
5232 // Enable deoptimization support through recompiled code.
5233 void EnableDeoptimizationSupport(Code* recompiled);
5234
Ben Murdoch257744e2011-11-30 15:57:28 +00005235 // Disable (further) attempted optimization of all functions sharing this
5236 // shared function info. The function is the one we actually tried to
5237 // optimize.
5238 void DisableOptimization(JSFunction* function);
5239
Ben Murdochb0fe1622011-05-05 13:52:32 +01005240 // Lookup the bailout ID and ASSERT that it exists in the non-optimized
5241 // code, returns whether it asserted (i.e., always true if assertions are
5242 // disabled).
5243 bool VerifyBailoutId(int id);
Iain Merrick75681382010-08-19 15:07:18 +01005244
Andrei Popescu402d9372010-02-26 13:31:12 +00005245 // Check whether a inlined constructor can be generated with the given
5246 // prototype.
5247 bool CanGenerateInlineConstructor(Object* prototype);
5248
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005249 // Prevents further attempts to generate inline constructors.
5250 // To be called if generation failed for any reason.
5251 void ForbidInlineConstructor();
5252
Steve Blocka7e24c12009-10-30 11:49:00 +00005253 // For functions which only contains this property assignments this provides
5254 // access to the names for the properties assigned.
5255 DECL_ACCESSORS(this_property_assignments, Object)
5256 inline int this_property_assignments_count();
5257 inline void set_this_property_assignments_count(int value);
5258 String* GetThisPropertyAssignmentName(int index);
5259 bool IsThisPropertyAssignmentArgument(int index);
5260 int GetThisPropertyAssignmentArgument(int index);
5261 Object* GetThisPropertyAssignmentConstant(int index);
5262
5263 // [source code]: Source code for the function.
5264 bool HasSourceCode();
5265 Object* GetSourceCode();
5266
Ben Murdochb0fe1622011-05-05 13:52:32 +01005267 inline int opt_count();
5268 inline void set_opt_count(int opt_count);
5269
5270 // Source size of this function.
5271 int SourceSize();
5272
Steve Blocka7e24c12009-10-30 11:49:00 +00005273 // Calculate the instance size.
5274 int CalculateInstanceSize();
5275
5276 // Calculate the number of in-object properties.
5277 int CalculateInObjectProperties();
5278
5279 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00005280 // Set max_length to -1 for unlimited length.
5281 void SourceCodePrint(StringStream* accumulator, int max_length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005282#ifdef OBJECT_PRINT
5283 inline void SharedFunctionInfoPrint() {
5284 SharedFunctionInfoPrint(stdout);
5285 }
5286 void SharedFunctionInfoPrint(FILE* out);
5287#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005288#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005289 void SharedFunctionInfoVerify();
5290#endif
5291
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005292 // Helpers to compile the shared code. Returns true on success, false on
5293 // failure (e.g., stack overflow during compilation).
5294 static bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
5295 ClearExceptionFlag flag);
5296 static bool CompileLazy(Handle<SharedFunctionInfo> shared,
5297 ClearExceptionFlag flag);
5298
Steve Blocka7e24c12009-10-30 11:49:00 +00005299 // Casting.
5300 static inline SharedFunctionInfo* cast(Object* obj);
5301
5302 // Constants.
5303 static const int kDontAdaptArgumentsSentinel = -1;
5304
5305 // Layout description.
Steve Block6ded16b2010-05-10 14:33:55 +01005306 // Pointer fields.
Steve Blocka7e24c12009-10-30 11:49:00 +00005307 static const int kNameOffset = HeapObject::kHeaderSize;
5308 static const int kCodeOffset = kNameOffset + kPointerSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005309 static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
5310 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005311 static const int kInstanceClassNameOffset =
5312 kConstructStubOffset + kPointerSize;
5313 static const int kFunctionDataOffset =
5314 kInstanceClassNameOffset + kPointerSize;
5315 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
5316 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
5317 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005318 static const int kInitialMapOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01005319 kInferredNameOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005320 static const int kThisPropertyAssignmentsOffset =
5321 kInitialMapOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005322 static const int kDeoptCounterOffset =
5323 kThisPropertyAssignmentsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005324#if V8_HOST_ARCH_32_BIT
5325 // Smi fields.
Steve Block6ded16b2010-05-10 14:33:55 +01005326 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01005327 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005328 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
5329 static const int kExpectedNofPropertiesOffset =
5330 kFormalParameterCountOffset + kPointerSize;
5331 static const int kNumLiteralsOffset =
5332 kExpectedNofPropertiesOffset + kPointerSize;
5333 static const int kStartPositionAndTypeOffset =
5334 kNumLiteralsOffset + kPointerSize;
5335 static const int kEndPositionOffset =
5336 kStartPositionAndTypeOffset + kPointerSize;
5337 static const int kFunctionTokenPositionOffset =
5338 kEndPositionOffset + kPointerSize;
5339 static const int kCompilerHintsOffset =
5340 kFunctionTokenPositionOffset + kPointerSize;
5341 static const int kThisPropertyAssignmentsCountOffset =
5342 kCompilerHintsOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005343 static const int kOptCountOffset =
5344 kThisPropertyAssignmentsCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005345 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005346 static const int kSize = kOptCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005347#else
5348 // The only reason to use smi fields instead of int fields
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005349 // is to allow iteration without maps decoding during
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005350 // garbage collections.
5351 // To avoid wasting space on 64-bit architectures we use
5352 // the following trick: we group integer fields into pairs
5353 // First integer in each pair is shifted left by 1.
5354 // By doing this we guarantee that LSB of each kPointerSize aligned
5355 // word is not set and thus this word cannot be treated as pointer
5356 // to HeapObject during old space traversal.
5357 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01005358 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005359 static const int kFormalParameterCountOffset =
5360 kLengthOffset + kIntSize;
5361
Steve Blocka7e24c12009-10-30 11:49:00 +00005362 static const int kExpectedNofPropertiesOffset =
5363 kFormalParameterCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005364 static const int kNumLiteralsOffset =
5365 kExpectedNofPropertiesOffset + kIntSize;
5366
5367 static const int kEndPositionOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01005368 kNumLiteralsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005369 static const int kStartPositionAndTypeOffset =
5370 kEndPositionOffset + kIntSize;
5371
5372 static const int kFunctionTokenPositionOffset =
5373 kStartPositionAndTypeOffset + kIntSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005374 static const int kCompilerHintsOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00005375 kFunctionTokenPositionOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005376
Steve Blocka7e24c12009-10-30 11:49:00 +00005377 static const int kThisPropertyAssignmentsCountOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01005378 kCompilerHintsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005379 static const int kOptCountOffset =
5380 kThisPropertyAssignmentsCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005381
Steve Block6ded16b2010-05-10 14:33:55 +01005382 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005383 static const int kSize = kOptCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005384
5385#endif
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005386
5387 // The construction counter for inobject slack tracking is stored in the
5388 // most significant byte of compiler_hints which is otherwise unused.
5389 // Its offset depends on the endian-ness of the architecture.
5390#if __BYTE_ORDER == __LITTLE_ENDIAN
5391 static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
5392#elif __BYTE_ORDER == __BIG_ENDIAN
5393 static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
5394#else
5395#error Unknown byte ordering
5396#endif
5397
Steve Block6ded16b2010-05-10 14:33:55 +01005398 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005399
Iain Merrick75681382010-08-19 15:07:18 +01005400 typedef FixedBodyDescriptor<kNameOffset,
5401 kThisPropertyAssignmentsOffset + kPointerSize,
5402 kSize> BodyDescriptor;
5403
Steve Blocka7e24c12009-10-30 11:49:00 +00005404 // Bit positions in start_position_and_type.
5405 // The source code start position is in the 30 most significant bits of
5406 // the start_position_and_type field.
5407 static const int kIsExpressionBit = 0;
5408 static const int kIsTopLevelBit = 1;
5409 static const int kStartPositionShift = 2;
5410 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
5411
5412 // Bit positions in compiler_hints.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005413 static const int kCodeAgeSize = 3;
5414 static const int kCodeAgeMask = (1 << kCodeAgeSize) - 1;
5415
5416 enum CompilerHints {
5417 kHasOnlySimpleThisPropertyAssignments,
5418 kAllowLazyCompilation,
5419 kLiveObjectsMayExist,
5420 kCodeAgeShift,
5421 kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
5422 kStrictModeFunction,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005423 kExtendedModeFunction,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005424 kUsesArguments,
5425 kHasDuplicateParameters,
5426 kNative,
5427 kBoundFunction,
5428 kIsAnonymous,
5429 kNameShouldPrintAsAnonymous,
5430 kCompilerHintsCount // Pseudo entry
5431 };
Steve Blocka7e24c12009-10-30 11:49:00 +00005432
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005433 private:
5434#if V8_HOST_ARCH_32_BIT
5435 // On 32 bit platforms, compiler hints is a smi.
5436 static const int kCompilerHintsSmiTagSize = kSmiTagSize;
5437 static const int kCompilerHintsSize = kPointerSize;
5438#else
5439 // On 64 bit platforms, compiler hints is not a smi, see comment above.
5440 static const int kCompilerHintsSmiTagSize = 0;
5441 static const int kCompilerHintsSize = kIntSize;
5442#endif
5443
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005444 STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <=
5445 SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte);
5446
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005447 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00005448 // Constants for optimizing codegen for strict mode function and
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005449 // native tests.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005450 // Allows to use byte-width instructions.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005451 static const int kStrictModeBitWithinByte =
5452 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
5453
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005454 static const int kExtendedModeBitWithinByte =
5455 (kExtendedModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
5456
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005457 static const int kNativeBitWithinByte =
5458 (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
Ben Murdoch257744e2011-11-30 15:57:28 +00005459
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005460#if __BYTE_ORDER == __LITTLE_ENDIAN
5461 static const int kStrictModeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00005462 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005463 static const int kExtendedModeByteOffset = kCompilerHintsOffset +
5464 (kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005465 static const int kNativeByteOffset = kCompilerHintsOffset +
5466 (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005467#elif __BYTE_ORDER == __BIG_ENDIAN
5468 static const int kStrictModeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00005469 (kCompilerHintsSize - 1) -
5470 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005471 static const int kExtendedModeByteOffset = kCompilerHintsOffset +
5472 (kCompilerHintsSize - 1) -
5473 ((kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005474 static const int kNativeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00005475 (kCompilerHintsSize - 1) -
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005476 ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005477#else
5478#error Unknown byte ordering
5479#endif
5480
5481 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00005482 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
5483};
5484
5485
5486// JSFunction describes JavaScript functions.
5487class JSFunction: public JSObject {
5488 public:
5489 // [prototype_or_initial_map]:
5490 DECL_ACCESSORS(prototype_or_initial_map, Object)
5491
Ben Murdoch589d6972011-11-30 16:04:58 +00005492 // [shared]: The information about the function that
Steve Blocka7e24c12009-10-30 11:49:00 +00005493 // can be shared by instances.
5494 DECL_ACCESSORS(shared, SharedFunctionInfo)
5495
Iain Merrick75681382010-08-19 15:07:18 +01005496 inline SharedFunctionInfo* unchecked_shared();
5497
Steve Blocka7e24c12009-10-30 11:49:00 +00005498 // [context]: The context for this function.
5499 inline Context* context();
5500 inline Object* unchecked_context();
5501 inline void set_context(Object* context);
5502
5503 // [code]: The generated code object for this function. Executed
5504 // when the function is invoked, e.g. foo() or new foo(). See
5505 // [[Call]] and [[Construct]] description in ECMA-262, section
5506 // 8.6.2, page 27.
5507 inline Code* code();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005508 inline void set_code(Code* code);
5509 inline void ReplaceCode(Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00005510
Iain Merrick75681382010-08-19 15:07:18 +01005511 inline Code* unchecked_code();
5512
Steve Blocka7e24c12009-10-30 11:49:00 +00005513 // Tells whether this function is builtin.
5514 inline bool IsBuiltin();
5515
Ben Murdochb0fe1622011-05-05 13:52:32 +01005516 // Tells whether or not the function needs arguments adaption.
5517 inline bool NeedsArgumentsAdaption();
5518
5519 // Tells whether or not this function has been optimized.
5520 inline bool IsOptimized();
5521
Ben Murdoch8b112d22011-06-08 16:22:53 +01005522 // Tells whether or not this function can be optimized.
5523 inline bool IsOptimizable();
5524
Ben Murdochb0fe1622011-05-05 13:52:32 +01005525 // Mark this function for lazy recompilation. The function will be
5526 // recompiled the next time it is executed.
5527 void MarkForLazyRecompilation();
5528
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005529 // Helpers to compile this function. Returns true on success, false on
5530 // failure (e.g., stack overflow during compilation).
5531 static bool CompileLazy(Handle<JSFunction> function,
5532 ClearExceptionFlag flag);
5533 static bool CompileOptimized(Handle<JSFunction> function,
5534 int osr_ast_id,
5535 ClearExceptionFlag flag);
5536
Ben Murdochb0fe1622011-05-05 13:52:32 +01005537 // Tells whether or not the function is already marked for lazy
5538 // recompilation.
5539 inline bool IsMarkedForLazyRecompilation();
5540
Ben Murdochb0fe1622011-05-05 13:52:32 +01005541 // Check whether or not this function is inlineable.
5542 bool IsInlineable();
5543
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005544 // [literals_or_bindings]: Fixed array holding either
5545 // the materialized literals or the bindings of a bound function.
Steve Blocka7e24c12009-10-30 11:49:00 +00005546 //
5547 // If the function contains object, regexp or array literals, the
5548 // literals array prefix contains the object, regexp, and array
5549 // function to be used when creating these literals. This is
5550 // necessary so that we do not dynamically lookup the object, regexp
5551 // or array functions. Performing a dynamic lookup, we might end up
5552 // using the functions from a new context that we should not have
5553 // access to.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005554 //
5555 // On bound functions, the array is a (copy-on-write) fixed-array containing
5556 // the function that was bound, bound this-value and any bound
5557 // arguments. Bound functions never contain literals.
5558 DECL_ACCESSORS(literals_or_bindings, FixedArray)
5559
5560 inline FixedArray* literals();
5561 inline void set_literals(FixedArray* literals);
5562
5563 inline FixedArray* function_bindings();
5564 inline void set_function_bindings(FixedArray* bindings);
Steve Blocka7e24c12009-10-30 11:49:00 +00005565
5566 // The initial map for an object created by this constructor.
5567 inline Map* initial_map();
5568 inline void set_initial_map(Map* value);
5569 inline bool has_initial_map();
5570
5571 // Get and set the prototype property on a JSFunction. If the
5572 // function has an initial map the prototype is set on the initial
5573 // map. Otherwise, the prototype is put in the initial map field
5574 // until an initial map is needed.
5575 inline bool has_prototype();
5576 inline bool has_instance_prototype();
5577 inline Object* prototype();
5578 inline Object* instance_prototype();
5579 Object* SetInstancePrototype(Object* value);
John Reck59135872010-11-02 12:39:01 -07005580 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005581
Steve Block6ded16b2010-05-10 14:33:55 +01005582 // After prototype is removed, it will not be created when accessed, and
5583 // [[Construct]] from this function will not be allowed.
5584 Object* RemovePrototype();
5585 inline bool should_have_prototype();
5586
Steve Blocka7e24c12009-10-30 11:49:00 +00005587 // Accessor for this function's initial map's [[class]]
5588 // property. This is primarily used by ECMA native functions. This
5589 // method sets the class_name field of this function's initial map
5590 // to a given value. It creates an initial map if this function does
5591 // not have one. Note that this method does not copy the initial map
5592 // if it has one already, but simply replaces it with the new value.
5593 // Instances created afterwards will have a map whose [[class]] is
5594 // set to 'value', but there is no guarantees on instances created
5595 // before.
5596 Object* SetInstanceClassName(String* name);
5597
5598 // Returns if this function has been compiled to native code yet.
5599 inline bool is_compiled();
5600
Ben Murdochb0fe1622011-05-05 13:52:32 +01005601 // [next_function_link]: Field for linking functions. This list is treated as
5602 // a weak list by the GC.
5603 DECL_ACCESSORS(next_function_link, Object)
5604
5605 // Prints the name of the function using PrintF.
5606 inline void PrintName() {
5607 PrintName(stdout);
5608 }
5609 void PrintName(FILE* out);
5610
Steve Blocka7e24c12009-10-30 11:49:00 +00005611 // Casting.
5612 static inline JSFunction* cast(Object* obj);
5613
Steve Block791712a2010-08-27 10:21:07 +01005614 // Iterates the objects, including code objects indirectly referenced
5615 // through pointers to the first instruction in the code object.
5616 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
5617
Steve Blocka7e24c12009-10-30 11:49:00 +00005618 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005619#ifdef OBJECT_PRINT
5620 inline void JSFunctionPrint() {
5621 JSFunctionPrint(stdout);
5622 }
5623 void JSFunctionPrint(FILE* out);
5624#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005625#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005626 void JSFunctionVerify();
5627#endif
5628
5629 // Returns the number of allocated literals.
5630 inline int NumberOfLiterals();
5631
5632 // Retrieve the global context from a function's literal array.
5633 static Context* GlobalContextFromLiterals(FixedArray* literals);
5634
Ben Murdochb0fe1622011-05-05 13:52:32 +01005635 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
5636 // kSize) is weak and has special handling during garbage collection.
Steve Block791712a2010-08-27 10:21:07 +01005637 static const int kCodeEntryOffset = JSObject::kHeaderSize;
Iain Merrick75681382010-08-19 15:07:18 +01005638 static const int kPrototypeOrInitialMapOffset =
Steve Block791712a2010-08-27 10:21:07 +01005639 kCodeEntryOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005640 static const int kSharedFunctionInfoOffset =
5641 kPrototypeOrInitialMapOffset + kPointerSize;
5642 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
5643 static const int kLiteralsOffset = kContextOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005644 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
5645 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
5646 static const int kSize = kNextFunctionLinkOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005647
5648 // Layout of the literals array.
5649 static const int kLiteralsPrefixSize = 1;
5650 static const int kLiteralGlobalContextIndex = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005651
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005652 // Layout of the bound-function binding array.
5653 static const int kBoundFunctionIndex = 0;
5654 static const int kBoundThisIndex = 1;
5655 static const int kBoundArgumentsStartIndex = 2;
5656
Steve Blocka7e24c12009-10-30 11:49:00 +00005657 private:
5658 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
5659};
5660
5661
5662// JSGlobalProxy's prototype must be a JSGlobalObject or null,
5663// and the prototype is hidden. JSGlobalProxy always delegates
5664// property accesses to its prototype if the prototype is not null.
5665//
5666// A JSGlobalProxy can be reinitialized which will preserve its identity.
5667//
5668// Accessing a JSGlobalProxy requires security check.
5669
5670class JSGlobalProxy : public JSObject {
5671 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00005672 // [context]: the owner global context of this global proxy object.
Steve Blocka7e24c12009-10-30 11:49:00 +00005673 // It is null value if this object is not used by any context.
5674 DECL_ACCESSORS(context, Object)
5675
5676 // Casting.
5677 static inline JSGlobalProxy* cast(Object* obj);
5678
5679 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005680#ifdef OBJECT_PRINT
5681 inline void JSGlobalProxyPrint() {
5682 JSGlobalProxyPrint(stdout);
5683 }
5684 void JSGlobalProxyPrint(FILE* out);
5685#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005686#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005687 void JSGlobalProxyVerify();
5688#endif
5689
5690 // Layout description.
5691 static const int kContextOffset = JSObject::kHeaderSize;
5692 static const int kSize = kContextOffset + kPointerSize;
5693
5694 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00005695 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
5696};
5697
5698
5699// Forward declaration.
5700class JSBuiltinsObject;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005701class JSGlobalPropertyCell;
Steve Blocka7e24c12009-10-30 11:49:00 +00005702
5703// Common super class for JavaScript global objects and the special
5704// builtins global objects.
5705class GlobalObject: public JSObject {
5706 public:
5707 // [builtins]: the object holding the runtime routines written in JS.
5708 DECL_ACCESSORS(builtins, JSBuiltinsObject)
5709
5710 // [global context]: the global context corresponding to this global object.
5711 DECL_ACCESSORS(global_context, Context)
5712
5713 // [global receiver]: the global receiver object of the context
5714 DECL_ACCESSORS(global_receiver, JSObject)
5715
5716 // Retrieve the property cell used to store a property.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005717 JSGlobalPropertyCell* GetPropertyCell(LookupResult* result);
Steve Blocka7e24c12009-10-30 11:49:00 +00005718
John Reck59135872010-11-02 12:39:01 -07005719 // This is like GetProperty, but is used when you know the lookup won't fail
5720 // by throwing an exception. This is for the debug and builtins global
5721 // objects, where it is known which properties can be expected to be present
5722 // on the object.
5723 Object* GetPropertyNoExceptionThrown(String* key) {
5724 Object* answer = GetProperty(key)->ToObjectUnchecked();
5725 return answer;
5726 }
5727
Steve Blocka7e24c12009-10-30 11:49:00 +00005728 // Ensure that the global object has a cell for the given property name.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005729 static Handle<JSGlobalPropertyCell> EnsurePropertyCell(
5730 Handle<GlobalObject> global,
5731 Handle<String> name);
5732 // TODO(kmillikin): This function can be eliminated once the stub cache is
5733 // full handlified (and the static helper can be written directly).
John Reck59135872010-11-02 12:39:01 -07005734 MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00005735
5736 // Casting.
5737 static inline GlobalObject* cast(Object* obj);
5738
5739 // Layout description.
5740 static const int kBuiltinsOffset = JSObject::kHeaderSize;
5741 static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
5742 static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
5743 static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
5744
5745 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00005746 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
5747};
5748
5749
5750// JavaScript global object.
5751class JSGlobalObject: public GlobalObject {
5752 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00005753 // Casting.
5754 static inline JSGlobalObject* cast(Object* obj);
5755
5756 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005757#ifdef OBJECT_PRINT
5758 inline void JSGlobalObjectPrint() {
5759 JSGlobalObjectPrint(stdout);
5760 }
5761 void JSGlobalObjectPrint(FILE* out);
5762#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005763#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005764 void JSGlobalObjectVerify();
5765#endif
5766
5767 // Layout description.
5768 static const int kSize = GlobalObject::kHeaderSize;
5769
5770 private:
5771 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
5772};
5773
5774
5775// Builtins global object which holds the runtime routines written in
5776// JavaScript.
5777class JSBuiltinsObject: public GlobalObject {
5778 public:
5779 // Accessors for the runtime routines written in JavaScript.
5780 inline Object* javascript_builtin(Builtins::JavaScript id);
5781 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
5782
Steve Block6ded16b2010-05-10 14:33:55 +01005783 // Accessors for code of the runtime routines written in JavaScript.
5784 inline Code* javascript_builtin_code(Builtins::JavaScript id);
5785 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
5786
Steve Blocka7e24c12009-10-30 11:49:00 +00005787 // Casting.
5788 static inline JSBuiltinsObject* cast(Object* obj);
5789
5790 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005791#ifdef OBJECT_PRINT
5792 inline void JSBuiltinsObjectPrint() {
5793 JSBuiltinsObjectPrint(stdout);
5794 }
5795 void JSBuiltinsObjectPrint(FILE* out);
5796#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005797#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005798 void JSBuiltinsObjectVerify();
5799#endif
5800
5801 // Layout description. The size of the builtins object includes
Steve Block6ded16b2010-05-10 14:33:55 +01005802 // room for two pointers per runtime routine written in javascript
5803 // (function and code object).
Steve Blocka7e24c12009-10-30 11:49:00 +00005804 static const int kJSBuiltinsCount = Builtins::id_count;
5805 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005806 static const int kJSBuiltinsCodeOffset =
5807 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005808 static const int kSize =
Steve Block6ded16b2010-05-10 14:33:55 +01005809 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
5810
5811 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
5812 return kJSBuiltinsOffset + id * kPointerSize;
5813 }
5814
5815 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
5816 return kJSBuiltinsCodeOffset + id * kPointerSize;
5817 }
5818
Steve Blocka7e24c12009-10-30 11:49:00 +00005819 private:
5820 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
5821};
5822
5823
5824// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
5825class JSValue: public JSObject {
5826 public:
5827 // [value]: the object being wrapped.
5828 DECL_ACCESSORS(value, Object)
5829
5830 // Casting.
5831 static inline JSValue* cast(Object* obj);
5832
5833 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005834#ifdef OBJECT_PRINT
5835 inline void JSValuePrint() {
5836 JSValuePrint(stdout);
5837 }
5838 void JSValuePrint(FILE* out);
5839#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005840#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005841 void JSValueVerify();
5842#endif
5843
5844 // Layout description.
5845 static const int kValueOffset = JSObject::kHeaderSize;
5846 static const int kSize = kValueOffset + kPointerSize;
5847
5848 private:
5849 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
5850};
5851
Steve Block1e0659c2011-05-24 12:43:12 +01005852
5853// Representation of message objects used for error reporting through
5854// the API. The messages are formatted in JavaScript so this object is
5855// a real JavaScript object. The information used for formatting the
5856// error messages are not directly accessible from JavaScript to
5857// prevent leaking information to user code called during error
5858// formatting.
5859class JSMessageObject: public JSObject {
5860 public:
5861 // [type]: the type of error message.
5862 DECL_ACCESSORS(type, String)
5863
5864 // [arguments]: the arguments for formatting the error message.
5865 DECL_ACCESSORS(arguments, JSArray)
5866
5867 // [script]: the script from which the error message originated.
5868 DECL_ACCESSORS(script, Object)
5869
5870 // [stack_trace]: the stack trace for this error message.
5871 DECL_ACCESSORS(stack_trace, Object)
5872
5873 // [stack_frames]: an array of stack frames for this error object.
5874 DECL_ACCESSORS(stack_frames, Object)
5875
5876 // [start_position]: the start position in the script for the error message.
5877 inline int start_position();
5878 inline void set_start_position(int value);
5879
5880 // [end_position]: the end position in the script for the error message.
5881 inline int end_position();
5882 inline void set_end_position(int value);
5883
5884 // Casting.
5885 static inline JSMessageObject* cast(Object* obj);
5886
5887 // Dispatched behavior.
5888#ifdef OBJECT_PRINT
5889 inline void JSMessageObjectPrint() {
5890 JSMessageObjectPrint(stdout);
5891 }
5892 void JSMessageObjectPrint(FILE* out);
5893#endif
5894#ifdef DEBUG
5895 void JSMessageObjectVerify();
5896#endif
5897
5898 // Layout description.
5899 static const int kTypeOffset = JSObject::kHeaderSize;
5900 static const int kArgumentsOffset = kTypeOffset + kPointerSize;
5901 static const int kScriptOffset = kArgumentsOffset + kPointerSize;
5902 static const int kStackTraceOffset = kScriptOffset + kPointerSize;
5903 static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
5904 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
5905 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
5906 static const int kSize = kEndPositionOffset + kPointerSize;
5907
5908 typedef FixedBodyDescriptor<HeapObject::kMapOffset,
5909 kStackFramesOffset + kPointerSize,
5910 kSize> BodyDescriptor;
5911};
5912
5913
Steve Blocka7e24c12009-10-30 11:49:00 +00005914// Regular expressions
5915// The regular expression holds a single reference to a FixedArray in
5916// the kDataOffset field.
5917// The FixedArray contains the following data:
5918// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
5919// - reference to the original source string
5920// - reference to the original flag string
5921// If it is an atom regexp
5922// - a reference to a literal string to search for
5923// If it is an irregexp regexp:
Ben Murdoch257744e2011-11-30 15:57:28 +00005924// - a reference to code for ASCII inputs (bytecode or compiled), or a smi
5925// used for tracking the last usage (used for code flushing).
5926// - a reference to code for UC16 inputs (bytecode or compiled), or a smi
5927// used for tracking the last usage (used for code flushing)..
Steve Blocka7e24c12009-10-30 11:49:00 +00005928// - max number of registers used by irregexp implementations.
5929// - number of capture registers (output values) of the regexp.
5930class JSRegExp: public JSObject {
5931 public:
5932 // Meaning of Type:
5933 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
5934 // ATOM: A simple string to match against using an indexOf operation.
5935 // IRREGEXP: Compiled with Irregexp.
5936 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
5937 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
5938 enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
5939
5940 class Flags {
5941 public:
5942 explicit Flags(uint32_t value) : value_(value) { }
5943 bool is_global() { return (value_ & GLOBAL) != 0; }
5944 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
5945 bool is_multiline() { return (value_ & MULTILINE) != 0; }
5946 uint32_t value() { return value_; }
5947 private:
5948 uint32_t value_;
5949 };
5950
5951 DECL_ACCESSORS(data, Object)
5952
5953 inline Type TypeTag();
5954 inline int CaptureCount();
5955 inline Flags GetFlags();
5956 inline String* Pattern();
5957 inline Object* DataAt(int index);
5958 // Set implementation data after the object has been prepared.
5959 inline void SetDataAt(int index, Object* value);
Ben Murdoch257744e2011-11-30 15:57:28 +00005960
5961 // Used during GC when flushing code or setting age.
5962 inline Object* DataAtUnchecked(int index);
5963 inline void SetDataAtUnchecked(int index, Object* value, Heap* heap);
5964 inline Type TypeTagUnchecked();
5965
Steve Blocka7e24c12009-10-30 11:49:00 +00005966 static int code_index(bool is_ascii) {
5967 if (is_ascii) {
5968 return kIrregexpASCIICodeIndex;
5969 } else {
5970 return kIrregexpUC16CodeIndex;
5971 }
5972 }
5973
Ben Murdoch257744e2011-11-30 15:57:28 +00005974 static int saved_code_index(bool is_ascii) {
5975 if (is_ascii) {
5976 return kIrregexpASCIICodeSavedIndex;
5977 } else {
5978 return kIrregexpUC16CodeSavedIndex;
5979 }
5980 }
5981
Steve Blocka7e24c12009-10-30 11:49:00 +00005982 static inline JSRegExp* cast(Object* obj);
5983
5984 // Dispatched behavior.
5985#ifdef DEBUG
5986 void JSRegExpVerify();
5987#endif
5988
5989 static const int kDataOffset = JSObject::kHeaderSize;
5990 static const int kSize = kDataOffset + kPointerSize;
5991
5992 // Indices in the data array.
5993 static const int kTagIndex = 0;
5994 static const int kSourceIndex = kTagIndex + 1;
5995 static const int kFlagsIndex = kSourceIndex + 1;
5996 static const int kDataIndex = kFlagsIndex + 1;
5997 // The data fields are used in different ways depending on the
5998 // value of the tag.
5999 // Atom regexps (literal strings).
6000 static const int kAtomPatternIndex = kDataIndex;
6001
6002 static const int kAtomDataSize = kAtomPatternIndex + 1;
6003
6004 // Irregexp compiled code or bytecode for ASCII. If compilation
6005 // fails, this fields hold an exception object that should be
6006 // thrown if the regexp is used again.
6007 static const int kIrregexpASCIICodeIndex = kDataIndex;
6008 // Irregexp compiled code or bytecode for UC16. If compilation
6009 // fails, this fields hold an exception object that should be
6010 // thrown if the regexp is used again.
6011 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
Ben Murdoch257744e2011-11-30 15:57:28 +00006012
6013 // Saved instance of Irregexp compiled code or bytecode for ASCII that
6014 // is a potential candidate for flushing.
6015 static const int kIrregexpASCIICodeSavedIndex = kDataIndex + 2;
6016 // Saved instance of Irregexp compiled code or bytecode for UC16 that is
6017 // a potential candidate for flushing.
6018 static const int kIrregexpUC16CodeSavedIndex = kDataIndex + 3;
6019
Steve Blocka7e24c12009-10-30 11:49:00 +00006020 // Maximal number of registers used by either ASCII or UC16.
6021 // Only used to check that there is enough stack space
Ben Murdoch257744e2011-11-30 15:57:28 +00006022 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4;
Steve Blocka7e24c12009-10-30 11:49:00 +00006023 // Number of captures in the compiled regexp.
Ben Murdoch257744e2011-11-30 15:57:28 +00006024 static const int kIrregexpCaptureCountIndex = kDataIndex + 5;
Steve Blocka7e24c12009-10-30 11:49:00 +00006025
6026 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
Leon Clarkee46be812010-01-19 14:06:41 +00006027
6028 // Offsets directly into the data fixed array.
6029 static const int kDataTagOffset =
6030 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
6031 static const int kDataAsciiCodeOffset =
6032 FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +00006033 static const int kDataUC16CodeOffset =
6034 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00006035 static const int kIrregexpCaptureCountOffset =
6036 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01006037
6038 // In-object fields.
6039 static const int kSourceFieldIndex = 0;
6040 static const int kGlobalFieldIndex = 1;
6041 static const int kIgnoreCaseFieldIndex = 2;
6042 static const int kMultilineFieldIndex = 3;
6043 static const int kLastIndexFieldIndex = 4;
Ben Murdochbb769b22010-08-11 14:56:33 +01006044 static const int kInObjectFieldCount = 5;
Ben Murdoch257744e2011-11-30 15:57:28 +00006045
6046 // The uninitialized value for a regexp code object.
6047 static const int kUninitializedValue = -1;
6048
6049 // The compilation error value for the regexp code object. The real error
6050 // object is in the saved code field.
6051 static const int kCompilationErrorValue = -2;
6052
6053 // When we store the sweep generation at which we moved the code from the
6054 // code index to the saved code index we mask it of to be in the [0:255]
6055 // range.
6056 static const int kCodeAgeMask = 0xff;
Steve Blocka7e24c12009-10-30 11:49:00 +00006057};
6058
6059
Ben Murdochc7cc0282012-03-05 14:35:55 +00006060class CompilationCacheShape : public BaseShape<HashTableKey*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00006061 public:
6062 static inline bool IsMatch(HashTableKey* key, Object* value) {
6063 return key->IsMatch(value);
6064 }
6065
6066 static inline uint32_t Hash(HashTableKey* key) {
6067 return key->Hash();
6068 }
6069
6070 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
6071 return key->HashForObject(object);
6072 }
6073
John Reck59135872010-11-02 12:39:01 -07006074 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006075 return key->AsObject();
6076 }
6077
6078 static const int kPrefixSize = 0;
6079 static const int kEntrySize = 2;
6080};
6081
Steve Block3ce2e202009-11-05 08:53:23 +00006082
Steve Blocka7e24c12009-10-30 11:49:00 +00006083class CompilationCacheTable: public HashTable<CompilationCacheShape,
6084 HashTableKey*> {
6085 public:
6086 // Find cached value for a string key, otherwise return null.
6087 Object* Lookup(String* src);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006088 Object* LookupEval(String* src,
6089 Context* context,
6090 LanguageMode language_mode,
6091 int scope_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00006092 Object* LookupRegExp(String* source, JSRegExp::Flags flags);
John Reck59135872010-11-02 12:39:01 -07006093 MaybeObject* Put(String* src, Object* value);
Steve Block1e0659c2011-05-24 12:43:12 +01006094 MaybeObject* PutEval(String* src,
6095 Context* context,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006096 SharedFunctionInfo* value,
6097 int scope_position);
John Reck59135872010-11-02 12:39:01 -07006098 MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006099
Ben Murdochb0fe1622011-05-05 13:52:32 +01006100 // Remove given value from cache.
6101 void Remove(Object* value);
6102
Steve Blocka7e24c12009-10-30 11:49:00 +00006103 static inline CompilationCacheTable* cast(Object* obj);
6104
6105 private:
6106 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
6107};
6108
6109
Steve Block6ded16b2010-05-10 14:33:55 +01006110class CodeCache: public Struct {
6111 public:
6112 DECL_ACCESSORS(default_cache, FixedArray)
6113 DECL_ACCESSORS(normal_type_cache, Object)
6114
6115 // Add the code object to the cache.
John Reck59135872010-11-02 12:39:01 -07006116 MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01006117
6118 // Lookup code object in the cache. Returns code object if found and undefined
6119 // if not.
6120 Object* Lookup(String* name, Code::Flags flags);
6121
6122 // Get the internal index of a code object in the cache. Returns -1 if the
6123 // code object is not in that cache. This index can be used to later call
6124 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
6125 // RemoveByIndex.
6126 int GetIndex(Object* name, Code* code);
6127
6128 // Remove an object from the cache with the provided internal index.
6129 void RemoveByIndex(Object* name, Code* code, int index);
6130
6131 static inline CodeCache* cast(Object* obj);
6132
Ben Murdochb0fe1622011-05-05 13:52:32 +01006133#ifdef OBJECT_PRINT
6134 inline void CodeCachePrint() {
6135 CodeCachePrint(stdout);
6136 }
6137 void CodeCachePrint(FILE* out);
6138#endif
Steve Block6ded16b2010-05-10 14:33:55 +01006139#ifdef DEBUG
Steve Block6ded16b2010-05-10 14:33:55 +01006140 void CodeCacheVerify();
6141#endif
6142
6143 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
6144 static const int kNormalTypeCacheOffset =
6145 kDefaultCacheOffset + kPointerSize;
6146 static const int kSize = kNormalTypeCacheOffset + kPointerSize;
6147
6148 private:
John Reck59135872010-11-02 12:39:01 -07006149 MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
6150 MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01006151 Object* LookupDefaultCache(String* name, Code::Flags flags);
6152 Object* LookupNormalTypeCache(String* name, Code::Flags flags);
6153
6154 // Code cache layout of the default cache. Elements are alternating name and
6155 // code objects for non normal load/store/call IC's.
6156 static const int kCodeCacheEntrySize = 2;
6157 static const int kCodeCacheEntryNameOffset = 0;
6158 static const int kCodeCacheEntryCodeOffset = 1;
6159
6160 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
6161};
6162
6163
Ben Murdochc7cc0282012-03-05 14:35:55 +00006164class CodeCacheHashTableShape : public BaseShape<HashTableKey*> {
Steve Block6ded16b2010-05-10 14:33:55 +01006165 public:
6166 static inline bool IsMatch(HashTableKey* key, Object* value) {
6167 return key->IsMatch(value);
6168 }
6169
6170 static inline uint32_t Hash(HashTableKey* key) {
6171 return key->Hash();
6172 }
6173
6174 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
6175 return key->HashForObject(object);
6176 }
6177
John Reck59135872010-11-02 12:39:01 -07006178 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Block6ded16b2010-05-10 14:33:55 +01006179 return key->AsObject();
6180 }
6181
6182 static const int kPrefixSize = 0;
6183 static const int kEntrySize = 2;
6184};
6185
6186
6187class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
6188 HashTableKey*> {
6189 public:
6190 Object* Lookup(String* name, Code::Flags flags);
John Reck59135872010-11-02 12:39:01 -07006191 MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01006192
6193 int GetIndex(String* name, Code::Flags flags);
6194 void RemoveByIndex(int index);
6195
6196 static inline CodeCacheHashTable* cast(Object* obj);
6197
6198 // Initial size of the fixed array backing the hash table.
6199 static const int kInitialSize = 64;
6200
6201 private:
6202 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
6203};
6204
6205
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006206class PolymorphicCodeCache: public Struct {
6207 public:
6208 DECL_ACCESSORS(cache, Object)
6209
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006210 static void Update(Handle<PolymorphicCodeCache> cache,
6211 MapHandleList* maps,
6212 Code::Flags flags,
6213 Handle<Code> code);
6214
6215 MUST_USE_RESULT MaybeObject* Update(MapHandleList* maps,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006216 Code::Flags flags,
6217 Code* code);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006218
6219 // Returns an undefined value if the entry is not found.
6220 Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006221
6222 static inline PolymorphicCodeCache* cast(Object* obj);
6223
6224#ifdef OBJECT_PRINT
6225 inline void PolymorphicCodeCachePrint() {
6226 PolymorphicCodeCachePrint(stdout);
6227 }
6228 void PolymorphicCodeCachePrint(FILE* out);
6229#endif
6230#ifdef DEBUG
6231 void PolymorphicCodeCacheVerify();
6232#endif
6233
6234 static const int kCacheOffset = HeapObject::kHeaderSize;
6235 static const int kSize = kCacheOffset + kPointerSize;
6236
6237 private:
6238 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache);
6239};
6240
6241
6242class PolymorphicCodeCacheHashTable
6243 : public HashTable<CodeCacheHashTableShape, HashTableKey*> {
6244 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006245 Object* Lookup(MapHandleList* maps, int code_kind);
6246
6247 MUST_USE_RESULT MaybeObject* Put(MapHandleList* maps,
6248 int code_kind,
6249 Code* code);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006250
6251 static inline PolymorphicCodeCacheHashTable* cast(Object* obj);
6252
6253 static const int kInitialSize = 64;
6254 private:
6255 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable);
6256};
6257
6258
Steve Blocka7e24c12009-10-30 11:49:00 +00006259enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
6260enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
6261
6262
6263class StringHasher {
6264 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +00006265 explicit inline StringHasher(int length, uint32_t seed);
Steve Blocka7e24c12009-10-30 11:49:00 +00006266
6267 // Returns true if the hash of this string can be computed without
6268 // looking at the contents.
6269 inline bool has_trivial_hash();
6270
6271 // Add a character to the hash and update the array index calculation.
6272 inline void AddCharacter(uc32 c);
6273
6274 // Adds a character to the hash but does not update the array index
6275 // calculation. This can only be called when it has been verified
6276 // that the input is not an array index.
6277 inline void AddCharacterNoIndex(uc32 c);
6278
6279 // Returns the value to store in the hash field of a string with
6280 // the given length and contents.
6281 uint32_t GetHashField();
6282
6283 // Returns true if the characters seen so far make up a legal array
6284 // index.
6285 bool is_array_index() { return is_array_index_; }
6286
6287 bool is_valid() { return is_valid_; }
6288
6289 void invalidate() { is_valid_ = false; }
6290
Kristian Monsen80d68ea2010-09-08 11:05:35 +01006291 // Calculated hash value for a string consisting of 1 to
6292 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
6293 // value is represented decimal value.
Iain Merrick9ac36c92010-09-13 15:29:50 +01006294 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01006295
Ben Murdochc7cc0282012-03-05 14:35:55 +00006296 // No string is allowed to have a hash of zero. That value is reserved
6297 // for internal properties. If the hash calculation yields zero then we
6298 // use 27 instead.
6299 static const int kZeroHash = 27;
6300
Steve Blocka7e24c12009-10-30 11:49:00 +00006301 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00006302 uint32_t array_index() {
6303 ASSERT(is_array_index());
6304 return array_index_;
6305 }
6306
6307 inline uint32_t GetHash();
6308
6309 int length_;
6310 uint32_t raw_running_hash_;
6311 uint32_t array_index_;
6312 bool is_array_index_;
6313 bool is_first_char_;
6314 bool is_valid_;
Steve Blockd0582a62009-12-15 09:54:21 +00006315 friend class TwoCharHashTableKey;
Steve Blocka7e24c12009-10-30 11:49:00 +00006316};
6317
6318
Steve Block44f0eee2011-05-26 01:26:41 +01006319// Calculates string hash.
6320template <typename schar>
Ben Murdochc7cc0282012-03-05 14:35:55 +00006321inline uint32_t HashSequentialString(const schar* chars,
6322 int length,
6323 uint32_t seed);
Steve Block44f0eee2011-05-26 01:26:41 +01006324
6325
Steve Blocka7e24c12009-10-30 11:49:00 +00006326// The characteristics of a string are stored in its map. Retrieving these
6327// few bits of information is moderately expensive, involving two memory
6328// loads where the second is dependent on the first. To improve efficiency
6329// the shape of the string is given its own class so that it can be retrieved
6330// once and used for several string operations. A StringShape is small enough
6331// to be passed by value and is immutable, but be aware that flattening a
6332// string can potentially alter its shape. Also be aware that a GC caused by
6333// something else can alter the shape of a string due to ConsString
6334// shortcutting. Keeping these restrictions in mind has proven to be error-
6335// prone and so we no longer put StringShapes in variables unless there is a
6336// concrete performance benefit at that particular point in the code.
6337class StringShape BASE_EMBEDDED {
6338 public:
6339 inline explicit StringShape(String* s);
6340 inline explicit StringShape(Map* s);
6341 inline explicit StringShape(InstanceType t);
6342 inline bool IsSequential();
6343 inline bool IsExternal();
6344 inline bool IsCons();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006345 inline bool IsSliced();
6346 inline bool IsIndirect();
Steve Blocka7e24c12009-10-30 11:49:00 +00006347 inline bool IsExternalAscii();
6348 inline bool IsExternalTwoByte();
6349 inline bool IsSequentialAscii();
6350 inline bool IsSequentialTwoByte();
6351 inline bool IsSymbol();
6352 inline StringRepresentationTag representation_tag();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006353 inline uint32_t encoding_tag();
Steve Blocka7e24c12009-10-30 11:49:00 +00006354 inline uint32_t full_representation_tag();
6355 inline uint32_t size_tag();
6356#ifdef DEBUG
6357 inline uint32_t type() { return type_; }
6358 inline void invalidate() { valid_ = false; }
6359 inline bool valid() { return valid_; }
6360#else
6361 inline void invalidate() { }
6362#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006363
Steve Blocka7e24c12009-10-30 11:49:00 +00006364 private:
6365 uint32_t type_;
6366#ifdef DEBUG
6367 inline void set_valid() { valid_ = true; }
6368 bool valid_;
6369#else
6370 inline void set_valid() { }
6371#endif
6372};
6373
6374
6375// The String abstract class captures JavaScript string values:
6376//
6377// Ecma-262:
6378// 4.3.16 String Value
6379// A string value is a member of the type String and is a finite
6380// ordered sequence of zero or more 16-bit unsigned integer values.
6381//
6382// All string values have a length field.
6383class String: public HeapObject {
6384 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006385 // Representation of the flat content of a String.
6386 // A non-flat string doesn't have flat content.
6387 // A flat string has content that's encoded as a sequence of either
6388 // ASCII chars or two-byte UC16.
6389 // Returned by String::GetFlatContent().
6390 class FlatContent {
6391 public:
6392 // Returns true if the string is flat and this structure contains content.
6393 bool IsFlat() { return state_ != NON_FLAT; }
6394 // Returns true if the structure contains ASCII content.
6395 bool IsAscii() { return state_ == ASCII; }
6396 // Returns true if the structure contains two-byte content.
6397 bool IsTwoByte() { return state_ == TWO_BYTE; }
6398
6399 // Return the ASCII content of the string. Only use if IsAscii() returns
6400 // true.
6401 Vector<const char> ToAsciiVector() {
6402 ASSERT_EQ(ASCII, state_);
6403 return Vector<const char>::cast(buffer_);
6404 }
6405 // Return the two-byte content of the string. Only use if IsTwoByte()
6406 // returns true.
6407 Vector<const uc16> ToUC16Vector() {
6408 ASSERT_EQ(TWO_BYTE, state_);
6409 return Vector<const uc16>::cast(buffer_);
6410 }
6411
6412 private:
6413 enum State { NON_FLAT, ASCII, TWO_BYTE };
6414
6415 // Constructors only used by String::GetFlatContent().
6416 explicit FlatContent(Vector<const char> chars)
6417 : buffer_(Vector<const byte>::cast(chars)),
6418 state_(ASCII) { }
6419 explicit FlatContent(Vector<const uc16> chars)
6420 : buffer_(Vector<const byte>::cast(chars)),
6421 state_(TWO_BYTE) { }
6422 FlatContent() : buffer_(), state_(NON_FLAT) { }
6423
6424 Vector<const byte> buffer_;
6425 State state_;
6426
6427 friend class String;
6428 };
6429
Steve Blocka7e24c12009-10-30 11:49:00 +00006430 // Get and set the length of the string.
6431 inline int length();
6432 inline void set_length(int value);
6433
Steve Blockd0582a62009-12-15 09:54:21 +00006434 // Get and set the hash field of the string.
6435 inline uint32_t hash_field();
6436 inline void set_hash_field(uint32_t value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006437
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006438 // Returns whether this string has only ASCII chars, i.e. all of them can
6439 // be ASCII encoded. This might be the case even if the string is
6440 // two-byte. Such strings may appear when the embedder prefers
6441 // two-byte external representations even for ASCII data.
Steve Blocka7e24c12009-10-30 11:49:00 +00006442 inline bool IsAsciiRepresentation();
6443 inline bool IsTwoByteRepresentation();
6444
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006445 // Cons and slices have an encoding flag that may not represent the actual
6446 // encoding of the underlying string. This is taken into account here.
6447 // Requires: this->IsFlat()
6448 inline bool IsAsciiRepresentationUnderneath();
6449 inline bool IsTwoByteRepresentationUnderneath();
6450
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01006451 // NOTE: this should be considered only a hint. False negatives are
6452 // possible.
6453 inline bool HasOnlyAsciiChars();
Steve Block6ded16b2010-05-10 14:33:55 +01006454
Steve Blocka7e24c12009-10-30 11:49:00 +00006455 // Get and set individual two byte chars in the string.
6456 inline void Set(int index, uint16_t value);
6457 // Get individual two byte char in the string. Repeated calls
6458 // to this method are not efficient unless the string is flat.
6459 inline uint16_t Get(int index);
6460
Leon Clarkef7060e22010-06-03 12:02:55 +01006461 // Try to flatten the string. Checks first inline to see if it is
6462 // necessary. Does nothing if the string is not a cons string.
6463 // Flattening allocates a sequential string with the same data as
6464 // the given string and mutates the cons string to a degenerate
6465 // form, where the first component is the new sequential string and
6466 // the second component is the empty string. If allocation fails,
6467 // this function returns a failure. If flattening succeeds, this
6468 // function returns the sequential string that is now the first
6469 // component of the cons string.
6470 //
6471 // Degenerate cons strings are handled specially by the garbage
6472 // collector (see IsShortcutCandidate).
6473 //
6474 // Use FlattenString from Handles.cc to flatten even in case an
6475 // allocation failure happens.
John Reck59135872010-11-02 12:39:01 -07006476 inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00006477
Leon Clarkef7060e22010-06-03 12:02:55 +01006478 // Convenience function. Has exactly the same behavior as
6479 // TryFlatten(), except in the case of failure returns the original
6480 // string.
6481 inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
6482
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006483 // Tries to return the content of a flat string as a structure holding either
6484 // a flat vector of char or of uc16.
6485 // If the string isn't flat, and therefore doesn't have flat content, the
6486 // returned structure will report so, and can't provide a vector of either
6487 // kind.
6488 FlatContent GetFlatContent();
6489
6490 // Returns the parent of a sliced string or first part of a flat cons string.
6491 // Requires: StringShape(this).IsIndirect() && this->IsFlat()
6492 inline String* GetUnderlying();
Steve Blocka7e24c12009-10-30 11:49:00 +00006493
6494 // Mark the string as an undetectable object. It only applies to
Ben Murdochc7cc0282012-03-05 14:35:55 +00006495 // ASCII and two byte string types.
Steve Blocka7e24c12009-10-30 11:49:00 +00006496 bool MarkAsUndetectable();
6497
Steve Blockd0582a62009-12-15 09:54:21 +00006498 // Return a substring.
John Reck59135872010-11-02 12:39:01 -07006499 MUST_USE_RESULT MaybeObject* SubString(int from,
6500 int to,
6501 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00006502
6503 // String equality operations.
6504 inline bool Equals(String* other);
6505 bool IsEqualTo(Vector<const char> str);
Steve Block9fac8402011-05-12 15:51:54 +01006506 bool IsAsciiEqualTo(Vector<const char> str);
6507 bool IsTwoByteEqualTo(Vector<const uc16> str);
Steve Blocka7e24c12009-10-30 11:49:00 +00006508
6509 // Return a UTF8 representation of the string. The string is null
6510 // terminated but may optionally contain nulls. Length is returned
6511 // in length_output if length_output is not a null pointer The string
6512 // should be nearly flat, otherwise the performance of this method may
6513 // be very slow (quadratic in the length). Setting robustness_flag to
6514 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
6515 // handles unexpected data without causing assert failures and it does not
6516 // do any heap allocations. This is useful when printing stack traces.
Ben Murdoch589d6972011-11-30 16:04:58 +00006517 SmartArrayPointer<char> ToCString(AllowNullsFlag allow_nulls,
6518 RobustnessFlag robustness_flag,
6519 int offset,
6520 int length,
6521 int* length_output = 0);
6522 SmartArrayPointer<char> ToCString(
Steve Blocka7e24c12009-10-30 11:49:00 +00006523 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
6524 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
6525 int* length_output = 0);
6526
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006527 inline int Utf8Length() { return Utf8Length(this, 0, length()); }
6528 static int Utf8Length(String* input, int from, int to);
Steve Blocka7e24c12009-10-30 11:49:00 +00006529
6530 // Return a 16 bit Unicode representation of the string.
6531 // The string should be nearly flat, otherwise the performance of
6532 // of this method may be very bad. Setting robustness_flag to
6533 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
6534 // handles unexpected data without causing assert failures and it does not
6535 // do any heap allocations. This is useful when printing stack traces.
Ben Murdoch589d6972011-11-30 16:04:58 +00006536 SmartArrayPointer<uc16> ToWideCString(
Steve Blocka7e24c12009-10-30 11:49:00 +00006537 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
6538
6539 // Tells whether the hash code has been computed.
6540 inline bool HasHashCode();
6541
6542 // Returns a hash value used for the property table
6543 inline uint32_t Hash();
6544
Steve Blockd0582a62009-12-15 09:54:21 +00006545 static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
Ben Murdochc7cc0282012-03-05 14:35:55 +00006546 int length,
6547 uint32_t seed);
Steve Blocka7e24c12009-10-30 11:49:00 +00006548
6549 static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
6550 uint32_t* index,
6551 int length);
6552
6553 // Externalization.
6554 bool MakeExternal(v8::String::ExternalStringResource* resource);
6555 bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
6556
6557 // Conversion.
6558 inline bool AsArrayIndex(uint32_t* index);
6559
6560 // Casting.
6561 static inline String* cast(Object* obj);
6562
6563 void PrintOn(FILE* out);
6564
6565 // For use during stack traces. Performs rudimentary sanity check.
6566 bool LooksValid();
6567
6568 // Dispatched behavior.
6569 void StringShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01006570#ifdef OBJECT_PRINT
6571 inline void StringPrint() {
6572 StringPrint(stdout);
6573 }
6574 void StringPrint(FILE* out);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006575
6576 char* ToAsciiArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01006577#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006578#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006579 void StringVerify();
6580#endif
6581 inline bool IsFlat();
6582
6583 // Layout description.
6584 static const int kLengthOffset = HeapObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01006585 static const int kHashFieldOffset = kLengthOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006586 static const int kSize = kHashFieldOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006587
Steve Blockd0582a62009-12-15 09:54:21 +00006588 // Maximum number of characters to consider when trying to convert a string
6589 // value into an array index.
Steve Blocka7e24c12009-10-30 11:49:00 +00006590 static const int kMaxArrayIndexSize = 10;
6591
Ben Murdochc7cc0282012-03-05 14:35:55 +00006592 // Max ASCII char code.
Steve Blocka7e24c12009-10-30 11:49:00 +00006593 static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
6594 static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
6595 static const int kMaxUC16CharCode = 0xffff;
6596
Steve Blocka7e24c12009-10-30 11:49:00 +00006597 // Mask constant for checking if a string has a computed hash code
6598 // and if it is an array index. The least significant bit indicates
6599 // whether a hash code has been computed. If the hash code has been
6600 // computed the 2nd bit tells whether the string can be used as an
6601 // array index.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006602 static const int kHashNotComputedMask = 1;
6603 static const int kIsNotArrayIndexMask = 1 << 1;
6604 static const int kNofHashBitFields = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +00006605
Steve Blockd0582a62009-12-15 09:54:21 +00006606 // Shift constant retrieving hash code from hash field.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006607 static const int kHashShift = kNofHashBitFields;
Steve Blockd0582a62009-12-15 09:54:21 +00006608
Ben Murdochc7cc0282012-03-05 14:35:55 +00006609 // Only these bits are relevant in the hash, since the top two are shifted
6610 // out.
6611 static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift;
6612
Steve Blocka7e24c12009-10-30 11:49:00 +00006613 // Array index strings this short can keep their index in the hash
6614 // field.
6615 static const int kMaxCachedArrayIndexLength = 7;
6616
Steve Blockd0582a62009-12-15 09:54:21 +00006617 // For strings which are array indexes the hash value has the string length
6618 // mixed into the hash, mainly to avoid a hash value of zero which would be
6619 // the case for the string '0'. 24 bits are used for the array index value.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006620 static const int kArrayIndexValueBits = 24;
6621 static const int kArrayIndexLengthBits =
6622 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
6623
6624 STATIC_CHECK((kArrayIndexLengthBits > 0));
Iain Merrick9ac36c92010-09-13 15:29:50 +01006625 STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006626
6627 static const int kArrayIndexHashLengthShift =
6628 kArrayIndexValueBits + kNofHashBitFields;
6629
Steve Blockd0582a62009-12-15 09:54:21 +00006630 static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006631
6632 static const int kArrayIndexValueMask =
6633 ((1 << kArrayIndexValueBits) - 1) << kHashShift;
6634
6635 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
6636 // could use a mask to test if the length of string is less than or equal to
6637 // kMaxCachedArrayIndexLength.
6638 STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
6639
6640 static const int kContainsCachedArrayIndexMask =
6641 (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
6642 kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00006643
6644 // Value of empty hash field indicating that the hash is not computed.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006645 static const int kEmptyHashField =
6646 kIsNotArrayIndexMask | kHashNotComputedMask;
6647
6648 // Value of hash field containing computed hash equal to zero.
6649 static const int kZeroHash = kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00006650
6651 // Maximal string length.
6652 static const int kMaxLength = (1 << (32 - 2)) - 1;
6653
6654 // Max length for computing hash. For strings longer than this limit the
6655 // string length is used as the hash value.
6656 static const int kMaxHashCalcLength = 16383;
Steve Blocka7e24c12009-10-30 11:49:00 +00006657
6658 // Limit for truncation in short printing.
6659 static const int kMaxShortPrintLength = 1024;
6660
6661 // Support for regular expressions.
6662 const uc16* GetTwoByteData();
6663 const uc16* GetTwoByteData(unsigned start);
6664
6665 // Support for StringInputBuffer
6666 static const unibrow::byte* ReadBlock(String* input,
6667 unibrow::byte* util_buffer,
6668 unsigned capacity,
6669 unsigned* remaining,
6670 unsigned* offset);
6671 static const unibrow::byte* ReadBlock(String** input,
6672 unibrow::byte* util_buffer,
6673 unsigned capacity,
6674 unsigned* remaining,
6675 unsigned* offset);
6676
6677 // Helper function for flattening strings.
6678 template <typename sinkchar>
6679 static void WriteToFlat(String* source,
6680 sinkchar* sink,
6681 int from,
6682 int to);
6683
Steve Block9fac8402011-05-12 15:51:54 +01006684 static inline bool IsAscii(const char* chars, int length) {
6685 const char* limit = chars + length;
6686#ifdef V8_HOST_CAN_READ_UNALIGNED
6687 ASSERT(kMaxAsciiCharCode == 0x7F);
6688 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
6689 while (chars <= limit - sizeof(uintptr_t)) {
6690 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
6691 return false;
6692 }
6693 chars += sizeof(uintptr_t);
6694 }
6695#endif
6696 while (chars < limit) {
6697 if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
6698 ++chars;
6699 }
6700 return true;
6701 }
6702
6703 static inline bool IsAscii(const uc16* chars, int length) {
6704 const uc16* limit = chars + length;
6705 while (chars < limit) {
6706 if (*chars > kMaxAsciiCharCodeU) return false;
6707 ++chars;
6708 }
6709 return true;
6710 }
6711
Steve Blocka7e24c12009-10-30 11:49:00 +00006712 protected:
6713 class ReadBlockBuffer {
6714 public:
6715 ReadBlockBuffer(unibrow::byte* util_buffer_,
6716 unsigned cursor_,
6717 unsigned capacity_,
6718 unsigned remaining_) :
6719 util_buffer(util_buffer_),
6720 cursor(cursor_),
6721 capacity(capacity_),
6722 remaining(remaining_) {
6723 }
6724 unibrow::byte* util_buffer;
6725 unsigned cursor;
6726 unsigned capacity;
6727 unsigned remaining;
6728 };
6729
Steve Blocka7e24c12009-10-30 11:49:00 +00006730 static inline const unibrow::byte* ReadBlock(String* input,
6731 ReadBlockBuffer* buffer,
6732 unsigned* offset,
6733 unsigned max_chars);
6734 static void ReadBlockIntoBuffer(String* input,
6735 ReadBlockBuffer* buffer,
6736 unsigned* offset_ptr,
6737 unsigned max_chars);
6738
6739 private:
Leon Clarkef7060e22010-06-03 12:02:55 +01006740 // Try to flatten the top level ConsString that is hiding behind this
6741 // string. This is a no-op unless the string is a ConsString. Flatten
6742 // mutates the ConsString and might return a failure.
John Reck59135872010-11-02 12:39:01 -07006743 MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
Leon Clarkef7060e22010-06-03 12:02:55 +01006744
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006745 static inline bool IsHashFieldComputed(uint32_t field);
6746
Steve Blocka7e24c12009-10-30 11:49:00 +00006747 // Slow case of String::Equals. This implementation works on any strings
6748 // but it is most efficient on strings that are almost flat.
6749 bool SlowEquals(String* other);
6750
6751 // Slow case of AsArrayIndex.
6752 bool SlowAsArrayIndex(uint32_t* index);
6753
6754 // Compute and set the hash code.
6755 uint32_t ComputeAndSetHash();
6756
6757 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
6758};
6759
6760
6761// The SeqString abstract class captures sequential string values.
6762class SeqString: public String {
6763 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00006764 // Casting.
6765 static inline SeqString* cast(Object* obj);
6766
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006767 // Layout description.
6768 static const int kHeaderSize = String::kSize;
6769
Steve Blocka7e24c12009-10-30 11:49:00 +00006770 private:
6771 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
6772};
6773
6774
Ben Murdochc7cc0282012-03-05 14:35:55 +00006775// The AsciiString class captures sequential ASCII string objects.
6776// Each character in the AsciiString is an ASCII character.
Steve Blocka7e24c12009-10-30 11:49:00 +00006777class SeqAsciiString: public SeqString {
6778 public:
Leon Clarkeac952652010-07-15 11:15:24 +01006779 static const bool kHasAsciiEncoding = true;
6780
Steve Blocka7e24c12009-10-30 11:49:00 +00006781 // Dispatched behavior.
6782 inline uint16_t SeqAsciiStringGet(int index);
6783 inline void SeqAsciiStringSet(int index, uint16_t value);
6784
6785 // Get the address of the characters in this string.
6786 inline Address GetCharsAddress();
6787
6788 inline char* GetChars();
6789
6790 // Casting
6791 static inline SeqAsciiString* cast(Object* obj);
6792
6793 // Garbage collection support. This method is called by the
6794 // garbage collector to compute the actual size of an AsciiString
6795 // instance.
6796 inline int SeqAsciiStringSize(InstanceType instance_type);
6797
6798 // Computes the size for an AsciiString instance of a given length.
6799 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006800 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00006801 }
6802
Leon Clarkee46be812010-01-19 14:06:41 +00006803 // Maximal memory usage for a single sequential ASCII string.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006804 static const int kMaxSize = 512 * MB - 1;
Leon Clarkee46be812010-01-19 14:06:41 +00006805 // Maximal length of a single sequential ASCII string.
6806 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
6807 static const int kMaxLength = (kMaxSize - kHeaderSize);
6808
Steve Blocka7e24c12009-10-30 11:49:00 +00006809 // Support for StringInputBuffer.
6810 inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6811 unsigned* offset,
6812 unsigned chars);
6813 inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
6814 unsigned* offset,
6815 unsigned chars);
6816
6817 private:
6818 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
6819};
6820
6821
6822// The TwoByteString class captures sequential unicode string objects.
6823// Each character in the TwoByteString is a two-byte uint16_t.
6824class SeqTwoByteString: public SeqString {
6825 public:
Leon Clarkeac952652010-07-15 11:15:24 +01006826 static const bool kHasAsciiEncoding = false;
6827
Steve Blocka7e24c12009-10-30 11:49:00 +00006828 // Dispatched behavior.
6829 inline uint16_t SeqTwoByteStringGet(int index);
6830 inline void SeqTwoByteStringSet(int index, uint16_t value);
6831
6832 // Get the address of the characters in this string.
6833 inline Address GetCharsAddress();
6834
6835 inline uc16* GetChars();
6836
6837 // For regexp code.
6838 const uint16_t* SeqTwoByteStringGetData(unsigned start);
6839
6840 // Casting
6841 static inline SeqTwoByteString* cast(Object* obj);
6842
6843 // Garbage collection support. This method is called by the
6844 // garbage collector to compute the actual size of a TwoByteString
6845 // instance.
6846 inline int SeqTwoByteStringSize(InstanceType instance_type);
6847
6848 // Computes the size for a TwoByteString instance of a given length.
6849 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006850 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00006851 }
6852
Leon Clarkee46be812010-01-19 14:06:41 +00006853 // Maximal memory usage for a single sequential two-byte string.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006854 static const int kMaxSize = 512 * MB - 1;
Leon Clarkee46be812010-01-19 14:06:41 +00006855 // Maximal length of a single sequential two-byte string.
6856 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
6857 static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
6858
Steve Blocka7e24c12009-10-30 11:49:00 +00006859 // Support for StringInputBuffer.
6860 inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6861 unsigned* offset_ptr,
6862 unsigned chars);
6863
6864 private:
6865 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
6866};
6867
6868
6869// The ConsString class describes string values built by using the
6870// addition operator on strings. A ConsString is a pair where the
6871// first and second components are pointers to other string values.
6872// One or both components of a ConsString can be pointers to other
6873// ConsStrings, creating a binary tree of ConsStrings where the leaves
6874// are non-ConsString string values. The string value represented by
6875// a ConsString can be obtained by concatenating the leaf string
6876// values in a left-to-right depth-first traversal of the tree.
6877class ConsString: public String {
6878 public:
6879 // First string of the cons cell.
6880 inline String* first();
6881 // Doesn't check that the result is a string, even in debug mode. This is
6882 // useful during GC where the mark bits confuse the checks.
6883 inline Object* unchecked_first();
6884 inline void set_first(String* first,
6885 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
6886
6887 // Second string of the cons cell.
6888 inline String* second();
6889 // Doesn't check that the result is a string, even in debug mode. This is
6890 // useful during GC where the mark bits confuse the checks.
6891 inline Object* unchecked_second();
6892 inline void set_second(String* second,
6893 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
6894
6895 // Dispatched behavior.
6896 uint16_t ConsStringGet(int index);
6897
6898 // Casting.
6899 static inline ConsString* cast(Object* obj);
6900
Steve Blocka7e24c12009-10-30 11:49:00 +00006901 // Layout description.
6902 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
6903 static const int kSecondOffset = kFirstOffset + kPointerSize;
6904 static const int kSize = kSecondOffset + kPointerSize;
6905
6906 // Support for StringInputBuffer.
6907 inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
6908 unsigned* offset_ptr,
6909 unsigned chars);
6910 inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6911 unsigned* offset_ptr,
6912 unsigned chars);
6913
6914 // Minimum length for a cons string.
6915 static const int kMinLength = 13;
6916
Iain Merrick75681382010-08-19 15:07:18 +01006917 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
6918 BodyDescriptor;
6919
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006920#ifdef DEBUG
6921 void ConsStringVerify();
6922#endif
6923
Steve Blocka7e24c12009-10-30 11:49:00 +00006924 private:
6925 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
6926};
6927
6928
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006929// The Sliced String class describes strings that are substrings of another
6930// sequential string. The motivation is to save time and memory when creating
6931// a substring. A Sliced String is described as a pointer to the parent,
6932// the offset from the start of the parent string and the length. Using
6933// a Sliced String therefore requires unpacking of the parent string and
6934// adding the offset to the start address. A substring of a Sliced String
6935// are not nested since the double indirection is simplified when creating
6936// such a substring.
6937// Currently missing features are:
6938// - handling externalized parent strings
6939// - external strings as parent
6940// - truncating sliced string to enable otherwise unneeded parent to be GC'ed.
6941class SlicedString: public String {
6942 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006943 inline String* parent();
6944 inline void set_parent(String* parent);
6945 inline int offset();
6946 inline void set_offset(int offset);
6947
6948 // Dispatched behavior.
6949 uint16_t SlicedStringGet(int index);
6950
6951 // Casting.
6952 static inline SlicedString* cast(Object* obj);
6953
6954 // Layout description.
6955 static const int kParentOffset = POINTER_SIZE_ALIGN(String::kSize);
6956 static const int kOffsetOffset = kParentOffset + kPointerSize;
6957 static const int kSize = kOffsetOffset + kPointerSize;
6958
6959 // Support for StringInputBuffer
6960 inline const unibrow::byte* SlicedStringReadBlock(ReadBlockBuffer* buffer,
6961 unsigned* offset_ptr,
6962 unsigned chars);
6963 inline void SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6964 unsigned* offset_ptr,
6965 unsigned chars);
6966 // Minimum length for a sliced string.
6967 static const int kMinLength = 13;
6968
6969 typedef FixedBodyDescriptor<kParentOffset,
6970 kOffsetOffset + kPointerSize, kSize>
6971 BodyDescriptor;
6972
6973#ifdef DEBUG
6974 void SlicedStringVerify();
6975#endif
6976
6977 private:
6978 DISALLOW_IMPLICIT_CONSTRUCTORS(SlicedString);
6979};
6980
6981
Steve Blocka7e24c12009-10-30 11:49:00 +00006982// The ExternalString class describes string values that are backed by
6983// a string resource that lies outside the V8 heap. ExternalStrings
6984// consist of the length field common to all strings, a pointer to the
6985// external resource. It is important to ensure (externally) that the
6986// resource is not deallocated while the ExternalString is live in the
6987// V8 heap.
6988//
6989// The API expects that all ExternalStrings are created through the
6990// API. Therefore, ExternalStrings should not be used internally.
6991class ExternalString: public String {
6992 public:
6993 // Casting
6994 static inline ExternalString* cast(Object* obj);
6995
6996 // Layout description.
6997 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006998 static const int kShortSize = kResourceOffset + kPointerSize;
6999 static const int kResourceDataOffset = kResourceOffset + kPointerSize;
7000 static const int kSize = kResourceDataOffset + kPointerSize;
7001
7002 // Return whether external string is short (data pointer is not cached).
7003 inline bool is_short();
Steve Blocka7e24c12009-10-30 11:49:00 +00007004
7005 STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
7006
7007 private:
7008 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
7009};
7010
7011
7012// The ExternalAsciiString class is an external string backed by an
7013// ASCII string.
7014class ExternalAsciiString: public ExternalString {
7015 public:
Leon Clarkeac952652010-07-15 11:15:24 +01007016 static const bool kHasAsciiEncoding = true;
7017
Steve Blocka7e24c12009-10-30 11:49:00 +00007018 typedef v8::String::ExternalAsciiStringResource Resource;
7019
7020 // The underlying resource.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007021 inline const Resource* resource();
7022 inline void set_resource(const Resource* buffer);
7023
7024 // Update the pointer cache to the external character array.
7025 // The cached pointer is always valid, as the external character array does =
7026 // not move during lifetime. Deserialization is the only exception, after
7027 // which the pointer cache has to be refreshed.
7028 inline void update_data_cache();
7029
7030 inline const char* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00007031
7032 // Dispatched behavior.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007033 inline uint16_t ExternalAsciiStringGet(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00007034
7035 // Casting.
7036 static inline ExternalAsciiString* cast(Object* obj);
7037
Steve Blockd0582a62009-12-15 09:54:21 +00007038 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01007039 inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
7040
7041 template<typename StaticVisitor>
7042 inline void ExternalAsciiStringIterateBody();
Steve Blockd0582a62009-12-15 09:54:21 +00007043
Steve Blocka7e24c12009-10-30 11:49:00 +00007044 // Support for StringInputBuffer.
7045 const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
7046 unsigned* offset,
7047 unsigned chars);
7048 inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
7049 unsigned* offset,
7050 unsigned chars);
7051
Steve Blocka7e24c12009-10-30 11:49:00 +00007052 private:
7053 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
7054};
7055
7056
7057// The ExternalTwoByteString class is an external string backed by a UTF-16
7058// encoded string.
7059class ExternalTwoByteString: public ExternalString {
7060 public:
Leon Clarkeac952652010-07-15 11:15:24 +01007061 static const bool kHasAsciiEncoding = false;
7062
Steve Blocka7e24c12009-10-30 11:49:00 +00007063 typedef v8::String::ExternalStringResource Resource;
7064
7065 // The underlying string resource.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007066 inline const Resource* resource();
7067 inline void set_resource(const Resource* buffer);
7068
7069 // Update the pointer cache to the external character array.
7070 // The cached pointer is always valid, as the external character array does =
7071 // not move during lifetime. Deserialization is the only exception, after
7072 // which the pointer cache has to be refreshed.
7073 inline void update_data_cache();
7074
7075 inline const uint16_t* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00007076
7077 // Dispatched behavior.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007078 inline uint16_t ExternalTwoByteStringGet(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00007079
7080 // For regexp code.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007081 inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
Steve Blocka7e24c12009-10-30 11:49:00 +00007082
7083 // Casting.
7084 static inline ExternalTwoByteString* cast(Object* obj);
7085
Steve Blockd0582a62009-12-15 09:54:21 +00007086 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01007087 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
7088
7089 template<typename StaticVisitor>
7090 inline void ExternalTwoByteStringIterateBody();
7091
Steve Blockd0582a62009-12-15 09:54:21 +00007092
Steve Blocka7e24c12009-10-30 11:49:00 +00007093 // Support for StringInputBuffer.
7094 void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
7095 unsigned* offset_ptr,
7096 unsigned chars);
7097
Steve Blocka7e24c12009-10-30 11:49:00 +00007098 private:
7099 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
7100};
7101
7102
7103// Utility superclass for stack-allocated objects that must be updated
7104// on gc. It provides two ways for the gc to update instances, either
7105// iterating or updating after gc.
7106class Relocatable BASE_EMBEDDED {
7107 public:
Steve Block44f0eee2011-05-26 01:26:41 +01007108 explicit inline Relocatable(Isolate* isolate);
7109 inline virtual ~Relocatable();
Steve Blocka7e24c12009-10-30 11:49:00 +00007110 virtual void IterateInstance(ObjectVisitor* v) { }
7111 virtual void PostGarbageCollection() { }
7112
7113 static void PostGarbageCollectionProcessing();
7114 static int ArchiveSpacePerThread();
Ben Murdoch257744e2011-11-30 15:57:28 +00007115 static char* ArchiveState(Isolate* isolate, char* to);
7116 static char* RestoreState(Isolate* isolate, char* from);
Steve Blocka7e24c12009-10-30 11:49:00 +00007117 static void Iterate(ObjectVisitor* v);
7118 static void Iterate(ObjectVisitor* v, Relocatable* top);
7119 static char* Iterate(ObjectVisitor* v, char* t);
7120 private:
Steve Block44f0eee2011-05-26 01:26:41 +01007121 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00007122 Relocatable* prev_;
7123};
7124
7125
7126// A flat string reader provides random access to the contents of a
7127// string independent of the character width of the string. The handle
7128// must be valid as long as the reader is being used.
7129class FlatStringReader : public Relocatable {
7130 public:
Steve Block44f0eee2011-05-26 01:26:41 +01007131 FlatStringReader(Isolate* isolate, Handle<String> str);
7132 FlatStringReader(Isolate* isolate, Vector<const char> input);
Steve Blocka7e24c12009-10-30 11:49:00 +00007133 void PostGarbageCollection();
7134 inline uc32 Get(int index);
7135 int length() { return length_; }
7136 private:
7137 String** str_;
7138 bool is_ascii_;
7139 int length_;
7140 const void* start_;
7141};
7142
7143
7144// Note that StringInputBuffers are not valid across a GC! To fix this
7145// it would have to store a String Handle instead of a String* and
7146// AsciiStringReadBlock would have to be modified to use memcpy.
7147//
7148// StringInputBuffer is able to traverse any string regardless of how
7149// deeply nested a sequence of ConsStrings it is made of. However,
7150// performance will be better if deep strings are flattened before they
7151// are traversed. Since flattening requires memory allocation this is
7152// not always desirable, however (esp. in debugging situations).
7153class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
7154 public:
7155 virtual void Seek(unsigned pos);
7156 inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
Ben Murdoch8b112d22011-06-08 16:22:53 +01007157 explicit inline StringInputBuffer(String* backing):
Steve Blocka7e24c12009-10-30 11:49:00 +00007158 unibrow::InputBuffer<String, String*, 1024>(backing) {}
7159};
7160
7161
7162class SafeStringInputBuffer
7163 : public unibrow::InputBuffer<String, String**, 256> {
7164 public:
7165 virtual void Seek(unsigned pos);
7166 inline SafeStringInputBuffer()
7167 : unibrow::InputBuffer<String, String**, 256>() {}
Ben Murdoch8b112d22011-06-08 16:22:53 +01007168 explicit inline SafeStringInputBuffer(String** backing)
Steve Blocka7e24c12009-10-30 11:49:00 +00007169 : unibrow::InputBuffer<String, String**, 256>(backing) {}
7170};
7171
7172
7173template <typename T>
7174class VectorIterator {
7175 public:
7176 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
7177 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
7178 T GetNext() { return data_[index_++]; }
7179 bool has_more() { return index_ < data_.length(); }
7180 private:
7181 Vector<const T> data_;
7182 int index_;
7183};
7184
7185
7186// The Oddball describes objects null, undefined, true, and false.
7187class Oddball: public HeapObject {
7188 public:
7189 // [to_string]: Cached to_string computed at startup.
7190 DECL_ACCESSORS(to_string, String)
7191
7192 // [to_number]: Cached to_number computed at startup.
7193 DECL_ACCESSORS(to_number, Object)
7194
Steve Block44f0eee2011-05-26 01:26:41 +01007195 inline byte kind();
7196 inline void set_kind(byte kind);
7197
Steve Blocka7e24c12009-10-30 11:49:00 +00007198 // Casting.
7199 static inline Oddball* cast(Object* obj);
7200
7201 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00007202#ifdef DEBUG
7203 void OddballVerify();
7204#endif
7205
7206 // Initialize the fields.
John Reck59135872010-11-02 12:39:01 -07007207 MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
Steve Block44f0eee2011-05-26 01:26:41 +01007208 Object* to_number,
7209 byte kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00007210
7211 // Layout description.
7212 static const int kToStringOffset = HeapObject::kHeaderSize;
7213 static const int kToNumberOffset = kToStringOffset + kPointerSize;
Steve Block44f0eee2011-05-26 01:26:41 +01007214 static const int kKindOffset = kToNumberOffset + kPointerSize;
7215 static const int kSize = kKindOffset + kPointerSize;
7216
7217 static const byte kFalse = 0;
7218 static const byte kTrue = 1;
7219 static const byte kNotBooleanMask = ~1;
7220 static const byte kTheHole = 2;
7221 static const byte kNull = 3;
7222 static const byte kArgumentMarker = 4;
7223 static const byte kUndefined = 5;
7224 static const byte kOther = 6;
Steve Blocka7e24c12009-10-30 11:49:00 +00007225
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007226 // The ToNumber value of a hidden oddball is a negative smi.
7227 static const int kLeastHiddenOddballNumber = -5;
7228
Iain Merrick75681382010-08-19 15:07:18 +01007229 typedef FixedBodyDescriptor<kToStringOffset,
7230 kToNumberOffset + kPointerSize,
7231 kSize> BodyDescriptor;
7232
Steve Blocka7e24c12009-10-30 11:49:00 +00007233 private:
7234 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
7235};
7236
7237
7238class JSGlobalPropertyCell: public HeapObject {
7239 public:
7240 // [value]: value of the global property.
7241 DECL_ACCESSORS(value, Object)
7242
7243 // Casting.
7244 static inline JSGlobalPropertyCell* cast(Object* obj);
7245
Steve Blocka7e24c12009-10-30 11:49:00 +00007246#ifdef DEBUG
7247 void JSGlobalPropertyCellVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007248#endif
7249#ifdef OBJECT_PRINT
7250 inline void JSGlobalPropertyCellPrint() {
7251 JSGlobalPropertyCellPrint(stdout);
7252 }
7253 void JSGlobalPropertyCellPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00007254#endif
7255
7256 // Layout description.
7257 static const int kValueOffset = HeapObject::kHeaderSize;
7258 static const int kSize = kValueOffset + kPointerSize;
7259
Iain Merrick75681382010-08-19 15:07:18 +01007260 typedef FixedBodyDescriptor<kValueOffset,
7261 kValueOffset + kPointerSize,
7262 kSize> BodyDescriptor;
7263
Steve Blocka7e24c12009-10-30 11:49:00 +00007264 private:
7265 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
7266};
7267
7268
Ben Murdoch257744e2011-11-30 15:57:28 +00007269// The JSProxy describes EcmaScript Harmony proxies
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007270class JSProxy: public JSReceiver {
Steve Blocka7e24c12009-10-30 11:49:00 +00007271 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00007272 // [handler]: The handler property.
7273 DECL_ACCESSORS(handler, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00007274
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007275 // [hash]: The hash code property (undefined if not initialized yet).
7276 DECL_ACCESSORS(hash, Object)
7277
Steve Blocka7e24c12009-10-30 11:49:00 +00007278 // Casting.
Ben Murdoch257744e2011-11-30 15:57:28 +00007279 static inline JSProxy* cast(Object* obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00007280
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007281 bool HasPropertyWithHandler(String* name);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007282 bool HasElementWithHandler(uint32_t index);
7283
7284 MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
7285 Object* receiver,
7286 String* name);
7287 MUST_USE_RESULT MaybeObject* GetElementWithHandler(
7288 Object* receiver,
7289 uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007290
7291 MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
7292 String* name,
7293 Object* value,
7294 PropertyAttributes attributes,
7295 StrictModeFlag strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007296 MUST_USE_RESULT MaybeObject* SetElementWithHandler(
7297 uint32_t index,
7298 Object* value,
7299 StrictModeFlag strict_mode);
7300
7301 // If the handler defines an accessor property, invoke its setter
7302 // (or throw if only a getter exists) and set *found to true. Otherwise false.
7303 MUST_USE_RESULT MaybeObject* SetPropertyWithHandlerIfDefiningSetter(
7304 String* name,
7305 Object* value,
7306 PropertyAttributes attributes,
7307 StrictModeFlag strict_mode,
7308 bool* found);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007309
7310 MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
7311 String* name,
7312 DeleteMode mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007313 MUST_USE_RESULT MaybeObject* DeleteElementWithHandler(
7314 uint32_t index,
7315 DeleteMode mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007316
7317 MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
7318 JSReceiver* receiver,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007319 String* name);
7320 MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(
7321 JSReceiver* receiver,
7322 uint32_t index);
7323
7324 MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007325
7326 // Turn this into an (empty) JSObject.
7327 void Fix();
7328
Ben Murdoch589d6972011-11-30 16:04:58 +00007329 // Initializes the body after the handler slot.
7330 inline void InitializeBody(int object_size, Object* value);
7331
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007332 // Invoke a trap by name. If the trap does not exist on this's handler,
7333 // but derived_trap is non-NULL, invoke that instead. May cause GC.
7334 Handle<Object> CallTrap(const char* name,
7335 Handle<Object> derived_trap,
7336 int argc,
7337 Handle<Object> args[]);
7338
Steve Blocka7e24c12009-10-30 11:49:00 +00007339 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01007340#ifdef OBJECT_PRINT
Ben Murdoch257744e2011-11-30 15:57:28 +00007341 inline void JSProxyPrint() {
7342 JSProxyPrint(stdout);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007343 }
Ben Murdoch257744e2011-11-30 15:57:28 +00007344 void JSProxyPrint(FILE* out);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007345#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007346#ifdef DEBUG
Ben Murdoch257744e2011-11-30 15:57:28 +00007347 void JSProxyVerify();
7348#endif
7349
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007350 // Layout description. We add padding so that a proxy has the same
7351 // size as a virgin JSObject. This is essential for becoming a JSObject
7352 // upon freeze.
Ben Murdoch257744e2011-11-30 15:57:28 +00007353 static const int kHandlerOffset = HeapObject::kHeaderSize;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007354 static const int kHashOffset = kHandlerOffset + kPointerSize;
7355 static const int kPaddingOffset = kHashOffset + kPointerSize;
Ben Murdoch589d6972011-11-30 16:04:58 +00007356 static const int kSize = JSObject::kHeaderSize;
7357 static const int kHeaderSize = kPaddingOffset;
7358 static const int kPaddingSize = kSize - kPaddingOffset;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007359
Ben Murdoch589d6972011-11-30 16:04:58 +00007360 STATIC_CHECK(kPaddingSize >= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00007361
7362 typedef FixedBodyDescriptor<kHandlerOffset,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007363 kPaddingOffset,
Ben Murdoch257744e2011-11-30 15:57:28 +00007364 kSize> BodyDescriptor;
7365
7366 private:
7367 DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy);
7368};
7369
7370
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007371class JSFunctionProxy: public JSProxy {
7372 public:
Ben Murdoch589d6972011-11-30 16:04:58 +00007373 // [call_trap]: The call trap.
7374 DECL_ACCESSORS(call_trap, Object)
7375
7376 // [construct_trap]: The construct trap.
7377 DECL_ACCESSORS(construct_trap, Object)
7378
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007379 // Casting.
7380 static inline JSFunctionProxy* cast(Object* obj);
7381
Ben Murdoch589d6972011-11-30 16:04:58 +00007382 // Dispatched behavior.
7383#ifdef OBJECT_PRINT
7384 inline void JSFunctionProxyPrint() {
7385 JSFunctionProxyPrint(stdout);
7386 }
7387 void JSFunctionProxyPrint(FILE* out);
7388#endif
7389#ifdef DEBUG
7390 void JSFunctionProxyVerify();
7391#endif
7392
7393 // Layout description.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007394 static const int kCallTrapOffset = JSProxy::kPaddingOffset;
Ben Murdoch589d6972011-11-30 16:04:58 +00007395 static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize;
7396 static const int kPaddingOffset = kConstructTrapOffset + kPointerSize;
7397 static const int kSize = JSFunction::kSize;
7398 static const int kPaddingSize = kSize - kPaddingOffset;
7399
7400 STATIC_CHECK(kPaddingSize >= 0);
7401
7402 typedef FixedBodyDescriptor<kHandlerOffset,
7403 kConstructTrapOffset + kPointerSize,
7404 kSize> BodyDescriptor;
7405
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007406 private:
7407 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy);
7408};
7409
Ben Murdoch257744e2011-11-30 15:57:28 +00007410
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007411// The JSSet describes EcmaScript Harmony sets
7412class JSSet: public JSObject {
7413 public:
7414 // [set]: the backing hash set containing keys.
7415 DECL_ACCESSORS(table, Object)
7416
7417 // Casting.
7418 static inline JSSet* cast(Object* obj);
7419
7420#ifdef OBJECT_PRINT
7421 inline void JSSetPrint() {
7422 JSSetPrint(stdout);
7423 }
7424 void JSSetPrint(FILE* out);
7425#endif
7426#ifdef DEBUG
7427 void JSSetVerify();
7428#endif
7429
7430 static const int kTableOffset = JSObject::kHeaderSize;
7431 static const int kSize = kTableOffset + kPointerSize;
7432
7433 private:
7434 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet);
7435};
7436
7437
7438// The JSMap describes EcmaScript Harmony maps
7439class JSMap: public JSObject {
7440 public:
7441 // [table]: the backing hash table mapping keys to values.
7442 DECL_ACCESSORS(table, Object)
7443
7444 // Casting.
7445 static inline JSMap* cast(Object* obj);
7446
7447#ifdef OBJECT_PRINT
7448 inline void JSMapPrint() {
7449 JSMapPrint(stdout);
7450 }
7451 void JSMapPrint(FILE* out);
7452#endif
7453#ifdef DEBUG
7454 void JSMapVerify();
7455#endif
7456
7457 static const int kTableOffset = JSObject::kHeaderSize;
7458 static const int kSize = kTableOffset + kPointerSize;
7459
7460 private:
7461 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
7462};
7463
7464
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007465// The JSWeakMap describes EcmaScript Harmony weak maps
7466class JSWeakMap: public JSObject {
7467 public:
7468 // [table]: the backing hash table mapping keys to values.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007469 DECL_ACCESSORS(table, Object)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007470
7471 // [next]: linked list of encountered weak maps during GC.
7472 DECL_ACCESSORS(next, Object)
7473
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007474 // Casting.
7475 static inline JSWeakMap* cast(Object* obj);
7476
7477#ifdef OBJECT_PRINT
7478 inline void JSWeakMapPrint() {
7479 JSWeakMapPrint(stdout);
7480 }
7481 void JSWeakMapPrint(FILE* out);
7482#endif
7483#ifdef DEBUG
7484 void JSWeakMapVerify();
7485#endif
7486
7487 static const int kTableOffset = JSObject::kHeaderSize;
7488 static const int kNextOffset = kTableOffset + kPointerSize;
7489 static const int kSize = kNextOffset + kPointerSize;
7490
7491 private:
7492 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
7493};
7494
7495
Ben Murdoch257744e2011-11-30 15:57:28 +00007496// Foreign describes objects pointing from JavaScript to C structures.
7497// Since they cannot contain references to JS HeapObjects they can be
7498// placed in old_data_space.
7499class Foreign: public HeapObject {
7500 public:
7501 // [address]: field containing the address.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007502 inline Address foreign_address();
7503 inline void set_foreign_address(Address value);
Ben Murdoch257744e2011-11-30 15:57:28 +00007504
7505 // Casting.
7506 static inline Foreign* cast(Object* obj);
7507
7508 // Dispatched behavior.
7509 inline void ForeignIterateBody(ObjectVisitor* v);
7510
7511 template<typename StaticVisitor>
7512 inline void ForeignIterateBody();
7513
7514#ifdef OBJECT_PRINT
7515 inline void ForeignPrint() {
7516 ForeignPrint(stdout);
7517 }
7518 void ForeignPrint(FILE* out);
7519#endif
7520#ifdef DEBUG
7521 void ForeignVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00007522#endif
7523
7524 // Layout description.
7525
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007526 static const int kForeignAddressOffset = HeapObject::kHeaderSize;
7527 static const int kSize = kForeignAddressOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007528
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007529 STATIC_CHECK(kForeignAddressOffset == Internals::kForeignAddressOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00007530
7531 private:
Ben Murdoch257744e2011-11-30 15:57:28 +00007532 DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
Steve Blocka7e24c12009-10-30 11:49:00 +00007533};
7534
7535
7536// The JSArray describes JavaScript Arrays
7537// Such an array can be in one of two modes:
7538// - fast, backing storage is a FixedArray and length <= elements.length();
7539// Please note: push and pop can be used to grow and shrink the array.
7540// - slow, backing storage is a HashTable with numbers as keys.
7541class JSArray: public JSObject {
7542 public:
7543 // [length]: The length property.
7544 DECL_ACCESSORS(length, Object)
7545
Leon Clarke4515c472010-02-03 11:58:03 +00007546 // Overload the length setter to skip write barrier when the length
7547 // is set to a smi. This matches the set function on FixedArray.
7548 inline void set_length(Smi* length);
7549
John Reck59135872010-11-02 12:39:01 -07007550 MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
7551 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00007552
7553 // Initialize the array with the given capacity. The function may
7554 // fail due to out-of-memory situations, but only if the requested
7555 // capacity is non-zero.
John Reck59135872010-11-02 12:39:01 -07007556 MUST_USE_RESULT MaybeObject* Initialize(int capacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00007557
Ben Murdochc7cc0282012-03-05 14:35:55 +00007558 // Initializes the array to a certain length.
7559 inline bool AllowsSetElementsLength();
7560 MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
7561
Steve Blocka7e24c12009-10-30 11:49:00 +00007562 // Set the content of the array to the content of storage.
Ben Murdochc7cc0282012-03-05 14:35:55 +00007563 inline MaybeObject* SetContent(FixedArrayBase* storage);
Steve Blocka7e24c12009-10-30 11:49:00 +00007564
7565 // Casting.
7566 static inline JSArray* cast(Object* obj);
7567
7568 // Uses handles. Ensures that the fixed array backing the JSArray has at
7569 // least the stated size.
7570 inline void EnsureSize(int minimum_size_of_backing_fixed_array);
7571
7572 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01007573#ifdef OBJECT_PRINT
7574 inline void JSArrayPrint() {
7575 JSArrayPrint(stdout);
7576 }
7577 void JSArrayPrint(FILE* out);
7578#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007579#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007580 void JSArrayVerify();
7581#endif
7582
7583 // Number of element slots to pre-allocate for an empty array.
7584 static const int kPreallocatedArrayElements = 4;
7585
7586 // Layout description.
7587 static const int kLengthOffset = JSObject::kHeaderSize;
7588 static const int kSize = kLengthOffset + kPointerSize;
7589
7590 private:
7591 // Expand the fixed array backing of a fast-case JSArray to at least
7592 // the requested size.
7593 void Expand(int minimum_size_of_backing_fixed_array);
7594
7595 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
7596};
7597
7598
Steve Block6ded16b2010-05-10 14:33:55 +01007599// JSRegExpResult is just a JSArray with a specific initial map.
7600// This initial map adds in-object properties for "index" and "input"
7601// properties, as assigned by RegExp.prototype.exec, which allows
7602// faster creation of RegExp exec results.
7603// This class just holds constants used when creating the result.
7604// After creation the result must be treated as a JSArray in all regards.
7605class JSRegExpResult: public JSArray {
7606 public:
7607 // Offsets of object fields.
7608 static const int kIndexOffset = JSArray::kSize;
7609 static const int kInputOffset = kIndexOffset + kPointerSize;
7610 static const int kSize = kInputOffset + kPointerSize;
7611 // Indices of in-object properties.
7612 static const int kIndexIndex = 0;
7613 static const int kInputIndex = 1;
7614 private:
7615 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
7616};
7617
7618
Steve Blocka7e24c12009-10-30 11:49:00 +00007619// An accessor must have a getter, but can have no setter.
7620//
7621// When setting a property, V8 searches accessors in prototypes.
7622// If an accessor was found and it does not have a setter,
7623// the request is ignored.
7624//
7625// If the accessor in the prototype has the READ_ONLY property attribute, then
7626// a new value is added to the local object when the property is set.
7627// This shadows the accessor in the prototype.
7628class AccessorInfo: public Struct {
7629 public:
7630 DECL_ACCESSORS(getter, Object)
7631 DECL_ACCESSORS(setter, Object)
7632 DECL_ACCESSORS(data, Object)
7633 DECL_ACCESSORS(name, Object)
7634 DECL_ACCESSORS(flag, Smi)
7635
7636 inline bool all_can_read();
7637 inline void set_all_can_read(bool value);
7638
7639 inline bool all_can_write();
7640 inline void set_all_can_write(bool value);
7641
7642 inline bool prohibits_overwriting();
7643 inline void set_prohibits_overwriting(bool value);
7644
7645 inline PropertyAttributes property_attributes();
7646 inline void set_property_attributes(PropertyAttributes attributes);
7647
7648 static inline AccessorInfo* cast(Object* obj);
7649
Ben Murdochb0fe1622011-05-05 13:52:32 +01007650#ifdef OBJECT_PRINT
7651 inline void AccessorInfoPrint() {
7652 AccessorInfoPrint(stdout);
7653 }
7654 void AccessorInfoPrint(FILE* out);
7655#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007656#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007657 void AccessorInfoVerify();
7658#endif
7659
7660 static const int kGetterOffset = HeapObject::kHeaderSize;
7661 static const int kSetterOffset = kGetterOffset + kPointerSize;
7662 static const int kDataOffset = kSetterOffset + kPointerSize;
7663 static const int kNameOffset = kDataOffset + kPointerSize;
7664 static const int kFlagOffset = kNameOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007665 static const int kSize = kFlagOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007666
7667 private:
7668 // Bit positions in flag.
7669 static const int kAllCanReadBit = 0;
7670 static const int kAllCanWriteBit = 1;
7671 static const int kProhibitsOverwritingBit = 2;
7672 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
7673
7674 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
7675};
7676
7677
Ben Murdochc7cc0282012-03-05 14:35:55 +00007678// Support for JavaScript accessors: A pair of a getter and a setter. Each
7679// accessor can either be
7680// * a pointer to a JavaScript function or proxy: a real accessor
7681// * undefined: considered an accessor by the spec, too, strangely enough
7682// * the hole: an accessor which has not been set
7683// * a pointer to a map: a transition used to ensure map sharing
7684class AccessorPair: public Struct {
7685 public:
7686 DECL_ACCESSORS(getter, Object)
7687 DECL_ACCESSORS(setter, Object)
7688
7689 static inline AccessorPair* cast(Object* obj);
7690
7691#ifdef OBJECT_PRINT
7692 void AccessorPairPrint(FILE* out = stdout);
7693#endif
7694#ifdef DEBUG
7695 void AccessorPairVerify();
7696#endif
7697
7698 static const int kGetterOffset = HeapObject::kHeaderSize;
7699 static const int kSetterOffset = kGetterOffset + kPointerSize;
7700 static const int kSize = kSetterOffset + kPointerSize;
7701
7702 private:
7703 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair);
7704};
7705
7706
Steve Blocka7e24c12009-10-30 11:49:00 +00007707class AccessCheckInfo: public Struct {
7708 public:
7709 DECL_ACCESSORS(named_callback, Object)
7710 DECL_ACCESSORS(indexed_callback, Object)
7711 DECL_ACCESSORS(data, Object)
7712
7713 static inline AccessCheckInfo* cast(Object* obj);
7714
Ben Murdochb0fe1622011-05-05 13:52:32 +01007715#ifdef OBJECT_PRINT
7716 inline void AccessCheckInfoPrint() {
7717 AccessCheckInfoPrint(stdout);
7718 }
7719 void AccessCheckInfoPrint(FILE* out);
7720#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007721#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007722 void AccessCheckInfoVerify();
7723#endif
7724
7725 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
7726 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
7727 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
7728 static const int kSize = kDataOffset + kPointerSize;
7729
7730 private:
7731 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
7732};
7733
7734
7735class InterceptorInfo: public Struct {
7736 public:
7737 DECL_ACCESSORS(getter, Object)
7738 DECL_ACCESSORS(setter, Object)
7739 DECL_ACCESSORS(query, Object)
7740 DECL_ACCESSORS(deleter, Object)
7741 DECL_ACCESSORS(enumerator, Object)
7742 DECL_ACCESSORS(data, Object)
7743
7744 static inline InterceptorInfo* cast(Object* obj);
7745
Ben Murdochb0fe1622011-05-05 13:52:32 +01007746#ifdef OBJECT_PRINT
7747 inline void InterceptorInfoPrint() {
7748 InterceptorInfoPrint(stdout);
7749 }
7750 void InterceptorInfoPrint(FILE* out);
7751#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007752#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007753 void InterceptorInfoVerify();
7754#endif
7755
7756 static const int kGetterOffset = HeapObject::kHeaderSize;
7757 static const int kSetterOffset = kGetterOffset + kPointerSize;
7758 static const int kQueryOffset = kSetterOffset + kPointerSize;
7759 static const int kDeleterOffset = kQueryOffset + kPointerSize;
7760 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
7761 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
7762 static const int kSize = kDataOffset + kPointerSize;
7763
7764 private:
7765 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
7766};
7767
7768
7769class CallHandlerInfo: public Struct {
7770 public:
7771 DECL_ACCESSORS(callback, Object)
7772 DECL_ACCESSORS(data, Object)
7773
7774 static inline CallHandlerInfo* cast(Object* obj);
7775
Ben Murdochb0fe1622011-05-05 13:52:32 +01007776#ifdef OBJECT_PRINT
7777 inline void CallHandlerInfoPrint() {
7778 CallHandlerInfoPrint(stdout);
7779 }
7780 void CallHandlerInfoPrint(FILE* out);
7781#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007782#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007783 void CallHandlerInfoVerify();
7784#endif
7785
7786 static const int kCallbackOffset = HeapObject::kHeaderSize;
7787 static const int kDataOffset = kCallbackOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007788 static const int kSize = kDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007789
7790 private:
7791 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
7792};
7793
7794
7795class TemplateInfo: public Struct {
7796 public:
7797 DECL_ACCESSORS(tag, Object)
7798 DECL_ACCESSORS(property_list, Object)
7799
7800#ifdef DEBUG
7801 void TemplateInfoVerify();
7802#endif
7803
7804 static const int kTagOffset = HeapObject::kHeaderSize;
7805 static const int kPropertyListOffset = kTagOffset + kPointerSize;
7806 static const int kHeaderSize = kPropertyListOffset + kPointerSize;
Ben Murdochc7cc0282012-03-05 14:35:55 +00007807
7808 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00007809 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
7810};
7811
7812
7813class FunctionTemplateInfo: public TemplateInfo {
7814 public:
7815 DECL_ACCESSORS(serial_number, Object)
7816 DECL_ACCESSORS(call_code, Object)
7817 DECL_ACCESSORS(property_accessors, Object)
7818 DECL_ACCESSORS(prototype_template, Object)
7819 DECL_ACCESSORS(parent_template, Object)
7820 DECL_ACCESSORS(named_property_handler, Object)
7821 DECL_ACCESSORS(indexed_property_handler, Object)
7822 DECL_ACCESSORS(instance_template, Object)
7823 DECL_ACCESSORS(class_name, Object)
7824 DECL_ACCESSORS(signature, Object)
7825 DECL_ACCESSORS(instance_call_handler, Object)
7826 DECL_ACCESSORS(access_check_info, Object)
7827 DECL_ACCESSORS(flag, Smi)
7828
7829 // Following properties use flag bits.
7830 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
7831 DECL_BOOLEAN_ACCESSORS(undetectable)
7832 // If the bit is set, object instances created by this function
7833 // requires access check.
7834 DECL_BOOLEAN_ACCESSORS(needs_access_check)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007835 DECL_BOOLEAN_ACCESSORS(read_only_prototype)
Steve Blocka7e24c12009-10-30 11:49:00 +00007836
7837 static inline FunctionTemplateInfo* cast(Object* obj);
7838
Ben Murdochb0fe1622011-05-05 13:52:32 +01007839#ifdef OBJECT_PRINT
7840 inline void FunctionTemplateInfoPrint() {
7841 FunctionTemplateInfoPrint(stdout);
7842 }
7843 void FunctionTemplateInfoPrint(FILE* out);
7844#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007845#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007846 void FunctionTemplateInfoVerify();
7847#endif
7848
7849 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
7850 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
7851 static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
7852 static const int kPrototypeTemplateOffset =
7853 kPropertyAccessorsOffset + kPointerSize;
7854 static const int kParentTemplateOffset =
7855 kPrototypeTemplateOffset + kPointerSize;
7856 static const int kNamedPropertyHandlerOffset =
7857 kParentTemplateOffset + kPointerSize;
7858 static const int kIndexedPropertyHandlerOffset =
7859 kNamedPropertyHandlerOffset + kPointerSize;
7860 static const int kInstanceTemplateOffset =
7861 kIndexedPropertyHandlerOffset + kPointerSize;
7862 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
7863 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
7864 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
7865 static const int kAccessCheckInfoOffset =
7866 kInstanceCallHandlerOffset + kPointerSize;
7867 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007868 static const int kSize = kFlagOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007869
7870 private:
7871 // Bit position in the flag, from least significant bit position.
7872 static const int kHiddenPrototypeBit = 0;
7873 static const int kUndetectableBit = 1;
7874 static const int kNeedsAccessCheckBit = 2;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007875 static const int kReadOnlyPrototypeBit = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +00007876
7877 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
7878};
7879
7880
7881class ObjectTemplateInfo: public TemplateInfo {
7882 public:
7883 DECL_ACCESSORS(constructor, Object)
7884 DECL_ACCESSORS(internal_field_count, Object)
7885
7886 static inline ObjectTemplateInfo* cast(Object* obj);
7887
Ben Murdochb0fe1622011-05-05 13:52:32 +01007888#ifdef OBJECT_PRINT
7889 inline void ObjectTemplateInfoPrint() {
7890 ObjectTemplateInfoPrint(stdout);
7891 }
7892 void ObjectTemplateInfoPrint(FILE* out);
7893#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007894#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007895 void ObjectTemplateInfoVerify();
7896#endif
7897
7898 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
7899 static const int kInternalFieldCountOffset =
7900 kConstructorOffset + kPointerSize;
7901 static const int kSize = kInternalFieldCountOffset + kPointerSize;
7902};
7903
7904
7905class SignatureInfo: public Struct {
7906 public:
7907 DECL_ACCESSORS(receiver, Object)
7908 DECL_ACCESSORS(args, Object)
7909
7910 static inline SignatureInfo* cast(Object* obj);
7911
Ben Murdochb0fe1622011-05-05 13:52:32 +01007912#ifdef OBJECT_PRINT
7913 inline void SignatureInfoPrint() {
7914 SignatureInfoPrint(stdout);
7915 }
7916 void SignatureInfoPrint(FILE* out);
7917#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007918#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007919 void SignatureInfoVerify();
7920#endif
7921
7922 static const int kReceiverOffset = Struct::kHeaderSize;
7923 static const int kArgsOffset = kReceiverOffset + kPointerSize;
7924 static const int kSize = kArgsOffset + kPointerSize;
7925
7926 private:
7927 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
7928};
7929
7930
7931class TypeSwitchInfo: public Struct {
7932 public:
7933 DECL_ACCESSORS(types, Object)
7934
7935 static inline TypeSwitchInfo* cast(Object* obj);
7936
Ben Murdochb0fe1622011-05-05 13:52:32 +01007937#ifdef OBJECT_PRINT
7938 inline void TypeSwitchInfoPrint() {
7939 TypeSwitchInfoPrint(stdout);
7940 }
7941 void TypeSwitchInfoPrint(FILE* out);
7942#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007943#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007944 void TypeSwitchInfoVerify();
7945#endif
7946
7947 static const int kTypesOffset = Struct::kHeaderSize;
7948 static const int kSize = kTypesOffset + kPointerSize;
7949};
7950
7951
7952#ifdef ENABLE_DEBUGGER_SUPPORT
7953// The DebugInfo class holds additional information for a function being
7954// debugged.
7955class DebugInfo: public Struct {
7956 public:
7957 // The shared function info for the source being debugged.
7958 DECL_ACCESSORS(shared, SharedFunctionInfo)
7959 // Code object for the original code.
7960 DECL_ACCESSORS(original_code, Code)
7961 // Code object for the patched code. This code object is the code object
7962 // currently active for the function.
7963 DECL_ACCESSORS(code, Code)
7964 // Fixed array holding status information for each active break point.
7965 DECL_ACCESSORS(break_points, FixedArray)
7966
7967 // Check if there is a break point at a code position.
7968 bool HasBreakPoint(int code_position);
7969 // Get the break point info object for a code position.
7970 Object* GetBreakPointInfo(int code_position);
7971 // Clear a break point.
7972 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
7973 int code_position,
7974 Handle<Object> break_point_object);
7975 // Set a break point.
7976 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
7977 int source_position, int statement_position,
7978 Handle<Object> break_point_object);
7979 // Get the break point objects for a code position.
7980 Object* GetBreakPointObjects(int code_position);
7981 // Find the break point info holding this break point object.
7982 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
7983 Handle<Object> break_point_object);
7984 // Get the number of break points for this function.
7985 int GetBreakPointCount();
7986
7987 static inline DebugInfo* cast(Object* obj);
7988
Ben Murdochb0fe1622011-05-05 13:52:32 +01007989#ifdef OBJECT_PRINT
7990 inline void DebugInfoPrint() {
7991 DebugInfoPrint(stdout);
7992 }
7993 void DebugInfoPrint(FILE* out);
7994#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007995#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007996 void DebugInfoVerify();
7997#endif
7998
7999 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
8000 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
8001 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
8002 static const int kActiveBreakPointsCountIndex =
8003 kPatchedCodeIndex + kPointerSize;
8004 static const int kBreakPointsStateIndex =
8005 kActiveBreakPointsCountIndex + kPointerSize;
8006 static const int kSize = kBreakPointsStateIndex + kPointerSize;
8007
8008 private:
8009 static const int kNoBreakPointInfo = -1;
8010
8011 // Lookup the index in the break_points array for a code position.
8012 int GetBreakPointInfoIndex(int code_position);
8013
8014 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
8015};
8016
8017
8018// The BreakPointInfo class holds information for break points set in a
8019// function. The DebugInfo object holds a BreakPointInfo object for each code
8020// position with one or more break points.
8021class BreakPointInfo: public Struct {
8022 public:
8023 // The position in the code for the break point.
8024 DECL_ACCESSORS(code_position, Smi)
8025 // The position in the source for the break position.
8026 DECL_ACCESSORS(source_position, Smi)
8027 // The position in the source for the last statement before this break
8028 // position.
8029 DECL_ACCESSORS(statement_position, Smi)
8030 // List of related JavaScript break points.
8031 DECL_ACCESSORS(break_point_objects, Object)
8032
8033 // Removes a break point.
8034 static void ClearBreakPoint(Handle<BreakPointInfo> info,
8035 Handle<Object> break_point_object);
8036 // Set a break point.
8037 static void SetBreakPoint(Handle<BreakPointInfo> info,
8038 Handle<Object> break_point_object);
8039 // Check if break point info has this break point object.
8040 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
8041 Handle<Object> break_point_object);
8042 // Get the number of break points for this code position.
8043 int GetBreakPointCount();
8044
8045 static inline BreakPointInfo* cast(Object* obj);
8046
Ben Murdochb0fe1622011-05-05 13:52:32 +01008047#ifdef OBJECT_PRINT
8048 inline void BreakPointInfoPrint() {
8049 BreakPointInfoPrint(stdout);
8050 }
8051 void BreakPointInfoPrint(FILE* out);
8052#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00008053#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00008054 void BreakPointInfoVerify();
8055#endif
8056
8057 static const int kCodePositionIndex = Struct::kHeaderSize;
8058 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
8059 static const int kStatementPositionIndex =
8060 kSourcePositionIndex + kPointerSize;
8061 static const int kBreakPointObjectsIndex =
8062 kStatementPositionIndex + kPointerSize;
8063 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
8064
8065 private:
8066 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
8067};
8068#endif // ENABLE_DEBUGGER_SUPPORT
8069
8070
8071#undef DECL_BOOLEAN_ACCESSORS
8072#undef DECL_ACCESSORS
8073
Ben Murdochc7cc0282012-03-05 14:35:55 +00008074#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V) \
8075 V(kSymbolTable, "symbol_table", "(Symbols)") \
8076 V(kExternalStringsTable, "external_strings_table", "(External strings)") \
8077 V(kStrongRootList, "strong_root_list", "(Strong roots)") \
8078 V(kSymbol, "symbol", "(Symbol)") \
8079 V(kBootstrapper, "bootstrapper", "(Bootstrapper)") \
8080 V(kTop, "top", "(Isolate)") \
8081 V(kRelocatable, "relocatable", "(Relocatable)") \
8082 V(kDebug, "debug", "(Debugger)") \
8083 V(kCompilationCache, "compilationcache", "(Compilation cache)") \
8084 V(kHandleScope, "handlescope", "(Handle scope)") \
8085 V(kBuiltins, "builtins", "(Builtins)") \
8086 V(kGlobalHandles, "globalhandles", "(Global handles)") \
8087 V(kThreadManager, "threadmanager", "(Thread manager)") \
8088 V(kExtensions, "Extensions", "(Extensions)")
8089
8090class VisitorSynchronization : public AllStatic {
8091 public:
8092#define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item,
8093 enum SyncTag {
8094 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_ENUM)
8095 kNumberOfSyncTags
8096 };
8097#undef DECLARE_ENUM
8098
8099 static const char* const kTags[kNumberOfSyncTags];
8100 static const char* const kTagNames[kNumberOfSyncTags];
8101};
Steve Blocka7e24c12009-10-30 11:49:00 +00008102
8103// Abstract base class for visiting, and optionally modifying, the
8104// pointers contained in Objects. Used in GC and serialization/deserialization.
8105class ObjectVisitor BASE_EMBEDDED {
8106 public:
8107 virtual ~ObjectVisitor() {}
8108
8109 // Visits a contiguous arrays of pointers in the half-open range
8110 // [start, end). Any or all of the values may be modified on return.
8111 virtual void VisitPointers(Object** start, Object** end) = 0;
8112
8113 // To allow lazy clearing of inline caches the visitor has
8114 // a rich interface for iterating over Code objects..
8115
8116 // Visits a code target in the instruction stream.
8117 virtual void VisitCodeTarget(RelocInfo* rinfo);
8118
Steve Block791712a2010-08-27 10:21:07 +01008119 // Visits a code entry in a JS function.
8120 virtual void VisitCodeEntry(Address entry_address);
8121
Ben Murdochb0fe1622011-05-05 13:52:32 +01008122 // Visits a global property cell reference in the instruction stream.
8123 virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
8124
Steve Blocka7e24c12009-10-30 11:49:00 +00008125 // Visits a runtime entry in the instruction stream.
8126 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
8127
Steve Blockd0582a62009-12-15 09:54:21 +00008128 // Visits the resource of an ASCII or two-byte string.
8129 virtual void VisitExternalAsciiString(
8130 v8::String::ExternalAsciiStringResource** resource) {}
8131 virtual void VisitExternalTwoByteString(
8132 v8::String::ExternalStringResource** resource) {}
8133
Steve Blocka7e24c12009-10-30 11:49:00 +00008134 // Visits a debug call target in the instruction stream.
8135 virtual void VisitDebugTarget(RelocInfo* rinfo);
8136
8137 // Handy shorthand for visiting a single pointer.
8138 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
8139
Ben Murdoch592a9fc2012-03-05 11:04:45 +00008140 // Visit pointer embedded into a code object.
8141 virtual void VisitEmbeddedPointer(RelocInfo* rinfo);
8142
Steve Blocka7e24c12009-10-30 11:49:00 +00008143 // Visits a contiguous arrays of external references (references to the C++
8144 // heap) in the half-open range [start, end). Any or all of the values
8145 // may be modified on return.
8146 virtual void VisitExternalReferences(Address* start, Address* end) {}
8147
Ben Murdoch592a9fc2012-03-05 11:04:45 +00008148 virtual void VisitExternalReference(RelocInfo* rinfo);
8149
Steve Blocka7e24c12009-10-30 11:49:00 +00008150 inline void VisitExternalReference(Address* p) {
8151 VisitExternalReferences(p, p + 1);
8152 }
8153
Steve Block44f0eee2011-05-26 01:26:41 +01008154 // Visits a handle that has an embedder-assigned class ID.
8155 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
8156
Steve Blocka7e24c12009-10-30 11:49:00 +00008157 // Intended for serialization/deserialization checking: insert, or
8158 // check for the presence of, a tag at this position in the stream.
Ben Murdochc7cc0282012-03-05 14:35:55 +00008159 // Also used for marking up GC roots in heap snapshots.
8160 virtual void Synchronize(VisitorSynchronization::SyncTag tag) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00008161};
8162
8163
Iain Merrick75681382010-08-19 15:07:18 +01008164class StructBodyDescriptor : public
8165 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
8166 public:
8167 static inline int SizeOf(Map* map, HeapObject* object) {
8168 return map->instance_size();
8169 }
8170};
8171
8172
Steve Blocka7e24c12009-10-30 11:49:00 +00008173// BooleanBit is a helper class for setting and getting a bit in an
8174// integer or Smi.
8175class BooleanBit : public AllStatic {
8176 public:
8177 static inline bool get(Smi* smi, int bit_position) {
8178 return get(smi->value(), bit_position);
8179 }
8180
8181 static inline bool get(int value, int bit_position) {
8182 return (value & (1 << bit_position)) != 0;
8183 }
8184
8185 static inline Smi* set(Smi* smi, int bit_position, bool v) {
8186 return Smi::FromInt(set(smi->value(), bit_position, v));
8187 }
8188
8189 static inline int set(int value, int bit_position, bool v) {
8190 if (v) {
8191 value |= (1 << bit_position);
8192 } else {
8193 value &= ~(1 << bit_position);
8194 }
8195 return value;
8196 }
8197};
8198
8199} } // namespace v8::internal
8200
8201#endif // V8_OBJECTS_H_