blob: 49aa2f730013f9922b74f71670d58d21ef6c68b0 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_OBJECTS_H_
29#define V8_OBJECTS_H_
30
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
110// - AccessCheckInfo
111// - InterceptorInfo
112// - CallHandlerInfo
113// - TemplateInfo
114// - FunctionTemplateInfo
115// - ObjectTemplateInfo
116// - Script
117// - SignatureInfo
118// - TypeSwitchInfo
119// - DebugInfo
120// - BreakPointInfo
Steve Block6ded16b2010-05-10 14:33:55 +0100121// - CodeCache
Steve Blocka7e24c12009-10-30 11:49:00 +0000122//
123// Formats of Object*:
124// Smi: [31 bit signed int] 0
125// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
126// Failure: [30 bit signed int] 11
127
Steve Blocka7e24c12009-10-30 11:49:00 +0000128namespace v8 {
129namespace internal {
130
Ben Murdoch589d6972011-11-30 16:04:58 +0000131enum ElementsKind {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000132 // The "fast" kind for elements that only contain SMI values. Must be first
133 // to make it possible to efficiently check maps for this kind.
134 FAST_SMI_ONLY_ELEMENTS,
135
136 // The "fast" kind for tagged values. Must be second to make it possible to
137 // efficiently check maps for this and the FAST_SMI_ONLY_ELEMENTS kind
138 // together at once.
Ben Murdoch589d6972011-11-30 16:04:58 +0000139 FAST_ELEMENTS,
140
141 // The "fast" kind for unwrapped, non-tagged double values.
142 FAST_DOUBLE_ELEMENTS,
143
144 // The "slow" kind.
145 DICTIONARY_ELEMENTS,
146 NON_STRICT_ARGUMENTS_ELEMENTS,
147 // The "fast" kind for external arrays
148 EXTERNAL_BYTE_ELEMENTS,
149 EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
150 EXTERNAL_SHORT_ELEMENTS,
151 EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
152 EXTERNAL_INT_ELEMENTS,
153 EXTERNAL_UNSIGNED_INT_ELEMENTS,
154 EXTERNAL_FLOAT_ELEMENTS,
155 EXTERNAL_DOUBLE_ELEMENTS,
156 EXTERNAL_PIXEL_ELEMENTS,
157
158 // Derived constants from ElementsKind
159 FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_BYTE_ELEMENTS,
160 LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000161 FIRST_ELEMENTS_KIND = FAST_SMI_ONLY_ELEMENTS,
Ben Murdoch589d6972011-11-30 16:04:58 +0000162 LAST_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS
163};
164
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000165const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000166
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000167void PrintElementsKind(FILE* out, ElementsKind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000169inline bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
170 ElementsKind to_kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000171
172// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
173enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
174
175
176// PropertyNormalizationMode is used to specify whether to keep
177// inobject properties when normalizing properties of a JSObject.
178enum PropertyNormalizationMode {
179 CLEAR_INOBJECT_PROPERTIES,
180 KEEP_INOBJECT_PROPERTIES
181};
182
183
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100184// NormalizedMapSharingMode is used to specify whether a map may be shared
185// by different objects with normalized properties.
186enum NormalizedMapSharingMode {
187 UNIQUE_NORMALIZED_MAP,
188 SHARED_NORMALIZED_MAP
189};
190
191
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000192// Indicates whether a get method should implicitly create the object looked up.
193enum CreationFlag {
194 ALLOW_CREATION,
195 OMIT_CREATION
196};
197
198
Steve Block791712a2010-08-27 10:21:07 +0100199// Instance size sentinel for objects of variable size.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000200const int kVariableSizeSentinel = 0;
Steve Block791712a2010-08-27 10:21:07 +0100201
202
Steve Blocka7e24c12009-10-30 11:49:00 +0000203// All Maps have a field instance_type containing a InstanceType.
204// It describes the type of the instances.
205//
206// As an example, a JavaScript object is a heap object and its map
207// instance_type is JS_OBJECT_TYPE.
208//
209// The names of the string instance types are intended to systematically
Leon Clarkee46be812010-01-19 14:06:41 +0000210// mirror their encoding in the instance_type field of the map. The default
211// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
212// encoding is mentioned explicitly in the name. Likewise, the default
213// representation is considered sequential. It is not mentioned in the
214// name. The other representations (eg, CONS, EXTERNAL) are explicitly
215// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
216// symbol) or a STRING_TYPE (if it is not a symbol).
Steve Blocka7e24c12009-10-30 11:49:00 +0000217//
218// NOTE: The following things are some that depend on the string types having
219// instance_types that are less than those of all other types:
220// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
221// Object::IsString.
222//
223// NOTE: Everything following JS_VALUE_TYPE is considered a
224// JSObject for GC purposes. The first four entries here have typeof
225// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
Steve Blockd0582a62009-12-15 09:54:21 +0000226#define INSTANCE_TYPE_LIST_ALL(V) \
227 V(SYMBOL_TYPE) \
228 V(ASCII_SYMBOL_TYPE) \
229 V(CONS_SYMBOL_TYPE) \
230 V(CONS_ASCII_SYMBOL_TYPE) \
231 V(EXTERNAL_SYMBOL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100232 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000233 V(EXTERNAL_ASCII_SYMBOL_TYPE) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000234 V(SHORT_EXTERNAL_SYMBOL_TYPE) \
235 V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
236 V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000237 V(STRING_TYPE) \
238 V(ASCII_STRING_TYPE) \
239 V(CONS_STRING_TYPE) \
240 V(CONS_ASCII_STRING_TYPE) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000241 V(SLICED_STRING_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000242 V(EXTERNAL_STRING_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100243 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000244 V(EXTERNAL_ASCII_STRING_TYPE) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000245 V(SHORT_EXTERNAL_STRING_TYPE) \
246 V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
247 V(SHORT_EXTERNAL_ASCII_STRING_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000248 V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
249 \
250 V(MAP_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000251 V(CODE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000252 V(ODDBALL_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100253 V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
Leon Clarkee46be812010-01-19 14:06:41 +0000254 \
255 V(HEAP_NUMBER_TYPE) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000256 V(FOREIGN_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000257 V(BYTE_ARRAY_TYPE) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000258 V(FREE_SPACE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000259 /* Note: the order of these external array */ \
260 /* types is relied upon in */ \
261 /* Object::IsExternalArray(). */ \
262 V(EXTERNAL_BYTE_ARRAY_TYPE) \
263 V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
264 V(EXTERNAL_SHORT_ARRAY_TYPE) \
265 V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
266 V(EXTERNAL_INT_ARRAY_TYPE) \
267 V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
268 V(EXTERNAL_FLOAT_ARRAY_TYPE) \
Steve Block44f0eee2011-05-26 01:26:41 +0100269 V(EXTERNAL_PIXEL_ARRAY_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000270 V(FILLER_TYPE) \
271 \
272 V(ACCESSOR_INFO_TYPE) \
273 V(ACCESS_CHECK_INFO_TYPE) \
274 V(INTERCEPTOR_INFO_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000275 V(CALL_HANDLER_INFO_TYPE) \
276 V(FUNCTION_TEMPLATE_INFO_TYPE) \
277 V(OBJECT_TEMPLATE_INFO_TYPE) \
278 V(SIGNATURE_INFO_TYPE) \
279 V(TYPE_SWITCH_INFO_TYPE) \
280 V(SCRIPT_TYPE) \
Steve Block6ded16b2010-05-10 14:33:55 +0100281 V(CODE_CACHE_TYPE) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000282 V(POLYMORPHIC_CODE_CACHE_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000283 \
Iain Merrick75681382010-08-19 15:07:18 +0100284 V(FIXED_ARRAY_TYPE) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000285 V(FIXED_DOUBLE_ARRAY_TYPE) \
Iain Merrick75681382010-08-19 15:07:18 +0100286 V(SHARED_FUNCTION_INFO_TYPE) \
287 \
Steve Block1e0659c2011-05-24 12:43:12 +0100288 V(JS_MESSAGE_OBJECT_TYPE) \
289 \
Steve Blockd0582a62009-12-15 09:54:21 +0000290 V(JS_VALUE_TYPE) \
291 V(JS_OBJECT_TYPE) \
292 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
293 V(JS_GLOBAL_OBJECT_TYPE) \
294 V(JS_BUILTINS_OBJECT_TYPE) \
295 V(JS_GLOBAL_PROXY_TYPE) \
296 V(JS_ARRAY_TYPE) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000297 V(JS_PROXY_TYPE) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000298 V(JS_WEAK_MAP_TYPE) \
Steve Blockd0582a62009-12-15 09:54:21 +0000299 V(JS_REGEXP_TYPE) \
300 \
301 V(JS_FUNCTION_TYPE) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000302 V(JS_FUNCTION_PROXY_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000303
304#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000305#define INSTANCE_TYPE_LIST_DEBUGGER(V) \
306 V(DEBUG_INFO_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 V(BREAK_POINT_INFO_TYPE)
308#else
309#define INSTANCE_TYPE_LIST_DEBUGGER(V)
310#endif
311
Steve Blockd0582a62009-12-15 09:54:21 +0000312#define INSTANCE_TYPE_LIST(V) \
313 INSTANCE_TYPE_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 INSTANCE_TYPE_LIST_DEBUGGER(V)
315
316
317// Since string types are not consecutive, this macro is used to
318// iterate over them.
319#define STRING_TYPE_LIST(V) \
Steve Blockd0582a62009-12-15 09:54:21 +0000320 V(SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100321 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000322 symbol, \
323 Symbol) \
324 V(ASCII_SYMBOL_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100325 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000326 ascii_symbol, \
327 AsciiSymbol) \
328 V(CONS_SYMBOL_TYPE, \
329 ConsString::kSize, \
330 cons_symbol, \
331 ConsSymbol) \
332 V(CONS_ASCII_SYMBOL_TYPE, \
333 ConsString::kSize, \
334 cons_ascii_symbol, \
335 ConsAsciiSymbol) \
336 V(EXTERNAL_SYMBOL_TYPE, \
337 ExternalTwoByteString::kSize, \
338 external_symbol, \
339 ExternalSymbol) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100340 V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
341 ExternalTwoByteString::kSize, \
342 external_symbol_with_ascii_data, \
343 ExternalSymbolWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000344 V(EXTERNAL_ASCII_SYMBOL_TYPE, \
345 ExternalAsciiString::kSize, \
346 external_ascii_symbol, \
347 ExternalAsciiSymbol) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000348 V(SHORT_EXTERNAL_SYMBOL_TYPE, \
349 ExternalTwoByteString::kShortSize, \
350 short_external_symbol, \
351 ShortExternalSymbol) \
352 V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
353 ExternalTwoByteString::kShortSize, \
354 short_external_symbol_with_ascii_data, \
355 ShortExternalSymbolWithAsciiData) \
356 V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE, \
357 ExternalAsciiString::kShortSize, \
358 short_external_ascii_symbol, \
359 ShortExternalAsciiSymbol) \
Steve Blockd0582a62009-12-15 09:54:21 +0000360 V(STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100361 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000362 string, \
363 String) \
364 V(ASCII_STRING_TYPE, \
Steve Block791712a2010-08-27 10:21:07 +0100365 kVariableSizeSentinel, \
Steve Blockd0582a62009-12-15 09:54:21 +0000366 ascii_string, \
367 AsciiString) \
368 V(CONS_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000370 cons_string, \
371 ConsString) \
372 V(CONS_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000373 ConsString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000374 cons_ascii_string, \
375 ConsAsciiString) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000376 V(SLICED_STRING_TYPE, \
377 SlicedString::kSize, \
378 sliced_string, \
379 SlicedString) \
380 V(SLICED_ASCII_STRING_TYPE, \
381 SlicedString::kSize, \
382 sliced_ascii_string, \
383 SlicedAsciiString) \
Steve Blockd0582a62009-12-15 09:54:21 +0000384 V(EXTERNAL_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 ExternalTwoByteString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000386 external_string, \
387 ExternalString) \
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100388 V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
389 ExternalTwoByteString::kSize, \
390 external_string_with_ascii_data, \
391 ExternalStringWithAsciiData) \
Steve Blockd0582a62009-12-15 09:54:21 +0000392 V(EXTERNAL_ASCII_STRING_TYPE, \
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 ExternalAsciiString::kSize, \
Steve Blockd0582a62009-12-15 09:54:21 +0000394 external_ascii_string, \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000395 ExternalAsciiString) \
396 V(SHORT_EXTERNAL_STRING_TYPE, \
397 ExternalTwoByteString::kShortSize, \
398 short_external_string, \
399 ShortExternalString) \
400 V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
401 ExternalTwoByteString::kShortSize, \
402 short_external_string_with_ascii_data, \
403 ShortExternalStringWithAsciiData) \
404 V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
405 ExternalAsciiString::kShortSize, \
406 short_external_ascii_string, \
407 ShortExternalAsciiString)
Steve Blocka7e24c12009-10-30 11:49:00 +0000408
409// A struct is a simple object a set of object-valued fields. Including an
410// object type in this causes the compiler to generate most of the boilerplate
411// code for the class including allocation and garbage collection routines,
412// casts and predicates. All you need to define is the class, methods and
413// object verification routines. Easy, no?
414//
415// Note that for subtle reasons related to the ordering or numerical values of
416// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
417// manually.
Steve Blockd0582a62009-12-15 09:54:21 +0000418#define STRUCT_LIST_ALL(V) \
419 V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
420 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
421 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
422 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
423 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
424 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
425 V(SIGNATURE_INFO, SignatureInfo, signature_info) \
426 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
Steve Block6ded16b2010-05-10 14:33:55 +0100427 V(SCRIPT, Script, script) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000428 V(CODE_CACHE, CodeCache, code_cache) \
429 V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache)
Steve Blocka7e24c12009-10-30 11:49:00 +0000430
431#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blockd0582a62009-12-15 09:54:21 +0000432#define STRUCT_LIST_DEBUGGER(V) \
433 V(DEBUG_INFO, DebugInfo, debug_info) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
435#else
436#define STRUCT_LIST_DEBUGGER(V)
437#endif
438
Steve Blockd0582a62009-12-15 09:54:21 +0000439#define STRUCT_LIST(V) \
440 STRUCT_LIST_ALL(V) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 STRUCT_LIST_DEBUGGER(V)
442
443// We use the full 8 bits of the instance_type field to encode heap object
444// instance types. The high-order bit (bit 7) is set if the object is not a
445// string, and cleared if it is a string.
446const uint32_t kIsNotStringMask = 0x80;
447const uint32_t kStringTag = 0x0;
448const uint32_t kNotStringTag = 0x80;
449
Leon Clarkee46be812010-01-19 14:06:41 +0000450// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
451// There are not enough types that the non-string types (with bit 7 set) can
452// have bit 6 set too.
453const uint32_t kIsSymbolMask = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000454const uint32_t kNotSymbolTag = 0x0;
Leon Clarkee46be812010-01-19 14:06:41 +0000455const uint32_t kSymbolTag = 0x40;
Steve Blocka7e24c12009-10-30 11:49:00 +0000456
Steve Blocka7e24c12009-10-30 11:49:00 +0000457// If bit 7 is clear then bit 2 indicates whether the string consists of
458// two-byte characters or one-byte characters.
459const uint32_t kStringEncodingMask = 0x4;
460const uint32_t kTwoByteStringTag = 0x0;
461const uint32_t kAsciiStringTag = 0x4;
462
463// If bit 7 is clear, the low-order 2 bits indicate the representation
464// of the string.
465const uint32_t kStringRepresentationMask = 0x03;
466enum StringRepresentationTag {
467 kSeqStringTag = 0x0,
468 kConsStringTag = 0x1,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000469 kExternalStringTag = 0x2,
470 kSlicedStringTag = 0x3
Steve Blocka7e24c12009-10-30 11:49:00 +0000471};
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000472const uint32_t kIsIndirectStringMask = 0x1;
473const uint32_t kIsIndirectStringTag = 0x1;
474STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0);
475STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0);
476STATIC_ASSERT(
477 (kConsStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
478STATIC_ASSERT(
479 (kSlicedStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
480
481// Use this mask to distinguish between cons and slice only after making
482// sure that the string is one of the two (an indirect string).
483const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
484STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000485
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100486// If bit 7 is clear, then bit 3 indicates whether this two-byte
487// string actually contains ascii data.
488const uint32_t kAsciiDataHintMask = 0x08;
489const uint32_t kAsciiDataHintTag = 0x08;
490
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000491// If bit 7 is clear and string representation indicates an external string,
492// then bit 4 indicates whether the data pointer is cached.
493const uint32_t kShortExternalStringMask = 0x10;
494const uint32_t kShortExternalStringTag = 0x10;
495
Steve Blocka7e24c12009-10-30 11:49:00 +0000496
497// A ConsString with an empty string as the right side is a candidate
498// for being shortcut by the garbage collector unless it is a
499// symbol. It's not common to have non-flat symbols, so we do not
500// shortcut them thereby avoiding turning symbols into strings. See
501// heap.cc and mark-compact.cc.
502const uint32_t kShortcutTypeMask =
503 kIsNotStringMask |
504 kIsSymbolMask |
505 kStringRepresentationMask;
506const uint32_t kShortcutTypeTag = kConsStringTag;
507
508
509enum InstanceType {
Leon Clarkee46be812010-01-19 14:06:41 +0000510 // String types.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100511 SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000512 ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100513 CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000514 CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000515 SHORT_EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag |
516 kExternalStringTag | kShortExternalStringTag,
517 SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
518 kTwoByteStringTag | kSymbolTag | kExternalStringTag |
519 kAsciiDataHintTag | kShortExternalStringTag,
520 SHORT_EXTERNAL_ASCII_SYMBOL_TYPE = kAsciiStringTag | kExternalStringTag |
521 kSymbolTag | kShortExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100522 EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
523 EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
524 kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000525 EXTERNAL_ASCII_SYMBOL_TYPE =
526 kAsciiStringTag | kSymbolTag | kExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100527 STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000528 ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100529 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
Steve Blockd0582a62009-12-15 09:54:21 +0000530 CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000531 SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
532 SLICED_ASCII_STRING_TYPE = kAsciiStringTag | kSlicedStringTag,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000533 SHORT_EXTERNAL_STRING_TYPE =
534 kTwoByteStringTag | kExternalStringTag | kShortExternalStringTag,
535 SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
536 kTwoByteStringTag | kExternalStringTag |
537 kAsciiDataHintTag | kShortExternalStringTag,
538 SHORT_EXTERNAL_ASCII_STRING_TYPE =
539 kAsciiStringTag | kExternalStringTag | kShortExternalStringTag,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100540 EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
541 EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
542 kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
Steve Block1e0659c2011-05-24 12:43:12 +0100543 // LAST_STRING_TYPE
Steve Blockd0582a62009-12-15 09:54:21 +0000544 EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
545 PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000546
Leon Clarkee46be812010-01-19 14:06:41 +0000547 // Objects allocated in their own spaces (never in new space).
548 MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000549 CODE_TYPE,
550 ODDBALL_TYPE,
551 JS_GLOBAL_PROPERTY_CELL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000552
553 // "Data", objects that cannot contain non-map-word pointers to heap
554 // objects.
555 HEAP_NUMBER_TYPE,
Ben Murdoch257744e2011-11-30 15:57:28 +0000556 FOREIGN_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000557 BYTE_ARRAY_TYPE,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000558 FREE_SPACE_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000559 EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
Steve Block3ce2e202009-11-05 08:53:23 +0000560 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
561 EXTERNAL_SHORT_ARRAY_TYPE,
562 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
563 EXTERNAL_INT_ARRAY_TYPE,
564 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100565 EXTERNAL_FLOAT_ARRAY_TYPE,
Ben Murdoch257744e2011-11-30 15:57:28 +0000566 EXTERNAL_DOUBLE_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100567 EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000568 FIXED_DOUBLE_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000569 FILLER_TYPE, // LAST_DATA_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000570
Leon Clarkee46be812010-01-19 14:06:41 +0000571 // Structs.
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 ACCESSOR_INFO_TYPE,
573 ACCESS_CHECK_INFO_TYPE,
574 INTERCEPTOR_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000575 CALL_HANDLER_INFO_TYPE,
576 FUNCTION_TEMPLATE_INFO_TYPE,
577 OBJECT_TEMPLATE_INFO_TYPE,
578 SIGNATURE_INFO_TYPE,
579 TYPE_SWITCH_INFO_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000580 SCRIPT_TYPE,
Steve Block6ded16b2010-05-10 14:33:55 +0100581 CODE_CACHE_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000582 POLYMORPHIC_CODE_CACHE_TYPE,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100583 // The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
584 // is defined. However as include/v8.h contain some of the instance type
585 // constants always having them avoids them getting different numbers
586 // depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 DEBUG_INFO_TYPE,
588 BREAK_POINT_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000589
Leon Clarkee46be812010-01-19 14:06:41 +0000590 FIXED_ARRAY_TYPE,
591 SHARED_FUNCTION_INFO_TYPE,
592
Steve Block1e0659c2011-05-24 12:43:12 +0100593 JS_MESSAGE_OBJECT_TYPE,
594
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000595 // All the following types are subtypes of JSReceiver, which corresponds to
596 // objects in the JS sense. The first and the last type in this range are
597 // the two forms of function. This organization enables using the same
598 // compares for checking the JS_RECEIVER/SPEC_OBJECT range and the
599 // NONCALLABLE_JS_OBJECT range.
600 JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE
601 JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE
602
603 JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000604 JS_OBJECT_TYPE,
605 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
606 JS_GLOBAL_OBJECT_TYPE,
607 JS_BUILTINS_OBJECT_TYPE,
608 JS_GLOBAL_PROXY_TYPE,
609 JS_ARRAY_TYPE,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000610 JS_SET_TYPE,
611 JS_MAP_TYPE,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000612 JS_WEAK_MAP_TYPE,
Steve Block1e0659c2011-05-24 12:43:12 +0100613
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000614 JS_REGEXP_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000615
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000616 JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000617
618 // Pseudo-types
Steve Blocka7e24c12009-10-30 11:49:00 +0000619 FIRST_TYPE = 0x0,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000620 LAST_TYPE = JS_FUNCTION_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000621 INVALID_TYPE = FIRST_TYPE - 1,
622 FIRST_NONSTRING_TYPE = MAP_TYPE,
623 // Boundaries for testing for an external array.
624 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
Steve Block44f0eee2011-05-26 01:26:41 +0100625 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000626 // Boundary for promotion to old data space/old pointer space.
627 LAST_DATA_TYPE = FILLER_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000628 // Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
629 // Note that there is no range for JSObject or JSProxy, since their subtypes
630 // are not continuous in this enum! The enum ranges instead reflect the
631 // external class names, where proxies are treated as either ordinary objects,
632 // or functions.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000633 FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000634 LAST_JS_RECEIVER_TYPE = LAST_TYPE,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000635 // Boundaries for testing the types represented as JSObject
636 FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
637 LAST_JS_OBJECT_TYPE = LAST_TYPE,
638 // Boundaries for testing the types represented as JSProxy
639 FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE,
640 LAST_JS_PROXY_TYPE = JS_PROXY_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000641 // Boundaries for testing whether the type is a JavaScript object.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000642 FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE,
643 LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE,
644 // Boundaries for testing the types for which typeof is "object".
645 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE,
646 LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE,
647 // Note that the types for which typeof is "function" are not continuous.
648 // Define this so that we can put assertions on discrete checks.
649 NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2
Steve Blocka7e24c12009-10-30 11:49:00 +0000650};
651
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000652const int kExternalArrayTypeCount =
653 LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000654
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100655STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
656STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
Ben Murdoch257744e2011-11-30 15:57:28 +0000657STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100658
659
Steve Blocka7e24c12009-10-30 11:49:00 +0000660enum CompareResult {
661 LESS = -1,
662 EQUAL = 0,
663 GREATER = 1,
664
665 NOT_EQUAL = GREATER
666};
667
668
669#define DECL_BOOLEAN_ACCESSORS(name) \
670 inline bool name(); \
671 inline void set_##name(bool value); \
672
673
674#define DECL_ACCESSORS(name, type) \
675 inline type* name(); \
676 inline void set_##name(type* value, \
677 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
678
679
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000680class DictionaryElementsAccessor;
681class ElementsAccessor;
682class FixedArrayBase;
Steve Blocka7e24c12009-10-30 11:49:00 +0000683class ObjectVisitor;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000684class StringStream;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000685class Failure;
Steve Blocka7e24c12009-10-30 11:49:00 +0000686
687struct ValueInfo : public Malloced {
688 ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
689 InstanceType type;
690 Object* ptr;
691 const char* str;
692 double number;
693};
694
695
696// A template-ized version of the IsXXX functions.
697template <class C> static inline bool Is(Object* obj);
698
Ben Murdochb0fe1622011-05-05 13:52:32 +0100699
John Reck59135872010-11-02 12:39:01 -0700700class MaybeObject BASE_EMBEDDED {
701 public:
702 inline bool IsFailure();
703 inline bool IsRetryAfterGC();
704 inline bool IsOutOfMemory();
705 inline bool IsException();
706 INLINE(bool IsTheHole());
707 inline bool ToObject(Object** obj) {
708 if (IsFailure()) return false;
709 *obj = reinterpret_cast<Object*>(this);
710 return true;
711 }
Steve Block053d10c2011-06-13 19:13:29 +0100712 inline Failure* ToFailureUnchecked() {
713 ASSERT(IsFailure());
714 return reinterpret_cast<Failure*>(this);
715 }
John Reck59135872010-11-02 12:39:01 -0700716 inline Object* ToObjectUnchecked() {
717 ASSERT(!IsFailure());
718 return reinterpret_cast<Object*>(this);
719 }
720 inline Object* ToObjectChecked() {
721 CHECK(!IsFailure());
722 return reinterpret_cast<Object*>(this);
723 }
724
Steve Block053d10c2011-06-13 19:13:29 +0100725 template<typename T>
726 inline bool To(T** obj) {
727 if (IsFailure()) return false;
728 *obj = T::cast(reinterpret_cast<Object*>(this));
729 return true;
730 }
731
Ben Murdochb0fe1622011-05-05 13:52:32 +0100732#ifdef OBJECT_PRINT
John Reck59135872010-11-02 12:39:01 -0700733 // Prints this object with details.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100734 inline void Print() {
735 Print(stdout);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000736 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100737 inline void PrintLn() {
738 PrintLn(stdout);
739 }
740 void Print(FILE* out);
741 void PrintLn(FILE* out);
742#endif
743#ifdef DEBUG
John Reck59135872010-11-02 12:39:01 -0700744 // Verifies the object.
745 void Verify();
746#endif
747};
Steve Blocka7e24c12009-10-30 11:49:00 +0000748
Ben Murdochb8e0da22011-05-16 14:20:40 +0100749
750#define OBJECT_TYPE_LIST(V) \
751 V(Smi) \
752 V(HeapObject) \
753 V(Number) \
754
755#define HEAP_OBJECT_TYPE_LIST(V) \
756 V(HeapNumber) \
757 V(String) \
758 V(Symbol) \
759 V(SeqString) \
760 V(ExternalString) \
761 V(ConsString) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000762 V(SlicedString) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100763 V(ExternalTwoByteString) \
764 V(ExternalAsciiString) \
765 V(SeqTwoByteString) \
766 V(SeqAsciiString) \
767 \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100768 V(ExternalArray) \
769 V(ExternalByteArray) \
770 V(ExternalUnsignedByteArray) \
771 V(ExternalShortArray) \
772 V(ExternalUnsignedShortArray) \
773 V(ExternalIntArray) \
774 V(ExternalUnsignedIntArray) \
775 V(ExternalFloatArray) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000776 V(ExternalDoubleArray) \
Steve Block44f0eee2011-05-26 01:26:41 +0100777 V(ExternalPixelArray) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100778 V(ByteArray) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000779 V(FreeSpace) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000780 V(JSReceiver) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100781 V(JSObject) \
782 V(JSContextExtensionObject) \
783 V(Map) \
784 V(DescriptorArray) \
785 V(DeoptimizationInputData) \
786 V(DeoptimizationOutputData) \
787 V(FixedArray) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000788 V(FixedDoubleArray) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100789 V(Context) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100790 V(GlobalContext) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000791 V(ScopeInfo) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100792 V(JSFunction) \
793 V(Code) \
794 V(Oddball) \
795 V(SharedFunctionInfo) \
796 V(JSValue) \
Steve Block1e0659c2011-05-24 12:43:12 +0100797 V(JSMessageObject) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100798 V(StringWrapper) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000799 V(Foreign) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100800 V(Boolean) \
801 V(JSArray) \
Ben Murdoch257744e2011-11-30 15:57:28 +0000802 V(JSProxy) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000803 V(JSFunctionProxy) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000804 V(JSSet) \
805 V(JSMap) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000806 V(JSWeakMap) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100807 V(JSRegExp) \
808 V(HashTable) \
809 V(Dictionary) \
810 V(SymbolTable) \
811 V(JSFunctionResultCache) \
812 V(NormalizedMapCache) \
813 V(CompilationCacheTable) \
814 V(CodeCacheHashTable) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000815 V(PolymorphicCodeCacheHashTable) \
Ben Murdochb8e0da22011-05-16 14:20:40 +0100816 V(MapCache) \
817 V(Primitive) \
818 V(GlobalObject) \
819 V(JSGlobalObject) \
820 V(JSBuiltinsObject) \
821 V(JSGlobalProxy) \
822 V(UndetectableObject) \
823 V(AccessCheckNeeded) \
824 V(JSGlobalPropertyCell) \
825
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000826
827class JSReceiver;
828
Steve Blocka7e24c12009-10-30 11:49:00 +0000829// Object is the abstract superclass for all classes in the
830// object hierarchy.
831// Object does not use any virtual functions to avoid the
832// allocation of the C++ vtable.
833// Since Smi and Failure are subclasses of Object no
834// data members can be present in Object.
John Reck59135872010-11-02 12:39:01 -0700835class Object : public MaybeObject {
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 public:
837 // Type testing.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100838#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
839 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
840 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
841#undef IS_TYPE_FUNCTION_DECL
Steve Blocka7e24c12009-10-30 11:49:00 +0000842
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000843 inline bool IsFixedArrayBase();
844
Steve Blocka7e24c12009-10-30 11:49:00 +0000845 // Returns true if this object is an instance of the specified
846 // function template.
847 inline bool IsInstanceOf(FunctionTemplateInfo* type);
848
849 inline bool IsStruct();
850#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
851 STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
852#undef DECLARE_STRUCT_PREDICATE
853
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000854 INLINE(bool IsSpecObject());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000855 INLINE(bool IsSpecFunction());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000856
Steve Blocka7e24c12009-10-30 11:49:00 +0000857 // Oddball testing.
858 INLINE(bool IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 INLINE(bool IsNull());
Steve Block44f0eee2011-05-26 01:26:41 +0100860 INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 INLINE(bool IsTrue());
862 INLINE(bool IsFalse());
Ben Murdoch086aeea2011-05-13 15:57:08 +0100863 inline bool IsArgumentsMarker();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000864 inline bool NonFailureIsHeapObject();
865
866 // Filler objects (fillers and free space objects).
867 inline bool IsFiller();
Steve Blocka7e24c12009-10-30 11:49:00 +0000868
869 // Extract the number.
870 inline double Number();
871
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000872 // Returns true if the object is of the correct type to be used as a
873 // implementation of a JSObject's elements.
874 inline bool HasValidElements();
875
Steve Blocka7e24c12009-10-30 11:49:00 +0000876 inline bool HasSpecificClassOf(String* name);
877
John Reck59135872010-11-02 12:39:01 -0700878 MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9.
879 Object* ToBoolean(); // ECMA-262 9.2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000880
881 // Convert to a JSObject if needed.
882 // global_context is used when creating wrapper object.
John Reck59135872010-11-02 12:39:01 -0700883 MUST_USE_RESULT MaybeObject* ToObject(Context* global_context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000884
885 // Converts this to a Smi if possible.
886 // Failure is returned otherwise.
John Reck59135872010-11-02 12:39:01 -0700887 MUST_USE_RESULT inline MaybeObject* ToSmi();
Steve Blocka7e24c12009-10-30 11:49:00 +0000888
889 void Lookup(String* name, LookupResult* result);
890
891 // Property access.
John Reck59135872010-11-02 12:39:01 -0700892 MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
893 MUST_USE_RESULT inline MaybeObject* GetProperty(
894 String* key,
895 PropertyAttributes* attributes);
896 MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
897 Object* receiver,
898 String* key,
899 PropertyAttributes* attributes);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000900
901 static Handle<Object> GetProperty(Handle<Object> object,
902 Handle<Object> receiver,
903 LookupResult* result,
904 Handle<String> key,
905 PropertyAttributes* attributes);
906
John Reck59135872010-11-02 12:39:01 -0700907 MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
908 LookupResult* result,
909 String* key,
910 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000911
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000912 MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
913 JSReceiver* getter);
914
915 static Handle<Object> GetElement(Handle<Object> object, uint32_t index);
John Reck59135872010-11-02 12:39:01 -0700916 inline MaybeObject* GetElement(uint32_t index);
917 // For use when we know that no exception can be thrown.
918 inline Object* GetElementNoExceptionThrown(uint32_t index);
919 MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000920
921 // Return the object's prototype (might be Heap::null_value()).
922 Object* GetPrototype();
923
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000924 // Returns the permanent hash code associated with this object depending on
925 // the actual object type. Might return a failure in case no hash was
926 // created yet or GC was caused by creation.
927 MUST_USE_RESULT MaybeObject* GetHash(CreationFlag flag);
928
929 // Checks whether this object has the same value as the given one. This
930 // function is implemented according to ES5, section 9.12 and can be used
931 // to implement the Harmony "egal" function.
932 bool SameValue(Object* other);
933
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100934 // Tries to convert an object to an array index. Returns true and sets
935 // the output parameter if it succeeds.
936 inline bool ToArrayIndex(uint32_t* index);
937
Steve Blocka7e24c12009-10-30 11:49:00 +0000938 // Returns true if this is a JSValue containing a string and the index is
939 // < the length of the string. Used to implement [] on strings.
940 inline bool IsStringObjectWithCharacterAt(uint32_t index);
941
942#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 // Verify a pointer is a valid object pointer.
944 static void VerifyPointer(Object* p);
945#endif
946
947 // Prints this object without details.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100948 inline void ShortPrint() {
949 ShortPrint(stdout);
950 }
951 void ShortPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000952
953 // Prints this object without details to a message accumulator.
954 void ShortPrint(StringStream* accumulator);
955
956 // Casting: This cast is only needed to satisfy macros in objects-inl.h.
957 static Object* cast(Object* value) { return value; }
958
959 // Layout description.
960 static const int kHeaderSize = 0; // Object does not take up any space.
961
962 private:
963 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
964};
965
966
967// Smi represents integer Numbers that can be stored in 31 bits.
968// Smis are immediate which means they are NOT allocated in the heap.
Steve Blocka7e24c12009-10-30 11:49:00 +0000969// The this pointer has the following format: [31 bit signed int] 0
Steve Block3ce2e202009-11-05 08:53:23 +0000970// For long smis it has the following format:
971// [32 bit signed int] [31 bits zero padding] 0
972// Smi stands for small integer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000973class Smi: public Object {
974 public:
975 // Returns the integer value.
976 inline int value();
977
978 // Convert a value to a Smi object.
979 static inline Smi* FromInt(int value);
980
981 static inline Smi* FromIntptr(intptr_t value);
982
983 // Returns whether value can be represented in a Smi.
984 static inline bool IsValid(intptr_t value);
985
Steve Blocka7e24c12009-10-30 11:49:00 +0000986 // Casting.
987 static inline Smi* cast(Object* object);
988
989 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100990 inline void SmiPrint() {
991 SmiPrint(stdout);
992 }
993 void SmiPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 void SmiPrint(StringStream* accumulator);
995#ifdef DEBUG
996 void SmiVerify();
997#endif
998
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000999 static const int kMinValue =
1000 (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
Steve Block3ce2e202009-11-05 08:53:23 +00001001 static const int kMaxValue = -(kMinValue + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001002
1003 private:
1004 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
1005};
1006
1007
1008// Failure is used for reporting out of memory situations and
1009// propagating exceptions through the runtime system. Failure objects
1010// are transient and cannot occur as part of the object graph.
1011//
1012// Failures are a single word, encoded as follows:
1013// +-------------------------+---+--+--+
Ben Murdochf87a2032010-10-22 12:50:53 +01001014// |.........unused..........|sss|tt|11|
Steve Blocka7e24c12009-10-30 11:49:00 +00001015// +-------------------------+---+--+--+
Steve Block3ce2e202009-11-05 08:53:23 +00001016// 7 6 4 32 10
1017//
Steve Blocka7e24c12009-10-30 11:49:00 +00001018//
1019// The low two bits, 0-1, are the failure tag, 11. The next two bits,
1020// 2-3, are a failure type tag 'tt' with possible values:
1021// 00 RETRY_AFTER_GC
1022// 01 EXCEPTION
1023// 10 INTERNAL_ERROR
1024// 11 OUT_OF_MEMORY_EXCEPTION
1025//
1026// The next three bits, 4-6, are an allocation space tag 'sss'. The
1027// allocation space tag is 000 for all failure types except
1028// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
1029// allocation spaces (the encoding is found in globals.h).
Steve Blocka7e24c12009-10-30 11:49:00 +00001030
1031// Failure type tag info.
1032const int kFailureTypeTagSize = 2;
1033const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
1034
John Reck59135872010-11-02 12:39:01 -07001035class Failure: public MaybeObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 public:
1037 // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
1038 enum Type {
1039 RETRY_AFTER_GC = 0,
1040 EXCEPTION = 1, // Returning this marker tells the real exception
Steve Block44f0eee2011-05-26 01:26:41 +01001041 // is in Isolate::pending_exception.
Steve Blocka7e24c12009-10-30 11:49:00 +00001042 INTERNAL_ERROR = 2,
1043 OUT_OF_MEMORY_EXCEPTION = 3
1044 };
1045
1046 inline Type type() const;
1047
1048 // Returns the space that needs to be collected for RetryAfterGC failures.
1049 inline AllocationSpace allocation_space() const;
1050
Steve Blocka7e24c12009-10-30 11:49:00 +00001051 inline bool IsInternalError() const;
1052 inline bool IsOutOfMemoryException() const;
1053
Ben Murdochf87a2032010-10-22 12:50:53 +01001054 static inline Failure* RetryAfterGC(AllocationSpace space);
1055 static inline Failure* RetryAfterGC(); // NEW_SPACE
Steve Blocka7e24c12009-10-30 11:49:00 +00001056 static inline Failure* Exception();
1057 static inline Failure* InternalError();
1058 static inline Failure* OutOfMemoryException();
1059 // Casting.
John Reck59135872010-11-02 12:39:01 -07001060 static inline Failure* cast(MaybeObject* object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001061
1062 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001063 inline void FailurePrint() {
1064 FailurePrint(stdout);
1065 }
1066 void FailurePrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001067 void FailurePrint(StringStream* accumulator);
1068#ifdef DEBUG
1069 void FailureVerify();
1070#endif
1071
1072 private:
Steve Block3ce2e202009-11-05 08:53:23 +00001073 inline intptr_t value() const;
1074 static inline Failure* Construct(Type type, intptr_t value = 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001075
1076 DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
1077};
1078
1079
1080// Heap objects typically have a map pointer in their first word. However,
1081// during GC other data (eg, mark bits, forwarding addresses) is sometimes
1082// encoded in the first word. The class MapWord is an abstraction of the
1083// value in a heap object's first word.
1084class MapWord BASE_EMBEDDED {
1085 public:
1086 // Normal state: the map word contains a map pointer.
1087
1088 // Create a map word from a map pointer.
1089 static inline MapWord FromMap(Map* map);
1090
1091 // View this map word as a map pointer.
1092 inline Map* ToMap();
1093
1094
1095 // Scavenge collection: the map word of live objects in the from space
1096 // contains a forwarding address (a heap object pointer in the to space).
1097
1098 // True if this map word is a forwarding address for a scavenge
1099 // collection. Only valid during a scavenge collection (specifically,
1100 // when all map words are heap object pointers, ie. not during a full GC).
1101 inline bool IsForwardingAddress();
1102
1103 // Create a map word from a forwarding address.
1104 static inline MapWord FromForwardingAddress(HeapObject* object);
1105
1106 // View this map word as a forwarding address.
1107 inline HeapObject* ToForwardingAddress();
1108
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001109 static inline MapWord FromRawValue(uintptr_t value) {
1110 return MapWord(value);
1111 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001112
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001113 inline uintptr_t ToRawValue() {
1114 return value_;
1115 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001116
1117 private:
1118 // HeapObject calls the private constructor and directly reads the value.
1119 friend class HeapObject;
1120
1121 explicit MapWord(uintptr_t value) : value_(value) {}
1122
1123 uintptr_t value_;
1124};
1125
1126
1127// HeapObject is the superclass for all classes describing heap allocated
1128// objects.
1129class HeapObject: public Object {
1130 public:
1131 // [map]: Contains a map which contains the object's reflective
1132 // information.
1133 inline Map* map();
1134 inline void set_map(Map* value);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001135 inline void set_map_unsafe(Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001136
1137 // During garbage collection, the map word of a heap object does not
1138 // necessarily contain a map pointer.
1139 inline MapWord map_word();
1140 inline void set_map_word(MapWord map_word);
1141
Steve Block44f0eee2011-05-26 01:26:41 +01001142 // The Heap the object was allocated in. Used also to access Isolate.
Steve Block44f0eee2011-05-26 01:26:41 +01001143 inline Heap* GetHeap();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001144
Steve Block44f0eee2011-05-26 01:26:41 +01001145 // Convenience method to get current isolate. This method can be
1146 // accessed only when its result is the same as
1147 // Isolate::Current(), it ASSERTs this. See also comment for GetHeap.
1148 inline Isolate* GetIsolate();
1149
Steve Blocka7e24c12009-10-30 11:49:00 +00001150 // Converts an address to a HeapObject pointer.
1151 static inline HeapObject* FromAddress(Address address);
1152
1153 // Returns the address of this HeapObject.
1154 inline Address address();
1155
1156 // Iterates over pointers contained in the object (including the Map)
1157 void Iterate(ObjectVisitor* v);
1158
1159 // Iterates over all pointers contained in the object except the
1160 // first map pointer. The object type is given in the first
1161 // parameter. This function does not access the map pointer in the
1162 // object, and so is safe to call while the map pointer is modified.
1163 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
1164
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 // Returns the heap object's size in bytes
1166 inline int Size();
1167
1168 // Given a heap object's map pointer, returns the heap size in bytes
1169 // Useful when the map pointer field is used for other purposes.
1170 // GC internal.
1171 inline int SizeFromMap(Map* map);
1172
Steve Blocka7e24c12009-10-30 11:49:00 +00001173 // Returns the field at offset in obj, as a read/write Object* reference.
1174 // Does no checking, and is safe to use during GC, while maps are invalid.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001175 // Does not invoke write barrier, so should only be assigned to
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 // during marking GC.
1177 static inline Object** RawField(HeapObject* obj, int offset);
1178
1179 // Casting.
1180 static inline HeapObject* cast(Object* obj);
1181
Leon Clarke4515c472010-02-03 11:58:03 +00001182 // Return the write barrier mode for this. Callers of this function
1183 // must be able to present a reference to an AssertNoAllocation
1184 // object as a sign that they are not going to use this function
1185 // from code that allocates and thus invalidates the returned write
1186 // barrier mode.
1187 inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
Steve Blocka7e24c12009-10-30 11:49:00 +00001188
1189 // Dispatched behavior.
1190 void HeapObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001191#ifdef OBJECT_PRINT
1192 inline void HeapObjectPrint() {
1193 HeapObjectPrint(stdout);
1194 }
1195 void HeapObjectPrint(FILE* out);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001196 void PrintHeader(FILE* out, const char* id);
1197#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001198
Ben Murdochb0fe1622011-05-05 13:52:32 +01001199#ifdef DEBUG
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001200 void HeapObjectVerify();
1201 inline void VerifyObjectField(int offset);
1202 inline void VerifySmiField(int offset);
1203
Steve Blocka7e24c12009-10-30 11:49:00 +00001204 // Verify a pointer is a valid HeapObject pointer that points to object
1205 // areas in the heap.
1206 static void VerifyHeapPointer(Object* p);
1207#endif
1208
1209 // Layout description.
1210 // First field in a heap object is map.
1211 static const int kMapOffset = Object::kHeaderSize;
1212 static const int kHeaderSize = kMapOffset + kPointerSize;
1213
1214 STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
1215
1216 protected:
1217 // helpers for calling an ObjectVisitor to iterate over pointers in the
1218 // half-open range [start, end) specified as integer offsets
1219 inline void IteratePointers(ObjectVisitor* v, int start, int end);
1220 // as above, for the single element at "offset"
1221 inline void IteratePointer(ObjectVisitor* v, int offset);
1222
Steve Blocka7e24c12009-10-30 11:49:00 +00001223 private:
1224 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
1225};
1226
1227
Iain Merrick75681382010-08-19 15:07:18 +01001228#define SLOT_ADDR(obj, offset) \
1229 reinterpret_cast<Object**>((obj)->address() + offset)
1230
1231// This class describes a body of an object of a fixed size
1232// in which all pointer fields are located in the [start_offset, end_offset)
1233// interval.
1234template<int start_offset, int end_offset, int size>
1235class FixedBodyDescriptor {
1236 public:
1237 static const int kStartOffset = start_offset;
1238 static const int kEndOffset = end_offset;
1239 static const int kSize = size;
1240
1241 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
1242
1243 template<typename StaticVisitor>
1244 static inline void IterateBody(HeapObject* obj) {
1245 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1246 SLOT_ADDR(obj, end_offset));
1247 }
1248};
1249
1250
1251// This class describes a body of an object of a variable size
1252// in which all pointer fields are located in the [start_offset, object_size)
1253// interval.
1254template<int start_offset>
1255class FlexibleBodyDescriptor {
1256 public:
1257 static const int kStartOffset = start_offset;
1258
1259 static inline void IterateBody(HeapObject* obj,
1260 int object_size,
1261 ObjectVisitor* v);
1262
1263 template<typename StaticVisitor>
1264 static inline void IterateBody(HeapObject* obj, int object_size) {
1265 StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
1266 SLOT_ADDR(obj, object_size));
1267 }
1268};
1269
1270#undef SLOT_ADDR
1271
1272
Steve Blocka7e24c12009-10-30 11:49:00 +00001273// The HeapNumber class describes heap allocated numbers that cannot be
1274// represented in a Smi (small integer)
1275class HeapNumber: public HeapObject {
1276 public:
1277 // [value]: number value.
1278 inline double value();
1279 inline void set_value(double value);
1280
1281 // Casting.
1282 static inline HeapNumber* cast(Object* obj);
1283
1284 // Dispatched behavior.
1285 Object* HeapNumberToBoolean();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001286 inline void HeapNumberPrint() {
1287 HeapNumberPrint(stdout);
1288 }
1289 void HeapNumberPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 void HeapNumberPrint(StringStream* accumulator);
1291#ifdef DEBUG
1292 void HeapNumberVerify();
1293#endif
1294
Steve Block6ded16b2010-05-10 14:33:55 +01001295 inline int get_exponent();
1296 inline int get_sign();
1297
Steve Blocka7e24c12009-10-30 11:49:00 +00001298 // Layout description.
1299 static const int kValueOffset = HeapObject::kHeaderSize;
1300 // IEEE doubles are two 32 bit words. The first is just mantissa, the second
1301 // is a mixture of sign, exponent and mantissa. Our current platforms are all
1302 // little endian apart from non-EABI arm which is little endian with big
1303 // endian floating point word ordering!
Steve Blocka7e24c12009-10-30 11:49:00 +00001304 static const int kMantissaOffset = kValueOffset;
1305 static const int kExponentOffset = kValueOffset + 4;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001306
Steve Blocka7e24c12009-10-30 11:49:00 +00001307 static const int kSize = kValueOffset + kDoubleSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 static const uint32_t kSignMask = 0x80000000u;
1309 static const uint32_t kExponentMask = 0x7ff00000u;
1310 static const uint32_t kMantissaMask = 0xfffffu;
Steve Block6ded16b2010-05-10 14:33:55 +01001311 static const int kMantissaBits = 52;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001312 static const int kExponentBits = 11;
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 static const int kExponentBias = 1023;
1314 static const int kExponentShift = 20;
1315 static const int kMantissaBitsInTopWord = 20;
1316 static const int kNonMantissaBitsInTopWord = 12;
1317
1318 private:
1319 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1320};
1321
1322
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001323// JSReceiver includes types on which properties can be defined, i.e.,
1324// JSObject and JSProxy.
1325class JSReceiver: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001326 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001327 enum DeleteMode {
1328 NORMAL_DELETION,
1329 STRICT_DELETION,
1330 FORCE_DELETION
1331 };
1332
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001333 // Casting.
1334 static inline JSReceiver* cast(Object* obj);
1335
1336 // Can cause GC.
1337 MUST_USE_RESULT MaybeObject* SetProperty(String* key,
1338 Object* value,
1339 PropertyAttributes attributes,
1340 StrictModeFlag strict_mode);
1341 MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
1342 String* key,
1343 Object* value,
1344 PropertyAttributes attributes,
1345 StrictModeFlag strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001346 MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
1347 Object* value);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001348
1349 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001350 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
1351
1352 // Set the index'th array element.
1353 // Can cause GC, or return failure if GC is required.
1354 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1355 Object* value,
1356 StrictModeFlag strict_mode,
1357 bool check_prototype);
1358
1359 // Tests for the fast common case for property enumeration.
1360 bool IsSimpleEnum();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001361
1362 // Returns the class name ([[Class]] property in the specification).
1363 String* class_name();
1364
1365 // Returns the constructor name (the name (possibly, inferred name) of the
1366 // function that was used to instantiate the object).
1367 String* constructor_name();
1368
1369 inline PropertyAttributes GetPropertyAttribute(String* name);
1370 PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
1371 String* name);
1372 PropertyAttributes GetLocalPropertyAttribute(String* name);
1373
1374 // Can cause a GC.
1375 inline bool HasProperty(String* name);
1376 inline bool HasLocalProperty(String* name);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001377 inline bool HasElement(uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001378
1379 // Return the object's prototype (might be Heap::null_value()).
1380 inline Object* GetPrototype();
1381
1382 // Set the object's prototype (only JSReceiver and null are allowed).
1383 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
1384 bool skip_hidden_prototypes);
1385
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001386 // Retrieves a permanent object identity hash code. The undefined value might
1387 // be returned in case no hash was created yet and OMIT_CREATION was used.
1388 inline MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
1389
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001390 // Lookup a property. If found, the result is valid and has
1391 // detailed information.
1392 void LocalLookup(String* name, LookupResult* result);
1393 void Lookup(String* name, LookupResult* result);
1394
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001395 protected:
1396 Smi* GenerateIdentityHash();
1397
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001398 private:
1399 PropertyAttributes GetPropertyAttribute(JSReceiver* receiver,
1400 LookupResult* result,
1401 String* name,
1402 bool continue_search);
1403
1404 DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
1405};
1406
1407// The JSObject describes real heap allocated JavaScript objects with
1408// properties.
1409// Note that the map of JSObject changes during execution to enable inline
1410// caching.
1411class JSObject: public JSReceiver {
1412 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 // [properties]: Backing storage for properties.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001414 // properties is a FixedArray in the fast case and a Dictionary in the
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 // slow case.
1416 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
1417 inline void initialize_properties();
1418 inline bool HasFastProperties();
1419 inline StringDictionary* property_dictionary(); // Gets slow properties.
1420
1421 // [elements]: The elements (properties with names that are integers).
Iain Merrick75681382010-08-19 15:07:18 +01001422 //
1423 // Elements can be in two general modes: fast and slow. Each mode
1424 // corrensponds to a set of object representations of elements that
1425 // have something in common.
1426 //
1427 // In the fast mode elements is a FixedArray and so each element can
1428 // be quickly accessed. This fact is used in the generated code. The
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001429 // elements array can have one of three maps in this mode:
1430 // fixed_array_map, non_strict_arguments_elements_map or
1431 // fixed_cow_array_map (for copy-on-write arrays). In the latter case
1432 // the elements array may be shared by a few objects and so before
1433 // writing to any element the array must be copied. Use
1434 // EnsureWritableFastElements in this case.
Iain Merrick75681382010-08-19 15:07:18 +01001435 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001436 // In the slow mode the elements is either a NumberDictionary, an
1437 // ExternalArray, or a FixedArray parameter map for a (non-strict)
1438 // arguments object.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001439 DECL_ACCESSORS(elements, FixedArrayBase)
Steve Blocka7e24c12009-10-30 11:49:00 +00001440 inline void initialize_elements();
John Reck59135872010-11-02 12:39:01 -07001441 MUST_USE_RESULT inline MaybeObject* ResetElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001442 inline ElementsKind GetElementsKind();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001443 inline ElementsAccessor* GetElementsAccessor();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001444 inline bool HasFastSmiOnlyElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 inline bool HasFastElements();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001446 // Returns if an object has either FAST_ELEMENT or FAST_SMI_ONLY_ELEMENT
1447 // elements. TODO(danno): Rename HasFastTypeElements to HasFastElements() and
1448 // HasFastElements to HasFastObjectElements.
1449 inline bool HasFastTypeElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001450 inline bool HasFastDoubleElements();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001451 inline bool HasNonStrictArgumentsElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001452 inline bool HasDictionaryElements();
Steve Block44f0eee2011-05-26 01:26:41 +01001453 inline bool HasExternalPixelElements();
Steve Block3ce2e202009-11-05 08:53:23 +00001454 inline bool HasExternalArrayElements();
1455 inline bool HasExternalByteElements();
1456 inline bool HasExternalUnsignedByteElements();
1457 inline bool HasExternalShortElements();
1458 inline bool HasExternalUnsignedShortElements();
1459 inline bool HasExternalIntElements();
1460 inline bool HasExternalUnsignedIntElements();
1461 inline bool HasExternalFloatElements();
Ben Murdoch257744e2011-11-30 15:57:28 +00001462 inline bool HasExternalDoubleElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001463 bool HasFastArgumentsElements();
1464 bool HasDictionaryArgumentsElements();
Steve Block6ded16b2010-05-10 14:33:55 +01001465 inline bool AllowsSetElementsLength();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001466 inline NumberDictionary* element_dictionary(); // Gets slow elements.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001467
1468 // Requires: HasFastElements().
John Reck59135872010-11-02 12:39:01 -07001469 MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001470
1471 // Collects elements starting at index 0.
1472 // Undefined values are placed after non-undefined values.
1473 // Returns the number of non-undefined values.
John Reck59135872010-11-02 12:39:01 -07001474 MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 // As PrepareElementsForSort, but only on objects where elements is
1476 // a dictionary, and it will stay a dictionary.
John Reck59135872010-11-02 12:39:01 -07001477 MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001478
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001479 MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
1480 Object* structure,
1481 String* name);
1482
1483 // Can cause GC.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001484 MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
John Reck59135872010-11-02 12:39:01 -07001485 String* key,
1486 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001487 PropertyAttributes attributes,
1488 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001489 MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
1490 LookupResult* result,
1491 String* name,
Ben Murdoch086aeea2011-05-13 15:57:08 +01001492 Object* value,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001493 bool check_prototype,
1494 StrictModeFlag strict_mode);
1495 MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
1496 Object* structure,
1497 String* name,
1498 Object* value,
1499 JSObject* holder,
1500 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001501 MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
1502 String* name,
1503 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001504 PropertyAttributes attributes,
1505 StrictModeFlag strict_mode);
John Reck59135872010-11-02 12:39:01 -07001506 MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
1507 String* name,
1508 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001509 PropertyAttributes attributes,
1510 StrictModeFlag strict_mode);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001511 MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
John Reck59135872010-11-02 12:39:01 -07001512 String* key,
1513 Object* value,
1514 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001515
1516 // Retrieve a value in a normalized object given a lookup result.
1517 // Handles the special representation of JS global objects.
1518 Object* GetNormalizedProperty(LookupResult* result);
1519
1520 // Sets the property value in a normalized object given a lookup result.
1521 // Handles the special representation of JS global objects.
1522 Object* SetNormalizedProperty(LookupResult* result, Object* value);
1523
1524 // Sets the property value in a normalized object given (key, value, details).
1525 // Handles the special representation of JS global objects.
John Reck59135872010-11-02 12:39:01 -07001526 MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
1527 Object* value,
1528 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00001529
1530 // Deletes the named property in a normalized object.
John Reck59135872010-11-02 12:39:01 -07001531 MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
1532 DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001533
Steve Blocka7e24c12009-10-30 11:49:00 +00001534 // Retrieve interceptors.
1535 InterceptorInfo* GetNamedInterceptor();
1536 InterceptorInfo* GetIndexedInterceptor();
1537
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001538 // Used from JSReceiver.
1539 PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
1540 String* name,
1541 bool continue_search);
1542 PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
1543 String* name,
1544 bool continue_search);
1545 PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
1546 Object* receiver,
1547 LookupResult* result,
1548 String* name,
1549 bool continue_search);
Steve Blocka7e24c12009-10-30 11:49:00 +00001550
John Reck59135872010-11-02 12:39:01 -07001551 MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
1552 bool is_getter,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001553 Object* fun,
John Reck59135872010-11-02 12:39:01 -07001554 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 Object* LookupAccessor(String* name, bool is_getter);
1556
John Reck59135872010-11-02 12:39:01 -07001557 MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
Leon Clarkef7060e22010-06-03 12:02:55 +01001558
Steve Blocka7e24c12009-10-30 11:49:00 +00001559 // Used from Object::GetProperty().
John Reck59135872010-11-02 12:39:01 -07001560 MaybeObject* GetPropertyWithFailedAccessCheck(
1561 Object* receiver,
1562 LookupResult* result,
1563 String* name,
1564 PropertyAttributes* attributes);
1565 MaybeObject* GetPropertyWithInterceptor(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001566 JSReceiver* receiver,
John Reck59135872010-11-02 12:39:01 -07001567 String* name,
1568 PropertyAttributes* attributes);
1569 MaybeObject* GetPropertyPostInterceptor(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001570 JSReceiver* receiver,
John Reck59135872010-11-02 12:39:01 -07001571 String* name,
1572 PropertyAttributes* attributes);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001573 MaybeObject* GetLocalPropertyPostInterceptor(JSReceiver* receiver,
John Reck59135872010-11-02 12:39:01 -07001574 String* name,
1575 PropertyAttributes* attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001576
1577 // Returns true if this is an instance of an api function and has
1578 // been modified since it was created. May give false positives.
1579 bool IsDirty();
1580
Steve Blockd0582a62009-12-15 09:54:21 +00001581 // If the receiver is a JSGlobalProxy this method will return its prototype,
1582 // otherwise the result is the receiver itself.
1583 inline Object* BypassGlobalProxy();
1584
1585 // Accessors for hidden properties object.
1586 //
1587 // Hidden properties are not local properties of the object itself.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001588 // Instead they are stored in an auxiliary structure kept as a local
Steve Blockd0582a62009-12-15 09:54:21 +00001589 // property with a special name Heap::hidden_symbol(). But if the
1590 // receiver is a JSGlobalProxy then the auxiliary object is a property
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001591 // of its prototype, and if it's a detached proxy, then you can't have
1592 // hidden properties.
Steve Blockd0582a62009-12-15 09:54:21 +00001593
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001594 // Sets a hidden property on this object. Returns this object if successful,
1595 // undefined if called on a detached proxy, and a failure if a GC
1596 // is required
1597 MaybeObject* SetHiddenProperty(String* key, Object* value);
1598 // Gets the value of a hidden property with the given key. Returns undefined
1599 // if the property doesn't exist (or if called on a detached proxy),
1600 // otherwise returns the value set for the key.
1601 Object* GetHiddenProperty(String* key);
1602 // Deletes a hidden property. Deleting a non-existing property is
1603 // considered successful.
1604 void DeleteHiddenProperty(String* key);
1605 // Returns true if the object has a property with the hidden symbol as name.
1606 bool HasHiddenProperties();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001607
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001608 MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
1609 MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag flag);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001610
John Reck59135872010-11-02 12:39:01 -07001611 MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
1612 MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001613
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001614 inline void ValidateSmiOnlyElements();
1615
1616 // Makes sure that this object can contain non-smi Object as elements.
1617 inline MaybeObject* EnsureCanContainNonSmiElements();
1618
1619 // Makes sure that this object can contain the specified elements.
1620 inline MaybeObject* EnsureCanContainElements(Object** elements,
1621 uint32_t count);
1622 inline MaybeObject* EnsureCanContainElements(FixedArray* elements);
1623 MaybeObject* EnsureCanContainElements(Arguments* arguments,
1624 uint32_t first_arg,
1625 uint32_t arg_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00001626
1627 // Do we want to keep the elements in fast case when increasing the
1628 // capacity?
1629 bool ShouldConvertToSlowElements(int new_capacity);
1630 // Returns true if the backing storage for the slow-case elements of
1631 // this object takes up nearly as much space as a fast-case backing
1632 // storage would. In that case the JSObject should have fast
1633 // elements.
1634 bool ShouldConvertToFastElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001635 // Returns true if the elements of JSObject contains only values that can be
1636 // represented in a FixedDoubleArray.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001637 bool CanConvertToFastDoubleElements();
Andrei Popescu402d9372010-02-26 13:31:12 +00001638
Steve Blocka7e24c12009-10-30 11:49:00 +00001639 // Tells whether the index'th element is present.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001640 bool HasElementWithReceiver(JSReceiver* receiver, uint32_t index);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001641
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001642 // Computes the new capacity when expanding the elements of a JSObject.
1643 static int NewElementsCapacity(int old_capacity) {
1644 // (old_capacity + 50%) + 16
1645 return old_capacity + (old_capacity >> 1) + 16;
1646 }
1647
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001648 // Tells whether the index'th element is present and how it is stored.
1649 enum LocalElementType {
1650 // There is no element with given index.
1651 UNDEFINED_ELEMENT,
1652
1653 // Element with given index is handled by interceptor.
1654 INTERCEPTED_ELEMENT,
1655
1656 // Element with given index is character in string.
1657 STRING_CHARACTER_ELEMENT,
1658
1659 // Element with given index is stored in fast backing store.
1660 FAST_ELEMENT,
1661
1662 // Element with given index is stored in slow backing store.
1663 DICTIONARY_ELEMENT
1664 };
1665
1666 LocalElementType HasLocalElement(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001667
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001668 bool HasElementWithInterceptor(JSReceiver* receiver, uint32_t index);
1669 bool HasElementPostInterceptor(JSReceiver* receiver, uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001670
Steve Block9fac8402011-05-12 15:51:54 +01001671 MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
1672 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001673 StrictModeFlag strict_mode,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001674 bool check_prototype);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001675
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001676 MUST_USE_RESULT MaybeObject* SetDictionaryElement(uint32_t index,
1677 Object* value,
1678 StrictModeFlag strict_mode,
1679 bool check_prototype);
1680
1681 MUST_USE_RESULT MaybeObject* SetFastDoubleElement(
1682 uint32_t index,
1683 Object* value,
1684 StrictModeFlag strict_mode,
1685 bool check_prototype = true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001686
1687 // Set the index'th array element.
1688 // A Failure object is returned if GC is needed.
Steve Block9fac8402011-05-12 15:51:54 +01001689 MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
1690 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001691 StrictModeFlag strict_mode,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001692 bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00001693
1694 // Returns the index'th element.
1695 // The undefined object if index is out of bounds.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001696 MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
1697
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001698 enum SetFastElementsCapacityMode {
1699 kAllowSmiOnlyElements,
1700 kDontAllowSmiOnlyElements
1701 };
1702
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001703 // Replace the elements' backing store with fast elements of the given
1704 // capacity. Update the length for JSArrays. Returns the new backing
1705 // store.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001706 MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(
1707 int capacity,
1708 int length,
1709 SetFastElementsCapacityMode set_capacity_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001710 MUST_USE_RESULT MaybeObject* SetFastDoubleElementsCapacityAndLength(
1711 int capacity,
1712 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001713
1714 // Lookup interceptors are used for handling properties controlled by host
1715 // objects.
1716 inline bool HasNamedInterceptor();
1717 inline bool HasIndexedInterceptor();
1718
1719 // Support functions for v8 api (needed for correct interceptor behavior).
1720 bool HasRealNamedProperty(String* key);
1721 bool HasRealElementProperty(uint32_t index);
1722 bool HasRealNamedCallbackProperty(String* key);
1723
1724 // Initializes the array to a certain length
John Reck59135872010-11-02 12:39:01 -07001725 MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001726
1727 // Get the header size for a JSObject. Used to compute the index of
1728 // internal fields as well as the number of internal fields.
1729 inline int GetHeaderSize();
1730
1731 inline int GetInternalFieldCount();
Steve Block44f0eee2011-05-26 01:26:41 +01001732 inline int GetInternalFieldOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001733 inline Object* GetInternalField(int index);
1734 inline void SetInternalField(int index, Object* value);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001735 inline void SetInternalField(int index, Smi* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001736
1737 // The following lookup functions skip interceptors.
1738 void LocalLookupRealNamedProperty(String* name, LookupResult* result);
1739 void LookupRealNamedProperty(String* name, LookupResult* result);
1740 void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
1741 void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
Steve Block1e0659c2011-05-24 12:43:12 +01001742 MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001743 uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001744 void LookupCallback(String* name, LookupResult* result);
1745
1746 // Returns the number of properties on this object filtering out properties
1747 // with the specified attributes (ignoring interceptors).
1748 int NumberOfLocalProperties(PropertyAttributes filter);
1749 // Returns the number of enumerable properties (ignoring interceptors).
1750 int NumberOfEnumProperties();
1751 // Fill in details for properties into storage starting at the specified
1752 // index.
1753 void GetLocalPropertyNames(FixedArray* storage, int index);
1754
1755 // Returns the number of properties on this object filtering out properties
1756 // with the specified attributes (ignoring interceptors).
1757 int NumberOfLocalElements(PropertyAttributes filter);
1758 // Returns the number of enumerable elements (ignoring interceptors).
1759 int NumberOfEnumElements();
1760 // Returns the number of elements on this object filtering out elements
1761 // with the specified attributes (ignoring interceptors).
1762 int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
1763 // Count and fill in the enumerable elements into storage.
1764 // (storage->length() == NumberOfEnumElements()).
1765 // If storage is NULL, will count the elements without adding
1766 // them to any storage.
1767 // Returns the number of enumerable elements.
1768 int GetEnumElementKeys(FixedArray* storage);
1769
1770 // Add a property to a fast-case object using a map transition to
1771 // new_map.
John Reck59135872010-11-02 12:39:01 -07001772 MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
1773 String* name,
1774 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001775
1776 // Add a constant function property to a fast-case object.
1777 // This leaves a CONSTANT_TRANSITION in the old map, and
1778 // if it is called on a second object with this map, a
1779 // normal property is added instead, with a map transition.
1780 // This avoids the creation of many maps with the same constant
1781 // function, all orphaned.
John Reck59135872010-11-02 12:39:01 -07001782 MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
1783 String* name,
1784 JSFunction* function,
1785 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001786
John Reck59135872010-11-02 12:39:01 -07001787 MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
1788 String* name,
1789 Object* value,
1790 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001791
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001792 // Returns a new map with all transitions dropped from the object's current
1793 // map and the ElementsKind set.
1794 static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
1795 ElementsKind to_kind);
1796 MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
1797 ElementsKind elements_kind);
1798
1799 MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
1800
Steve Blocka7e24c12009-10-30 11:49:00 +00001801 // Converts a descriptor of any other type to a real field,
1802 // backed by the properties array. Descriptors of visible
1803 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
1804 // Converts the descriptor on the original object's map to a
1805 // map transition, and the the new field is on the object's new map.
John Reck59135872010-11-02 12:39:01 -07001806 MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
Steve Blocka7e24c12009-10-30 11:49:00 +00001807 String* name,
1808 Object* new_value,
1809 PropertyAttributes attributes);
1810
1811 // Converts a descriptor of any other type to a real field,
1812 // backed by the properties array. Descriptors of visible
1813 // types, such as CONSTANT_FUNCTION, keep their enumeration order.
John Reck59135872010-11-02 12:39:01 -07001814 MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
1815 String* name,
1816 Object* new_value,
1817 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001818
1819 // Add a property to a fast-case object.
John Reck59135872010-11-02 12:39:01 -07001820 MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
1821 Object* value,
1822 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001823
1824 // Add a property to a slow-case object.
John Reck59135872010-11-02 12:39:01 -07001825 MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
1826 Object* value,
1827 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001828
1829 // Add a property to an object.
John Reck59135872010-11-02 12:39:01 -07001830 MUST_USE_RESULT MaybeObject* AddProperty(String* name,
1831 Object* value,
Steve Block44f0eee2011-05-26 01:26:41 +01001832 PropertyAttributes attributes,
1833 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001834
1835 // Convert the object to use the canonical dictionary
1836 // representation. If the object is expected to have additional properties
1837 // added this number can be indicated to have the backing store allocated to
1838 // an initial capacity for holding these properties.
John Reck59135872010-11-02 12:39:01 -07001839 MUST_USE_RESULT MaybeObject* NormalizeProperties(
1840 PropertyNormalizationMode mode,
1841 int expected_additional_properties);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001842
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001843 // Convert and update the elements backing store to be a NumberDictionary
1844 // dictionary. Returns the backing after conversion.
John Reck59135872010-11-02 12:39:01 -07001845 MUST_USE_RESULT MaybeObject* NormalizeElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001846
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001847 static void UpdateMapCodeCache(Handle<JSObject> object,
1848 Handle<String> name,
1849 Handle<Code> code);
1850
John Reck59135872010-11-02 12:39:01 -07001851 MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001852
Steve Blocka7e24c12009-10-30 11:49:00 +00001853 // Transform slow named properties to fast variants.
1854 // Returns failure if allocation failed.
John Reck59135872010-11-02 12:39:01 -07001855 MUST_USE_RESULT MaybeObject* TransformToFastProperties(
1856 int unused_property_fields);
Steve Blocka7e24c12009-10-30 11:49:00 +00001857
1858 // Access fast-case object properties at index.
1859 inline Object* FastPropertyAt(int index);
1860 inline Object* FastPropertyAtPut(int index, Object* value);
1861
1862 // Access to in object properties.
Steve Block44f0eee2011-05-26 01:26:41 +01001863 inline int GetInObjectPropertyOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001864 inline Object* InObjectPropertyAt(int index);
1865 inline Object* InObjectPropertyAtPut(int index,
1866 Object* value,
1867 WriteBarrierMode mode
1868 = UPDATE_WRITE_BARRIER);
1869
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001870 // Initializes the body after properties slot, properties slot is
1871 // initialized by set_properties. Fill the pre-allocated fields with
1872 // pre_allocated_value and the rest with filler_value.
1873 // Note: this call does not update write barrier, the caller is responsible
1874 // to ensure that |filler_value| can be collected without WB here.
1875 inline void InitializeBody(Map* map,
1876 Object* pre_allocated_value,
1877 Object* filler_value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001878
1879 // Check whether this object references another object
1880 bool ReferencesObject(Object* obj);
1881
1882 // Casting.
1883 static inline JSObject* cast(Object* obj);
1884
Steve Block8defd9f2010-07-08 12:39:36 +01001885 // Disalow further properties to be added to the object.
John Reck59135872010-11-02 12:39:01 -07001886 MUST_USE_RESULT MaybeObject* PreventExtensions();
Steve Block8defd9f2010-07-08 12:39:36 +01001887
1888
Steve Blocka7e24c12009-10-30 11:49:00 +00001889 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00001890 void JSObjectShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001891#ifdef OBJECT_PRINT
1892 inline void JSObjectPrint() {
1893 JSObjectPrint(stdout);
1894 }
1895 void JSObjectPrint(FILE* out);
1896#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001897#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001898 void JSObjectVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001899#endif
1900#ifdef OBJECT_PRINT
1901 inline void PrintProperties() {
1902 PrintProperties(stdout);
1903 }
1904 void PrintProperties(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00001905
Ben Murdochb0fe1622011-05-05 13:52:32 +01001906 inline void PrintElements() {
1907 PrintElements(stdout);
1908 }
1909 void PrintElements(FILE* out);
1910#endif
1911
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001912 void PrintElementsTransition(
1913 FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
1914 ElementsKind to_kind, FixedArrayBase* to_elements);
1915
Ben Murdochb0fe1622011-05-05 13:52:32 +01001916#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00001917 // Structure for collecting spill information about JSObjects.
1918 class SpillInformation {
1919 public:
1920 void Clear();
1921 void Print();
1922 int number_of_objects_;
1923 int number_of_objects_with_fast_properties_;
1924 int number_of_objects_with_fast_elements_;
1925 int number_of_fast_used_fields_;
1926 int number_of_fast_unused_fields_;
1927 int number_of_slow_used_properties_;
1928 int number_of_slow_unused_properties_;
1929 int number_of_fast_used_elements_;
1930 int number_of_fast_unused_elements_;
1931 int number_of_slow_used_elements_;
1932 int number_of_slow_unused_elements_;
1933 };
1934
1935 void IncrementSpillStatistics(SpillInformation* info);
1936#endif
1937 Object* SlowReverseLookup(Object* value);
1938
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001939 // Getters and setters are stored in a fixed array property.
1940 // These are constants for their indices.
1941 static const int kGetterIndex = 0;
1942 static const int kSetterIndex = 1;
1943
Steve Block8defd9f2010-07-08 12:39:36 +01001944 // Maximal number of fast properties for the JSObject. Used to
1945 // restrict the number of map transitions to avoid an explosion in
1946 // the number of maps for objects used as dictionaries.
1947 inline int MaxFastProperties();
1948
Leon Clarkee46be812010-01-19 14:06:41 +00001949 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
1950 // Also maximal value of JSArray's length property.
1951 static const uint32_t kMaxElementCount = 0xffffffffu;
1952
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001953 // Constants for heuristics controlling conversion of fast elements
1954 // to slow elements.
1955
1956 // Maximal gap that can be introduced by adding an element beyond
1957 // the current elements length.
Steve Blocka7e24c12009-10-30 11:49:00 +00001958 static const uint32_t kMaxGap = 1024;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001959
1960 // Maximal length of fast elements array that won't be checked for
1961 // being dense enough on expansion.
1962 static const int kMaxUncheckedFastElementsLength = 5000;
1963
1964 // Same as above but for old arrays. This limit is more strict. We
1965 // don't want to be wasteful with long lived objects.
1966 static const int kMaxUncheckedOldFastElementsLength = 500;
1967
Steve Blocka7e24c12009-10-30 11:49:00 +00001968 static const int kInitialMaxFastElementArray = 100000;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001969 static const int kMaxFastProperties = 12;
Steve Blocka7e24c12009-10-30 11:49:00 +00001970 static const int kMaxInstanceSize = 255 * kPointerSize;
1971 // When extending the backing storage for property values, we increase
1972 // its size by more than the 1 entry necessary, so sequentially adding fields
1973 // to the same object requires fewer allocations and copies.
1974 static const int kFieldsAdded = 3;
1975
1976 // Layout description.
1977 static const int kPropertiesOffset = HeapObject::kHeaderSize;
1978 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
1979 static const int kHeaderSize = kElementsOffset + kPointerSize;
1980
1981 STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
1982
Iain Merrick75681382010-08-19 15:07:18 +01001983 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
1984 public:
1985 static inline int SizeOf(Map* map, HeapObject* object);
1986 };
1987
Steve Blocka7e24c12009-10-30 11:49:00 +00001988 private:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001989 friend class DictionaryElementsAccessor;
1990
John Reck59135872010-11-02 12:39:01 -07001991 MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
1992 Object* structure,
1993 uint32_t index,
1994 Object* holder);
1995 MaybeObject* SetElementWithCallback(Object* structure,
1996 uint32_t index,
1997 Object* value,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001998 JSObject* holder,
1999 StrictModeFlag strict_mode);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002000 MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
2001 uint32_t index,
2002 Object* value,
2003 StrictModeFlag strict_mode,
2004 bool check_prototype);
Steve Block9fac8402011-05-12 15:51:54 +01002005 MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
2006 uint32_t index,
2007 Object* value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002008 StrictModeFlag strict_mode,
Steve Block9fac8402011-05-12 15:51:54 +01002009 bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00002010
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002011 // Searches the prototype chain for a callback setter and sets the property
2012 // with the setter if it finds one. The '*found' flag indicates whether
2013 // a setter was found or not.
2014 // This function can cause GC and can return a failure result with
2015 // '*found==true'.
2016 MUST_USE_RESULT MaybeObject* SetPropertyWithCallbackSetterInPrototypes(
2017 String* name,
2018 Object* value,
2019 PropertyAttributes attributes,
2020 bool* found,
2021 StrictModeFlag strict_mode);
2022
John Reck59135872010-11-02 12:39:01 -07002023 MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
2024 DeleteMode mode);
2025 MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002026
John Reck59135872010-11-02 12:39:01 -07002027 MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002028
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002029 MUST_USE_RESULT MaybeObject* DeleteFastElement(uint32_t index);
2030 MUST_USE_RESULT MaybeObject* DeleteDictionaryElement(uint32_t index,
2031 DeleteMode mode);
2032
2033 bool ReferencesObjectFromElements(FixedArray* elements,
2034 ElementsKind kind,
2035 Object* object);
2036 bool HasElementInElements(FixedArray* elements,
2037 ElementsKind kind,
2038 uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002039
2040 // Returns true if most of the elements backing storage is used.
2041 bool HasDenseElements();
2042
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002043 // Gets the current elements capacity and the number of used elements.
2044 void GetElementsCapacityAndUsage(int* capacity, int* used);
2045
Leon Clarkef7060e22010-06-03 12:02:55 +01002046 bool CanSetCallback(String* name);
John Reck59135872010-11-02 12:39:01 -07002047 MUST_USE_RESULT MaybeObject* SetElementCallback(
2048 uint32_t index,
2049 Object* structure,
2050 PropertyAttributes attributes);
2051 MUST_USE_RESULT MaybeObject* SetPropertyCallback(
2052 String* name,
2053 Object* structure,
2054 PropertyAttributes attributes);
2055 MUST_USE_RESULT MaybeObject* DefineGetterSetter(
2056 String* name,
2057 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00002058
2059 void LookupInDescriptor(String* name, LookupResult* result);
2060
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002061 // Returns the hidden properties backing store object, currently
2062 // a StringDictionary, stored on this object.
2063 // If no hidden properties object has been put on this object,
2064 // return undefined, unless create_if_absent is true, in which case
2065 // a new dictionary is created, added to this object, and returned.
2066 MaybeObject* GetHiddenPropertiesDictionary(bool create_if_absent);
2067 // Updates the existing hidden properties dictionary.
2068 MaybeObject* SetHiddenPropertiesDictionary(StringDictionary* dictionary);
2069
Steve Blocka7e24c12009-10-30 11:49:00 +00002070 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
2071};
2072
2073
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002074// Common superclass for FixedArrays that allow implementations to share
2075// common accessors and some code paths.
2076class FixedArrayBase: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002077 public:
2078 // [length]: length of the array.
2079 inline int length();
2080 inline void set_length(int value);
2081
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002082 inline static FixedArrayBase* cast(Object* object);
2083
2084 // Layout description.
2085 // Length is smi tagged when it is stored.
2086 static const int kLengthOffset = HeapObject::kHeaderSize;
2087 static const int kHeaderSize = kLengthOffset + kPointerSize;
2088};
2089
2090
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002091class FixedDoubleArray;
2092
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002093// FixedArray describes fixed-sized arrays with element type Object*.
2094class FixedArray: public FixedArrayBase {
2095 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00002096 // Setter and getter for elements.
2097 inline Object* get(int index);
2098 // Setter that uses write barrier.
2099 inline void set(int index, Object* value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002100 inline bool is_the_hole(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002101
2102 // Setter that doesn't need write barrier).
2103 inline void set(int index, Smi* value);
2104 // Setter with explicit barrier mode.
2105 inline void set(int index, Object* value, WriteBarrierMode mode);
2106
2107 // Setters for frequently used oddballs located in old space.
2108 inline void set_undefined(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01002109 // TODO(isolates): duplicate.
2110 inline void set_undefined(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002111 inline void set_null(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01002112 // TODO(isolates): duplicate.
2113 inline void set_null(Heap* heap, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002114 inline void set_the_hole(int index);
2115
Iain Merrick75681382010-08-19 15:07:18 +01002116 // Setters with less debug checks for the GC to use.
2117 inline void set_unchecked(int index, Smi* value);
Steve Block44f0eee2011-05-26 01:26:41 +01002118 inline void set_null_unchecked(Heap* heap, int index);
2119 inline void set_unchecked(Heap* heap, int index, Object* value,
2120 WriteBarrierMode mode);
Iain Merrick75681382010-08-19 15:07:18 +01002121
Steve Block6ded16b2010-05-10 14:33:55 +01002122 // Gives access to raw memory which stores the array's data.
2123 inline Object** data_start();
2124
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 // Copy operations.
John Reck59135872010-11-02 12:39:01 -07002126 MUST_USE_RESULT inline MaybeObject* Copy();
2127 MUST_USE_RESULT MaybeObject* CopySize(int new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +00002128
2129 // Add the elements of a JSArray to this FixedArray.
John Reck59135872010-11-02 12:39:01 -07002130 MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
Steve Blocka7e24c12009-10-30 11:49:00 +00002131
2132 // Compute the union of this and other.
John Reck59135872010-11-02 12:39:01 -07002133 MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
Steve Blocka7e24c12009-10-30 11:49:00 +00002134
2135 // Copy a sub array from the receiver to dest.
2136 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
2137
2138 // Garbage collection support.
2139 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
2140
2141 // Code Generation support.
2142 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2143
2144 // Casting.
2145 static inline FixedArray* cast(Object* obj);
2146
Leon Clarkee46be812010-01-19 14:06:41 +00002147 // Maximal allowed size, in bytes, of a single FixedArray.
2148 // Prevents overflowing size computations, as well as extreme memory
2149 // consumption.
Ben Murdoch692be652012-01-10 18:47:50 +00002150 static const int kMaxSize = 128 * MB * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002151 // Maximally allowed length of a FixedArray.
2152 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002153
2154 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002155#ifdef OBJECT_PRINT
2156 inline void FixedArrayPrint() {
2157 FixedArrayPrint(stdout);
2158 }
2159 void FixedArrayPrint(FILE* out);
2160#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002161#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002162 void FixedArrayVerify();
2163 // Checks if two FixedArrays have identical contents.
2164 bool IsEqualTo(FixedArray* other);
2165#endif
2166
2167 // Swap two elements in a pair of arrays. If this array and the
2168 // numbers array are the same object, the elements are only swapped
2169 // once.
2170 void SwapPairs(FixedArray* numbers, int i, int j);
2171
2172 // Sort prefix of this array and the numbers array as pairs wrt. the
2173 // numbers. If the numbers array and the this array are the same
2174 // object, the prefix of this array is sorted.
2175 void SortPairs(FixedArray* numbers, uint32_t len);
2176
Iain Merrick75681382010-08-19 15:07:18 +01002177 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
2178 public:
2179 static inline int SizeOf(Map* map, HeapObject* object) {
2180 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
2181 }
2182 };
2183
Steve Blocka7e24c12009-10-30 11:49:00 +00002184 protected:
Leon Clarke4515c472010-02-03 11:58:03 +00002185 // Set operation on FixedArray without using write barriers. Can
2186 // only be used for storing old space objects or smis.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002187 static inline void NoWriteBarrierSet(FixedArray* array,
2188 int index,
2189 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002190
2191 private:
2192 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
2193};
2194
2195
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002196// FixedDoubleArray describes fixed-sized arrays with element type double.
2197class FixedDoubleArray: public FixedArrayBase {
2198 public:
2199 inline void Initialize(FixedArray* from);
2200 inline void Initialize(FixedDoubleArray* from);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002201 inline void Initialize(NumberDictionary* from);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002202
2203 // Setter and getter for elements.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002204 inline double get_scalar(int index);
2205 inline MaybeObject* get(int index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002206 inline void set(int index, double value);
2207 inline void set_the_hole(int index);
2208
2209 // Checking for the hole.
2210 inline bool is_the_hole(int index);
2211
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002212 // Copy operations
2213 MUST_USE_RESULT inline MaybeObject* Copy();
2214
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002215 // Garbage collection support.
2216 inline static int SizeFor(int length) {
2217 return kHeaderSize + length * kDoubleSize;
2218 }
2219
2220 // Code Generation support.
2221 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2222
2223 inline static bool is_the_hole_nan(double value);
2224 inline static double hole_nan_as_double();
2225 inline static double canonical_not_the_hole_nan_as_double();
2226
2227 // Casting.
2228 static inline FixedDoubleArray* cast(Object* obj);
2229
2230 // Maximal allowed size, in bytes, of a single FixedDoubleArray.
2231 // Prevents overflowing size computations, as well as extreme memory
2232 // consumption.
2233 static const int kMaxSize = 512 * MB;
2234 // Maximally allowed length of a FixedArray.
2235 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
2236
2237 // Dispatched behavior.
2238#ifdef OBJECT_PRINT
2239 inline void FixedDoubleArrayPrint() {
2240 FixedDoubleArrayPrint(stdout);
2241 }
2242 void FixedDoubleArrayPrint(FILE* out);
2243#endif
2244
2245#ifdef DEBUG
2246 void FixedDoubleArrayVerify();
2247#endif
2248
2249 private:
2250 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
2251};
2252
2253
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002254class IncrementalMarking;
2255
2256
Steve Blocka7e24c12009-10-30 11:49:00 +00002257// DescriptorArrays are fixed arrays used to hold instance descriptors.
2258// The format of the these objects is:
Ben Murdoch257744e2011-11-30 15:57:28 +00002259// TODO(1399): It should be possible to make room for bit_field3 in the map
2260// without overloading the instance descriptors field in the map
2261// (and storing it in the DescriptorArray when the map has one).
2262// [0]: storage for bit_field3 for Map owning this object (Smi)
2263// [1]: point to a fixed array with (value, detail) pairs.
2264// [2]: next enumeration index (Smi), or pointer to small fixed array:
Steve Blocka7e24c12009-10-30 11:49:00 +00002265// [0]: next enumeration index (Smi)
2266// [1]: pointer to fixed array with enum cache
Ben Murdoch257744e2011-11-30 15:57:28 +00002267// [3]: first key
Steve Blocka7e24c12009-10-30 11:49:00 +00002268// [length() - 1]: last key
2269//
2270class DescriptorArray: public FixedArray {
2271 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00002272 // Returns true for both shared empty_descriptor_array and for smis, which the
2273 // map uses to encode additional bit fields when the descriptor array is not
2274 // yet used.
Steve Blocka7e24c12009-10-30 11:49:00 +00002275 inline bool IsEmpty();
Leon Clarkee46be812010-01-19 14:06:41 +00002276
Steve Blocka7e24c12009-10-30 11:49:00 +00002277 // Returns the number of descriptors in the array.
2278 int number_of_descriptors() {
Steve Block44f0eee2011-05-26 01:26:41 +01002279 ASSERT(length() > kFirstIndex || IsEmpty());
2280 int len = length();
2281 return len <= kFirstIndex ? 0 : len - kFirstIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00002282 }
2283
2284 int NextEnumerationIndex() {
2285 if (IsEmpty()) return PropertyDetails::kInitialIndex;
2286 Object* obj = get(kEnumerationIndexIndex);
2287 if (obj->IsSmi()) {
2288 return Smi::cast(obj)->value();
2289 } else {
2290 Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
2291 return Smi::cast(index)->value();
2292 }
2293 }
2294
2295 // Set next enumeration index and flush any enum cache.
2296 void SetNextEnumerationIndex(int value) {
2297 if (!IsEmpty()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002298 set(kEnumerationIndexIndex, Smi::FromInt(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00002299 }
2300 }
2301 bool HasEnumCache() {
2302 return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
2303 }
2304
2305 Object* GetEnumCache() {
2306 ASSERT(HasEnumCache());
2307 FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
2308 return bridge->get(kEnumCacheBridgeCacheIndex);
2309 }
2310
Ben Murdoch257744e2011-11-30 15:57:28 +00002311 // TODO(1399): It should be possible to make room for bit_field3 in the map
2312 // without overloading the instance descriptors field in the map
2313 // (and storing it in the DescriptorArray when the map has one).
2314 inline int bit_field3_storage();
2315 inline void set_bit_field3_storage(int value);
2316
Steve Blocka7e24c12009-10-30 11:49:00 +00002317 // Initialize or change the enum cache,
2318 // using the supplied storage for the small "bridge".
2319 void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
2320
2321 // Accessors for fetching instance descriptor at descriptor number.
2322 inline String* GetKey(int descriptor_number);
2323 inline Object* GetValue(int descriptor_number);
2324 inline Smi* GetDetails(int descriptor_number);
2325 inline PropertyType GetType(int descriptor_number);
2326 inline int GetFieldIndex(int descriptor_number);
2327 inline JSFunction* GetConstantFunction(int descriptor_number);
2328 inline Object* GetCallbacksObject(int descriptor_number);
2329 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
2330 inline bool IsProperty(int descriptor_number);
2331 inline bool IsTransition(int descriptor_number);
2332 inline bool IsNullDescriptor(int descriptor_number);
2333 inline bool IsDontEnum(int descriptor_number);
2334
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002335 class WhitenessWitness {
2336 public:
2337 inline explicit WhitenessWitness(DescriptorArray* array);
2338 inline ~WhitenessWitness();
2339
2340 private:
2341 IncrementalMarking* marking_;
2342 };
2343
Steve Blocka7e24c12009-10-30 11:49:00 +00002344 // Accessor for complete descriptor.
2345 inline void Get(int descriptor_number, Descriptor* desc);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002346 inline void Set(int descriptor_number,
2347 Descriptor* desc,
2348 const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00002349
2350 // Transfer complete descriptor from another descriptor array to
2351 // this one.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002352 inline void CopyFrom(int index,
2353 DescriptorArray* src,
2354 int src_index,
2355 const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00002356
2357 // Copy the descriptor array, insert a new descriptor and optionally
2358 // remove map transitions. If the descriptor is already present, it is
2359 // replaced. If a replaced descriptor is a real property (not a transition
2360 // or null), its enumeration index is kept as is.
2361 // If adding a real property, map transitions must be removed. If adding
2362 // a transition, they must not be removed. All null descriptors are removed.
John Reck59135872010-11-02 12:39:01 -07002363 MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
2364 TransitionFlag transition_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +00002365
2366 // Remove all transitions. Return a copy of the array with all transitions
2367 // removed, or a Failure object if the new array could not be allocated.
John Reck59135872010-11-02 12:39:01 -07002368 MUST_USE_RESULT MaybeObject* RemoveTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002369
2370 // Sort the instance descriptors by the hash codes of their keys.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002371 // Does not check for duplicates.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002372 void SortUnchecked(const WhitenessWitness&);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002373
2374 // Sort the instance descriptors by the hash codes of their keys.
2375 // Checks the result for duplicates.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002376 void Sort(const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00002377
2378 // Search the instance descriptors for given name.
2379 inline int Search(String* name);
2380
Iain Merrick75681382010-08-19 15:07:18 +01002381 // As the above, but uses DescriptorLookupCache and updates it when
2382 // necessary.
2383 inline int SearchWithCache(String* name);
2384
Steve Blocka7e24c12009-10-30 11:49:00 +00002385 // Tells whether the name is present int the array.
2386 bool Contains(String* name) { return kNotFound != Search(name); }
2387
2388 // Perform a binary search in the instance descriptors represented
2389 // by this fixed array. low and high are descriptor indices. If there
2390 // are three instance descriptors in this array it should be called
2391 // with low=0 and high=2.
2392 int BinarySearch(String* name, int low, int high);
2393
2394 // Perform a linear search in the instance descriptors represented
2395 // by this fixed array. len is the number of descriptor indices that are
2396 // valid. Does not require the descriptors to be sorted.
2397 int LinearSearch(String* name, int len);
2398
2399 // Allocates a DescriptorArray, but returns the singleton
2400 // empty descriptor array object if number_of_descriptors is 0.
John Reck59135872010-11-02 12:39:01 -07002401 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
Steve Blocka7e24c12009-10-30 11:49:00 +00002402
2403 // Casting.
2404 static inline DescriptorArray* cast(Object* obj);
2405
2406 // Constant for denoting key was not found.
2407 static const int kNotFound = -1;
2408
Ben Murdoch257744e2011-11-30 15:57:28 +00002409 static const int kBitField3StorageIndex = 0;
2410 static const int kContentArrayIndex = 1;
2411 static const int kEnumerationIndexIndex = 2;
2412 static const int kFirstIndex = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +00002413
2414 // The length of the "bridge" to the enum cache.
2415 static const int kEnumCacheBridgeLength = 2;
2416 static const int kEnumCacheBridgeEnumIndex = 0;
2417 static const int kEnumCacheBridgeCacheIndex = 1;
2418
2419 // Layout description.
Ben Murdoch257744e2011-11-30 15:57:28 +00002420 static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
2421 static const int kContentArrayOffset = kBitField3StorageOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002422 static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
2423 static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
2424
2425 // Layout description for the bridge array.
2426 static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
2427 static const int kEnumCacheBridgeCacheOffset =
2428 kEnumCacheBridgeEnumOffset + kPointerSize;
2429
Ben Murdochb0fe1622011-05-05 13:52:32 +01002430#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +00002431 // Print all the descriptors.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002432 inline void PrintDescriptors() {
2433 PrintDescriptors(stdout);
2434 }
2435 void PrintDescriptors(FILE* out);
2436#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002437
Ben Murdochb0fe1622011-05-05 13:52:32 +01002438#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002439 // Is the descriptor array sorted and without duplicates?
2440 bool IsSortedNoDuplicates();
2441
2442 // Are two DescriptorArrays equal?
2443 bool IsEqualTo(DescriptorArray* other);
2444#endif
2445
2446 // The maximum number of descriptors we want in a descriptor array (should
2447 // fit in a page).
2448 static const int kMaxNumberOfDescriptors = 1024 + 512;
2449
2450 private:
2451 // Conversion from descriptor number to array indices.
2452 static int ToKeyIndex(int descriptor_number) {
2453 return descriptor_number+kFirstIndex;
2454 }
Leon Clarkee46be812010-01-19 14:06:41 +00002455
2456 static int ToDetailsIndex(int descriptor_number) {
2457 return (descriptor_number << 1) + 1;
2458 }
2459
Steve Blocka7e24c12009-10-30 11:49:00 +00002460 static int ToValueIndex(int descriptor_number) {
2461 return descriptor_number << 1;
2462 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002463
2464 bool is_null_descriptor(int descriptor_number) {
2465 return PropertyDetails(GetDetails(descriptor_number)).type() ==
2466 NULL_DESCRIPTOR;
2467 }
2468 // Swap operation on FixedArray without using write barriers.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002469 static inline void NoWriteBarrierSwap(FixedArray* array,
2470 int first,
2471 int second);
Steve Blocka7e24c12009-10-30 11:49:00 +00002472
2473 // Swap descriptor first and second.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002474 inline void NoWriteBarrierSwapDescriptors(int first, int second);
Steve Blocka7e24c12009-10-30 11:49:00 +00002475
2476 FixedArray* GetContentArray() {
2477 return FixedArray::cast(get(kContentArrayIndex));
2478 }
2479 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
2480};
2481
2482
2483// HashTable is a subclass of FixedArray that implements a hash table
2484// that uses open addressing and quadratic probing.
2485//
2486// In order for the quadratic probing to work, elements that have not
2487// yet been used and elements that have been deleted are
2488// distinguished. Probing continues when deleted elements are
2489// encountered and stops when unused elements are encountered.
2490//
2491// - Elements with key == undefined have not been used yet.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002492// - Elements with key == the_hole have been deleted.
Steve Blocka7e24c12009-10-30 11:49:00 +00002493//
2494// The hash table class is parameterized with a Shape and a Key.
2495// Shape must be a class with the following interface:
2496// class ExampleShape {
2497// public:
2498// // Tells whether key matches other.
2499// static bool IsMatch(Key key, Object* other);
2500// // Returns the hash value for key.
2501// static uint32_t Hash(Key key);
2502// // Returns the hash value for object.
2503// static uint32_t HashForObject(Key key, Object* object);
2504// // Convert key to an object.
2505// static inline Object* AsObject(Key key);
2506// // The prefix size indicates number of elements in the beginning
2507// // of the backing storage.
2508// static const int kPrefixSize = ..;
2509// // The Element size indicates number of elements per entry.
2510// static const int kEntrySize = ..;
2511// };
Steve Block3ce2e202009-11-05 08:53:23 +00002512// The prefix size indicates an amount of memory in the
Steve Blocka7e24c12009-10-30 11:49:00 +00002513// beginning of the backing storage that can be used for non-element
2514// information by subclasses.
2515
2516template<typename Shape, typename Key>
2517class HashTable: public FixedArray {
2518 public:
Steve Block3ce2e202009-11-05 08:53:23 +00002519 // Returns the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002520 int NumberOfElements() {
2521 return Smi::cast(get(kNumberOfElementsIndex))->value();
2522 }
2523
Leon Clarkee46be812010-01-19 14:06:41 +00002524 // Returns the number of deleted elements in the hash table.
2525 int NumberOfDeletedElements() {
2526 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
2527 }
2528
Steve Block3ce2e202009-11-05 08:53:23 +00002529 // Returns the capacity of the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002530 int Capacity() {
2531 return Smi::cast(get(kCapacityIndex))->value();
2532 }
2533
2534 // ElementAdded should be called whenever an element is added to a
Steve Block3ce2e202009-11-05 08:53:23 +00002535 // hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002536 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
2537
2538 // ElementRemoved should be called whenever an element is removed from
Steve Block3ce2e202009-11-05 08:53:23 +00002539 // a hash table.
Leon Clarkee46be812010-01-19 14:06:41 +00002540 void ElementRemoved() {
2541 SetNumberOfElements(NumberOfElements() - 1);
2542 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
2543 }
2544 void ElementsRemoved(int n) {
2545 SetNumberOfElements(NumberOfElements() - n);
2546 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
2547 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002548
Steve Block3ce2e202009-11-05 08:53:23 +00002549 // Returns a new HashTable object. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002550 MUST_USE_RESULT static MaybeObject* Allocate(
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002551 int at_least_space_for,
2552 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002553
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002554 // Computes the required capacity for a table holding the given
2555 // number of elements. May be more than HashTable::kMaxCapacity.
2556 static int ComputeCapacity(int at_least_space_for);
2557
Steve Blocka7e24c12009-10-30 11:49:00 +00002558 // Returns the key at entry.
2559 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
2560
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002561 // Tells whether k is a real key. The hole and undefined are not allowed
Steve Blocka7e24c12009-10-30 11:49:00 +00002562 // as keys and can be used to indicate missing or deleted elements.
2563 bool IsKey(Object* k) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002564 return !k->IsTheHole() && !k->IsUndefined();
Steve Blocka7e24c12009-10-30 11:49:00 +00002565 }
2566
2567 // Garbage collection support.
2568 void IteratePrefix(ObjectVisitor* visitor);
2569 void IterateElements(ObjectVisitor* visitor);
2570
2571 // Casting.
2572 static inline HashTable* cast(Object* obj);
2573
2574 // Compute the probe offset (quadratic probing).
2575 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
2576 return (n + n * n) >> 1;
2577 }
2578
2579 static const int kNumberOfElementsIndex = 0;
Leon Clarkee46be812010-01-19 14:06:41 +00002580 static const int kNumberOfDeletedElementsIndex = 1;
2581 static const int kCapacityIndex = 2;
2582 static const int kPrefixStartIndex = 3;
2583 static const int kElementsStartIndex =
Steve Blocka7e24c12009-10-30 11:49:00 +00002584 kPrefixStartIndex + Shape::kPrefixSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002585 static const int kEntrySize = Shape::kEntrySize;
2586 static const int kElementsStartOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00002587 kHeaderSize + kElementsStartIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01002588 static const int kCapacityOffset =
2589 kHeaderSize + kCapacityIndex * kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002590
2591 // Constant used for denoting a absent entry.
2592 static const int kNotFound = -1;
2593
Leon Clarkee46be812010-01-19 14:06:41 +00002594 // Maximal capacity of HashTable. Based on maximal length of underlying
2595 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
2596 // cannot overflow.
2597 static const int kMaxCapacity =
2598 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
2599
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002600 // Find entry for key otherwise return kNotFound.
Steve Block44f0eee2011-05-26 01:26:41 +01002601 inline int FindEntry(Key key);
2602 int FindEntry(Isolate* isolate, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002603
2604 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +00002605 // Find the entry at which to insert element with the given key that
2606 // has the given hash value.
2607 uint32_t FindInsertionEntry(uint32_t hash);
2608
2609 // Returns the index for an entry (of the key)
2610 static inline int EntryToIndex(int entry) {
2611 return (entry * kEntrySize) + kElementsStartIndex;
2612 }
2613
Steve Block3ce2e202009-11-05 08:53:23 +00002614 // Update the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002615 void SetNumberOfElements(int nof) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002616 set(kNumberOfElementsIndex, Smi::FromInt(nof));
Steve Blocka7e24c12009-10-30 11:49:00 +00002617 }
2618
Leon Clarkee46be812010-01-19 14:06:41 +00002619 // Update the number of deleted elements in the hash table.
2620 void SetNumberOfDeletedElements(int nod) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002621 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
Leon Clarkee46be812010-01-19 14:06:41 +00002622 }
2623
Steve Blocka7e24c12009-10-30 11:49:00 +00002624 // Sets the capacity of the hash table.
2625 void SetCapacity(int capacity) {
2626 // To scale a computed hash code to fit within the hash table, we
2627 // use bit-wise AND with a mask, so the capacity must be positive
2628 // and non-zero.
2629 ASSERT(capacity > 0);
Leon Clarkee46be812010-01-19 14:06:41 +00002630 ASSERT(capacity <= kMaxCapacity);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002631 set(kCapacityIndex, Smi::FromInt(capacity));
Steve Blocka7e24c12009-10-30 11:49:00 +00002632 }
2633
2634
2635 // Returns probe entry.
2636 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
2637 ASSERT(IsPowerOf2(size));
2638 return (hash + GetProbeOffset(number)) & (size - 1);
2639 }
2640
Leon Clarkee46be812010-01-19 14:06:41 +00002641 static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
2642 return hash & (size - 1);
2643 }
2644
2645 static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
2646 return (last + number) & (size - 1);
2647 }
2648
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002649 // Rehashes this hash-table into the new table.
2650 MUST_USE_RESULT MaybeObject* Rehash(HashTable* new_table, Key key);
2651
2652 // Attempt to shrink hash table after removal of key.
2653 MUST_USE_RESULT MaybeObject* Shrink(Key key);
2654
Steve Blocka7e24c12009-10-30 11:49:00 +00002655 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002656 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002657};
2658
2659
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002660
Steve Blocka7e24c12009-10-30 11:49:00 +00002661// HashTableKey is an abstract superclass for virtual key behavior.
2662class HashTableKey {
2663 public:
2664 // Returns whether the other object matches this key.
2665 virtual bool IsMatch(Object* other) = 0;
2666 // Returns the hash value for this key.
2667 virtual uint32_t Hash() = 0;
2668 // Returns the hash value for object.
2669 virtual uint32_t HashForObject(Object* key) = 0;
Steve Block3ce2e202009-11-05 08:53:23 +00002670 // Returns the key object for storing into the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00002671 // If allocations fails a failure object is returned.
John Reck59135872010-11-02 12:39:01 -07002672 MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002673 // Required.
2674 virtual ~HashTableKey() {}
2675};
2676
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002677class SymbolTableShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00002678 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002679 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002680 return key->IsMatch(value);
2681 }
Steve Block44f0eee2011-05-26 01:26:41 +01002682 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002683 return key->Hash();
2684 }
Steve Block44f0eee2011-05-26 01:26:41 +01002685 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002686 return key->HashForObject(object);
2687 }
Steve Block44f0eee2011-05-26 01:26:41 +01002688 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002689 return key->AsObject();
2690 }
2691
2692 static const int kPrefixSize = 0;
2693 static const int kEntrySize = 1;
2694};
2695
Ben Murdoch257744e2011-11-30 15:57:28 +00002696class SeqAsciiString;
2697
Steve Blocka7e24c12009-10-30 11:49:00 +00002698// SymbolTable.
2699//
2700// No special elements in the prefix and the element size is 1
2701// because only the symbol itself (the key) needs to be stored.
2702class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
2703 public:
2704 // Find symbol in the symbol table. If it is not there yet, it is
2705 // added. The return value is the symbol table which might have
2706 // been enlarged. If the return value is not a failure, the symbol
2707 // pointer *s is set to the symbol found.
John Reck59135872010-11-02 12:39:01 -07002708 MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
Steve Block9fac8402011-05-12 15:51:54 +01002709 MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
2710 Object** s);
Ben Murdoch257744e2011-11-30 15:57:28 +00002711 MUST_USE_RESULT MaybeObject* LookupSubStringAsciiSymbol(
2712 Handle<SeqAsciiString> str,
2713 int from,
2714 int length,
2715 Object** s);
Steve Block9fac8402011-05-12 15:51:54 +01002716 MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
2717 Object** s);
John Reck59135872010-11-02 12:39:01 -07002718 MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002719
2720 // Looks up a symbol that is equal to the given string and returns
2721 // true if it is found, assigning the symbol to the given output
2722 // parameter.
2723 bool LookupSymbolIfExists(String* str, String** symbol);
Steve Blockd0582a62009-12-15 09:54:21 +00002724 bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002725
2726 // Casting.
2727 static inline SymbolTable* cast(Object* obj);
2728
2729 private:
John Reck59135872010-11-02 12:39:01 -07002730 MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
Steve Blocka7e24c12009-10-30 11:49:00 +00002731
2732 DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
2733};
2734
2735
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002736class MapCacheShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00002737 public:
Steve Block44f0eee2011-05-26 01:26:41 +01002738 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002739 return key->IsMatch(value);
2740 }
Steve Block44f0eee2011-05-26 01:26:41 +01002741 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002742 return key->Hash();
2743 }
2744
Steve Block44f0eee2011-05-26 01:26:41 +01002745 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002746 return key->HashForObject(object);
2747 }
2748
Steve Block44f0eee2011-05-26 01:26:41 +01002749 MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002750 return key->AsObject();
2751 }
2752
2753 static const int kPrefixSize = 0;
2754 static const int kEntrySize = 2;
2755};
2756
2757
2758// MapCache.
2759//
2760// Maps keys that are a fixed array of symbols to a map.
2761// Used for canonicalize maps for object literals.
2762class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
2763 public:
2764 // Find cached value for a string key, otherwise return null.
2765 Object* Lookup(FixedArray* key);
John Reck59135872010-11-02 12:39:01 -07002766 MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002767 static inline MapCache* cast(Object* obj);
2768
2769 private:
2770 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
2771};
2772
2773
2774template <typename Shape, typename Key>
2775class Dictionary: public HashTable<Shape, Key> {
2776 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00002777 static inline Dictionary<Shape, Key>* cast(Object* obj) {
2778 return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
2779 }
2780
2781 // Returns the value at entry.
2782 Object* ValueAt(int entry) {
Steve Block6ded16b2010-05-10 14:33:55 +01002783 return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002784 }
2785
2786 // Set the value for entry.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002787 // Returns false if the put wasn't performed due to property being read only.
2788 // Returns true on successful put.
2789 bool ValueAtPut(int entry, Object* value) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002790 // Check that this value can actually be written.
2791 PropertyDetails details = DetailsAt(entry);
2792 // If a value has not been initilized we allow writing to it even if
2793 // it is read only (a declared const that has not been initialized).
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002794 if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
2795 return false;
2796 }
2797 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
2798 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002799 }
2800
2801 // Returns the property details for the property at entry.
2802 PropertyDetails DetailsAt(int entry) {
2803 ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
2804 return PropertyDetails(
Steve Block6ded16b2010-05-10 14:33:55 +01002805 Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
Steve Blocka7e24c12009-10-30 11:49:00 +00002806 }
2807
2808 // Set the details for entry.
2809 void DetailsAtPut(int entry, PropertyDetails value) {
Steve Block6ded16b2010-05-10 14:33:55 +01002810 this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00002811 }
2812
2813 // Sorting support
2814 void CopyValuesTo(FixedArray* elements);
2815
2816 // Delete a property from the dictionary.
2817 Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
2818
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002819 // Attempt to shrink the dictionary after deletion of key.
2820 MUST_USE_RESULT MaybeObject* Shrink(Key key);
2821
Steve Blocka7e24c12009-10-30 11:49:00 +00002822 // Returns the number of elements in the dictionary filtering out properties
2823 // with the specified attributes.
2824 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
2825
2826 // Returns the number of enumerable elements in the dictionary.
2827 int NumberOfEnumElements();
2828
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002829 enum SortMode { UNSORTED, SORTED };
Steve Blocka7e24c12009-10-30 11:49:00 +00002830 // Copies keys to preallocated fixed array.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002831 void CopyKeysTo(FixedArray* storage,
2832 PropertyAttributes filter,
2833 SortMode sort_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002834 // Fill in details for properties into storage.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002835 void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002836
2837 // Accessors for next enumeration index.
2838 void SetNextEnumerationIndex(int index) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002839 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00002840 }
2841
2842 int NextEnumerationIndex() {
2843 return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
2844 }
2845
2846 // Returns a new array for dictionary usage. Might return Failure.
John Reck59135872010-11-02 12:39:01 -07002847 MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
Steve Blocka7e24c12009-10-30 11:49:00 +00002848
2849 // Ensure enough space for n additional elements.
John Reck59135872010-11-02 12:39:01 -07002850 MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002851
Ben Murdochb0fe1622011-05-05 13:52:32 +01002852#ifdef OBJECT_PRINT
2853 inline void Print() {
2854 Print(stdout);
2855 }
2856 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00002857#endif
2858 // Returns the key (slow).
2859 Object* SlowReverseLookup(Object* value);
2860
2861 // Sets the entry to (key, value) pair.
2862 inline void SetEntry(int entry,
2863 Object* key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002864 Object* value);
2865 inline void SetEntry(int entry,
2866 Object* key,
Steve Blocka7e24c12009-10-30 11:49:00 +00002867 Object* value,
2868 PropertyDetails details);
2869
John Reck59135872010-11-02 12:39:01 -07002870 MUST_USE_RESULT MaybeObject* Add(Key key,
2871 Object* value,
2872 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002873
2874 protected:
2875 // Generic at put operation.
John Reck59135872010-11-02 12:39:01 -07002876 MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002877
2878 // Add entry to dictionary.
John Reck59135872010-11-02 12:39:01 -07002879 MUST_USE_RESULT MaybeObject* AddEntry(Key key,
2880 Object* value,
2881 PropertyDetails details,
2882 uint32_t hash);
Steve Blocka7e24c12009-10-30 11:49:00 +00002883
2884 // Generate new enumeration indices to avoid enumeration index overflow.
John Reck59135872010-11-02 12:39:01 -07002885 MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
Steve Blocka7e24c12009-10-30 11:49:00 +00002886 static const int kMaxNumberKeyIndex =
2887 HashTable<Shape, Key>::kPrefixStartIndex;
2888 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
2889};
2890
2891
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002892class StringDictionaryShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00002893 public:
2894 static inline bool IsMatch(String* key, Object* other);
2895 static inline uint32_t Hash(String* key);
2896 static inline uint32_t HashForObject(String* key, Object* object);
John Reck59135872010-11-02 12:39:01 -07002897 MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002898 static const int kPrefixSize = 2;
2899 static const int kEntrySize = 3;
2900 static const bool kIsEnumerable = true;
2901};
2902
2903
2904class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
2905 public:
2906 static inline StringDictionary* cast(Object* obj) {
2907 ASSERT(obj->IsDictionary());
2908 return reinterpret_cast<StringDictionary*>(obj);
2909 }
2910
2911 // Copies enumerable keys to preallocated fixed array.
2912 void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
2913
2914 // For transforming properties of a JSObject.
John Reck59135872010-11-02 12:39:01 -07002915 MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
2916 JSObject* obj,
2917 int unused_property_fields);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002918
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002919 // Find entry for key, otherwise return kNotFound. Optimized version of
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002920 // HashTable::FindEntry.
2921 int FindEntry(String* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002922};
2923
2924
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002925class NumberDictionaryShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00002926 public:
2927 static inline bool IsMatch(uint32_t key, Object* other);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002928 static inline uint32_t Hash(uint32_t key);
2929 static inline uint32_t HashForObject(uint32_t key, Object* object);
John Reck59135872010-11-02 12:39:01 -07002930 MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002931 static const int kPrefixSize = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +00002932 static const int kEntrySize = 3;
2933 static const bool kIsEnumerable = false;
2934};
2935
2936
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002937class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
Steve Blocka7e24c12009-10-30 11:49:00 +00002938 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002939 static NumberDictionary* cast(Object* obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002940 ASSERT(obj->IsDictionary());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002941 return reinterpret_cast<NumberDictionary*>(obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00002942 }
2943
2944 // Type specific at put (default NONE attributes is used when adding).
John Reck59135872010-11-02 12:39:01 -07002945 MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
2946 MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
2947 Object* value,
2948 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002949
2950 // Set an existing entry or add a new one if needed.
John Reck59135872010-11-02 12:39:01 -07002951 MUST_USE_RESULT MaybeObject* Set(uint32_t key,
2952 Object* value,
2953 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00002954
2955 void UpdateMaxNumberKey(uint32_t key);
2956
2957 // If slow elements are required we will never go back to fast-case
2958 // for the elements kept in this dictionary. We require slow
2959 // elements if an element has been added at an index larger than
2960 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
2961 // when defining a getter or setter with a number key.
2962 inline bool requires_slow_elements();
2963 inline void set_requires_slow_elements();
2964
2965 // Get the value of the max number key that has been added to this
2966 // dictionary. max_number_key can only be called if
2967 // requires_slow_elements returns false.
2968 inline uint32_t max_number_key();
2969
Steve Blocka7e24c12009-10-30 11:49:00 +00002970 // Bit masks.
2971 static const int kRequiresSlowElementsMask = 1;
2972 static const int kRequiresSlowElementsTagSize = 1;
2973 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
2974};
2975
2976
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002977template <int entrysize>
2978class ObjectHashTableShape {
Ben Murdoch2b4ba112012-01-20 14:57:15 +00002979 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002980 static inline bool IsMatch(Object* key, Object* other);
2981 static inline uint32_t Hash(Object* key);
2982 static inline uint32_t HashForObject(Object* key, Object* object);
2983 MUST_USE_RESULT static inline MaybeObject* AsObject(Object* key);
2984 static const int kPrefixSize = 0;
2985 static const int kEntrySize = entrysize;
2986};
2987
2988
2989// ObjectHashSet holds keys that are arbitrary objects by using the identity
2990// hash of the key for hashing purposes.
2991class ObjectHashSet: public HashTable<ObjectHashTableShape<1>, Object*> {
2992 public:
2993 static inline ObjectHashSet* cast(Object* obj) {
2994 ASSERT(obj->IsHashTable());
2995 return reinterpret_cast<ObjectHashSet*>(obj);
Ben Murdoch2b4ba112012-01-20 14:57:15 +00002996 }
2997
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002998 // Looks up whether the given key is part of this hash set.
2999 bool Contains(Object* key);
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003000
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003001 // Adds the given key to this hash set.
3002 MUST_USE_RESULT MaybeObject* Add(Object* key);
3003
3004 // Removes the given key from this hash set.
3005 MUST_USE_RESULT MaybeObject* Remove(Object* key);
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003006};
3007
3008
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003009// ObjectHashTable maps keys that are arbitrary objects to object values by
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003010// using the identity hash of the key for hashing purposes.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003011class ObjectHashTable: public HashTable<ObjectHashTableShape<2>, Object*> {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003012 public:
3013 static inline ObjectHashTable* cast(Object* obj) {
3014 ASSERT(obj->IsHashTable());
3015 return reinterpret_cast<ObjectHashTable*>(obj);
3016 }
3017
3018 // Looks up the value associated with the given key. The undefined value is
3019 // returned in case the key is not present.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003020 Object* Lookup(Object* key);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003021
3022 // Adds (or overwrites) the value associated with the given key. Mapping a
3023 // key to the undefined value causes removal of the whole entry.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003024 MUST_USE_RESULT MaybeObject* Put(Object* key, Object* value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003025
3026 private:
3027 friend class MarkCompactCollector;
3028
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003029 void AddEntry(int entry, Object* key, Object* value);
3030 void RemoveEntry(int entry);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003031
3032 // Returns the index to the value of an entry.
3033 static inline int EntryToValueIndex(int entry) {
3034 return EntryToIndex(entry) + 1;
3035 }
3036};
3037
3038
Steve Block6ded16b2010-05-10 14:33:55 +01003039// JSFunctionResultCache caches results of some JSFunction invocation.
3040// It is a fixed array with fixed structure:
3041// [0]: factory function
3042// [1]: finger index
3043// [2]: current cache size
3044// [3]: dummy field.
3045// The rest of array are key/value pairs.
3046class JSFunctionResultCache: public FixedArray {
3047 public:
3048 static const int kFactoryIndex = 0;
3049 static const int kFingerIndex = kFactoryIndex + 1;
3050 static const int kCacheSizeIndex = kFingerIndex + 1;
3051 static const int kDummyIndex = kCacheSizeIndex + 1;
3052 static const int kEntriesIndex = kDummyIndex + 1;
3053
3054 static const int kEntrySize = 2; // key + value
3055
Kristian Monsen25f61362010-05-21 11:50:48 +01003056 static const int kFactoryOffset = kHeaderSize;
3057 static const int kFingerOffset = kFactoryOffset + kPointerSize;
3058 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
3059
Steve Block6ded16b2010-05-10 14:33:55 +01003060 inline void MakeZeroSize();
3061 inline void Clear();
3062
Ben Murdochb8e0da22011-05-16 14:20:40 +01003063 inline int size();
3064 inline void set_size(int size);
3065 inline int finger_index();
3066 inline void set_finger_index(int finger_index);
3067
Steve Block6ded16b2010-05-10 14:33:55 +01003068 // Casting
3069 static inline JSFunctionResultCache* cast(Object* obj);
3070
3071#ifdef DEBUG
3072 void JSFunctionResultCacheVerify();
3073#endif
3074};
3075
3076
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003077// ScopeInfo represents information about different scopes of a source
3078// program and the allocation of the scope's variables. Scope information
3079// is stored in a compressed form in ScopeInfo objects and is used
3080// at runtime (stack dumps, deoptimization, etc.).
3081
3082// This object provides quick access to scope info details for runtime
3083// routines.
3084class ScopeInfo : public FixedArray {
3085 public:
3086 static inline ScopeInfo* cast(Object* object);
3087
3088 // Return the type of this scope.
3089 ScopeType Type();
3090
3091 // Does this scope call eval?
3092 bool CallsEval();
3093
3094 // Return the language mode of this scope.
3095 LanguageMode language_mode();
3096
3097 // Does this scope make a non-strict eval call?
3098 bool CallsNonStrictEval() {
3099 return CallsEval() && (language_mode() == CLASSIC_MODE);
3100 }
3101
3102 // Return the total number of locals allocated on the stack and in the
3103 // context. This includes the parameters that are allocated in the context.
3104 int LocalCount();
3105
3106 // Return the number of stack slots for code. This number consists of two
3107 // parts:
3108 // 1. One stack slot per stack allocated local.
3109 // 2. One stack slot for the function name if it is stack allocated.
3110 int StackSlotCount();
3111
3112 // Return the number of context slots for code if a context is allocated. This
3113 // number consists of three parts:
3114 // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS
3115 // 2. One context slot per context allocated local.
3116 // 3. One context slot for the function name if it is context allocated.
3117 // Parameters allocated in the context count as context allocated locals. If
3118 // no contexts are allocated for this scope ContextLength returns 0.
3119 int ContextLength();
3120
3121 // Is this scope the scope of a named function expression?
3122 bool HasFunctionName();
3123
3124 // Return if this has context allocated locals.
3125 bool HasHeapAllocatedLocals();
3126
3127 // Return if contexts are allocated for this scope.
3128 bool HasContext();
3129
3130 // Return the function_name if present.
3131 String* FunctionName();
3132
3133 // Return the name of the given parameter.
3134 String* ParameterName(int var);
3135
3136 // Return the name of the given local.
3137 String* LocalName(int var);
3138
3139 // Return the name of the given stack local.
3140 String* StackLocalName(int var);
3141
3142 // Return the name of the given context local.
3143 String* ContextLocalName(int var);
3144
3145 // Return the mode of the given context local.
3146 VariableMode ContextLocalMode(int var);
3147
3148 // Return the initialization flag of the given context local.
3149 InitializationFlag ContextLocalInitFlag(int var);
3150
3151 // Lookup support for serialized scope info. Returns the
3152 // the stack slot index for a given slot name if the slot is
3153 // present; otherwise returns a value < 0. The name must be a symbol
3154 // (canonicalized).
3155 int StackSlotIndex(String* name);
3156
3157 // Lookup support for serialized scope info. Returns the
3158 // context slot index for a given slot name if the slot is present; otherwise
3159 // returns a value < 0. The name must be a symbol (canonicalized).
3160 // If the slot is present and mode != NULL, sets *mode to the corresponding
3161 // mode for that variable.
3162 int ContextSlotIndex(String* name,
3163 VariableMode* mode,
3164 InitializationFlag* init_flag);
3165
3166 // Lookup support for serialized scope info. Returns the
3167 // parameter index for a given parameter name if the parameter is present;
3168 // otherwise returns a value < 0. The name must be a symbol (canonicalized).
3169 int ParameterIndex(String* name);
3170
3171 // Lookup support for serialized scope info. Returns the
3172 // function context slot index if the function name is present (named
3173 // function expressions, only), otherwise returns a value < 0. The name
3174 // must be a symbol (canonicalized).
3175 int FunctionContextSlotIndex(String* name, VariableMode* mode);
3176
3177 static Handle<ScopeInfo> Create(Scope* scope);
3178
3179 // Serializes empty scope info.
3180 static ScopeInfo* Empty();
3181
3182#ifdef DEBUG
3183 void Print();
3184#endif
3185
3186 // The layout of the static part of a ScopeInfo is as follows. Each entry is
3187 // numeric and occupies one array slot.
3188 // 1. A set of properties of the scope
3189 // 2. The number of parameters. This only applies to function scopes. For
3190 // non-function scopes this is 0.
3191 // 3. The number of non-parameter variables allocated on the stack.
3192 // 4. The number of non-parameter and parameter variables allocated in the
3193 // context.
3194#define FOR_EACH_NUMERIC_FIELD(V) \
3195 V(Flags) \
3196 V(ParameterCount) \
3197 V(StackLocalCount) \
3198 V(ContextLocalCount)
3199
3200#define FIELD_ACCESSORS(name) \
3201 void Set##name(int value) { \
3202 set(k##name, Smi::FromInt(value)); \
3203 } \
3204 int name() { \
3205 if (length() > 0) { \
3206 return Smi::cast(get(k##name))->value(); \
3207 } else { \
3208 return 0; \
3209 } \
3210 }
3211 FOR_EACH_NUMERIC_FIELD(FIELD_ACCESSORS)
3212#undef FIELD_ACCESSORS
3213
3214 private:
3215 enum {
3216#define DECL_INDEX(name) k##name,
3217 FOR_EACH_NUMERIC_FIELD(DECL_INDEX)
3218#undef DECL_INDEX
3219#undef FOR_EACH_NUMERIC_FIELD
3220 kVariablePartIndex
3221 };
3222
3223 // The layout of the variable part of a ScopeInfo is as follows:
3224 // 1. ParameterEntries:
3225 // This part stores the names of the parameters for function scopes. One
3226 // slot is used per parameter, so in total this part occupies
3227 // ParameterCount() slots in the array. For other scopes than function
3228 // scopes ParameterCount() is 0.
3229 // 2. StackLocalEntries:
3230 // Contains the names of local variables that are allocated on the stack,
3231 // in increasing order of the stack slot index. One slot is used per stack
3232 // local, so in total this part occupies StackLocalCount() slots in the
3233 // array.
3234 // 3. ContextLocalNameEntries:
3235 // Contains the names of local variables and parameters that are allocated
3236 // in the context. They are stored in increasing order of the context slot
3237 // index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
3238 // context local, so in total this part occupies ContextLocalCount() slots
3239 // in the array.
3240 // 4. ContextLocalInfoEntries:
3241 // Contains the variable modes and initialization flags corresponding to
3242 // the context locals in ContextLocalNameEntries. One slot is used per
3243 // context local, so in total this part occupies ContextLocalCount()
3244 // slots in the array.
3245 // 5. FunctionNameEntryIndex:
3246 // If the scope belongs to a named function expression this part contains
3247 // information about the function variable. It always occupies two array
3248 // slots: a. The name of the function variable.
3249 // b. The context or stack slot index for the variable.
3250 int ParameterEntriesIndex();
3251 int StackLocalEntriesIndex();
3252 int ContextLocalNameEntriesIndex();
3253 int ContextLocalInfoEntriesIndex();
3254 int FunctionNameEntryIndex();
3255
3256 // Location of the function variable for named function expressions.
3257 enum FunctionVariableInfo {
3258 NONE, // No function name present.
3259 STACK, // Function
3260 CONTEXT,
3261 UNUSED
3262 };
3263
3264 // Properties of scopes.
3265 class TypeField: public BitField<ScopeType, 0, 3> {};
3266 class CallsEvalField: public BitField<bool, 3, 1> {};
3267 class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
3268 class FunctionVariableField: public BitField<FunctionVariableInfo, 6, 2> {};
3269 class FunctionVariableMode: public BitField<VariableMode, 8, 3> {};
3270
3271 // BitFields representing the encoded information for context locals in the
3272 // ContextLocalInfoEntries part.
3273 class ContextLocalMode: public BitField<VariableMode, 0, 3> {};
3274 class ContextLocalInitFlag: public BitField<InitializationFlag, 3, 1> {};
3275};
3276
3277
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003278// The cache for maps used by normalized (dictionary mode) objects.
3279// Such maps do not have property descriptors, so a typical program
3280// needs very limited number of distinct normalized maps.
3281class NormalizedMapCache: public FixedArray {
3282 public:
3283 static const int kEntries = 64;
3284
John Reck59135872010-11-02 12:39:01 -07003285 MUST_USE_RESULT MaybeObject* Get(JSObject* object,
3286 PropertyNormalizationMode mode);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003287
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003288 void Clear();
3289
3290 // Casting
3291 static inline NormalizedMapCache* cast(Object* obj);
3292
3293#ifdef DEBUG
3294 void NormalizedMapCacheVerify();
3295#endif
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003296};
3297
3298
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003299// ByteArray represents fixed sized byte arrays. Used for the relocation info
3300// that is attached to code objects.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003301class ByteArray: public FixedArrayBase {
Steve Blocka7e24c12009-10-30 11:49:00 +00003302 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003303 inline int Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
3304
Steve Blocka7e24c12009-10-30 11:49:00 +00003305 // Setter and getter.
3306 inline byte get(int index);
3307 inline void set(int index, byte value);
3308
3309 // Treat contents as an int array.
3310 inline int get_int(int index);
3311
3312 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003313 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
Steve Blocka7e24c12009-10-30 11:49:00 +00003314 }
3315 // We use byte arrays for free blocks in the heap. Given a desired size in
3316 // bytes that is a multiple of the word size and big enough to hold a byte
3317 // array, this function returns the number of elements a byte array should
3318 // have.
3319 static int LengthFor(int size_in_bytes) {
3320 ASSERT(IsAligned(size_in_bytes, kPointerSize));
3321 ASSERT(size_in_bytes >= kHeaderSize);
3322 return size_in_bytes - kHeaderSize;
3323 }
3324
3325 // Returns data start address.
3326 inline Address GetDataStartAddress();
3327
3328 // Returns a pointer to the ByteArray object for a given data start address.
3329 static inline ByteArray* FromDataStartAddress(Address address);
3330
3331 // Casting.
3332 static inline ByteArray* cast(Object* obj);
3333
3334 // Dispatched behavior.
Iain Merrick75681382010-08-19 15:07:18 +01003335 inline int ByteArraySize() {
3336 return SizeFor(this->length());
3337 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003338#ifdef OBJECT_PRINT
3339 inline void ByteArrayPrint() {
3340 ByteArrayPrint(stdout);
3341 }
3342 void ByteArrayPrint(FILE* out);
3343#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00003344#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00003345 void ByteArrayVerify();
3346#endif
3347
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003348 // Layout description.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003349 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00003350
Leon Clarkee46be812010-01-19 14:06:41 +00003351 // Maximal memory consumption for a single ByteArray.
3352 static const int kMaxSize = 512 * MB;
3353 // Maximal length of a single ByteArray.
3354 static const int kMaxLength = kMaxSize - kHeaderSize;
3355
Steve Blocka7e24c12009-10-30 11:49:00 +00003356 private:
3357 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
3358};
3359
3360
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003361// FreeSpace represents fixed sized areas of the heap that are not currently in
3362// use. Used by the heap and GC.
3363class FreeSpace: public HeapObject {
3364 public:
3365 // [size]: size of the free space including the header.
3366 inline int size();
3367 inline void set_size(int value);
3368
3369 inline int Size() { return size(); }
3370
3371 // Casting.
3372 static inline FreeSpace* cast(Object* obj);
3373
3374#ifdef OBJECT_PRINT
3375 inline void FreeSpacePrint() {
3376 FreeSpacePrint(stdout);
3377 }
3378 void FreeSpacePrint(FILE* out);
3379#endif
3380#ifdef DEBUG
3381 void FreeSpaceVerify();
3382#endif
3383
3384 // Layout description.
3385 // Size is smi tagged when it is stored.
3386 static const int kSizeOffset = HeapObject::kHeaderSize;
3387 static const int kHeaderSize = kSizeOffset + kPointerSize;
3388
3389 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
3390
3391 private:
3392 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace);
3393};
3394
3395
Steve Block3ce2e202009-11-05 08:53:23 +00003396// An ExternalArray represents a fixed-size array of primitive values
3397// which live outside the JavaScript heap. Its subclasses are used to
3398// implement the CanvasArray types being defined in the WebGL
3399// specification. As of this writing the first public draft is not yet
3400// available, but Khronos members can access the draft at:
3401// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
3402//
3403// The semantics of these arrays differ from CanvasPixelArray.
3404// Out-of-range values passed to the setter are converted via a C
3405// cast, not clamping. Out-of-range indices cause exceptions to be
3406// raised rather than being silently ignored.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003407class ExternalArray: public FixedArrayBase {
Steve Block3ce2e202009-11-05 08:53:23 +00003408 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003409 inline bool is_the_hole(int index) { return false; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003410
Steve Block3ce2e202009-11-05 08:53:23 +00003411 // [external_pointer]: The pointer to the external memory area backing this
3412 // external array.
3413 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
3414
3415 // Casting.
3416 static inline ExternalArray* cast(Object* obj);
3417
3418 // Maximal acceptable length for an external array.
3419 static const int kMaxLength = 0x3fffffff;
3420
3421 // ExternalArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003422 static const int kExternalPointerOffset =
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003423 POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize);
Steve Block3ce2e202009-11-05 08:53:23 +00003424 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003425 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Block3ce2e202009-11-05 08:53:23 +00003426
3427 private:
3428 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
3429};
3430
3431
Steve Block44f0eee2011-05-26 01:26:41 +01003432// A ExternalPixelArray represents a fixed-size byte array with special
3433// semantics used for implementing the CanvasPixelArray object. Please see the
3434// specification at:
3435
3436// http://www.whatwg.org/specs/web-apps/current-work/
3437// multipage/the-canvas-element.html#canvaspixelarray
3438// In particular, write access clamps the value written to 0 or 255 if the
3439// value written is outside this range.
3440class ExternalPixelArray: public ExternalArray {
3441 public:
3442 inline uint8_t* external_pixel_pointer();
3443
3444 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003445 inline uint8_t get_scalar(int index);
3446 inline MaybeObject* get(int index);
Steve Block44f0eee2011-05-26 01:26:41 +01003447 inline void set(int index, uint8_t value);
3448
3449 // This accessor applies the correct conversion from Smi, HeapNumber and
3450 // undefined and clamps the converted value between 0 and 255.
3451 Object* SetValue(uint32_t index, Object* value);
3452
3453 // Casting.
3454 static inline ExternalPixelArray* cast(Object* obj);
3455
3456#ifdef OBJECT_PRINT
3457 inline void ExternalPixelArrayPrint() {
3458 ExternalPixelArrayPrint(stdout);
3459 }
3460 void ExternalPixelArrayPrint(FILE* out);
3461#endif
3462#ifdef DEBUG
3463 void ExternalPixelArrayVerify();
3464#endif // DEBUG
3465
3466 private:
3467 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
3468};
3469
3470
Steve Block3ce2e202009-11-05 08:53:23 +00003471class ExternalByteArray: public ExternalArray {
3472 public:
3473 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003474 inline int8_t get_scalar(int index);
3475 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003476 inline void set(int index, int8_t value);
3477
3478 // This accessor applies the correct conversion from Smi, HeapNumber
3479 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003480 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003481
3482 // Casting.
3483 static inline ExternalByteArray* cast(Object* obj);
3484
Ben Murdochb0fe1622011-05-05 13:52:32 +01003485#ifdef OBJECT_PRINT
3486 inline void ExternalByteArrayPrint() {
3487 ExternalByteArrayPrint(stdout);
3488 }
3489 void ExternalByteArrayPrint(FILE* out);
3490#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003491#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003492 void ExternalByteArrayVerify();
3493#endif // DEBUG
3494
3495 private:
3496 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
3497};
3498
3499
3500class ExternalUnsignedByteArray: public ExternalArray {
3501 public:
3502 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003503 inline uint8_t get_scalar(int index);
3504 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003505 inline void set(int index, uint8_t value);
3506
3507 // This accessor applies the correct conversion from Smi, HeapNumber
3508 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003509 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003510
3511 // Casting.
3512 static inline ExternalUnsignedByteArray* cast(Object* obj);
3513
Ben Murdochb0fe1622011-05-05 13:52:32 +01003514#ifdef OBJECT_PRINT
3515 inline void ExternalUnsignedByteArrayPrint() {
3516 ExternalUnsignedByteArrayPrint(stdout);
3517 }
3518 void ExternalUnsignedByteArrayPrint(FILE* out);
3519#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003520#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003521 void ExternalUnsignedByteArrayVerify();
3522#endif // DEBUG
3523
3524 private:
3525 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
3526};
3527
3528
3529class ExternalShortArray: public ExternalArray {
3530 public:
3531 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003532 inline int16_t get_scalar(int index);
3533 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003534 inline void set(int index, int16_t value);
3535
3536 // This accessor applies the correct conversion from Smi, HeapNumber
3537 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003538 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003539
3540 // Casting.
3541 static inline ExternalShortArray* cast(Object* obj);
3542
Ben Murdochb0fe1622011-05-05 13:52:32 +01003543#ifdef OBJECT_PRINT
3544 inline void ExternalShortArrayPrint() {
3545 ExternalShortArrayPrint(stdout);
3546 }
3547 void ExternalShortArrayPrint(FILE* out);
3548#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003549#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003550 void ExternalShortArrayVerify();
3551#endif // DEBUG
3552
3553 private:
3554 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
3555};
3556
3557
3558class ExternalUnsignedShortArray: public ExternalArray {
3559 public:
3560 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003561 inline uint16_t get_scalar(int index);
3562 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003563 inline void set(int index, uint16_t value);
3564
3565 // This accessor applies the correct conversion from Smi, HeapNumber
3566 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003567 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003568
3569 // Casting.
3570 static inline ExternalUnsignedShortArray* cast(Object* obj);
3571
Ben Murdochb0fe1622011-05-05 13:52:32 +01003572#ifdef OBJECT_PRINT
3573 inline void ExternalUnsignedShortArrayPrint() {
3574 ExternalUnsignedShortArrayPrint(stdout);
3575 }
3576 void ExternalUnsignedShortArrayPrint(FILE* out);
3577#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003578#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003579 void ExternalUnsignedShortArrayVerify();
3580#endif // DEBUG
3581
3582 private:
3583 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
3584};
3585
3586
3587class ExternalIntArray: public ExternalArray {
3588 public:
3589 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003590 inline int32_t get_scalar(int index);
3591 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003592 inline void set(int index, int32_t value);
3593
3594 // This accessor applies the correct conversion from Smi, HeapNumber
3595 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003596 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003597
3598 // Casting.
3599 static inline ExternalIntArray* cast(Object* obj);
3600
Ben Murdochb0fe1622011-05-05 13:52:32 +01003601#ifdef OBJECT_PRINT
3602 inline void ExternalIntArrayPrint() {
3603 ExternalIntArrayPrint(stdout);
3604 }
3605 void ExternalIntArrayPrint(FILE* out);
3606#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003607#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003608 void ExternalIntArrayVerify();
3609#endif // DEBUG
3610
3611 private:
3612 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
3613};
3614
3615
3616class ExternalUnsignedIntArray: public ExternalArray {
3617 public:
3618 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003619 inline uint32_t get_scalar(int index);
3620 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003621 inline void set(int index, uint32_t value);
3622
3623 // This accessor applies the correct conversion from Smi, HeapNumber
3624 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003625 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003626
3627 // Casting.
3628 static inline ExternalUnsignedIntArray* cast(Object* obj);
3629
Ben Murdochb0fe1622011-05-05 13:52:32 +01003630#ifdef OBJECT_PRINT
3631 inline void ExternalUnsignedIntArrayPrint() {
3632 ExternalUnsignedIntArrayPrint(stdout);
3633 }
3634 void ExternalUnsignedIntArrayPrint(FILE* out);
3635#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003636#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003637 void ExternalUnsignedIntArrayVerify();
3638#endif // DEBUG
3639
3640 private:
3641 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
3642};
3643
3644
3645class ExternalFloatArray: public ExternalArray {
3646 public:
3647 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003648 inline float get_scalar(int index);
3649 inline MaybeObject* get(int index);
Steve Block3ce2e202009-11-05 08:53:23 +00003650 inline void set(int index, float value);
3651
3652 // This accessor applies the correct conversion from Smi, HeapNumber
3653 // and undefined.
John Reck59135872010-11-02 12:39:01 -07003654 MaybeObject* SetValue(uint32_t index, Object* value);
Steve Block3ce2e202009-11-05 08:53:23 +00003655
3656 // Casting.
3657 static inline ExternalFloatArray* cast(Object* obj);
3658
Ben Murdochb0fe1622011-05-05 13:52:32 +01003659#ifdef OBJECT_PRINT
3660 inline void ExternalFloatArrayPrint() {
3661 ExternalFloatArrayPrint(stdout);
3662 }
3663 void ExternalFloatArrayPrint(FILE* out);
3664#endif
Steve Block3ce2e202009-11-05 08:53:23 +00003665#ifdef DEBUG
Steve Block3ce2e202009-11-05 08:53:23 +00003666 void ExternalFloatArrayVerify();
3667#endif // DEBUG
3668
3669 private:
3670 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
3671};
3672
3673
Ben Murdoch257744e2011-11-30 15:57:28 +00003674class ExternalDoubleArray: public ExternalArray {
3675 public:
3676 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003677 inline double get_scalar(int index);
3678 inline MaybeObject* get(int index);
Ben Murdoch257744e2011-11-30 15:57:28 +00003679 inline void set(int index, double value);
3680
3681 // This accessor applies the correct conversion from Smi, HeapNumber
3682 // and undefined.
3683 MaybeObject* SetValue(uint32_t index, Object* value);
3684
3685 // Casting.
3686 static inline ExternalDoubleArray* cast(Object* obj);
3687
3688#ifdef OBJECT_PRINT
3689 inline void ExternalDoubleArrayPrint() {
3690 ExternalDoubleArrayPrint(stdout);
3691 }
3692 void ExternalDoubleArrayPrint(FILE* out);
3693#endif // OBJECT_PRINT
3694#ifdef DEBUG
3695 void ExternalDoubleArrayVerify();
3696#endif // DEBUG
3697
3698 private:
3699 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalDoubleArray);
3700};
3701
3702
Ben Murdochb0fe1622011-05-05 13:52:32 +01003703// DeoptimizationInputData is a fixed array used to hold the deoptimization
3704// data for code generated by the Hydrogen/Lithium compiler. It also
3705// contains information about functions that were inlined. If N different
3706// functions were inlined then first N elements of the literal array will
3707// contain these functions.
3708//
3709// It can be empty.
3710class DeoptimizationInputData: public FixedArray {
3711 public:
3712 // Layout description. Indices in the array.
3713 static const int kTranslationByteArrayIndex = 0;
3714 static const int kInlinedFunctionCountIndex = 1;
3715 static const int kLiteralArrayIndex = 2;
3716 static const int kOsrAstIdIndex = 3;
3717 static const int kOsrPcOffsetIndex = 4;
3718 static const int kFirstDeoptEntryIndex = 5;
3719
3720 // Offsets of deopt entry elements relative to the start of the entry.
3721 static const int kAstIdOffset = 0;
3722 static const int kTranslationIndexOffset = 1;
3723 static const int kArgumentsStackHeightOffset = 2;
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003724 static const int kPcOffset = 3;
3725 static const int kDeoptEntrySize = 4;
Ben Murdochb0fe1622011-05-05 13:52:32 +01003726
3727 // Simple element accessors.
3728#define DEFINE_ELEMENT_ACCESSORS(name, type) \
3729 type* name() { \
3730 return type::cast(get(k##name##Index)); \
3731 } \
3732 void Set##name(type* value) { \
3733 set(k##name##Index, value); \
3734 }
3735
3736 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
3737 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
3738 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
3739 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
3740 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
3741
Ben Murdochb0fe1622011-05-05 13:52:32 +01003742#undef DEFINE_ELEMENT_ACCESSORS
3743
3744 // Accessors for elements of the ith deoptimization entry.
3745#define DEFINE_ENTRY_ACCESSORS(name, type) \
3746 type* name(int i) { \
3747 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
3748 } \
3749 void Set##name(int i, type* value) { \
3750 set(IndexForEntry(i) + k##name##Offset, value); \
3751 }
3752
3753 DEFINE_ENTRY_ACCESSORS(AstId, Smi)
3754 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
3755 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003756 DEFINE_ENTRY_ACCESSORS(Pc, Smi)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003757
3758#undef DEFINE_ENTRY_ACCESSORS
3759
3760 int DeoptCount() {
3761 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
3762 }
3763
3764 // Allocates a DeoptimizationInputData.
3765 MUST_USE_RESULT static MaybeObject* Allocate(int deopt_entry_count,
3766 PretenureFlag pretenure);
3767
3768 // Casting.
3769 static inline DeoptimizationInputData* cast(Object* obj);
3770
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003771#ifdef ENABLE_DISASSEMBLER
Ben Murdochb0fe1622011-05-05 13:52:32 +01003772 void DeoptimizationInputDataPrint(FILE* out);
3773#endif
3774
3775 private:
3776 static int IndexForEntry(int i) {
3777 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
3778 }
3779
3780 static int LengthFor(int entry_count) {
3781 return IndexForEntry(entry_count);
3782 }
3783};
3784
3785
3786// DeoptimizationOutputData is a fixed array used to hold the deoptimization
3787// data for code generated by the full compiler.
3788// The format of the these objects is
3789// [i * 2]: Ast ID for ith deoptimization.
3790// [i * 2 + 1]: PC and state of ith deoptimization
3791class DeoptimizationOutputData: public FixedArray {
3792 public:
3793 int DeoptPoints() { return length() / 2; }
3794 Smi* AstId(int index) { return Smi::cast(get(index * 2)); }
3795 void SetAstId(int index, Smi* id) { set(index * 2, id); }
3796 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
3797 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
3798
3799 static int LengthOfFixedArray(int deopt_points) {
3800 return deopt_points * 2;
3801 }
3802
3803 // Allocates a DeoptimizationOutputData.
3804 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_deopt_points,
3805 PretenureFlag pretenure);
3806
3807 // Casting.
3808 static inline DeoptimizationOutputData* cast(Object* obj);
3809
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003810#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003811 void DeoptimizationOutputDataPrint(FILE* out);
3812#endif
3813};
3814
3815
Ben Murdochb8e0da22011-05-16 14:20:40 +01003816class SafepointEntry;
3817
3818
Steve Blocka7e24c12009-10-30 11:49:00 +00003819// Code describes objects with on-the-fly generated machine code.
3820class Code: public HeapObject {
3821 public:
3822 // Opaque data type for encapsulating code flags like kind, inline
3823 // cache state, and arguments count.
Iain Merrick75681382010-08-19 15:07:18 +01003824 // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
3825 // enumeration type has correct value range (see Issue 830 for more details).
3826 enum Flags {
3827 FLAGS_MIN_VALUE = kMinInt,
3828 FLAGS_MAX_VALUE = kMaxInt
3829 };
Steve Blocka7e24c12009-10-30 11:49:00 +00003830
3831 enum Kind {
3832 FUNCTION,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003833 OPTIMIZED_FUNCTION,
Steve Blocka7e24c12009-10-30 11:49:00 +00003834 STUB,
3835 BUILTIN,
3836 LOAD_IC,
3837 KEYED_LOAD_IC,
3838 CALL_IC,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003839 KEYED_CALL_IC,
Steve Blocka7e24c12009-10-30 11:49:00 +00003840 STORE_IC,
3841 KEYED_STORE_IC,
Ben Murdoch257744e2011-11-30 15:57:28 +00003842 UNARY_OP_IC,
3843 BINARY_OP_IC,
Ben Murdochb0fe1622011-05-05 13:52:32 +01003844 COMPARE_IC,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003845 TO_BOOLEAN_IC,
Steve Block6ded16b2010-05-10 14:33:55 +01003846 // No more than 16 kinds. The value currently encoded in four bits in
Steve Blocka7e24c12009-10-30 11:49:00 +00003847 // Flags.
3848
3849 // Pseudo-kinds.
3850 REGEXP = BUILTIN,
3851 FIRST_IC_KIND = LOAD_IC,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003852 LAST_IC_KIND = TO_BOOLEAN_IC
Steve Blocka7e24c12009-10-30 11:49:00 +00003853 };
3854
3855 enum {
Kristian Monsen50ef84f2010-07-29 15:18:00 +01003856 NUMBER_OF_KINDS = LAST_IC_KIND + 1
Steve Blocka7e24c12009-10-30 11:49:00 +00003857 };
3858
Ben Murdochb8e0da22011-05-16 14:20:40 +01003859 typedef int ExtraICState;
3860
3861 static const ExtraICState kNoExtraICState = 0;
3862
Steve Blocka7e24c12009-10-30 11:49:00 +00003863#ifdef ENABLE_DISASSEMBLER
3864 // Printing
3865 static const char* Kind2String(Kind kind);
3866 static const char* ICState2String(InlineCacheState state);
3867 static const char* PropertyType2String(PropertyType type);
Steve Block1e0659c2011-05-24 12:43:12 +01003868 static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003869 inline void Disassemble(const char* name) {
3870 Disassemble(name, stdout);
3871 }
3872 void Disassemble(const char* name, FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00003873#endif // ENABLE_DISASSEMBLER
3874
3875 // [instruction_size]: Size of the native instructions
3876 inline int instruction_size();
3877 inline void set_instruction_size(int value);
3878
Leon Clarkeac952652010-07-15 11:15:24 +01003879 // [relocation_info]: Code relocation information
3880 DECL_ACCESSORS(relocation_info, ByteArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01003881 void InvalidateRelocation();
Leon Clarkeac952652010-07-15 11:15:24 +01003882
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003883 // [handler_table]: Fixed array containing offsets of exception handlers.
3884 DECL_ACCESSORS(handler_table, FixedArray)
3885
Ben Murdochb0fe1622011-05-05 13:52:32 +01003886 // [deoptimization_data]: Array containing data for deopt.
3887 DECL_ACCESSORS(deoptimization_data, FixedArray)
3888
Ben Murdoch257744e2011-11-30 15:57:28 +00003889 // [code_flushing_candidate]: Field only used during garbage
3890 // collection to hold code flushing candidates. The contents of this
3891 // field does not have to be traced during garbage collection since
3892 // it is only used by the garbage collector itself.
3893 DECL_ACCESSORS(next_code_flushing_candidate, Object)
3894
Ben Murdochb0fe1622011-05-05 13:52:32 +01003895 // Unchecked accessors to be used during GC.
Leon Clarkeac952652010-07-15 11:15:24 +01003896 inline ByteArray* unchecked_relocation_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003897 inline FixedArray* unchecked_deoptimization_data();
Leon Clarkeac952652010-07-15 11:15:24 +01003898
Steve Blocka7e24c12009-10-30 11:49:00 +00003899 inline int relocation_size();
Steve Blocka7e24c12009-10-30 11:49:00 +00003900
Steve Blocka7e24c12009-10-30 11:49:00 +00003901 // [flags]: Various code flags.
3902 inline Flags flags();
3903 inline void set_flags(Flags flags);
3904
3905 // [flags]: Access to specific code flags.
3906 inline Kind kind();
3907 inline InlineCacheState ic_state(); // Only valid for IC stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003908 inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
Steve Blocka7e24c12009-10-30 11:49:00 +00003909 inline PropertyType type(); // Only valid for monomorphic IC stubs.
3910 inline int arguments_count(); // Only valid for call IC stubs.
3911
3912 // Testers for IC stub kinds.
3913 inline bool is_inline_cache_stub();
3914 inline bool is_load_stub() { return kind() == LOAD_IC; }
3915 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
3916 inline bool is_store_stub() { return kind() == STORE_IC; }
3917 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
3918 inline bool is_call_stub() { return kind() == CALL_IC; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003919 inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003920 inline bool is_unary_op_stub() { return kind() == UNARY_OP_IC; }
3921 inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003922 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003923 inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
Steve Blocka7e24c12009-10-30 11:49:00 +00003924
Steve Block6ded16b2010-05-10 14:33:55 +01003925 // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003926 inline int major_key();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003927 inline void set_major_key(int value);
3928
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003929 // For stubs, tells whether they should always exist, so that they can be
3930 // called from other stubs.
3931 inline bool is_pregenerated();
3932 inline void set_is_pregenerated(bool value);
3933
Ben Murdochb0fe1622011-05-05 13:52:32 +01003934 // [optimizable]: For FUNCTION kind, tells if it is optimizable.
3935 inline bool optimizable();
3936 inline void set_optimizable(bool value);
3937
3938 // [has_deoptimization_support]: For FUNCTION kind, tells if it has
3939 // deoptimization support.
3940 inline bool has_deoptimization_support();
3941 inline void set_has_deoptimization_support(bool value);
3942
Ben Murdoch589d6972011-11-30 16:04:58 +00003943 // [has_debug_break_slots]: For FUNCTION kind, tells if it has
3944 // been compiled with debug break slots.
3945 inline bool has_debug_break_slots();
3946 inline void set_has_debug_break_slots(bool value);
3947
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003948 // [compiled_with_optimizing]: For FUNCTION kind, tells if it has
3949 // been compiled with IsOptimizing set to true.
3950 inline bool is_compiled_optimizable();
3951 inline void set_compiled_optimizable(bool value);
3952
Ben Murdochb0fe1622011-05-05 13:52:32 +01003953 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
3954 // how long the function has been marked for OSR and therefore which
3955 // level of loop nesting we are willing to do on-stack replacement
3956 // for.
3957 inline void set_allow_osr_at_loop_nesting_level(int level);
3958 inline int allow_osr_at_loop_nesting_level();
3959
3960 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
3961 // reserved in the code prologue.
3962 inline unsigned stack_slots();
3963 inline void set_stack_slots(unsigned slots);
3964
3965 // [safepoint_table_start]: For kind OPTIMIZED_CODE, the offset in
3966 // the instruction stream where the safepoint table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01003967 inline unsigned safepoint_table_offset();
3968 inline void set_safepoint_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003969
3970 // [stack_check_table_start]: For kind FUNCTION, the offset in the
3971 // instruction stream where the stack check table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01003972 inline unsigned stack_check_table_offset();
3973 inline void set_stack_check_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003974
3975 // [check type]: For kind CALL_IC, tells how to check if the
3976 // receiver is valid for the given call.
3977 inline CheckType check_type();
3978 inline void set_check_type(CheckType value);
3979
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003980 // [type-recording unary op type]: For kind UNARY_OP_IC.
Ben Murdoch257744e2011-11-30 15:57:28 +00003981 inline byte unary_op_type();
3982 inline void set_unary_op_type(byte value);
3983
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003984 // [type-recording binary op type]: For kind BINARY_OP_IC.
Ben Murdoch257744e2011-11-30 15:57:28 +00003985 inline byte binary_op_type();
3986 inline void set_binary_op_type(byte value);
3987 inline byte binary_op_result_type();
3988 inline void set_binary_op_result_type(byte value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003989
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003990 // [compare state]: For kind COMPARE_IC, tells what state the stub is in.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003991 inline byte compare_state();
3992 inline void set_compare_state(byte value);
3993
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003994 // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
3995 inline byte to_boolean_state();
3996 inline void set_to_boolean_state(byte value);
3997
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003998 // For kind STUB, major_key == CallFunction, tells whether there is
3999 // a function cache in the instruction stream.
4000 inline bool has_function_cache();
4001 inline void set_has_function_cache(bool flag);
4002
Ben Murdochb8e0da22011-05-16 14:20:40 +01004003 // Get the safepoint entry for the given pc.
4004 SafepointEntry GetSafepointEntry(Address pc);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004005
4006 // Mark this code object as not having a stack check table. Assumes kind
4007 // is FUNCTION.
4008 void SetNoStackCheckTable();
4009
4010 // Find the first map in an IC stub.
4011 Map* FindFirstMap();
Steve Blocka7e24c12009-10-30 11:49:00 +00004012
4013 // Flags operations.
Ben Murdochb8e0da22011-05-16 14:20:40 +01004014 static inline Flags ComputeFlags(
4015 Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01004016 InlineCacheState ic_state = UNINITIALIZED,
4017 ExtraICState extra_ic_state = kNoExtraICState,
4018 PropertyType type = NORMAL,
4019 int argc = -1,
4020 InlineCacheHolderFlag holder = OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +00004021
4022 static inline Flags ComputeMonomorphicFlags(
4023 Kind kind,
4024 PropertyType type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01004025 ExtraICState extra_ic_state = kNoExtraICState,
Steve Block8defd9f2010-07-08 12:39:36 +01004026 InlineCacheHolderFlag holder = OWN_MAP,
Steve Blocka7e24c12009-10-30 11:49:00 +00004027 int argc = -1);
4028
Steve Blocka7e24c12009-10-30 11:49:00 +00004029 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00004030 static inline PropertyType ExtractTypeFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00004031 static inline Kind ExtractKindFromFlags(Flags flags);
Steve Block8defd9f2010-07-08 12:39:36 +01004032 static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00004033 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
4034 static inline int ExtractArgumentsCountFromFlags(Flags flags);
4035
Steve Blocka7e24c12009-10-30 11:49:00 +00004036 static inline Flags RemoveTypeFromFlags(Flags flags);
4037
4038 // Convert a target address into a code object.
4039 static inline Code* GetCodeFromTargetAddress(Address address);
4040
Steve Block791712a2010-08-27 10:21:07 +01004041 // Convert an entry address into an object.
4042 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
4043
Steve Blocka7e24c12009-10-30 11:49:00 +00004044 // Returns the address of the first instruction.
4045 inline byte* instruction_start();
4046
Leon Clarkeac952652010-07-15 11:15:24 +01004047 // Returns the address right after the last instruction.
4048 inline byte* instruction_end();
4049
Steve Blocka7e24c12009-10-30 11:49:00 +00004050 // Returns the size of the instructions, padding, and relocation information.
4051 inline int body_size();
4052
4053 // Returns the address of the first relocation info (read backwards!).
4054 inline byte* relocation_start();
4055
4056 // Code entry point.
4057 inline byte* entry();
4058
4059 // Returns true if pc is inside this object's instructions.
4060 inline bool contains(byte* pc);
4061
Steve Blocka7e24c12009-10-30 11:49:00 +00004062 // Relocate the code by delta bytes. Called to signal that this code
4063 // object has been moved by delta bytes.
Steve Blockd0582a62009-12-15 09:54:21 +00004064 void Relocate(intptr_t delta);
Steve Blocka7e24c12009-10-30 11:49:00 +00004065
4066 // Migrate code described by desc.
4067 void CopyFrom(const CodeDesc& desc);
4068
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004069 // Returns the object size for a given body (used for allocation).
4070 static int SizeFor(int body_size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004071 ASSERT_SIZE_TAG_ALIGNED(body_size);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004072 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
Steve Blocka7e24c12009-10-30 11:49:00 +00004073 }
4074
4075 // Calculate the size of the code object to report for log events. This takes
4076 // the layout of the code object into account.
4077 int ExecutableSize() {
4078 // Check that the assumptions about the layout of the code object holds.
4079 ASSERT_EQ(static_cast<int>(instruction_start() - address()),
4080 Code::kHeaderSize);
4081 return instruction_size() + Code::kHeaderSize;
4082 }
4083
4084 // Locating source position.
4085 int SourcePosition(Address pc);
4086 int SourceStatementPosition(Address pc);
4087
4088 // Casting.
4089 static inline Code* cast(Object* obj);
4090
4091 // Dispatched behavior.
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004092 int CodeSize() { return SizeFor(body_size()); }
Iain Merrick75681382010-08-19 15:07:18 +01004093 inline void CodeIterateBody(ObjectVisitor* v);
4094
4095 template<typename StaticVisitor>
Steve Block44f0eee2011-05-26 01:26:41 +01004096 inline void CodeIterateBody(Heap* heap);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004097#ifdef OBJECT_PRINT
4098 inline void CodePrint() {
4099 CodePrint(stdout);
4100 }
4101 void CodePrint(FILE* out);
4102#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004103#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004104 void CodeVerify();
4105#endif
Ben Murdochb0fe1622011-05-05 13:52:32 +01004106
4107 // Max loop nesting marker used to postpose OSR. We don't take loop
4108 // nesting that is deeper than 5 levels into account.
4109 static const int kMaxLoopNestingMarker = 6;
4110
Steve Blocka7e24c12009-10-30 11:49:00 +00004111 // Layout description.
4112 static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
Leon Clarkeac952652010-07-15 11:15:24 +01004113 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004114 static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004115 static const int kDeoptimizationDataOffset =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004116 kHandlerTableOffset + kPointerSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00004117 static const int kNextCodeFlushingCandidateOffset =
4118 kDeoptimizationDataOffset + kPointerSize;
4119 static const int kFlagsOffset =
4120 kNextCodeFlushingCandidateOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004121
Ben Murdoch257744e2011-11-30 15:57:28 +00004122 static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004123 static const int kKindSpecificFlagsSize = 2 * kIntSize;
4124
4125 static const int kHeaderPaddingStart = kKindSpecificFlagsOffset +
4126 kKindSpecificFlagsSize;
4127
Steve Blocka7e24c12009-10-30 11:49:00 +00004128 // Add padding to align the instruction start following right after
4129 // the Code object header.
4130 static const int kHeaderSize =
Ben Murdochb0fe1622011-05-05 13:52:32 +01004131 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00004132
4133 // Byte offsets within kKindSpecificFlagsOffset.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004134 static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset;
4135 static const int kOptimizableOffset = kKindSpecificFlagsOffset;
4136 static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
4137 static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
4138
Ben Murdoch257744e2011-11-30 15:57:28 +00004139 static const int kUnaryOpTypeOffset = kStubMajorKeyOffset + 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004140 static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004141 static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
4142 static const int kToBooleanTypeOffset = kStubMajorKeyOffset + 1;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004143 static const int kHasFunctionCacheOffset = kStubMajorKeyOffset + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00004144
4145 static const int kFullCodeFlags = kOptimizableOffset + 1;
4146 class FullCodeFlagsHasDeoptimizationSupportField:
4147 public BitField<bool, 0, 1> {}; // NOLINT
4148 class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004149 class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
Ben Murdochb0fe1622011-05-05 13:52:32 +01004150
4151 static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00004152
4153 static const int kAllowOSRAtLoopNestingLevelOffset = kFullCodeFlags + 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004154
Steve Block1e0659c2011-05-24 12:43:12 +01004155 static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
4156 static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004157
Ben Murdoch589d6972011-11-30 16:04:58 +00004158 // Flags layout. BitField<type, shift, size>.
4159 class ICStateField: public BitField<InlineCacheState, 0, 3> {};
4160 class TypeField: public BitField<PropertyType, 3, 4> {};
4161 class KindField: public BitField<Kind, 7, 4> {};
4162 class CacheHolderField: public BitField<InlineCacheHolderFlag, 11, 1> {};
4163 class ExtraICStateField: public BitField<ExtraICState, 12, 2> {};
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004164 class IsPregeneratedField: public BitField<bool, 14, 1> {};
Steve Blocka7e24c12009-10-30 11:49:00 +00004165
Ben Murdoch589d6972011-11-30 16:04:58 +00004166 // Signed field cannot be encoded using the BitField class.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004167 static const int kArgumentsCountShift = 15;
Ben Murdoch589d6972011-11-30 16:04:58 +00004168 static const int kArgumentsCountMask = ~((1 << kArgumentsCountShift) - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00004169
4170 static const int kFlagsNotUsedInLookup =
Ben Murdoch589d6972011-11-30 16:04:58 +00004171 TypeField::kMask | CacheHolderField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00004172
4173 private:
4174 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
4175};
4176
4177
4178// All heap objects have a Map that describes their structure.
4179// A Map contains information about:
4180// - Size information about the object
4181// - How to iterate over an object (for garbage collection)
4182class Map: public HeapObject {
4183 public:
4184 // Instance size.
Steve Block791712a2010-08-27 10:21:07 +01004185 // Size in bytes or kVariableSizeSentinel if instances do not have
4186 // a fixed size.
Steve Blocka7e24c12009-10-30 11:49:00 +00004187 inline int instance_size();
4188 inline void set_instance_size(int value);
4189
4190 // Count of properties allocated in the object.
4191 inline int inobject_properties();
4192 inline void set_inobject_properties(int value);
4193
4194 // Count of property fields pre-allocated in the object when first allocated.
4195 inline int pre_allocated_property_fields();
4196 inline void set_pre_allocated_property_fields(int value);
4197
4198 // Instance type.
4199 inline InstanceType instance_type();
4200 inline void set_instance_type(InstanceType value);
4201
4202 // Tells how many unused property fields are available in the
4203 // instance (only used for JSObject in fast mode).
4204 inline int unused_property_fields();
4205 inline void set_unused_property_fields(int value);
4206
4207 // Bit field.
4208 inline byte bit_field();
4209 inline void set_bit_field(byte value);
4210
4211 // Bit field 2.
4212 inline byte bit_field2();
4213 inline void set_bit_field2(byte value);
4214
Ben Murdoch257744e2011-11-30 15:57:28 +00004215 // Bit field 3.
4216 // TODO(1399): It should be possible to make room for bit_field3 in the map
4217 // without overloading the instance descriptors field (and storing it in the
4218 // DescriptorArray when the map has one).
4219 inline int bit_field3();
4220 inline void set_bit_field3(int value);
4221
Steve Blocka7e24c12009-10-30 11:49:00 +00004222 // Tells whether the object in the prototype property will be used
4223 // for instances created from this function. If the prototype
4224 // property is set to a value that is not a JSObject, the prototype
4225 // property will not be used to create instances of the function.
4226 // See ECMA-262, 13.2.2.
4227 inline void set_non_instance_prototype(bool value);
4228 inline bool has_non_instance_prototype();
4229
Steve Block6ded16b2010-05-10 14:33:55 +01004230 // Tells whether function has special prototype property. If not, prototype
4231 // property will not be created when accessed (will return undefined),
4232 // and construction from this function will not be allowed.
4233 inline void set_function_with_prototype(bool value);
4234 inline bool function_with_prototype();
4235
Steve Blocka7e24c12009-10-30 11:49:00 +00004236 // Tells whether the instance with this map should be ignored by the
4237 // __proto__ accessor.
4238 inline void set_is_hidden_prototype() {
4239 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
4240 }
4241
4242 inline bool is_hidden_prototype() {
4243 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
4244 }
4245
4246 // Records and queries whether the instance has a named interceptor.
4247 inline void set_has_named_interceptor() {
4248 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
4249 }
4250
4251 inline bool has_named_interceptor() {
4252 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
4253 }
4254
4255 // Records and queries whether the instance has an indexed interceptor.
4256 inline void set_has_indexed_interceptor() {
4257 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
4258 }
4259
4260 inline bool has_indexed_interceptor() {
4261 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
4262 }
4263
4264 // Tells whether the instance is undetectable.
4265 // An undetectable object is a special class of JSObject: 'typeof' operator
4266 // returns undefined, ToBoolean returns false. Otherwise it behaves like
4267 // a normal JS object. It is useful for implementing undetectable
4268 // document.all in Firefox & Safari.
4269 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
4270 inline void set_is_undetectable() {
4271 set_bit_field(bit_field() | (1 << kIsUndetectable));
4272 }
4273
4274 inline bool is_undetectable() {
4275 return ((1 << kIsUndetectable) & bit_field()) != 0;
4276 }
4277
Steve Blocka7e24c12009-10-30 11:49:00 +00004278 // Tells whether the instance has a call-as-function handler.
4279 inline void set_has_instance_call_handler() {
4280 set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
4281 }
4282
4283 inline bool has_instance_call_handler() {
4284 return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
4285 }
4286
Steve Block8defd9f2010-07-08 12:39:36 +01004287 inline void set_is_extensible(bool value);
4288 inline bool is_extensible();
4289
Ben Murdoch589d6972011-11-30 16:04:58 +00004290 inline void set_elements_kind(ElementsKind elements_kind) {
4291 ASSERT(elements_kind < kElementsKindCount);
4292 ASSERT(kElementsKindCount <= (1 << kElementsKindBitCount));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004293 set_bit_field2((bit_field2() & ~kElementsKindMask) |
4294 (elements_kind << kElementsKindShift));
4295 ASSERT(this->elements_kind() == elements_kind);
4296 }
4297
Ben Murdoch589d6972011-11-30 16:04:58 +00004298 inline ElementsKind elements_kind() {
4299 return static_cast<ElementsKind>(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004300 (bit_field2() & kElementsKindMask) >> kElementsKindShift);
4301 }
4302
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004303 // Tells whether the instance has fast elements that are only Smis.
4304 inline bool has_fast_smi_only_elements() {
4305 return elements_kind() == FAST_SMI_ONLY_ELEMENTS;
4306 }
4307
Steve Block8defd9f2010-07-08 12:39:36 +01004308 // Tells whether the instance has fast elements.
Iain Merrick75681382010-08-19 15:07:18 +01004309 inline bool has_fast_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004310 return elements_kind() == FAST_ELEMENTS;
Leon Clarkee46be812010-01-19 14:06:41 +00004311 }
4312
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004313 inline bool has_fast_double_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004314 return elements_kind() == FAST_DOUBLE_ELEMENTS;
Steve Block1e0659c2011-05-24 12:43:12 +01004315 }
4316
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004317 inline bool has_non_strict_arguments_elements() {
4318 return elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4319 }
4320
Steve Block44f0eee2011-05-26 01:26:41 +01004321 inline bool has_external_array_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004322 ElementsKind kind(elements_kind());
4323 return kind >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
4324 kind <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004325 }
4326
4327 inline bool has_dictionary_elements() {
Ben Murdoch589d6972011-11-30 16:04:58 +00004328 return elements_kind() == DICTIONARY_ELEMENTS;
Steve Block1e0659c2011-05-24 12:43:12 +01004329 }
4330
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004331 static bool IsValidElementsTransition(ElementsKind from_kind,
4332 ElementsKind to_kind);
4333
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004334 // Tells whether the map is attached to SharedFunctionInfo
4335 // (for inobject slack tracking).
4336 inline void set_attached_to_shared_function_info(bool value);
4337
4338 inline bool attached_to_shared_function_info();
4339
4340 // Tells whether the map is shared between objects that may have different
4341 // behavior. If true, the map should never be modified, instead a clone
4342 // should be created and modified.
4343 inline void set_is_shared(bool value);
4344
4345 inline bool is_shared();
4346
Steve Blocka7e24c12009-10-30 11:49:00 +00004347 // Tells whether the instance needs security checks when accessing its
4348 // properties.
4349 inline void set_is_access_check_needed(bool access_check_needed);
4350 inline bool is_access_check_needed();
4351
4352 // [prototype]: implicit prototype object.
4353 DECL_ACCESSORS(prototype, Object)
4354
4355 // [constructor]: points back to the function responsible for this map.
4356 DECL_ACCESSORS(constructor, Object)
4357
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004358 inline JSFunction* unchecked_constructor();
4359
Ben Murdoch257744e2011-11-30 15:57:28 +00004360 // Should only be called by the code that initializes map to set initial valid
4361 // value of the instance descriptor member.
4362 inline void init_instance_descriptors();
4363
Steve Blocka7e24c12009-10-30 11:49:00 +00004364 // [instance descriptors]: describes the object.
4365 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
4366
Ben Murdoch257744e2011-11-30 15:57:28 +00004367 // Sets the instance descriptor array for the map to be an empty descriptor
4368 // array.
4369 inline void clear_instance_descriptors();
4370
Steve Blocka7e24c12009-10-30 11:49:00 +00004371 // [stub cache]: contains stubs compiled for this map.
Steve Block6ded16b2010-05-10 14:33:55 +01004372 DECL_ACCESSORS(code_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00004373
Steve Block053d10c2011-06-13 19:13:29 +01004374 // [prototype transitions]: cache of prototype transitions.
4375 // Prototype transition is a transition that happens
4376 // when we change object's prototype to a new one.
4377 // Cache format:
4378 // 0: finger - index of the first free cell in the cache
4379 // 1 + 2 * i: prototype
4380 // 2 + 2 * i: target map
4381 DECL_ACCESSORS(prototype_transitions, FixedArray)
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004382
Steve Block053d10c2011-06-13 19:13:29 +01004383 inline FixedArray* unchecked_prototype_transitions();
4384
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004385 static const int kProtoTransitionHeaderSize = 1;
4386 static const int kProtoTransitionNumberOfEntriesOffset = 0;
4387 static const int kProtoTransitionElementsPerEntry = 2;
4388 static const int kProtoTransitionPrototypeOffset = 0;
4389 static const int kProtoTransitionMapOffset = 1;
4390
4391 inline int NumberOfProtoTransitions() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004392 FixedArray* cache = prototype_transitions();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004393 if (cache->length() == 0) return 0;
4394 return
4395 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
4396 }
4397
4398 inline void SetNumberOfProtoTransitions(int value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004399 FixedArray* cache = prototype_transitions();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004400 ASSERT(cache->length() != 0);
4401 cache->set_unchecked(kProtoTransitionNumberOfEntriesOffset,
4402 Smi::FromInt(value));
4403 }
4404
Ben Murdochb0fe1622011-05-05 13:52:32 +01004405 // Lookup in the map's instance descriptors and fill out the result
4406 // with the given holder if the name is found. The holder may be
4407 // NULL when this function is used from the compiler.
4408 void LookupInDescriptors(JSObject* holder,
4409 String* name,
4410 LookupResult* result);
4411
John Reck59135872010-11-02 12:39:01 -07004412 MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004413
John Reck59135872010-11-02 12:39:01 -07004414 MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
4415 NormalizedMapSharingMode sharing);
Steve Blocka7e24c12009-10-30 11:49:00 +00004416
4417 // Returns a copy of the map, with all transitions dropped from the
4418 // instance descriptors.
John Reck59135872010-11-02 12:39:01 -07004419 MUST_USE_RESULT MaybeObject* CopyDropTransitions();
Steve Blocka7e24c12009-10-30 11:49:00 +00004420
4421 // Returns the property index for name (only valid for FAST MODE).
4422 int PropertyIndexFor(String* name);
4423
4424 // Returns the next free property index (only valid for FAST MODE).
4425 int NextFreePropertyIndex();
4426
4427 // Returns the number of properties described in instance_descriptors.
4428 int NumberOfDescribedProperties();
4429
4430 // Casting.
4431 static inline Map* cast(Object* obj);
4432
4433 // Locate an accessor in the instance descriptor.
4434 AccessorDescriptor* FindAccessor(String* name);
4435
4436 // Code cache operations.
4437
4438 // Clears the code cache.
Steve Block44f0eee2011-05-26 01:26:41 +01004439 inline void ClearCodeCache(Heap* heap);
Steve Blocka7e24c12009-10-30 11:49:00 +00004440
4441 // Update code cache.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004442 static void UpdateCodeCache(Handle<Map> map,
4443 Handle<String> name,
4444 Handle<Code> code);
John Reck59135872010-11-02 12:39:01 -07004445 MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00004446
4447 // Returns the found code or undefined if absent.
4448 Object* FindInCodeCache(String* name, Code::Flags flags);
4449
4450 // Returns the non-negative index of the code object if it is in the
4451 // cache and -1 otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +01004452 int IndexInCodeCache(Object* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00004453
4454 // Removes a code object from the code cache at the given index.
Steve Block6ded16b2010-05-10 14:33:55 +01004455 void RemoveFromCodeCache(String* name, Code* code, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004456
4457 // For every transition in this map, makes the transition's
4458 // target's prototype pointer point back to this map.
4459 // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
4460 void CreateBackPointers();
4461
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004462 void CreateOneBackPointer(Map* transition_target);
4463
Steve Blocka7e24c12009-10-30 11:49:00 +00004464 // Set all map transitions from this map to dead maps to null.
4465 // Also, restore the original prototype on the targets of these
4466 // transitions, so that we do not process this map again while
4467 // following back pointers.
Steve Block44f0eee2011-05-26 01:26:41 +01004468 void ClearNonLiveTransitions(Heap* heap, Object* real_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00004469
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004470 // Computes a hash value for this map, to be used in HashTables and such.
4471 int Hash();
4472
4473 // Compares this map to another to see if they describe equivalent objects.
4474 // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if
4475 // it had exactly zero inobject properties.
4476 // The "shared" flags of both this map and |other| are ignored.
4477 bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode);
4478
4479 // Returns true if this map and |other| describe equivalent objects.
4480 // The "shared" flags of both this map and |other| are ignored.
4481 bool EquivalentTo(Map* other) {
4482 return EquivalentToForNormalization(other, KEEP_INOBJECT_PROPERTIES);
4483 }
4484
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004485 // Returns the contents of this map's descriptor array for the given string.
4486 // May return NULL. |safe_to_add_transition| is set to false and NULL
4487 // is returned if adding transitions is not allowed.
4488 Object* GetDescriptorContents(String* sentinel_name,
4489 bool* safe_to_add_transitions);
4490
4491 // Returns the map that this map transitions to if its elements_kind
4492 // is changed to |elements_kind|, or NULL if no such map is cached yet.
4493 // |safe_to_add_transitions| is set to false if adding transitions is not
4494 // allowed.
4495 Map* LookupElementsTransitionMap(ElementsKind elements_kind,
4496 bool* safe_to_add_transition);
4497
4498 // Adds an entry to this map's descriptor array for a transition to
4499 // |transitioned_map| when its elements_kind is changed to |elements_kind|.
4500 MaybeObject* AddElementsTransition(ElementsKind elements_kind,
4501 Map* transitioned_map);
4502
4503 // Returns the transitioned map for this map with the most generic
4504 // elements_kind that's found in |candidates|, or null handle if no match is
4505 // found at all.
4506 Handle<Map> FindTransitionedMap(MapHandleList* candidates);
4507 Map* FindTransitionedMap(MapList* candidates);
4508
4509
Steve Blocka7e24c12009-10-30 11:49:00 +00004510 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004511#ifdef OBJECT_PRINT
4512 inline void MapPrint() {
4513 MapPrint(stdout);
4514 }
4515 void MapPrint(FILE* out);
4516#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004517#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004518 void MapVerify();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004519 void SharedMapVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00004520#endif
4521
Iain Merrick75681382010-08-19 15:07:18 +01004522 inline int visitor_id();
4523 inline void set_visitor_id(int visitor_id);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004524
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004525 typedef void (*TraverseCallback)(Map* map, void* data);
4526
4527 void TraverseTransitionTree(TraverseCallback callback, void* data);
4528
Steve Block053d10c2011-06-13 19:13:29 +01004529 static const int kMaxCachedPrototypeTransitions = 256;
4530
4531 Object* GetPrototypeTransition(Object* prototype);
4532
4533 MaybeObject* PutPrototypeTransition(Object* prototype, Map* map);
4534
Steve Blocka7e24c12009-10-30 11:49:00 +00004535 static const int kMaxPreAllocatedPropertyFields = 255;
4536
4537 // Layout description.
4538 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
4539 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
4540 static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
4541 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00004542 // Storage for instance descriptors is overloaded to also contain additional
4543 // map flags when unused (bit_field3). When the map has instance descriptors,
4544 // the flags are transferred to the instance descriptor array and accessed
4545 // through an extra indirection.
4546 // TODO(1399): It should be possible to make room for bit_field3 in the map
4547 // without overloading the instance descriptors field, but the map is
4548 // currently perfectly aligned to 32 bytes and extending it at all would
4549 // double its size. After the increment GC work lands, this size restriction
4550 // could be loosened and bit_field3 moved directly back in the map.
4551 static const int kInstanceDescriptorsOrBitField3Offset =
Steve Blocka7e24c12009-10-30 11:49:00 +00004552 kConstructorOffset + kPointerSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00004553 static const int kCodeCacheOffset =
4554 kInstanceDescriptorsOrBitField3Offset + kPointerSize;
Steve Block053d10c2011-06-13 19:13:29 +01004555 static const int kPrototypeTransitionsOffset =
4556 kCodeCacheOffset + kPointerSize;
4557 static const int kPadStart = kPrototypeTransitionsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004558 static const int kSize = MAP_POINTER_ALIGN(kPadStart);
4559
4560 // Layout of pointer fields. Heap iteration code relies on them
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004561 // being continuously allocated.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004562 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
4563 static const int kPointerFieldsEndOffset =
Steve Block053d10c2011-06-13 19:13:29 +01004564 Map::kPrototypeTransitionsOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004565
4566 // Byte offsets within kInstanceSizesOffset.
4567 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
4568 static const int kInObjectPropertiesByte = 1;
4569 static const int kInObjectPropertiesOffset =
4570 kInstanceSizesOffset + kInObjectPropertiesByte;
4571 static const int kPreAllocatedPropertyFieldsByte = 2;
4572 static const int kPreAllocatedPropertyFieldsOffset =
4573 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
Iain Merrick9ac36c92010-09-13 15:29:50 +01004574 static const int kVisitorIdByte = 3;
4575 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
Steve Blocka7e24c12009-10-30 11:49:00 +00004576
4577 // Byte offsets within kInstanceAttributesOffset attributes.
4578 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
4579 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
4580 static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
4581 static const int kBitField2Offset = kInstanceAttributesOffset + 3;
4582
4583 STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
4584
4585 // Bit positions for bit field.
4586 static const int kUnused = 0; // To be used for marking recently used maps.
4587 static const int kHasNonInstancePrototype = 1;
4588 static const int kIsHiddenPrototype = 2;
4589 static const int kHasNamedInterceptor = 3;
4590 static const int kHasIndexedInterceptor = 4;
4591 static const int kIsUndetectable = 5;
4592 static const int kHasInstanceCallHandler = 6;
4593 static const int kIsAccessCheckNeeded = 7;
4594
4595 // Bit positions for bit field 2
Andrei Popescu31002712010-02-23 13:46:05 +00004596 static const int kIsExtensible = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01004597 static const int kFunctionWithPrototype = 1;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004598 static const int kStringWrapperSafeForDefaultValueOf = 2;
4599 static const int kAttachedToSharedFunctionInfo = 3;
4600 // No bits can be used after kElementsKindFirstBit, they are all reserved for
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004601 // storing ElementKind.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004602 static const int kElementsKindShift = 4;
4603 static const int kElementsKindBitCount = 4;
4604
4605 // Derived values from bit field 2
4606 static const int kElementsKindMask = (-1 << kElementsKindShift) &
4607 ((1 << (kElementsKindShift + kElementsKindBitCount)) - 1);
4608 static const int8_t kMaximumBitField2FastElementValue = static_cast<int8_t>(
Ben Murdoch589d6972011-11-30 16:04:58 +00004609 (FAST_ELEMENTS + 1) << Map::kElementsKindShift) - 1;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004610 static const int8_t kMaximumBitField2FastSmiOnlyElementValue =
4611 static_cast<int8_t>((FAST_SMI_ONLY_ELEMENTS + 1) <<
4612 Map::kElementsKindShift) - 1;
Ben Murdoch257744e2011-11-30 15:57:28 +00004613
4614 // Bit positions for bit field 3
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004615 static const int kIsShared = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01004616
4617 // Layout of the default cache. It holds alternating name and code objects.
4618 static const int kCodeCacheEntrySize = 2;
4619 static const int kCodeCacheEntryNameOffset = 0;
4620 static const int kCodeCacheEntryCodeOffset = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00004621
Iain Merrick75681382010-08-19 15:07:18 +01004622 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
4623 kPointerFieldsEndOffset,
4624 kSize> BodyDescriptor;
4625
Steve Blocka7e24c12009-10-30 11:49:00 +00004626 private:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004627 String* elements_transition_sentinel_name();
Steve Blocka7e24c12009-10-30 11:49:00 +00004628 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
4629};
4630
4631
4632// An abstract superclass, a marker class really, for simple structure classes.
Ben Murdoch257744e2011-11-30 15:57:28 +00004633// It doesn't carry much functionality but allows struct classes to be
Steve Blocka7e24c12009-10-30 11:49:00 +00004634// identified in the type system.
4635class Struct: public HeapObject {
4636 public:
4637 inline void InitializeBody(int object_size);
4638 static inline Struct* cast(Object* that);
4639};
4640
4641
4642// Script describes a script which has been added to the VM.
4643class Script: public Struct {
4644 public:
4645 // Script types.
4646 enum Type {
4647 TYPE_NATIVE = 0,
4648 TYPE_EXTENSION = 1,
4649 TYPE_NORMAL = 2
4650 };
4651
4652 // Script compilation types.
4653 enum CompilationType {
4654 COMPILATION_TYPE_HOST = 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004655 COMPILATION_TYPE_EVAL = 1
Steve Blocka7e24c12009-10-30 11:49:00 +00004656 };
4657
4658 // [source]: the script source.
4659 DECL_ACCESSORS(source, Object)
4660
4661 // [name]: the script name.
4662 DECL_ACCESSORS(name, Object)
4663
4664 // [id]: the script id.
4665 DECL_ACCESSORS(id, Object)
4666
4667 // [line_offset]: script line offset in resource from where it was extracted.
4668 DECL_ACCESSORS(line_offset, Smi)
4669
4670 // [column_offset]: script column offset in resource from where it was
4671 // extracted.
4672 DECL_ACCESSORS(column_offset, Smi)
4673
4674 // [data]: additional data associated with this script.
4675 DECL_ACCESSORS(data, Object)
4676
4677 // [context_data]: context data for the context this script was compiled in.
4678 DECL_ACCESSORS(context_data, Object)
4679
4680 // [wrapper]: the wrapper cache.
Ben Murdoch257744e2011-11-30 15:57:28 +00004681 DECL_ACCESSORS(wrapper, Foreign)
Steve Blocka7e24c12009-10-30 11:49:00 +00004682
4683 // [type]: the script type.
4684 DECL_ACCESSORS(type, Smi)
4685
4686 // [compilation]: how the the script was compiled.
4687 DECL_ACCESSORS(compilation_type, Smi)
4688
Steve Blockd0582a62009-12-15 09:54:21 +00004689 // [line_ends]: FixedArray of line ends positions.
Steve Blocka7e24c12009-10-30 11:49:00 +00004690 DECL_ACCESSORS(line_ends, Object)
4691
Steve Blockd0582a62009-12-15 09:54:21 +00004692 // [eval_from_shared]: for eval scripts the shared funcion info for the
4693 // function from which eval was called.
4694 DECL_ACCESSORS(eval_from_shared, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00004695
4696 // [eval_from_instructions_offset]: the instruction offset in the code for the
4697 // function from which eval was called where eval was called.
4698 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
4699
4700 static inline Script* cast(Object* obj);
4701
Steve Block3ce2e202009-11-05 08:53:23 +00004702 // If script source is an external string, check that the underlying
4703 // resource is accessible. Otherwise, always return true.
4704 inline bool HasValidSource();
4705
Ben Murdochb0fe1622011-05-05 13:52:32 +01004706#ifdef OBJECT_PRINT
4707 inline void ScriptPrint() {
4708 ScriptPrint(stdout);
4709 }
4710 void ScriptPrint(FILE* out);
4711#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00004712#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00004713 void ScriptVerify();
4714#endif
4715
4716 static const int kSourceOffset = HeapObject::kHeaderSize;
4717 static const int kNameOffset = kSourceOffset + kPointerSize;
4718 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
4719 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
4720 static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
4721 static const int kContextOffset = kDataOffset + kPointerSize;
4722 static const int kWrapperOffset = kContextOffset + kPointerSize;
4723 static const int kTypeOffset = kWrapperOffset + kPointerSize;
4724 static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
4725 static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
4726 static const int kIdOffset = kLineEndsOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00004727 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004728 static const int kEvalFrominstructionsOffsetOffset =
Steve Blockd0582a62009-12-15 09:54:21 +00004729 kEvalFromSharedOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00004730 static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
4731
4732 private:
4733 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
4734};
4735
4736
Ben Murdochb0fe1622011-05-05 13:52:32 +01004737// List of builtin functions we want to identify to improve code
4738// generation.
4739//
4740// Each entry has a name of a global object property holding an object
4741// optionally followed by ".prototype", a name of a builtin function
4742// on the object (the one the id is set for), and a label.
4743//
4744// Installation of ids for the selected builtin functions is handled
4745// by the bootstrapper.
4746//
4747// NOTE: Order is important: math functions should be at the end of
4748// the list and MathFloor should be the first math function.
4749#define FUNCTIONS_WITH_ID_LIST(V) \
4750 V(Array.prototype, push, ArrayPush) \
4751 V(Array.prototype, pop, ArrayPop) \
Ben Murdoch42effa52011-08-19 16:40:31 +01004752 V(Function.prototype, apply, FunctionApply) \
Ben Murdochb0fe1622011-05-05 13:52:32 +01004753 V(String.prototype, charCodeAt, StringCharCodeAt) \
4754 V(String.prototype, charAt, StringCharAt) \
4755 V(String, fromCharCode, StringFromCharCode) \
4756 V(Math, floor, MathFloor) \
4757 V(Math, round, MathRound) \
4758 V(Math, ceil, MathCeil) \
4759 V(Math, abs, MathAbs) \
4760 V(Math, log, MathLog) \
4761 V(Math, sin, MathSin) \
4762 V(Math, cos, MathCos) \
4763 V(Math, tan, MathTan) \
4764 V(Math, asin, MathASin) \
4765 V(Math, acos, MathACos) \
4766 V(Math, atan, MathATan) \
4767 V(Math, exp, MathExp) \
4768 V(Math, sqrt, MathSqrt) \
4769 V(Math, pow, MathPow)
4770
4771
4772enum BuiltinFunctionId {
4773#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
4774 k##name,
4775 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
4776#undef DECLARE_FUNCTION_ID
4777 // Fake id for a special case of Math.pow. Note, it continues the
4778 // list of math functions.
4779 kMathPowHalf,
4780 kFirstMathFunctionId = kMathFloor
4781};
4782
4783
Steve Blocka7e24c12009-10-30 11:49:00 +00004784// SharedFunctionInfo describes the JSFunction information that can be
4785// shared by multiple instances of the function.
4786class SharedFunctionInfo: public HeapObject {
4787 public:
4788 // [name]: Function name.
4789 DECL_ACCESSORS(name, Object)
4790
4791 // [code]: Function code.
4792 DECL_ACCESSORS(code, Code)
4793
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004794 // [scope_info]: Scope info.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004795 DECL_ACCESSORS(scope_info, ScopeInfo)
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004796
Steve Blocka7e24c12009-10-30 11:49:00 +00004797 // [construct stub]: Code stub for constructing instances of this function.
4798 DECL_ACCESSORS(construct_stub, Code)
4799
Iain Merrick75681382010-08-19 15:07:18 +01004800 inline Code* unchecked_code();
4801
Steve Blocka7e24c12009-10-30 11:49:00 +00004802 // Returns if this function has been compiled to native code yet.
4803 inline bool is_compiled();
4804
4805 // [length]: The function length - usually the number of declared parameters.
4806 // Use up to 2^30 parameters.
4807 inline int length();
4808 inline void set_length(int value);
4809
4810 // [formal parameter count]: The declared number of parameters.
4811 inline int formal_parameter_count();
4812 inline void set_formal_parameter_count(int value);
4813
4814 // Set the formal parameter count so the function code will be
4815 // called without using argument adaptor frames.
4816 inline void DontAdaptArguments();
4817
4818 // [expected_nof_properties]: Expected number of properties for the function.
4819 inline int expected_nof_properties();
4820 inline void set_expected_nof_properties(int value);
4821
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004822 // Inobject slack tracking is the way to reclaim unused inobject space.
4823 //
4824 // The instance size is initially determined by adding some slack to
4825 // expected_nof_properties (to allow for a few extra properties added
4826 // after the constructor). There is no guarantee that the extra space
4827 // will not be wasted.
4828 //
4829 // Here is the algorithm to reclaim the unused inobject space:
4830 // - Detect the first constructor call for this SharedFunctionInfo.
4831 // When it happens enter the "in progress" state: remember the
4832 // constructor's initial_map and install a special construct stub that
4833 // counts constructor calls.
4834 // - While the tracking is in progress create objects filled with
4835 // one_pointer_filler_map instead of undefined_value. This way they can be
4836 // resized quickly and safely.
4837 // - Once enough (kGenerousAllocationCount) objects have been created
4838 // compute the 'slack' (traverse the map transition tree starting from the
4839 // initial_map and find the lowest value of unused_property_fields).
4840 // - Traverse the transition tree again and decrease the instance size
4841 // of every map. Existing objects will resize automatically (they are
4842 // filled with one_pointer_filler_map). All further allocations will
4843 // use the adjusted instance size.
4844 // - Decrease expected_nof_properties so that an allocations made from
4845 // another context will use the adjusted instance size too.
4846 // - Exit "in progress" state by clearing the reference to the initial_map
4847 // and setting the regular construct stub (generic or inline).
4848 //
4849 // The above is the main event sequence. Some special cases are possible
4850 // while the tracking is in progress:
4851 //
4852 // - GC occurs.
4853 // Check if the initial_map is referenced by any live objects (except this
4854 // SharedFunctionInfo). If it is, continue tracking as usual.
4855 // If it is not, clear the reference and reset the tracking state. The
4856 // tracking will be initiated again on the next constructor call.
4857 //
4858 // - The constructor is called from another context.
4859 // Immediately complete the tracking, perform all the necessary changes
4860 // to maps. This is necessary because there is no efficient way to track
4861 // multiple initial_maps.
4862 // Proceed to create an object in the current context (with the adjusted
4863 // size).
4864 //
4865 // - A different constructor function sharing the same SharedFunctionInfo is
4866 // called in the same context. This could be another closure in the same
4867 // context, or the first function could have been disposed.
4868 // This is handled the same way as the previous case.
4869 //
4870 // Important: inobject slack tracking is not attempted during the snapshot
4871 // creation.
4872
Ben Murdochf87a2032010-10-22 12:50:53 +01004873 static const int kGenerousAllocationCount = 8;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004874
4875 // [construction_count]: Counter for constructor calls made during
4876 // the tracking phase.
4877 inline int construction_count();
4878 inline void set_construction_count(int value);
4879
4880 // [initial_map]: initial map of the first function called as a constructor.
4881 // Saved for the duration of the tracking phase.
4882 // This is a weak link (GC resets it to undefined_value if no other live
4883 // object reference this map).
4884 DECL_ACCESSORS(initial_map, Object)
4885
4886 // True if the initial_map is not undefined and the countdown stub is
4887 // installed.
4888 inline bool IsInobjectSlackTrackingInProgress();
4889
4890 // Starts the tracking.
4891 // Stores the initial map and installs the countdown stub.
4892 // IsInobjectSlackTrackingInProgress is normally true after this call,
4893 // except when tracking have not been started (e.g. the map has no unused
4894 // properties or the snapshot is being built).
4895 void StartInobjectSlackTracking(Map* map);
4896
4897 // Completes the tracking.
4898 // IsInobjectSlackTrackingInProgress is false after this call.
4899 void CompleteInobjectSlackTracking();
4900
4901 // Clears the initial_map before the GC marking phase to ensure the reference
4902 // is weak. IsInobjectSlackTrackingInProgress is false after this call.
4903 void DetachInitialMap();
4904
4905 // Restores the link to the initial map after the GC marking phase.
4906 // IsInobjectSlackTrackingInProgress is true after this call.
4907 void AttachInitialMap(Map* map);
4908
4909 // False if there are definitely no live objects created from this function.
4910 // True if live objects _may_ exist (existence not guaranteed).
4911 // May go back from true to false after GC.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004912 DECL_BOOLEAN_ACCESSORS(live_objects_may_exist)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004913
Steve Blocka7e24c12009-10-30 11:49:00 +00004914 // [instance class name]: class name for instances.
4915 DECL_ACCESSORS(instance_class_name, Object)
4916
Steve Block6ded16b2010-05-10 14:33:55 +01004917 // [function data]: This field holds some additional data for function.
4918 // Currently it either has FunctionTemplateInfo to make benefit the API
Ben Murdochb0fe1622011-05-05 13:52:32 +01004919 // or Smi identifying a builtin function.
Steve Blocka7e24c12009-10-30 11:49:00 +00004920 // In the long run we don't want all functions to have this field but
4921 // we can fix that when we have a better model for storing hidden data
4922 // on objects.
4923 DECL_ACCESSORS(function_data, Object)
4924
Steve Block6ded16b2010-05-10 14:33:55 +01004925 inline bool IsApiFunction();
4926 inline FunctionTemplateInfo* get_api_func_data();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004927 inline bool HasBuiltinFunctionId();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004928 inline BuiltinFunctionId builtin_function_id();
Steve Block6ded16b2010-05-10 14:33:55 +01004929
Steve Blocka7e24c12009-10-30 11:49:00 +00004930 // [script info]: Script from which the function originates.
4931 DECL_ACCESSORS(script, Object)
4932
Steve Block6ded16b2010-05-10 14:33:55 +01004933 // [num_literals]: Number of literals used by this function.
4934 inline int num_literals();
4935 inline void set_num_literals(int value);
4936
Steve Blocka7e24c12009-10-30 11:49:00 +00004937 // [start_position_and_type]: Field used to store both the source code
4938 // position, whether or not the function is a function expression,
4939 // and whether or not the function is a toplevel function. The two
4940 // least significants bit indicates whether the function is an
4941 // expression and the rest contains the source code position.
4942 inline int start_position_and_type();
4943 inline void set_start_position_and_type(int value);
4944
4945 // [debug info]: Debug information.
4946 DECL_ACCESSORS(debug_info, Object)
4947
4948 // [inferred name]: Name inferred from variable or property
4949 // assignment of this function. Used to facilitate debugging and
4950 // profiling of JavaScript code written in OO style, where almost
4951 // all functions are anonymous but are assigned to object
4952 // properties.
4953 DECL_ACCESSORS(inferred_name, String)
4954
Ben Murdochf87a2032010-10-22 12:50:53 +01004955 // The function's name if it is non-empty, otherwise the inferred name.
4956 String* DebugName();
4957
Steve Blocka7e24c12009-10-30 11:49:00 +00004958 // Position of the 'function' token in the script source.
4959 inline int function_token_position();
4960 inline void set_function_token_position(int function_token_position);
4961
4962 // Position of this function in the script source.
4963 inline int start_position();
4964 inline void set_start_position(int start_position);
4965
4966 // End position of this function in the script source.
4967 inline int end_position();
4968 inline void set_end_position(int end_position);
4969
4970 // Is this function a function expression in the source code.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004971 DECL_BOOLEAN_ACCESSORS(is_expression)
Steve Blocka7e24c12009-10-30 11:49:00 +00004972
4973 // Is this function a top-level function (scripts, evals).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004974 DECL_BOOLEAN_ACCESSORS(is_toplevel)
Steve Blocka7e24c12009-10-30 11:49:00 +00004975
4976 // Bit field containing various information collected by the compiler to
4977 // drive optimization.
4978 inline int compiler_hints();
4979 inline void set_compiler_hints(int value);
4980
Ben Murdochb0fe1622011-05-05 13:52:32 +01004981 // A counter used to determine when to stress the deoptimizer with a
4982 // deopt.
4983 inline Smi* deopt_counter();
4984 inline void set_deopt_counter(Smi* counter);
4985
Steve Blocka7e24c12009-10-30 11:49:00 +00004986 // Add information on assignments of the form this.x = ...;
4987 void SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +00004988 bool has_only_simple_this_property_assignments,
4989 FixedArray* this_property_assignments);
4990
4991 // Clear information on assignments of the form this.x = ...;
4992 void ClearThisPropertyAssignmentsInfo();
4993
4994 // Indicate that this function only consists of assignments of the form
Steve Blocka7e24c12009-10-30 11:49:00 +00004995 // this.x = y; where y is either a constant or refers to an argument.
4996 inline bool has_only_simple_this_property_assignments();
4997
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004998 // Indicates if this function can be lazy compiled.
4999 // This is used to determine if we can safely flush code from a function
5000 // when doing GC if we expect that the function will no longer be used.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005001 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005002
Iain Merrick75681382010-08-19 15:07:18 +01005003 // Indicates how many full GCs this function has survived with assigned
5004 // code object. Used to determine when it is relatively safe to flush
5005 // this code object and replace it with lazy compilation stub.
5006 // Age is reset when GC notices that the code object is referenced
5007 // from the stack or compilation cache.
5008 inline int code_age();
5009 inline void set_code_age(int age);
5010
Ben Murdochb0fe1622011-05-05 13:52:32 +01005011 // Indicates whether optimizations have been disabled for this
5012 // shared function info. If a function is repeatedly optimized or if
5013 // we cannot optimize the function we disable optimization to avoid
5014 // spending time attempting to optimize it again.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005015 DECL_BOOLEAN_ACCESSORS(optimization_disabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01005016
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005017 // Indicates the language mode of the function's code as defined by the
5018 // current harmony drafts for the next ES language standard. Possible
5019 // values are:
5020 // 1. CLASSIC_MODE - Unrestricted syntax and semantics, same as in ES5.
5021 // 2. STRICT_MODE - Restricted syntax and semantics, same as in ES5.
5022 // 3. EXTENDED_MODE - Only available under the harmony flag, not part of ES5.
5023 inline LanguageMode language_mode();
5024 inline void set_language_mode(LanguageMode language_mode);
5025
5026 // Indicates whether the language mode of this function is CLASSIC_MODE.
5027 inline bool is_classic_mode();
5028
5029 // Indicates whether the language mode of this function is EXTENDED_MODE.
5030 inline bool is_extended_mode();
Steve Block1e0659c2011-05-24 12:43:12 +01005031
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005032 // False if the function definitely does not allocate an arguments object.
5033 DECL_BOOLEAN_ACCESSORS(uses_arguments)
5034
5035 // True if the function has any duplicated parameter names.
5036 DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters)
5037
5038 // Indicates whether the function is a native function.
Ben Murdoch589d6972011-11-30 16:04:58 +00005039 // These needs special treatment in .call and .apply since
Ben Murdoch257744e2011-11-30 15:57:28 +00005040 // null passed as the receiver should not be translated to the
5041 // global object.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005042 DECL_BOOLEAN_ACCESSORS(native)
5043
5044 // Indicates that the function was created by the Function function.
5045 // Though it's anonymous, toString should treat it as if it had the name
5046 // "anonymous". We don't set the name itself so that the system does not
5047 // see a binding for it.
5048 DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
5049
5050 // Indicates whether the function is a bound function created using
5051 // the bind function.
5052 DECL_BOOLEAN_ACCESSORS(bound)
5053
5054 // Indicates that the function is anonymous (the name field can be set
5055 // through the API, which does not change this flag).
5056 DECL_BOOLEAN_ACCESSORS(is_anonymous)
Ben Murdoch257744e2011-11-30 15:57:28 +00005057
Ben Murdochb0fe1622011-05-05 13:52:32 +01005058 // Indicates whether or not the code in the shared function support
5059 // deoptimization.
5060 inline bool has_deoptimization_support();
5061
5062 // Enable deoptimization support through recompiled code.
5063 void EnableDeoptimizationSupport(Code* recompiled);
5064
Ben Murdoch257744e2011-11-30 15:57:28 +00005065 // Disable (further) attempted optimization of all functions sharing this
5066 // shared function info. The function is the one we actually tried to
5067 // optimize.
5068 void DisableOptimization(JSFunction* function);
5069
Ben Murdochb0fe1622011-05-05 13:52:32 +01005070 // Lookup the bailout ID and ASSERT that it exists in the non-optimized
5071 // code, returns whether it asserted (i.e., always true if assertions are
5072 // disabled).
5073 bool VerifyBailoutId(int id);
Iain Merrick75681382010-08-19 15:07:18 +01005074
Andrei Popescu402d9372010-02-26 13:31:12 +00005075 // Check whether a inlined constructor can be generated with the given
5076 // prototype.
5077 bool CanGenerateInlineConstructor(Object* prototype);
5078
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005079 // Prevents further attempts to generate inline constructors.
5080 // To be called if generation failed for any reason.
5081 void ForbidInlineConstructor();
5082
Steve Blocka7e24c12009-10-30 11:49:00 +00005083 // For functions which only contains this property assignments this provides
5084 // access to the names for the properties assigned.
5085 DECL_ACCESSORS(this_property_assignments, Object)
5086 inline int this_property_assignments_count();
5087 inline void set_this_property_assignments_count(int value);
5088 String* GetThisPropertyAssignmentName(int index);
5089 bool IsThisPropertyAssignmentArgument(int index);
5090 int GetThisPropertyAssignmentArgument(int index);
5091 Object* GetThisPropertyAssignmentConstant(int index);
5092
5093 // [source code]: Source code for the function.
5094 bool HasSourceCode();
5095 Object* GetSourceCode();
5096
Ben Murdochb0fe1622011-05-05 13:52:32 +01005097 inline int opt_count();
5098 inline void set_opt_count(int opt_count);
5099
5100 // Source size of this function.
5101 int SourceSize();
5102
Steve Blocka7e24c12009-10-30 11:49:00 +00005103 // Calculate the instance size.
5104 int CalculateInstanceSize();
5105
5106 // Calculate the number of in-object properties.
5107 int CalculateInObjectProperties();
5108
5109 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00005110 // Set max_length to -1 for unlimited length.
5111 void SourceCodePrint(StringStream* accumulator, int max_length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005112#ifdef OBJECT_PRINT
5113 inline void SharedFunctionInfoPrint() {
5114 SharedFunctionInfoPrint(stdout);
5115 }
5116 void SharedFunctionInfoPrint(FILE* out);
5117#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005118#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005119 void SharedFunctionInfoVerify();
5120#endif
5121
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005122 // Helpers to compile the shared code. Returns true on success, false on
5123 // failure (e.g., stack overflow during compilation).
5124 static bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
5125 ClearExceptionFlag flag);
5126 static bool CompileLazy(Handle<SharedFunctionInfo> shared,
5127 ClearExceptionFlag flag);
5128
Steve Blocka7e24c12009-10-30 11:49:00 +00005129 // Casting.
5130 static inline SharedFunctionInfo* cast(Object* obj);
5131
5132 // Constants.
5133 static const int kDontAdaptArgumentsSentinel = -1;
5134
5135 // Layout description.
Steve Block6ded16b2010-05-10 14:33:55 +01005136 // Pointer fields.
Steve Blocka7e24c12009-10-30 11:49:00 +00005137 static const int kNameOffset = HeapObject::kHeaderSize;
5138 static const int kCodeOffset = kNameOffset + kPointerSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005139 static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
5140 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005141 static const int kInstanceClassNameOffset =
5142 kConstructStubOffset + kPointerSize;
5143 static const int kFunctionDataOffset =
5144 kInstanceClassNameOffset + kPointerSize;
5145 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
5146 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
5147 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005148 static const int kInitialMapOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01005149 kInferredNameOffset + kPointerSize;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005150 static const int kThisPropertyAssignmentsOffset =
5151 kInitialMapOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005152 static const int kDeoptCounterOffset =
5153 kThisPropertyAssignmentsOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005154#if V8_HOST_ARCH_32_BIT
5155 // Smi fields.
Steve Block6ded16b2010-05-10 14:33:55 +01005156 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01005157 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005158 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
5159 static const int kExpectedNofPropertiesOffset =
5160 kFormalParameterCountOffset + kPointerSize;
5161 static const int kNumLiteralsOffset =
5162 kExpectedNofPropertiesOffset + kPointerSize;
5163 static const int kStartPositionAndTypeOffset =
5164 kNumLiteralsOffset + kPointerSize;
5165 static const int kEndPositionOffset =
5166 kStartPositionAndTypeOffset + kPointerSize;
5167 static const int kFunctionTokenPositionOffset =
5168 kEndPositionOffset + kPointerSize;
5169 static const int kCompilerHintsOffset =
5170 kFunctionTokenPositionOffset + kPointerSize;
5171 static const int kThisPropertyAssignmentsCountOffset =
5172 kCompilerHintsOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005173 static const int kOptCountOffset =
5174 kThisPropertyAssignmentsCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005175 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005176 static const int kSize = kOptCountOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005177#else
5178 // The only reason to use smi fields instead of int fields
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005179 // is to allow iteration without maps decoding during
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005180 // garbage collections.
5181 // To avoid wasting space on 64-bit architectures we use
5182 // the following trick: we group integer fields into pairs
5183 // First integer in each pair is shifted left by 1.
5184 // By doing this we guarantee that LSB of each kPointerSize aligned
5185 // word is not set and thus this word cannot be treated as pointer
5186 // to HeapObject during old space traversal.
5187 static const int kLengthOffset =
Ben Murdochb0fe1622011-05-05 13:52:32 +01005188 kDeoptCounterOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005189 static const int kFormalParameterCountOffset =
5190 kLengthOffset + kIntSize;
5191
Steve Blocka7e24c12009-10-30 11:49:00 +00005192 static const int kExpectedNofPropertiesOffset =
5193 kFormalParameterCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005194 static const int kNumLiteralsOffset =
5195 kExpectedNofPropertiesOffset + kIntSize;
5196
5197 static const int kEndPositionOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01005198 kNumLiteralsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005199 static const int kStartPositionAndTypeOffset =
5200 kEndPositionOffset + kIntSize;
5201
5202 static const int kFunctionTokenPositionOffset =
5203 kStartPositionAndTypeOffset + kIntSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005204 static const int kCompilerHintsOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00005205 kFunctionTokenPositionOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005206
Steve Blocka7e24c12009-10-30 11:49:00 +00005207 static const int kThisPropertyAssignmentsCountOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01005208 kCompilerHintsOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005209 static const int kOptCountOffset =
5210 kThisPropertyAssignmentsCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005211
Steve Block6ded16b2010-05-10 14:33:55 +01005212 // Total size.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005213 static const int kSize = kOptCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005214
5215#endif
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005216
5217 // The construction counter for inobject slack tracking is stored in the
5218 // most significant byte of compiler_hints which is otherwise unused.
5219 // Its offset depends on the endian-ness of the architecture.
5220#if __BYTE_ORDER == __LITTLE_ENDIAN
5221 static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
5222#elif __BYTE_ORDER == __BIG_ENDIAN
5223 static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
5224#else
5225#error Unknown byte ordering
5226#endif
5227
Steve Block6ded16b2010-05-10 14:33:55 +01005228 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005229
Iain Merrick75681382010-08-19 15:07:18 +01005230 typedef FixedBodyDescriptor<kNameOffset,
5231 kThisPropertyAssignmentsOffset + kPointerSize,
5232 kSize> BodyDescriptor;
5233
Steve Blocka7e24c12009-10-30 11:49:00 +00005234 // Bit positions in start_position_and_type.
5235 // The source code start position is in the 30 most significant bits of
5236 // the start_position_and_type field.
5237 static const int kIsExpressionBit = 0;
5238 static const int kIsTopLevelBit = 1;
5239 static const int kStartPositionShift = 2;
5240 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
5241
5242 // Bit positions in compiler_hints.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005243 static const int kCodeAgeSize = 3;
5244 static const int kCodeAgeMask = (1 << kCodeAgeSize) - 1;
5245
5246 enum CompilerHints {
5247 kHasOnlySimpleThisPropertyAssignments,
5248 kAllowLazyCompilation,
5249 kLiveObjectsMayExist,
5250 kCodeAgeShift,
5251 kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
5252 kStrictModeFunction,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005253 kExtendedModeFunction,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005254 kUsesArguments,
5255 kHasDuplicateParameters,
5256 kNative,
5257 kBoundFunction,
5258 kIsAnonymous,
5259 kNameShouldPrintAsAnonymous,
5260 kCompilerHintsCount // Pseudo entry
5261 };
Steve Blocka7e24c12009-10-30 11:49:00 +00005262
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005263 private:
5264#if V8_HOST_ARCH_32_BIT
5265 // On 32 bit platforms, compiler hints is a smi.
5266 static const int kCompilerHintsSmiTagSize = kSmiTagSize;
5267 static const int kCompilerHintsSize = kPointerSize;
5268#else
5269 // On 64 bit platforms, compiler hints is not a smi, see comment above.
5270 static const int kCompilerHintsSmiTagSize = 0;
5271 static const int kCompilerHintsSize = kIntSize;
5272#endif
5273
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005274 STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <=
5275 SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte);
5276
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005277 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00005278 // Constants for optimizing codegen for strict mode function and
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005279 // native tests.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005280 // Allows to use byte-width instructions.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005281 static const int kStrictModeBitWithinByte =
5282 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
5283
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005284 static const int kExtendedModeBitWithinByte =
5285 (kExtendedModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
5286
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005287 static const int kNativeBitWithinByte =
5288 (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
Ben Murdoch257744e2011-11-30 15:57:28 +00005289
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005290#if __BYTE_ORDER == __LITTLE_ENDIAN
5291 static const int kStrictModeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00005292 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005293 static const int kExtendedModeByteOffset = kCompilerHintsOffset +
5294 (kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005295 static const int kNativeByteOffset = kCompilerHintsOffset +
5296 (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005297#elif __BYTE_ORDER == __BIG_ENDIAN
5298 static const int kStrictModeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00005299 (kCompilerHintsSize - 1) -
5300 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005301 static const int kExtendedModeByteOffset = kCompilerHintsOffset +
5302 (kCompilerHintsSize - 1) -
5303 ((kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005304 static const int kNativeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00005305 (kCompilerHintsSize - 1) -
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005306 ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01005307#else
5308#error Unknown byte ordering
5309#endif
5310
5311 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00005312 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
5313};
5314
5315
5316// JSFunction describes JavaScript functions.
5317class JSFunction: public JSObject {
5318 public:
5319 // [prototype_or_initial_map]:
5320 DECL_ACCESSORS(prototype_or_initial_map, Object)
5321
Ben Murdoch589d6972011-11-30 16:04:58 +00005322 // [shared]: The information about the function that
Steve Blocka7e24c12009-10-30 11:49:00 +00005323 // can be shared by instances.
5324 DECL_ACCESSORS(shared, SharedFunctionInfo)
5325
Iain Merrick75681382010-08-19 15:07:18 +01005326 inline SharedFunctionInfo* unchecked_shared();
5327
Steve Blocka7e24c12009-10-30 11:49:00 +00005328 // [context]: The context for this function.
5329 inline Context* context();
5330 inline Object* unchecked_context();
5331 inline void set_context(Object* context);
5332
5333 // [code]: The generated code object for this function. Executed
5334 // when the function is invoked, e.g. foo() or new foo(). See
5335 // [[Call]] and [[Construct]] description in ECMA-262, section
5336 // 8.6.2, page 27.
5337 inline Code* code();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005338 inline void set_code(Code* code);
5339 inline void ReplaceCode(Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00005340
Iain Merrick75681382010-08-19 15:07:18 +01005341 inline Code* unchecked_code();
5342
Steve Blocka7e24c12009-10-30 11:49:00 +00005343 // Tells whether this function is builtin.
5344 inline bool IsBuiltin();
5345
Ben Murdochb0fe1622011-05-05 13:52:32 +01005346 // Tells whether or not the function needs arguments adaption.
5347 inline bool NeedsArgumentsAdaption();
5348
5349 // Tells whether or not this function has been optimized.
5350 inline bool IsOptimized();
5351
Ben Murdoch8b112d22011-06-08 16:22:53 +01005352 // Tells whether or not this function can be optimized.
5353 inline bool IsOptimizable();
5354
Ben Murdochb0fe1622011-05-05 13:52:32 +01005355 // Mark this function for lazy recompilation. The function will be
5356 // recompiled the next time it is executed.
5357 void MarkForLazyRecompilation();
5358
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005359 // Helpers to compile this function. Returns true on success, false on
5360 // failure (e.g., stack overflow during compilation).
5361 static bool CompileLazy(Handle<JSFunction> function,
5362 ClearExceptionFlag flag);
5363 static bool CompileOptimized(Handle<JSFunction> function,
5364 int osr_ast_id,
5365 ClearExceptionFlag flag);
5366
Ben Murdochb0fe1622011-05-05 13:52:32 +01005367 // Tells whether or not the function is already marked for lazy
5368 // recompilation.
5369 inline bool IsMarkedForLazyRecompilation();
5370
Ben Murdochb0fe1622011-05-05 13:52:32 +01005371 // Check whether or not this function is inlineable.
5372 bool IsInlineable();
5373
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005374 // [literals_or_bindings]: Fixed array holding either
5375 // the materialized literals or the bindings of a bound function.
Steve Blocka7e24c12009-10-30 11:49:00 +00005376 //
5377 // If the function contains object, regexp or array literals, the
5378 // literals array prefix contains the object, regexp, and array
5379 // function to be used when creating these literals. This is
5380 // necessary so that we do not dynamically lookup the object, regexp
5381 // or array functions. Performing a dynamic lookup, we might end up
5382 // using the functions from a new context that we should not have
5383 // access to.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005384 //
5385 // On bound functions, the array is a (copy-on-write) fixed-array containing
5386 // the function that was bound, bound this-value and any bound
5387 // arguments. Bound functions never contain literals.
5388 DECL_ACCESSORS(literals_or_bindings, FixedArray)
5389
5390 inline FixedArray* literals();
5391 inline void set_literals(FixedArray* literals);
5392
5393 inline FixedArray* function_bindings();
5394 inline void set_function_bindings(FixedArray* bindings);
Steve Blocka7e24c12009-10-30 11:49:00 +00005395
5396 // The initial map for an object created by this constructor.
5397 inline Map* initial_map();
5398 inline void set_initial_map(Map* value);
5399 inline bool has_initial_map();
5400
5401 // Get and set the prototype property on a JSFunction. If the
5402 // function has an initial map the prototype is set on the initial
5403 // map. Otherwise, the prototype is put in the initial map field
5404 // until an initial map is needed.
5405 inline bool has_prototype();
5406 inline bool has_instance_prototype();
5407 inline Object* prototype();
5408 inline Object* instance_prototype();
5409 Object* SetInstancePrototype(Object* value);
John Reck59135872010-11-02 12:39:01 -07005410 MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005411
Steve Block6ded16b2010-05-10 14:33:55 +01005412 // After prototype is removed, it will not be created when accessed, and
5413 // [[Construct]] from this function will not be allowed.
5414 Object* RemovePrototype();
5415 inline bool should_have_prototype();
5416
Steve Blocka7e24c12009-10-30 11:49:00 +00005417 // Accessor for this function's initial map's [[class]]
5418 // property. This is primarily used by ECMA native functions. This
5419 // method sets the class_name field of this function's initial map
5420 // to a given value. It creates an initial map if this function does
5421 // not have one. Note that this method does not copy the initial map
5422 // if it has one already, but simply replaces it with the new value.
5423 // Instances created afterwards will have a map whose [[class]] is
5424 // set to 'value', but there is no guarantees on instances created
5425 // before.
5426 Object* SetInstanceClassName(String* name);
5427
5428 // Returns if this function has been compiled to native code yet.
5429 inline bool is_compiled();
5430
Ben Murdochb0fe1622011-05-05 13:52:32 +01005431 // [next_function_link]: Field for linking functions. This list is treated as
5432 // a weak list by the GC.
5433 DECL_ACCESSORS(next_function_link, Object)
5434
5435 // Prints the name of the function using PrintF.
5436 inline void PrintName() {
5437 PrintName(stdout);
5438 }
5439 void PrintName(FILE* out);
5440
Steve Blocka7e24c12009-10-30 11:49:00 +00005441 // Casting.
5442 static inline JSFunction* cast(Object* obj);
5443
Steve Block791712a2010-08-27 10:21:07 +01005444 // Iterates the objects, including code objects indirectly referenced
5445 // through pointers to the first instruction in the code object.
5446 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
5447
Steve Blocka7e24c12009-10-30 11:49:00 +00005448 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005449#ifdef OBJECT_PRINT
5450 inline void JSFunctionPrint() {
5451 JSFunctionPrint(stdout);
5452 }
5453 void JSFunctionPrint(FILE* out);
5454#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005455#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005456 void JSFunctionVerify();
5457#endif
5458
5459 // Returns the number of allocated literals.
5460 inline int NumberOfLiterals();
5461
5462 // Retrieve the global context from a function's literal array.
5463 static Context* GlobalContextFromLiterals(FixedArray* literals);
5464
Ben Murdochb0fe1622011-05-05 13:52:32 +01005465 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
5466 // kSize) is weak and has special handling during garbage collection.
Steve Block791712a2010-08-27 10:21:07 +01005467 static const int kCodeEntryOffset = JSObject::kHeaderSize;
Iain Merrick75681382010-08-19 15:07:18 +01005468 static const int kPrototypeOrInitialMapOffset =
Steve Block791712a2010-08-27 10:21:07 +01005469 kCodeEntryOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005470 static const int kSharedFunctionInfoOffset =
5471 kPrototypeOrInitialMapOffset + kPointerSize;
5472 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
5473 static const int kLiteralsOffset = kContextOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005474 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
5475 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
5476 static const int kSize = kNextFunctionLinkOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00005477
5478 // Layout of the literals array.
5479 static const int kLiteralsPrefixSize = 1;
5480 static const int kLiteralGlobalContextIndex = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005481
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005482 // Layout of the bound-function binding array.
5483 static const int kBoundFunctionIndex = 0;
5484 static const int kBoundThisIndex = 1;
5485 static const int kBoundArgumentsStartIndex = 2;
5486
Steve Blocka7e24c12009-10-30 11:49:00 +00005487 private:
5488 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
5489};
5490
5491
5492// JSGlobalProxy's prototype must be a JSGlobalObject or null,
5493// and the prototype is hidden. JSGlobalProxy always delegates
5494// property accesses to its prototype if the prototype is not null.
5495//
5496// A JSGlobalProxy can be reinitialized which will preserve its identity.
5497//
5498// Accessing a JSGlobalProxy requires security check.
5499
5500class JSGlobalProxy : public JSObject {
5501 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00005502 // [context]: the owner global context of this global proxy object.
Steve Blocka7e24c12009-10-30 11:49:00 +00005503 // It is null value if this object is not used by any context.
5504 DECL_ACCESSORS(context, Object)
5505
5506 // Casting.
5507 static inline JSGlobalProxy* cast(Object* obj);
5508
5509 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005510#ifdef OBJECT_PRINT
5511 inline void JSGlobalProxyPrint() {
5512 JSGlobalProxyPrint(stdout);
5513 }
5514 void JSGlobalProxyPrint(FILE* out);
5515#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005516#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005517 void JSGlobalProxyVerify();
5518#endif
5519
5520 // Layout description.
5521 static const int kContextOffset = JSObject::kHeaderSize;
5522 static const int kSize = kContextOffset + kPointerSize;
5523
5524 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00005525 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
5526};
5527
5528
5529// Forward declaration.
5530class JSBuiltinsObject;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005531class JSGlobalPropertyCell;
Steve Blocka7e24c12009-10-30 11:49:00 +00005532
5533// Common super class for JavaScript global objects and the special
5534// builtins global objects.
5535class GlobalObject: public JSObject {
5536 public:
5537 // [builtins]: the object holding the runtime routines written in JS.
5538 DECL_ACCESSORS(builtins, JSBuiltinsObject)
5539
5540 // [global context]: the global context corresponding to this global object.
5541 DECL_ACCESSORS(global_context, Context)
5542
5543 // [global receiver]: the global receiver object of the context
5544 DECL_ACCESSORS(global_receiver, JSObject)
5545
5546 // Retrieve the property cell used to store a property.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005547 JSGlobalPropertyCell* GetPropertyCell(LookupResult* result);
Steve Blocka7e24c12009-10-30 11:49:00 +00005548
John Reck59135872010-11-02 12:39:01 -07005549 // This is like GetProperty, but is used when you know the lookup won't fail
5550 // by throwing an exception. This is for the debug and builtins global
5551 // objects, where it is known which properties can be expected to be present
5552 // on the object.
5553 Object* GetPropertyNoExceptionThrown(String* key) {
5554 Object* answer = GetProperty(key)->ToObjectUnchecked();
5555 return answer;
5556 }
5557
Steve Blocka7e24c12009-10-30 11:49:00 +00005558 // Ensure that the global object has a cell for the given property name.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005559 static Handle<JSGlobalPropertyCell> EnsurePropertyCell(
5560 Handle<GlobalObject> global,
5561 Handle<String> name);
5562 // TODO(kmillikin): This function can be eliminated once the stub cache is
5563 // full handlified (and the static helper can be written directly).
John Reck59135872010-11-02 12:39:01 -07005564 MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00005565
5566 // Casting.
5567 static inline GlobalObject* cast(Object* obj);
5568
5569 // Layout description.
5570 static const int kBuiltinsOffset = JSObject::kHeaderSize;
5571 static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
5572 static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
5573 static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
5574
5575 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00005576 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
5577};
5578
5579
5580// JavaScript global object.
5581class JSGlobalObject: public GlobalObject {
5582 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00005583 // Casting.
5584 static inline JSGlobalObject* cast(Object* obj);
5585
5586 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005587#ifdef OBJECT_PRINT
5588 inline void JSGlobalObjectPrint() {
5589 JSGlobalObjectPrint(stdout);
5590 }
5591 void JSGlobalObjectPrint(FILE* out);
5592#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005593#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005594 void JSGlobalObjectVerify();
5595#endif
5596
5597 // Layout description.
5598 static const int kSize = GlobalObject::kHeaderSize;
5599
5600 private:
5601 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
5602};
5603
5604
5605// Builtins global object which holds the runtime routines written in
5606// JavaScript.
5607class JSBuiltinsObject: public GlobalObject {
5608 public:
5609 // Accessors for the runtime routines written in JavaScript.
5610 inline Object* javascript_builtin(Builtins::JavaScript id);
5611 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
5612
Steve Block6ded16b2010-05-10 14:33:55 +01005613 // Accessors for code of the runtime routines written in JavaScript.
5614 inline Code* javascript_builtin_code(Builtins::JavaScript id);
5615 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
5616
Steve Blocka7e24c12009-10-30 11:49:00 +00005617 // Casting.
5618 static inline JSBuiltinsObject* cast(Object* obj);
5619
5620 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005621#ifdef OBJECT_PRINT
5622 inline void JSBuiltinsObjectPrint() {
5623 JSBuiltinsObjectPrint(stdout);
5624 }
5625 void JSBuiltinsObjectPrint(FILE* out);
5626#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005627#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005628 void JSBuiltinsObjectVerify();
5629#endif
5630
5631 // Layout description. The size of the builtins object includes
Steve Block6ded16b2010-05-10 14:33:55 +01005632 // room for two pointers per runtime routine written in javascript
5633 // (function and code object).
Steve Blocka7e24c12009-10-30 11:49:00 +00005634 static const int kJSBuiltinsCount = Builtins::id_count;
5635 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005636 static const int kJSBuiltinsCodeOffset =
5637 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00005638 static const int kSize =
Steve Block6ded16b2010-05-10 14:33:55 +01005639 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
5640
5641 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
5642 return kJSBuiltinsOffset + id * kPointerSize;
5643 }
5644
5645 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
5646 return kJSBuiltinsCodeOffset + id * kPointerSize;
5647 }
5648
Steve Blocka7e24c12009-10-30 11:49:00 +00005649 private:
5650 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
5651};
5652
5653
5654// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
5655class JSValue: public JSObject {
5656 public:
5657 // [value]: the object being wrapped.
5658 DECL_ACCESSORS(value, Object)
5659
5660 // Casting.
5661 static inline JSValue* cast(Object* obj);
5662
5663 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005664#ifdef OBJECT_PRINT
5665 inline void JSValuePrint() {
5666 JSValuePrint(stdout);
5667 }
5668 void JSValuePrint(FILE* out);
5669#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00005670#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00005671 void JSValueVerify();
5672#endif
5673
5674 // Layout description.
5675 static const int kValueOffset = JSObject::kHeaderSize;
5676 static const int kSize = kValueOffset + kPointerSize;
5677
5678 private:
5679 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
5680};
5681
Steve Block1e0659c2011-05-24 12:43:12 +01005682
5683// Representation of message objects used for error reporting through
5684// the API. The messages are formatted in JavaScript so this object is
5685// a real JavaScript object. The information used for formatting the
5686// error messages are not directly accessible from JavaScript to
5687// prevent leaking information to user code called during error
5688// formatting.
5689class JSMessageObject: public JSObject {
5690 public:
5691 // [type]: the type of error message.
5692 DECL_ACCESSORS(type, String)
5693
5694 // [arguments]: the arguments for formatting the error message.
5695 DECL_ACCESSORS(arguments, JSArray)
5696
5697 // [script]: the script from which the error message originated.
5698 DECL_ACCESSORS(script, Object)
5699
5700 // [stack_trace]: the stack trace for this error message.
5701 DECL_ACCESSORS(stack_trace, Object)
5702
5703 // [stack_frames]: an array of stack frames for this error object.
5704 DECL_ACCESSORS(stack_frames, Object)
5705
5706 // [start_position]: the start position in the script for the error message.
5707 inline int start_position();
5708 inline void set_start_position(int value);
5709
5710 // [end_position]: the end position in the script for the error message.
5711 inline int end_position();
5712 inline void set_end_position(int value);
5713
5714 // Casting.
5715 static inline JSMessageObject* cast(Object* obj);
5716
5717 // Dispatched behavior.
5718#ifdef OBJECT_PRINT
5719 inline void JSMessageObjectPrint() {
5720 JSMessageObjectPrint(stdout);
5721 }
5722 void JSMessageObjectPrint(FILE* out);
5723#endif
5724#ifdef DEBUG
5725 void JSMessageObjectVerify();
5726#endif
5727
5728 // Layout description.
5729 static const int kTypeOffset = JSObject::kHeaderSize;
5730 static const int kArgumentsOffset = kTypeOffset + kPointerSize;
5731 static const int kScriptOffset = kArgumentsOffset + kPointerSize;
5732 static const int kStackTraceOffset = kScriptOffset + kPointerSize;
5733 static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
5734 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
5735 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
5736 static const int kSize = kEndPositionOffset + kPointerSize;
5737
5738 typedef FixedBodyDescriptor<HeapObject::kMapOffset,
5739 kStackFramesOffset + kPointerSize,
5740 kSize> BodyDescriptor;
5741};
5742
5743
Steve Blocka7e24c12009-10-30 11:49:00 +00005744// Regular expressions
5745// The regular expression holds a single reference to a FixedArray in
5746// the kDataOffset field.
5747// The FixedArray contains the following data:
5748// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
5749// - reference to the original source string
5750// - reference to the original flag string
5751// If it is an atom regexp
5752// - a reference to a literal string to search for
5753// If it is an irregexp regexp:
Ben Murdoch257744e2011-11-30 15:57:28 +00005754// - a reference to code for ASCII inputs (bytecode or compiled), or a smi
5755// used for tracking the last usage (used for code flushing).
5756// - a reference to code for UC16 inputs (bytecode or compiled), or a smi
5757// used for tracking the last usage (used for code flushing)..
Steve Blocka7e24c12009-10-30 11:49:00 +00005758// - max number of registers used by irregexp implementations.
5759// - number of capture registers (output values) of the regexp.
5760class JSRegExp: public JSObject {
5761 public:
5762 // Meaning of Type:
5763 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
5764 // ATOM: A simple string to match against using an indexOf operation.
5765 // IRREGEXP: Compiled with Irregexp.
5766 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
5767 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
5768 enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
5769
5770 class Flags {
5771 public:
5772 explicit Flags(uint32_t value) : value_(value) { }
5773 bool is_global() { return (value_ & GLOBAL) != 0; }
5774 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
5775 bool is_multiline() { return (value_ & MULTILINE) != 0; }
5776 uint32_t value() { return value_; }
5777 private:
5778 uint32_t value_;
5779 };
5780
5781 DECL_ACCESSORS(data, Object)
5782
5783 inline Type TypeTag();
5784 inline int CaptureCount();
5785 inline Flags GetFlags();
5786 inline String* Pattern();
5787 inline Object* DataAt(int index);
5788 // Set implementation data after the object has been prepared.
5789 inline void SetDataAt(int index, Object* value);
Ben Murdoch257744e2011-11-30 15:57:28 +00005790
5791 // Used during GC when flushing code or setting age.
5792 inline Object* DataAtUnchecked(int index);
5793 inline void SetDataAtUnchecked(int index, Object* value, Heap* heap);
5794 inline Type TypeTagUnchecked();
5795
Steve Blocka7e24c12009-10-30 11:49:00 +00005796 static int code_index(bool is_ascii) {
5797 if (is_ascii) {
5798 return kIrregexpASCIICodeIndex;
5799 } else {
5800 return kIrregexpUC16CodeIndex;
5801 }
5802 }
5803
Ben Murdoch257744e2011-11-30 15:57:28 +00005804 static int saved_code_index(bool is_ascii) {
5805 if (is_ascii) {
5806 return kIrregexpASCIICodeSavedIndex;
5807 } else {
5808 return kIrregexpUC16CodeSavedIndex;
5809 }
5810 }
5811
Steve Blocka7e24c12009-10-30 11:49:00 +00005812 static inline JSRegExp* cast(Object* obj);
5813
5814 // Dispatched behavior.
5815#ifdef DEBUG
5816 void JSRegExpVerify();
5817#endif
5818
5819 static const int kDataOffset = JSObject::kHeaderSize;
5820 static const int kSize = kDataOffset + kPointerSize;
5821
5822 // Indices in the data array.
5823 static const int kTagIndex = 0;
5824 static const int kSourceIndex = kTagIndex + 1;
5825 static const int kFlagsIndex = kSourceIndex + 1;
5826 static const int kDataIndex = kFlagsIndex + 1;
5827 // The data fields are used in different ways depending on the
5828 // value of the tag.
5829 // Atom regexps (literal strings).
5830 static const int kAtomPatternIndex = kDataIndex;
5831
5832 static const int kAtomDataSize = kAtomPatternIndex + 1;
5833
5834 // Irregexp compiled code or bytecode for ASCII. If compilation
5835 // fails, this fields hold an exception object that should be
5836 // thrown if the regexp is used again.
5837 static const int kIrregexpASCIICodeIndex = kDataIndex;
5838 // Irregexp compiled code or bytecode for UC16. If compilation
5839 // fails, this fields hold an exception object that should be
5840 // thrown if the regexp is used again.
5841 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
Ben Murdoch257744e2011-11-30 15:57:28 +00005842
5843 // Saved instance of Irregexp compiled code or bytecode for ASCII that
5844 // is a potential candidate for flushing.
5845 static const int kIrregexpASCIICodeSavedIndex = kDataIndex + 2;
5846 // Saved instance of Irregexp compiled code or bytecode for UC16 that is
5847 // a potential candidate for flushing.
5848 static const int kIrregexpUC16CodeSavedIndex = kDataIndex + 3;
5849
Steve Blocka7e24c12009-10-30 11:49:00 +00005850 // Maximal number of registers used by either ASCII or UC16.
5851 // Only used to check that there is enough stack space
Ben Murdoch257744e2011-11-30 15:57:28 +00005852 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4;
Steve Blocka7e24c12009-10-30 11:49:00 +00005853 // Number of captures in the compiled regexp.
Ben Murdoch257744e2011-11-30 15:57:28 +00005854 static const int kIrregexpCaptureCountIndex = kDataIndex + 5;
Steve Blocka7e24c12009-10-30 11:49:00 +00005855
5856 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
Leon Clarkee46be812010-01-19 14:06:41 +00005857
5858 // Offsets directly into the data fixed array.
5859 static const int kDataTagOffset =
5860 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
5861 static const int kDataAsciiCodeOffset =
5862 FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +00005863 static const int kDataUC16CodeOffset =
5864 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00005865 static const int kIrregexpCaptureCountOffset =
5866 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01005867
5868 // In-object fields.
5869 static const int kSourceFieldIndex = 0;
5870 static const int kGlobalFieldIndex = 1;
5871 static const int kIgnoreCaseFieldIndex = 2;
5872 static const int kMultilineFieldIndex = 3;
5873 static const int kLastIndexFieldIndex = 4;
Ben Murdochbb769b22010-08-11 14:56:33 +01005874 static const int kInObjectFieldCount = 5;
Ben Murdoch257744e2011-11-30 15:57:28 +00005875
5876 // The uninitialized value for a regexp code object.
5877 static const int kUninitializedValue = -1;
5878
5879 // The compilation error value for the regexp code object. The real error
5880 // object is in the saved code field.
5881 static const int kCompilationErrorValue = -2;
5882
5883 // When we store the sweep generation at which we moved the code from the
5884 // code index to the saved code index we mask it of to be in the [0:255]
5885 // range.
5886 static const int kCodeAgeMask = 0xff;
Steve Blocka7e24c12009-10-30 11:49:00 +00005887};
5888
5889
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005890class CompilationCacheShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00005891 public:
5892 static inline bool IsMatch(HashTableKey* key, Object* value) {
5893 return key->IsMatch(value);
5894 }
5895
5896 static inline uint32_t Hash(HashTableKey* key) {
5897 return key->Hash();
5898 }
5899
5900 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
5901 return key->HashForObject(object);
5902 }
5903
John Reck59135872010-11-02 12:39:01 -07005904 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005905 return key->AsObject();
5906 }
5907
5908 static const int kPrefixSize = 0;
5909 static const int kEntrySize = 2;
5910};
5911
Steve Block3ce2e202009-11-05 08:53:23 +00005912
Steve Blocka7e24c12009-10-30 11:49:00 +00005913class CompilationCacheTable: public HashTable<CompilationCacheShape,
5914 HashTableKey*> {
5915 public:
5916 // Find cached value for a string key, otherwise return null.
5917 Object* Lookup(String* src);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005918 Object* LookupEval(String* src,
5919 Context* context,
5920 LanguageMode language_mode,
5921 int scope_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00005922 Object* LookupRegExp(String* source, JSRegExp::Flags flags);
John Reck59135872010-11-02 12:39:01 -07005923 MaybeObject* Put(String* src, Object* value);
Steve Block1e0659c2011-05-24 12:43:12 +01005924 MaybeObject* PutEval(String* src,
5925 Context* context,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005926 SharedFunctionInfo* value,
5927 int scope_position);
John Reck59135872010-11-02 12:39:01 -07005928 MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00005929
Ben Murdochb0fe1622011-05-05 13:52:32 +01005930 // Remove given value from cache.
5931 void Remove(Object* value);
5932
Steve Blocka7e24c12009-10-30 11:49:00 +00005933 static inline CompilationCacheTable* cast(Object* obj);
5934
5935 private:
5936 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
5937};
5938
5939
Steve Block6ded16b2010-05-10 14:33:55 +01005940class CodeCache: public Struct {
5941 public:
5942 DECL_ACCESSORS(default_cache, FixedArray)
5943 DECL_ACCESSORS(normal_type_cache, Object)
5944
5945 // Add the code object to the cache.
John Reck59135872010-11-02 12:39:01 -07005946 MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005947
5948 // Lookup code object in the cache. Returns code object if found and undefined
5949 // if not.
5950 Object* Lookup(String* name, Code::Flags flags);
5951
5952 // Get the internal index of a code object in the cache. Returns -1 if the
5953 // code object is not in that cache. This index can be used to later call
5954 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
5955 // RemoveByIndex.
5956 int GetIndex(Object* name, Code* code);
5957
5958 // Remove an object from the cache with the provided internal index.
5959 void RemoveByIndex(Object* name, Code* code, int index);
5960
5961 static inline CodeCache* cast(Object* obj);
5962
Ben Murdochb0fe1622011-05-05 13:52:32 +01005963#ifdef OBJECT_PRINT
5964 inline void CodeCachePrint() {
5965 CodeCachePrint(stdout);
5966 }
5967 void CodeCachePrint(FILE* out);
5968#endif
Steve Block6ded16b2010-05-10 14:33:55 +01005969#ifdef DEBUG
Steve Block6ded16b2010-05-10 14:33:55 +01005970 void CodeCacheVerify();
5971#endif
5972
5973 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
5974 static const int kNormalTypeCacheOffset =
5975 kDefaultCacheOffset + kPointerSize;
5976 static const int kSize = kNormalTypeCacheOffset + kPointerSize;
5977
5978 private:
John Reck59135872010-11-02 12:39:01 -07005979 MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
5980 MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01005981 Object* LookupDefaultCache(String* name, Code::Flags flags);
5982 Object* LookupNormalTypeCache(String* name, Code::Flags flags);
5983
5984 // Code cache layout of the default cache. Elements are alternating name and
5985 // code objects for non normal load/store/call IC's.
5986 static const int kCodeCacheEntrySize = 2;
5987 static const int kCodeCacheEntryNameOffset = 0;
5988 static const int kCodeCacheEntryCodeOffset = 1;
5989
5990 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
5991};
5992
5993
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005994class CodeCacheHashTableShape {
Steve Block6ded16b2010-05-10 14:33:55 +01005995 public:
5996 static inline bool IsMatch(HashTableKey* key, Object* value) {
5997 return key->IsMatch(value);
5998 }
5999
6000 static inline uint32_t Hash(HashTableKey* key) {
6001 return key->Hash();
6002 }
6003
6004 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
6005 return key->HashForObject(object);
6006 }
6007
John Reck59135872010-11-02 12:39:01 -07006008 MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
Steve Block6ded16b2010-05-10 14:33:55 +01006009 return key->AsObject();
6010 }
6011
6012 static const int kPrefixSize = 0;
6013 static const int kEntrySize = 2;
6014};
6015
6016
6017class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
6018 HashTableKey*> {
6019 public:
6020 Object* Lookup(String* name, Code::Flags flags);
John Reck59135872010-11-02 12:39:01 -07006021 MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
Steve Block6ded16b2010-05-10 14:33:55 +01006022
6023 int GetIndex(String* name, Code::Flags flags);
6024 void RemoveByIndex(int index);
6025
6026 static inline CodeCacheHashTable* cast(Object* obj);
6027
6028 // Initial size of the fixed array backing the hash table.
6029 static const int kInitialSize = 64;
6030
6031 private:
6032 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
6033};
6034
6035
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006036class PolymorphicCodeCache: public Struct {
6037 public:
6038 DECL_ACCESSORS(cache, Object)
6039
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006040 static void Update(Handle<PolymorphicCodeCache> cache,
6041 MapHandleList* maps,
6042 Code::Flags flags,
6043 Handle<Code> code);
6044
6045 MUST_USE_RESULT MaybeObject* Update(MapHandleList* maps,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006046 Code::Flags flags,
6047 Code* code);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006048
6049 // Returns an undefined value if the entry is not found.
6050 Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006051
6052 static inline PolymorphicCodeCache* cast(Object* obj);
6053
6054#ifdef OBJECT_PRINT
6055 inline void PolymorphicCodeCachePrint() {
6056 PolymorphicCodeCachePrint(stdout);
6057 }
6058 void PolymorphicCodeCachePrint(FILE* out);
6059#endif
6060#ifdef DEBUG
6061 void PolymorphicCodeCacheVerify();
6062#endif
6063
6064 static const int kCacheOffset = HeapObject::kHeaderSize;
6065 static const int kSize = kCacheOffset + kPointerSize;
6066
6067 private:
6068 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache);
6069};
6070
6071
6072class PolymorphicCodeCacheHashTable
6073 : public HashTable<CodeCacheHashTableShape, HashTableKey*> {
6074 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006075 Object* Lookup(MapHandleList* maps, int code_kind);
6076
6077 MUST_USE_RESULT MaybeObject* Put(MapHandleList* maps,
6078 int code_kind,
6079 Code* code);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006080
6081 static inline PolymorphicCodeCacheHashTable* cast(Object* obj);
6082
6083 static const int kInitialSize = 64;
6084 private:
6085 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable);
6086};
6087
6088
Steve Blocka7e24c12009-10-30 11:49:00 +00006089enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
6090enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
6091
6092
6093class StringHasher {
6094 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006095 explicit inline StringHasher(int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00006096
6097 // Returns true if the hash of this string can be computed without
6098 // looking at the contents.
6099 inline bool has_trivial_hash();
6100
6101 // Add a character to the hash and update the array index calculation.
6102 inline void AddCharacter(uc32 c);
6103
6104 // Adds a character to the hash but does not update the array index
6105 // calculation. This can only be called when it has been verified
6106 // that the input is not an array index.
6107 inline void AddCharacterNoIndex(uc32 c);
6108
6109 // Returns the value to store in the hash field of a string with
6110 // the given length and contents.
6111 uint32_t GetHashField();
6112
6113 // Returns true if the characters seen so far make up a legal array
6114 // index.
6115 bool is_array_index() { return is_array_index_; }
6116
6117 bool is_valid() { return is_valid_; }
6118
6119 void invalidate() { is_valid_ = false; }
6120
Kristian Monsen80d68ea2010-09-08 11:05:35 +01006121 // Calculated hash value for a string consisting of 1 to
6122 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
6123 // value is represented decimal value.
Iain Merrick9ac36c92010-09-13 15:29:50 +01006124 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01006125
Steve Blocka7e24c12009-10-30 11:49:00 +00006126 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00006127 uint32_t array_index() {
6128 ASSERT(is_array_index());
6129 return array_index_;
6130 }
6131
6132 inline uint32_t GetHash();
6133
6134 int length_;
6135 uint32_t raw_running_hash_;
6136 uint32_t array_index_;
6137 bool is_array_index_;
6138 bool is_first_char_;
6139 bool is_valid_;
Steve Blockd0582a62009-12-15 09:54:21 +00006140 friend class TwoCharHashTableKey;
Steve Blocka7e24c12009-10-30 11:49:00 +00006141};
6142
6143
Steve Block44f0eee2011-05-26 01:26:41 +01006144// Calculates string hash.
6145template <typename schar>
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006146inline uint32_t HashSequentialString(const schar* chars, int length);
Steve Block44f0eee2011-05-26 01:26:41 +01006147
6148
Steve Blocka7e24c12009-10-30 11:49:00 +00006149// The characteristics of a string are stored in its map. Retrieving these
6150// few bits of information is moderately expensive, involving two memory
6151// loads where the second is dependent on the first. To improve efficiency
6152// the shape of the string is given its own class so that it can be retrieved
6153// once and used for several string operations. A StringShape is small enough
6154// to be passed by value and is immutable, but be aware that flattening a
6155// string can potentially alter its shape. Also be aware that a GC caused by
6156// something else can alter the shape of a string due to ConsString
6157// shortcutting. Keeping these restrictions in mind has proven to be error-
6158// prone and so we no longer put StringShapes in variables unless there is a
6159// concrete performance benefit at that particular point in the code.
6160class StringShape BASE_EMBEDDED {
6161 public:
6162 inline explicit StringShape(String* s);
6163 inline explicit StringShape(Map* s);
6164 inline explicit StringShape(InstanceType t);
6165 inline bool IsSequential();
6166 inline bool IsExternal();
6167 inline bool IsCons();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006168 inline bool IsSliced();
6169 inline bool IsIndirect();
Steve Blocka7e24c12009-10-30 11:49:00 +00006170 inline bool IsExternalAscii();
6171 inline bool IsExternalTwoByte();
6172 inline bool IsSequentialAscii();
6173 inline bool IsSequentialTwoByte();
6174 inline bool IsSymbol();
6175 inline StringRepresentationTag representation_tag();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006176 inline uint32_t encoding_tag();
Steve Blocka7e24c12009-10-30 11:49:00 +00006177 inline uint32_t full_representation_tag();
6178 inline uint32_t size_tag();
6179#ifdef DEBUG
6180 inline uint32_t type() { return type_; }
6181 inline void invalidate() { valid_ = false; }
6182 inline bool valid() { return valid_; }
6183#else
6184 inline void invalidate() { }
6185#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006186
Steve Blocka7e24c12009-10-30 11:49:00 +00006187 private:
6188 uint32_t type_;
6189#ifdef DEBUG
6190 inline void set_valid() { valid_ = true; }
6191 bool valid_;
6192#else
6193 inline void set_valid() { }
6194#endif
6195};
6196
6197
6198// The String abstract class captures JavaScript string values:
6199//
6200// Ecma-262:
6201// 4.3.16 String Value
6202// A string value is a member of the type String and is a finite
6203// ordered sequence of zero or more 16-bit unsigned integer values.
6204//
6205// All string values have a length field.
6206class String: public HeapObject {
6207 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006208 // Representation of the flat content of a String.
6209 // A non-flat string doesn't have flat content.
6210 // A flat string has content that's encoded as a sequence of either
6211 // ASCII chars or two-byte UC16.
6212 // Returned by String::GetFlatContent().
6213 class FlatContent {
6214 public:
6215 // Returns true if the string is flat and this structure contains content.
6216 bool IsFlat() { return state_ != NON_FLAT; }
6217 // Returns true if the structure contains ASCII content.
6218 bool IsAscii() { return state_ == ASCII; }
6219 // Returns true if the structure contains two-byte content.
6220 bool IsTwoByte() { return state_ == TWO_BYTE; }
6221
6222 // Return the ASCII content of the string. Only use if IsAscii() returns
6223 // true.
6224 Vector<const char> ToAsciiVector() {
6225 ASSERT_EQ(ASCII, state_);
6226 return Vector<const char>::cast(buffer_);
6227 }
6228 // Return the two-byte content of the string. Only use if IsTwoByte()
6229 // returns true.
6230 Vector<const uc16> ToUC16Vector() {
6231 ASSERT_EQ(TWO_BYTE, state_);
6232 return Vector<const uc16>::cast(buffer_);
6233 }
6234
6235 private:
6236 enum State { NON_FLAT, ASCII, TWO_BYTE };
6237
6238 // Constructors only used by String::GetFlatContent().
6239 explicit FlatContent(Vector<const char> chars)
6240 : buffer_(Vector<const byte>::cast(chars)),
6241 state_(ASCII) { }
6242 explicit FlatContent(Vector<const uc16> chars)
6243 : buffer_(Vector<const byte>::cast(chars)),
6244 state_(TWO_BYTE) { }
6245 FlatContent() : buffer_(), state_(NON_FLAT) { }
6246
6247 Vector<const byte> buffer_;
6248 State state_;
6249
6250 friend class String;
6251 };
6252
Steve Blocka7e24c12009-10-30 11:49:00 +00006253 // Get and set the length of the string.
6254 inline int length();
6255 inline void set_length(int value);
6256
Steve Blockd0582a62009-12-15 09:54:21 +00006257 // Get and set the hash field of the string.
6258 inline uint32_t hash_field();
6259 inline void set_hash_field(uint32_t value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006260
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006261 // Returns whether this string has only ASCII chars, i.e. all of them can
6262 // be ASCII encoded. This might be the case even if the string is
6263 // two-byte. Such strings may appear when the embedder prefers
6264 // two-byte external representations even for ASCII data.
Steve Blocka7e24c12009-10-30 11:49:00 +00006265 inline bool IsAsciiRepresentation();
6266 inline bool IsTwoByteRepresentation();
6267
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006268 // Cons and slices have an encoding flag that may not represent the actual
6269 // encoding of the underlying string. This is taken into account here.
6270 // Requires: this->IsFlat()
6271 inline bool IsAsciiRepresentationUnderneath();
6272 inline bool IsTwoByteRepresentationUnderneath();
6273
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01006274 // NOTE: this should be considered only a hint. False negatives are
6275 // possible.
6276 inline bool HasOnlyAsciiChars();
Steve Block6ded16b2010-05-10 14:33:55 +01006277
Steve Blocka7e24c12009-10-30 11:49:00 +00006278 // Get and set individual two byte chars in the string.
6279 inline void Set(int index, uint16_t value);
6280 // Get individual two byte char in the string. Repeated calls
6281 // to this method are not efficient unless the string is flat.
6282 inline uint16_t Get(int index);
6283
Leon Clarkef7060e22010-06-03 12:02:55 +01006284 // Try to flatten the string. Checks first inline to see if it is
6285 // necessary. Does nothing if the string is not a cons string.
6286 // Flattening allocates a sequential string with the same data as
6287 // the given string and mutates the cons string to a degenerate
6288 // form, where the first component is the new sequential string and
6289 // the second component is the empty string. If allocation fails,
6290 // this function returns a failure. If flattening succeeds, this
6291 // function returns the sequential string that is now the first
6292 // component of the cons string.
6293 //
6294 // Degenerate cons strings are handled specially by the garbage
6295 // collector (see IsShortcutCandidate).
6296 //
6297 // Use FlattenString from Handles.cc to flatten even in case an
6298 // allocation failure happens.
John Reck59135872010-11-02 12:39:01 -07006299 inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00006300
Leon Clarkef7060e22010-06-03 12:02:55 +01006301 // Convenience function. Has exactly the same behavior as
6302 // TryFlatten(), except in the case of failure returns the original
6303 // string.
6304 inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
6305
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006306 // Tries to return the content of a flat string as a structure holding either
6307 // a flat vector of char or of uc16.
6308 // If the string isn't flat, and therefore doesn't have flat content, the
6309 // returned structure will report so, and can't provide a vector of either
6310 // kind.
6311 FlatContent GetFlatContent();
6312
6313 // Returns the parent of a sliced string or first part of a flat cons string.
6314 // Requires: StringShape(this).IsIndirect() && this->IsFlat()
6315 inline String* GetUnderlying();
Steve Blocka7e24c12009-10-30 11:49:00 +00006316
6317 // Mark the string as an undetectable object. It only applies to
6318 // ascii and two byte string types.
6319 bool MarkAsUndetectable();
6320
Steve Blockd0582a62009-12-15 09:54:21 +00006321 // Return a substring.
John Reck59135872010-11-02 12:39:01 -07006322 MUST_USE_RESULT MaybeObject* SubString(int from,
6323 int to,
6324 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00006325
6326 // String equality operations.
6327 inline bool Equals(String* other);
6328 bool IsEqualTo(Vector<const char> str);
Steve Block9fac8402011-05-12 15:51:54 +01006329 bool IsAsciiEqualTo(Vector<const char> str);
6330 bool IsTwoByteEqualTo(Vector<const uc16> str);
Steve Blocka7e24c12009-10-30 11:49:00 +00006331
6332 // Return a UTF8 representation of the string. The string is null
6333 // terminated but may optionally contain nulls. Length is returned
6334 // in length_output if length_output is not a null pointer The string
6335 // should be nearly flat, otherwise the performance of this method may
6336 // be very slow (quadratic in the length). Setting robustness_flag to
6337 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
6338 // handles unexpected data without causing assert failures and it does not
6339 // do any heap allocations. This is useful when printing stack traces.
Ben Murdoch589d6972011-11-30 16:04:58 +00006340 SmartArrayPointer<char> ToCString(AllowNullsFlag allow_nulls,
6341 RobustnessFlag robustness_flag,
6342 int offset,
6343 int length,
6344 int* length_output = 0);
6345 SmartArrayPointer<char> ToCString(
Steve Blocka7e24c12009-10-30 11:49:00 +00006346 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
6347 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
6348 int* length_output = 0);
6349
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006350 inline int Utf8Length() { return Utf8Length(this, 0, length()); }
6351 static int Utf8Length(String* input, int from, int to);
Steve Blocka7e24c12009-10-30 11:49:00 +00006352
6353 // Return a 16 bit Unicode representation of the string.
6354 // The string should be nearly flat, otherwise the performance of
6355 // of this method may be very bad. Setting robustness_flag to
6356 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
6357 // handles unexpected data without causing assert failures and it does not
6358 // do any heap allocations. This is useful when printing stack traces.
Ben Murdoch589d6972011-11-30 16:04:58 +00006359 SmartArrayPointer<uc16> ToWideCString(
Steve Blocka7e24c12009-10-30 11:49:00 +00006360 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
6361
6362 // Tells whether the hash code has been computed.
6363 inline bool HasHashCode();
6364
6365 // Returns a hash value used for the property table
6366 inline uint32_t Hash();
6367
Steve Blockd0582a62009-12-15 09:54:21 +00006368 static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006369 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00006370
6371 static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
6372 uint32_t* index,
6373 int length);
6374
6375 // Externalization.
6376 bool MakeExternal(v8::String::ExternalStringResource* resource);
6377 bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
6378
6379 // Conversion.
6380 inline bool AsArrayIndex(uint32_t* index);
6381
6382 // Casting.
6383 static inline String* cast(Object* obj);
6384
6385 void PrintOn(FILE* out);
6386
6387 // For use during stack traces. Performs rudimentary sanity check.
6388 bool LooksValid();
6389
6390 // Dispatched behavior.
6391 void StringShortPrint(StringStream* accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01006392#ifdef OBJECT_PRINT
6393 inline void StringPrint() {
6394 StringPrint(stdout);
6395 }
6396 void StringPrint(FILE* out);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006397
6398 char* ToAsciiArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01006399#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00006400#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00006401 void StringVerify();
6402#endif
6403 inline bool IsFlat();
6404
6405 // Layout description.
6406 static const int kLengthOffset = HeapObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01006407 static const int kHashFieldOffset = kLengthOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006408 static const int kSize = kHashFieldOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006409
Steve Blockd0582a62009-12-15 09:54:21 +00006410 // Maximum number of characters to consider when trying to convert a string
6411 // value into an array index.
Steve Blocka7e24c12009-10-30 11:49:00 +00006412 static const int kMaxArrayIndexSize = 10;
6413
6414 // Max ascii char code.
6415 static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
6416 static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
6417 static const int kMaxUC16CharCode = 0xffff;
6418
Steve Blockd0582a62009-12-15 09:54:21 +00006419 // Minimum length for a cons string.
Steve Blocka7e24c12009-10-30 11:49:00 +00006420 static const int kMinNonFlatLength = 13;
6421
6422 // Mask constant for checking if a string has a computed hash code
6423 // and if it is an array index. The least significant bit indicates
6424 // whether a hash code has been computed. If the hash code has been
6425 // computed the 2nd bit tells whether the string can be used as an
6426 // array index.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006427 static const int kHashNotComputedMask = 1;
6428 static const int kIsNotArrayIndexMask = 1 << 1;
6429 static const int kNofHashBitFields = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +00006430
Steve Blockd0582a62009-12-15 09:54:21 +00006431 // Shift constant retrieving hash code from hash field.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006432 static const int kHashShift = kNofHashBitFields;
Steve Blockd0582a62009-12-15 09:54:21 +00006433
Steve Blocka7e24c12009-10-30 11:49:00 +00006434 // Array index strings this short can keep their index in the hash
6435 // field.
6436 static const int kMaxCachedArrayIndexLength = 7;
6437
Steve Blockd0582a62009-12-15 09:54:21 +00006438 // For strings which are array indexes the hash value has the string length
6439 // mixed into the hash, mainly to avoid a hash value of zero which would be
6440 // the case for the string '0'. 24 bits are used for the array index value.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006441 static const int kArrayIndexValueBits = 24;
6442 static const int kArrayIndexLengthBits =
6443 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
6444
6445 STATIC_CHECK((kArrayIndexLengthBits > 0));
Iain Merrick9ac36c92010-09-13 15:29:50 +01006446 STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006447
6448 static const int kArrayIndexHashLengthShift =
6449 kArrayIndexValueBits + kNofHashBitFields;
6450
Steve Blockd0582a62009-12-15 09:54:21 +00006451 static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006452
6453 static const int kArrayIndexValueMask =
6454 ((1 << kArrayIndexValueBits) - 1) << kHashShift;
6455
6456 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
6457 // could use a mask to test if the length of string is less than or equal to
6458 // kMaxCachedArrayIndexLength.
6459 STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
6460
6461 static const int kContainsCachedArrayIndexMask =
6462 (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
6463 kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00006464
6465 // Value of empty hash field indicating that the hash is not computed.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006466 static const int kEmptyHashField =
6467 kIsNotArrayIndexMask | kHashNotComputedMask;
6468
6469 // Value of hash field containing computed hash equal to zero.
6470 static const int kZeroHash = kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00006471
6472 // Maximal string length.
6473 static const int kMaxLength = (1 << (32 - 2)) - 1;
6474
6475 // Max length for computing hash. For strings longer than this limit the
6476 // string length is used as the hash value.
6477 static const int kMaxHashCalcLength = 16383;
Steve Blocka7e24c12009-10-30 11:49:00 +00006478
6479 // Limit for truncation in short printing.
6480 static const int kMaxShortPrintLength = 1024;
6481
6482 // Support for regular expressions.
6483 const uc16* GetTwoByteData();
6484 const uc16* GetTwoByteData(unsigned start);
6485
6486 // Support for StringInputBuffer
6487 static const unibrow::byte* ReadBlock(String* input,
6488 unibrow::byte* util_buffer,
6489 unsigned capacity,
6490 unsigned* remaining,
6491 unsigned* offset);
6492 static const unibrow::byte* ReadBlock(String** input,
6493 unibrow::byte* util_buffer,
6494 unsigned capacity,
6495 unsigned* remaining,
6496 unsigned* offset);
6497
6498 // Helper function for flattening strings.
6499 template <typename sinkchar>
6500 static void WriteToFlat(String* source,
6501 sinkchar* sink,
6502 int from,
6503 int to);
6504
Steve Block9fac8402011-05-12 15:51:54 +01006505 static inline bool IsAscii(const char* chars, int length) {
6506 const char* limit = chars + length;
6507#ifdef V8_HOST_CAN_READ_UNALIGNED
6508 ASSERT(kMaxAsciiCharCode == 0x7F);
6509 const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
6510 while (chars <= limit - sizeof(uintptr_t)) {
6511 if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
6512 return false;
6513 }
6514 chars += sizeof(uintptr_t);
6515 }
6516#endif
6517 while (chars < limit) {
6518 if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
6519 ++chars;
6520 }
6521 return true;
6522 }
6523
6524 static inline bool IsAscii(const uc16* chars, int length) {
6525 const uc16* limit = chars + length;
6526 while (chars < limit) {
6527 if (*chars > kMaxAsciiCharCodeU) return false;
6528 ++chars;
6529 }
6530 return true;
6531 }
6532
Steve Blocka7e24c12009-10-30 11:49:00 +00006533 protected:
6534 class ReadBlockBuffer {
6535 public:
6536 ReadBlockBuffer(unibrow::byte* util_buffer_,
6537 unsigned cursor_,
6538 unsigned capacity_,
6539 unsigned remaining_) :
6540 util_buffer(util_buffer_),
6541 cursor(cursor_),
6542 capacity(capacity_),
6543 remaining(remaining_) {
6544 }
6545 unibrow::byte* util_buffer;
6546 unsigned cursor;
6547 unsigned capacity;
6548 unsigned remaining;
6549 };
6550
Steve Blocka7e24c12009-10-30 11:49:00 +00006551 static inline const unibrow::byte* ReadBlock(String* input,
6552 ReadBlockBuffer* buffer,
6553 unsigned* offset,
6554 unsigned max_chars);
6555 static void ReadBlockIntoBuffer(String* input,
6556 ReadBlockBuffer* buffer,
6557 unsigned* offset_ptr,
6558 unsigned max_chars);
6559
6560 private:
Leon Clarkef7060e22010-06-03 12:02:55 +01006561 // Try to flatten the top level ConsString that is hiding behind this
6562 // string. This is a no-op unless the string is a ConsString. Flatten
6563 // mutates the ConsString and might return a failure.
John Reck59135872010-11-02 12:39:01 -07006564 MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
Leon Clarkef7060e22010-06-03 12:02:55 +01006565
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006566 static inline bool IsHashFieldComputed(uint32_t field);
6567
Steve Blocka7e24c12009-10-30 11:49:00 +00006568 // Slow case of String::Equals. This implementation works on any strings
6569 // but it is most efficient on strings that are almost flat.
6570 bool SlowEquals(String* other);
6571
6572 // Slow case of AsArrayIndex.
6573 bool SlowAsArrayIndex(uint32_t* index);
6574
6575 // Compute and set the hash code.
6576 uint32_t ComputeAndSetHash();
6577
6578 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
6579};
6580
6581
6582// The SeqString abstract class captures sequential string values.
6583class SeqString: public String {
6584 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00006585 // Casting.
6586 static inline SeqString* cast(Object* obj);
6587
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006588 // Layout description.
6589 static const int kHeaderSize = String::kSize;
6590
Steve Blocka7e24c12009-10-30 11:49:00 +00006591 private:
6592 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
6593};
6594
6595
6596// The AsciiString class captures sequential ascii string objects.
6597// Each character in the AsciiString is an ascii character.
6598class SeqAsciiString: public SeqString {
6599 public:
Leon Clarkeac952652010-07-15 11:15:24 +01006600 static const bool kHasAsciiEncoding = true;
6601
Steve Blocka7e24c12009-10-30 11:49:00 +00006602 // Dispatched behavior.
6603 inline uint16_t SeqAsciiStringGet(int index);
6604 inline void SeqAsciiStringSet(int index, uint16_t value);
6605
6606 // Get the address of the characters in this string.
6607 inline Address GetCharsAddress();
6608
6609 inline char* GetChars();
6610
6611 // Casting
6612 static inline SeqAsciiString* cast(Object* obj);
6613
6614 // Garbage collection support. This method is called by the
6615 // garbage collector to compute the actual size of an AsciiString
6616 // instance.
6617 inline int SeqAsciiStringSize(InstanceType instance_type);
6618
6619 // Computes the size for an AsciiString instance of a given length.
6620 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006621 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00006622 }
6623
Leon Clarkee46be812010-01-19 14:06:41 +00006624 // Maximal memory usage for a single sequential ASCII string.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006625 static const int kMaxSize = 512 * MB - 1;
Leon Clarkee46be812010-01-19 14:06:41 +00006626 // Maximal length of a single sequential ASCII string.
6627 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
6628 static const int kMaxLength = (kMaxSize - kHeaderSize);
6629
Steve Blocka7e24c12009-10-30 11:49:00 +00006630 // Support for StringInputBuffer.
6631 inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6632 unsigned* offset,
6633 unsigned chars);
6634 inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
6635 unsigned* offset,
6636 unsigned chars);
6637
6638 private:
6639 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
6640};
6641
6642
6643// The TwoByteString class captures sequential unicode string objects.
6644// Each character in the TwoByteString is a two-byte uint16_t.
6645class SeqTwoByteString: public SeqString {
6646 public:
Leon Clarkeac952652010-07-15 11:15:24 +01006647 static const bool kHasAsciiEncoding = false;
6648
Steve Blocka7e24c12009-10-30 11:49:00 +00006649 // Dispatched behavior.
6650 inline uint16_t SeqTwoByteStringGet(int index);
6651 inline void SeqTwoByteStringSet(int index, uint16_t value);
6652
6653 // Get the address of the characters in this string.
6654 inline Address GetCharsAddress();
6655
6656 inline uc16* GetChars();
6657
6658 // For regexp code.
6659 const uint16_t* SeqTwoByteStringGetData(unsigned start);
6660
6661 // Casting
6662 static inline SeqTwoByteString* cast(Object* obj);
6663
6664 // Garbage collection support. This method is called by the
6665 // garbage collector to compute the actual size of a TwoByteString
6666 // instance.
6667 inline int SeqTwoByteStringSize(InstanceType instance_type);
6668
6669 // Computes the size for a TwoByteString instance of a given length.
6670 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006671 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00006672 }
6673
Leon Clarkee46be812010-01-19 14:06:41 +00006674 // Maximal memory usage for a single sequential two-byte string.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006675 static const int kMaxSize = 512 * MB - 1;
Leon Clarkee46be812010-01-19 14:06:41 +00006676 // Maximal length of a single sequential two-byte string.
6677 // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
6678 static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
6679
Steve Blocka7e24c12009-10-30 11:49:00 +00006680 // Support for StringInputBuffer.
6681 inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6682 unsigned* offset_ptr,
6683 unsigned chars);
6684
6685 private:
6686 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
6687};
6688
6689
6690// The ConsString class describes string values built by using the
6691// addition operator on strings. A ConsString is a pair where the
6692// first and second components are pointers to other string values.
6693// One or both components of a ConsString can be pointers to other
6694// ConsStrings, creating a binary tree of ConsStrings where the leaves
6695// are non-ConsString string values. The string value represented by
6696// a ConsString can be obtained by concatenating the leaf string
6697// values in a left-to-right depth-first traversal of the tree.
6698class ConsString: public String {
6699 public:
6700 // First string of the cons cell.
6701 inline String* first();
6702 // Doesn't check that the result is a string, even in debug mode. This is
6703 // useful during GC where the mark bits confuse the checks.
6704 inline Object* unchecked_first();
6705 inline void set_first(String* first,
6706 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
6707
6708 // Second string of the cons cell.
6709 inline String* second();
6710 // Doesn't check that the result is a string, even in debug mode. This is
6711 // useful during GC where the mark bits confuse the checks.
6712 inline Object* unchecked_second();
6713 inline void set_second(String* second,
6714 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
6715
6716 // Dispatched behavior.
6717 uint16_t ConsStringGet(int index);
6718
6719 // Casting.
6720 static inline ConsString* cast(Object* obj);
6721
Steve Blocka7e24c12009-10-30 11:49:00 +00006722 // Layout description.
6723 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
6724 static const int kSecondOffset = kFirstOffset + kPointerSize;
6725 static const int kSize = kSecondOffset + kPointerSize;
6726
6727 // Support for StringInputBuffer.
6728 inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
6729 unsigned* offset_ptr,
6730 unsigned chars);
6731 inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6732 unsigned* offset_ptr,
6733 unsigned chars);
6734
6735 // Minimum length for a cons string.
6736 static const int kMinLength = 13;
6737
Iain Merrick75681382010-08-19 15:07:18 +01006738 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
6739 BodyDescriptor;
6740
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006741#ifdef DEBUG
6742 void ConsStringVerify();
6743#endif
6744
Steve Blocka7e24c12009-10-30 11:49:00 +00006745 private:
6746 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
6747};
6748
6749
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006750// The Sliced String class describes strings that are substrings of another
6751// sequential string. The motivation is to save time and memory when creating
6752// a substring. A Sliced String is described as a pointer to the parent,
6753// the offset from the start of the parent string and the length. Using
6754// a Sliced String therefore requires unpacking of the parent string and
6755// adding the offset to the start address. A substring of a Sliced String
6756// are not nested since the double indirection is simplified when creating
6757// such a substring.
6758// Currently missing features are:
6759// - handling externalized parent strings
6760// - external strings as parent
6761// - truncating sliced string to enable otherwise unneeded parent to be GC'ed.
6762class SlicedString: public String {
6763 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00006764 inline String* parent();
6765 inline void set_parent(String* parent);
6766 inline int offset();
6767 inline void set_offset(int offset);
6768
6769 // Dispatched behavior.
6770 uint16_t SlicedStringGet(int index);
6771
6772 // Casting.
6773 static inline SlicedString* cast(Object* obj);
6774
6775 // Layout description.
6776 static const int kParentOffset = POINTER_SIZE_ALIGN(String::kSize);
6777 static const int kOffsetOffset = kParentOffset + kPointerSize;
6778 static const int kSize = kOffsetOffset + kPointerSize;
6779
6780 // Support for StringInputBuffer
6781 inline const unibrow::byte* SlicedStringReadBlock(ReadBlockBuffer* buffer,
6782 unsigned* offset_ptr,
6783 unsigned chars);
6784 inline void SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6785 unsigned* offset_ptr,
6786 unsigned chars);
6787 // Minimum length for a sliced string.
6788 static const int kMinLength = 13;
6789
6790 typedef FixedBodyDescriptor<kParentOffset,
6791 kOffsetOffset + kPointerSize, kSize>
6792 BodyDescriptor;
6793
6794#ifdef DEBUG
6795 void SlicedStringVerify();
6796#endif
6797
6798 private:
6799 DISALLOW_IMPLICIT_CONSTRUCTORS(SlicedString);
6800};
6801
6802
Steve Blocka7e24c12009-10-30 11:49:00 +00006803// The ExternalString class describes string values that are backed by
6804// a string resource that lies outside the V8 heap. ExternalStrings
6805// consist of the length field common to all strings, a pointer to the
6806// external resource. It is important to ensure (externally) that the
6807// resource is not deallocated while the ExternalString is live in the
6808// V8 heap.
6809//
6810// The API expects that all ExternalStrings are created through the
6811// API. Therefore, ExternalStrings should not be used internally.
6812class ExternalString: public String {
6813 public:
6814 // Casting
6815 static inline ExternalString* cast(Object* obj);
6816
6817 // Layout description.
6818 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006819 static const int kShortSize = kResourceOffset + kPointerSize;
6820 static const int kResourceDataOffset = kResourceOffset + kPointerSize;
6821 static const int kSize = kResourceDataOffset + kPointerSize;
6822
6823 // Return whether external string is short (data pointer is not cached).
6824 inline bool is_short();
Steve Blocka7e24c12009-10-30 11:49:00 +00006825
6826 STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
6827
6828 private:
6829 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
6830};
6831
6832
6833// The ExternalAsciiString class is an external string backed by an
6834// ASCII string.
6835class ExternalAsciiString: public ExternalString {
6836 public:
Leon Clarkeac952652010-07-15 11:15:24 +01006837 static const bool kHasAsciiEncoding = true;
6838
Steve Blocka7e24c12009-10-30 11:49:00 +00006839 typedef v8::String::ExternalAsciiStringResource Resource;
6840
6841 // The underlying resource.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006842 inline const Resource* resource();
6843 inline void set_resource(const Resource* buffer);
6844
6845 // Update the pointer cache to the external character array.
6846 // The cached pointer is always valid, as the external character array does =
6847 // not move during lifetime. Deserialization is the only exception, after
6848 // which the pointer cache has to be refreshed.
6849 inline void update_data_cache();
6850
6851 inline const char* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00006852
6853 // Dispatched behavior.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006854 inline uint16_t ExternalAsciiStringGet(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00006855
6856 // Casting.
6857 static inline ExternalAsciiString* cast(Object* obj);
6858
Steve Blockd0582a62009-12-15 09:54:21 +00006859 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01006860 inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
6861
6862 template<typename StaticVisitor>
6863 inline void ExternalAsciiStringIterateBody();
Steve Blockd0582a62009-12-15 09:54:21 +00006864
Steve Blocka7e24c12009-10-30 11:49:00 +00006865 // Support for StringInputBuffer.
6866 const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
6867 unsigned* offset,
6868 unsigned chars);
6869 inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6870 unsigned* offset,
6871 unsigned chars);
6872
Steve Blocka7e24c12009-10-30 11:49:00 +00006873 private:
6874 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
6875};
6876
6877
6878// The ExternalTwoByteString class is an external string backed by a UTF-16
6879// encoded string.
6880class ExternalTwoByteString: public ExternalString {
6881 public:
Leon Clarkeac952652010-07-15 11:15:24 +01006882 static const bool kHasAsciiEncoding = false;
6883
Steve Blocka7e24c12009-10-30 11:49:00 +00006884 typedef v8::String::ExternalStringResource Resource;
6885
6886 // The underlying string resource.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006887 inline const Resource* resource();
6888 inline void set_resource(const Resource* buffer);
6889
6890 // Update the pointer cache to the external character array.
6891 // The cached pointer is always valid, as the external character array does =
6892 // not move during lifetime. Deserialization is the only exception, after
6893 // which the pointer cache has to be refreshed.
6894 inline void update_data_cache();
6895
6896 inline const uint16_t* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00006897
6898 // Dispatched behavior.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006899 inline uint16_t ExternalTwoByteStringGet(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00006900
6901 // For regexp code.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006902 inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
Steve Blocka7e24c12009-10-30 11:49:00 +00006903
6904 // Casting.
6905 static inline ExternalTwoByteString* cast(Object* obj);
6906
Steve Blockd0582a62009-12-15 09:54:21 +00006907 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01006908 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
6909
6910 template<typename StaticVisitor>
6911 inline void ExternalTwoByteStringIterateBody();
6912
Steve Blockd0582a62009-12-15 09:54:21 +00006913
Steve Blocka7e24c12009-10-30 11:49:00 +00006914 // Support for StringInputBuffer.
6915 void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
6916 unsigned* offset_ptr,
6917 unsigned chars);
6918
Steve Blocka7e24c12009-10-30 11:49:00 +00006919 private:
6920 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
6921};
6922
6923
6924// Utility superclass for stack-allocated objects that must be updated
6925// on gc. It provides two ways for the gc to update instances, either
6926// iterating or updating after gc.
6927class Relocatable BASE_EMBEDDED {
6928 public:
Steve Block44f0eee2011-05-26 01:26:41 +01006929 explicit inline Relocatable(Isolate* isolate);
6930 inline virtual ~Relocatable();
Steve Blocka7e24c12009-10-30 11:49:00 +00006931 virtual void IterateInstance(ObjectVisitor* v) { }
6932 virtual void PostGarbageCollection() { }
6933
6934 static void PostGarbageCollectionProcessing();
6935 static int ArchiveSpacePerThread();
Ben Murdoch257744e2011-11-30 15:57:28 +00006936 static char* ArchiveState(Isolate* isolate, char* to);
6937 static char* RestoreState(Isolate* isolate, char* from);
Steve Blocka7e24c12009-10-30 11:49:00 +00006938 static void Iterate(ObjectVisitor* v);
6939 static void Iterate(ObjectVisitor* v, Relocatable* top);
6940 static char* Iterate(ObjectVisitor* v, char* t);
6941 private:
Steve Block44f0eee2011-05-26 01:26:41 +01006942 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00006943 Relocatable* prev_;
6944};
6945
6946
6947// A flat string reader provides random access to the contents of a
6948// string independent of the character width of the string. The handle
6949// must be valid as long as the reader is being used.
6950class FlatStringReader : public Relocatable {
6951 public:
Steve Block44f0eee2011-05-26 01:26:41 +01006952 FlatStringReader(Isolate* isolate, Handle<String> str);
6953 FlatStringReader(Isolate* isolate, Vector<const char> input);
Steve Blocka7e24c12009-10-30 11:49:00 +00006954 void PostGarbageCollection();
6955 inline uc32 Get(int index);
6956 int length() { return length_; }
6957 private:
6958 String** str_;
6959 bool is_ascii_;
6960 int length_;
6961 const void* start_;
6962};
6963
6964
6965// Note that StringInputBuffers are not valid across a GC! To fix this
6966// it would have to store a String Handle instead of a String* and
6967// AsciiStringReadBlock would have to be modified to use memcpy.
6968//
6969// StringInputBuffer is able to traverse any string regardless of how
6970// deeply nested a sequence of ConsStrings it is made of. However,
6971// performance will be better if deep strings are flattened before they
6972// are traversed. Since flattening requires memory allocation this is
6973// not always desirable, however (esp. in debugging situations).
6974class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
6975 public:
6976 virtual void Seek(unsigned pos);
6977 inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
Ben Murdoch8b112d22011-06-08 16:22:53 +01006978 explicit inline StringInputBuffer(String* backing):
Steve Blocka7e24c12009-10-30 11:49:00 +00006979 unibrow::InputBuffer<String, String*, 1024>(backing) {}
6980};
6981
6982
6983class SafeStringInputBuffer
6984 : public unibrow::InputBuffer<String, String**, 256> {
6985 public:
6986 virtual void Seek(unsigned pos);
6987 inline SafeStringInputBuffer()
6988 : unibrow::InputBuffer<String, String**, 256>() {}
Ben Murdoch8b112d22011-06-08 16:22:53 +01006989 explicit inline SafeStringInputBuffer(String** backing)
Steve Blocka7e24c12009-10-30 11:49:00 +00006990 : unibrow::InputBuffer<String, String**, 256>(backing) {}
6991};
6992
6993
6994template <typename T>
6995class VectorIterator {
6996 public:
6997 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
6998 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
6999 T GetNext() { return data_[index_++]; }
7000 bool has_more() { return index_ < data_.length(); }
7001 private:
7002 Vector<const T> data_;
7003 int index_;
7004};
7005
7006
7007// The Oddball describes objects null, undefined, true, and false.
7008class Oddball: public HeapObject {
7009 public:
7010 // [to_string]: Cached to_string computed at startup.
7011 DECL_ACCESSORS(to_string, String)
7012
7013 // [to_number]: Cached to_number computed at startup.
7014 DECL_ACCESSORS(to_number, Object)
7015
Steve Block44f0eee2011-05-26 01:26:41 +01007016 inline byte kind();
7017 inline void set_kind(byte kind);
7018
Steve Blocka7e24c12009-10-30 11:49:00 +00007019 // Casting.
7020 static inline Oddball* cast(Object* obj);
7021
7022 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00007023#ifdef DEBUG
7024 void OddballVerify();
7025#endif
7026
7027 // Initialize the fields.
John Reck59135872010-11-02 12:39:01 -07007028 MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
Steve Block44f0eee2011-05-26 01:26:41 +01007029 Object* to_number,
7030 byte kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00007031
7032 // Layout description.
7033 static const int kToStringOffset = HeapObject::kHeaderSize;
7034 static const int kToNumberOffset = kToStringOffset + kPointerSize;
Steve Block44f0eee2011-05-26 01:26:41 +01007035 static const int kKindOffset = kToNumberOffset + kPointerSize;
7036 static const int kSize = kKindOffset + kPointerSize;
7037
7038 static const byte kFalse = 0;
7039 static const byte kTrue = 1;
7040 static const byte kNotBooleanMask = ~1;
7041 static const byte kTheHole = 2;
7042 static const byte kNull = 3;
7043 static const byte kArgumentMarker = 4;
7044 static const byte kUndefined = 5;
7045 static const byte kOther = 6;
Steve Blocka7e24c12009-10-30 11:49:00 +00007046
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007047 // The ToNumber value of a hidden oddball is a negative smi.
7048 static const int kLeastHiddenOddballNumber = -5;
7049
Iain Merrick75681382010-08-19 15:07:18 +01007050 typedef FixedBodyDescriptor<kToStringOffset,
7051 kToNumberOffset + kPointerSize,
7052 kSize> BodyDescriptor;
7053
Steve Blocka7e24c12009-10-30 11:49:00 +00007054 private:
7055 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
7056};
7057
7058
7059class JSGlobalPropertyCell: public HeapObject {
7060 public:
7061 // [value]: value of the global property.
7062 DECL_ACCESSORS(value, Object)
7063
7064 // Casting.
7065 static inline JSGlobalPropertyCell* cast(Object* obj);
7066
Steve Blocka7e24c12009-10-30 11:49:00 +00007067#ifdef DEBUG
7068 void JSGlobalPropertyCellVerify();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007069#endif
7070#ifdef OBJECT_PRINT
7071 inline void JSGlobalPropertyCellPrint() {
7072 JSGlobalPropertyCellPrint(stdout);
7073 }
7074 void JSGlobalPropertyCellPrint(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +00007075#endif
7076
7077 // Layout description.
7078 static const int kValueOffset = HeapObject::kHeaderSize;
7079 static const int kSize = kValueOffset + kPointerSize;
7080
Iain Merrick75681382010-08-19 15:07:18 +01007081 typedef FixedBodyDescriptor<kValueOffset,
7082 kValueOffset + kPointerSize,
7083 kSize> BodyDescriptor;
7084
Steve Blocka7e24c12009-10-30 11:49:00 +00007085 private:
7086 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
7087};
7088
7089
Ben Murdoch257744e2011-11-30 15:57:28 +00007090// The JSProxy describes EcmaScript Harmony proxies
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007091class JSProxy: public JSReceiver {
Steve Blocka7e24c12009-10-30 11:49:00 +00007092 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00007093 // [handler]: The handler property.
7094 DECL_ACCESSORS(handler, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00007095
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007096 // [hash]: The hash code property (undefined if not initialized yet).
7097 DECL_ACCESSORS(hash, Object)
7098
Steve Blocka7e24c12009-10-30 11:49:00 +00007099 // Casting.
Ben Murdoch257744e2011-11-30 15:57:28 +00007100 static inline JSProxy* cast(Object* obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00007101
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007102 bool HasPropertyWithHandler(String* name);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007103 bool HasElementWithHandler(uint32_t index);
7104
7105 MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
7106 Object* receiver,
7107 String* name);
7108 MUST_USE_RESULT MaybeObject* GetElementWithHandler(
7109 Object* receiver,
7110 uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007111
7112 MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
7113 String* name,
7114 Object* value,
7115 PropertyAttributes attributes,
7116 StrictModeFlag strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007117 MUST_USE_RESULT MaybeObject* SetElementWithHandler(
7118 uint32_t index,
7119 Object* value,
7120 StrictModeFlag strict_mode);
7121
7122 // If the handler defines an accessor property, invoke its setter
7123 // (or throw if only a getter exists) and set *found to true. Otherwise false.
7124 MUST_USE_RESULT MaybeObject* SetPropertyWithHandlerIfDefiningSetter(
7125 String* name,
7126 Object* value,
7127 PropertyAttributes attributes,
7128 StrictModeFlag strict_mode,
7129 bool* found);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007130
7131 MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
7132 String* name,
7133 DeleteMode mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007134 MUST_USE_RESULT MaybeObject* DeleteElementWithHandler(
7135 uint32_t index,
7136 DeleteMode mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007137
7138 MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
7139 JSReceiver* receiver,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007140 String* name);
7141 MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(
7142 JSReceiver* receiver,
7143 uint32_t index);
7144
7145 MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007146
7147 // Turn this into an (empty) JSObject.
7148 void Fix();
7149
Ben Murdoch589d6972011-11-30 16:04:58 +00007150 // Initializes the body after the handler slot.
7151 inline void InitializeBody(int object_size, Object* value);
7152
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007153 // Invoke a trap by name. If the trap does not exist on this's handler,
7154 // but derived_trap is non-NULL, invoke that instead. May cause GC.
7155 Handle<Object> CallTrap(const char* name,
7156 Handle<Object> derived_trap,
7157 int argc,
7158 Handle<Object> args[]);
7159
Steve Blocka7e24c12009-10-30 11:49:00 +00007160 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01007161#ifdef OBJECT_PRINT
Ben Murdoch257744e2011-11-30 15:57:28 +00007162 inline void JSProxyPrint() {
7163 JSProxyPrint(stdout);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007164 }
Ben Murdoch257744e2011-11-30 15:57:28 +00007165 void JSProxyPrint(FILE* out);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007166#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007167#ifdef DEBUG
Ben Murdoch257744e2011-11-30 15:57:28 +00007168 void JSProxyVerify();
7169#endif
7170
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007171 // Layout description. We add padding so that a proxy has the same
7172 // size as a virgin JSObject. This is essential for becoming a JSObject
7173 // upon freeze.
Ben Murdoch257744e2011-11-30 15:57:28 +00007174 static const int kHandlerOffset = HeapObject::kHeaderSize;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007175 static const int kHashOffset = kHandlerOffset + kPointerSize;
7176 static const int kPaddingOffset = kHashOffset + kPointerSize;
Ben Murdoch589d6972011-11-30 16:04:58 +00007177 static const int kSize = JSObject::kHeaderSize;
7178 static const int kHeaderSize = kPaddingOffset;
7179 static const int kPaddingSize = kSize - kPaddingOffset;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007180
Ben Murdoch589d6972011-11-30 16:04:58 +00007181 STATIC_CHECK(kPaddingSize >= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00007182
7183 typedef FixedBodyDescriptor<kHandlerOffset,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007184 kPaddingOffset,
Ben Murdoch257744e2011-11-30 15:57:28 +00007185 kSize> BodyDescriptor;
7186
7187 private:
7188 DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy);
7189};
7190
7191
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007192class JSFunctionProxy: public JSProxy {
7193 public:
Ben Murdoch589d6972011-11-30 16:04:58 +00007194 // [call_trap]: The call trap.
7195 DECL_ACCESSORS(call_trap, Object)
7196
7197 // [construct_trap]: The construct trap.
7198 DECL_ACCESSORS(construct_trap, Object)
7199
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007200 // Casting.
7201 static inline JSFunctionProxy* cast(Object* obj);
7202
Ben Murdoch589d6972011-11-30 16:04:58 +00007203 // Dispatched behavior.
7204#ifdef OBJECT_PRINT
7205 inline void JSFunctionProxyPrint() {
7206 JSFunctionProxyPrint(stdout);
7207 }
7208 void JSFunctionProxyPrint(FILE* out);
7209#endif
7210#ifdef DEBUG
7211 void JSFunctionProxyVerify();
7212#endif
7213
7214 // Layout description.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007215 static const int kCallTrapOffset = JSProxy::kPaddingOffset;
Ben Murdoch589d6972011-11-30 16:04:58 +00007216 static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize;
7217 static const int kPaddingOffset = kConstructTrapOffset + kPointerSize;
7218 static const int kSize = JSFunction::kSize;
7219 static const int kPaddingSize = kSize - kPaddingOffset;
7220
7221 STATIC_CHECK(kPaddingSize >= 0);
7222
7223 typedef FixedBodyDescriptor<kHandlerOffset,
7224 kConstructTrapOffset + kPointerSize,
7225 kSize> BodyDescriptor;
7226
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007227 private:
7228 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy);
7229};
7230
Ben Murdoch257744e2011-11-30 15:57:28 +00007231
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007232// The JSSet describes EcmaScript Harmony sets
7233class JSSet: public JSObject {
7234 public:
7235 // [set]: the backing hash set containing keys.
7236 DECL_ACCESSORS(table, Object)
7237
7238 // Casting.
7239 static inline JSSet* cast(Object* obj);
7240
7241#ifdef OBJECT_PRINT
7242 inline void JSSetPrint() {
7243 JSSetPrint(stdout);
7244 }
7245 void JSSetPrint(FILE* out);
7246#endif
7247#ifdef DEBUG
7248 void JSSetVerify();
7249#endif
7250
7251 static const int kTableOffset = JSObject::kHeaderSize;
7252 static const int kSize = kTableOffset + kPointerSize;
7253
7254 private:
7255 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet);
7256};
7257
7258
7259// The JSMap describes EcmaScript Harmony maps
7260class JSMap: public JSObject {
7261 public:
7262 // [table]: the backing hash table mapping keys to values.
7263 DECL_ACCESSORS(table, Object)
7264
7265 // Casting.
7266 static inline JSMap* cast(Object* obj);
7267
7268#ifdef OBJECT_PRINT
7269 inline void JSMapPrint() {
7270 JSMapPrint(stdout);
7271 }
7272 void JSMapPrint(FILE* out);
7273#endif
7274#ifdef DEBUG
7275 void JSMapVerify();
7276#endif
7277
7278 static const int kTableOffset = JSObject::kHeaderSize;
7279 static const int kSize = kTableOffset + kPointerSize;
7280
7281 private:
7282 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
7283};
7284
7285
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007286// The JSWeakMap describes EcmaScript Harmony weak maps
7287class JSWeakMap: public JSObject {
7288 public:
7289 // [table]: the backing hash table mapping keys to values.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007290 DECL_ACCESSORS(table, Object)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007291
7292 // [next]: linked list of encountered weak maps during GC.
7293 DECL_ACCESSORS(next, Object)
7294
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007295 // Casting.
7296 static inline JSWeakMap* cast(Object* obj);
7297
7298#ifdef OBJECT_PRINT
7299 inline void JSWeakMapPrint() {
7300 JSWeakMapPrint(stdout);
7301 }
7302 void JSWeakMapPrint(FILE* out);
7303#endif
7304#ifdef DEBUG
7305 void JSWeakMapVerify();
7306#endif
7307
7308 static const int kTableOffset = JSObject::kHeaderSize;
7309 static const int kNextOffset = kTableOffset + kPointerSize;
7310 static const int kSize = kNextOffset + kPointerSize;
7311
7312 private:
7313 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
7314};
7315
7316
Ben Murdoch257744e2011-11-30 15:57:28 +00007317// Foreign describes objects pointing from JavaScript to C structures.
7318// Since they cannot contain references to JS HeapObjects they can be
7319// placed in old_data_space.
7320class Foreign: public HeapObject {
7321 public:
7322 // [address]: field containing the address.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007323 inline Address foreign_address();
7324 inline void set_foreign_address(Address value);
Ben Murdoch257744e2011-11-30 15:57:28 +00007325
7326 // Casting.
7327 static inline Foreign* cast(Object* obj);
7328
7329 // Dispatched behavior.
7330 inline void ForeignIterateBody(ObjectVisitor* v);
7331
7332 template<typename StaticVisitor>
7333 inline void ForeignIterateBody();
7334
7335#ifdef OBJECT_PRINT
7336 inline void ForeignPrint() {
7337 ForeignPrint(stdout);
7338 }
7339 void ForeignPrint(FILE* out);
7340#endif
7341#ifdef DEBUG
7342 void ForeignVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +00007343#endif
7344
7345 // Layout description.
7346
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007347 static const int kForeignAddressOffset = HeapObject::kHeaderSize;
7348 static const int kSize = kForeignAddressOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007349
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007350 STATIC_CHECK(kForeignAddressOffset == Internals::kForeignAddressOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00007351
7352 private:
Ben Murdoch257744e2011-11-30 15:57:28 +00007353 DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
Steve Blocka7e24c12009-10-30 11:49:00 +00007354};
7355
7356
7357// The JSArray describes JavaScript Arrays
7358// Such an array can be in one of two modes:
7359// - fast, backing storage is a FixedArray and length <= elements.length();
7360// Please note: push and pop can be used to grow and shrink the array.
7361// - slow, backing storage is a HashTable with numbers as keys.
7362class JSArray: public JSObject {
7363 public:
7364 // [length]: The length property.
7365 DECL_ACCESSORS(length, Object)
7366
Leon Clarke4515c472010-02-03 11:58:03 +00007367 // Overload the length setter to skip write barrier when the length
7368 // is set to a smi. This matches the set function on FixedArray.
7369 inline void set_length(Smi* length);
7370
John Reck59135872010-11-02 12:39:01 -07007371 MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
7372 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00007373
7374 // Initialize the array with the given capacity. The function may
7375 // fail due to out-of-memory situations, but only if the requested
7376 // capacity is non-zero.
John Reck59135872010-11-02 12:39:01 -07007377 MUST_USE_RESULT MaybeObject* Initialize(int capacity);
Steve Blocka7e24c12009-10-30 11:49:00 +00007378
7379 // Set the content of the array to the content of storage.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007380 inline MaybeObject* SetContent(FixedArray* storage);
Steve Blocka7e24c12009-10-30 11:49:00 +00007381
7382 // Casting.
7383 static inline JSArray* cast(Object* obj);
7384
7385 // Uses handles. Ensures that the fixed array backing the JSArray has at
7386 // least the stated size.
7387 inline void EnsureSize(int minimum_size_of_backing_fixed_array);
7388
7389 // Dispatched behavior.
Ben Murdochb0fe1622011-05-05 13:52:32 +01007390#ifdef OBJECT_PRINT
7391 inline void JSArrayPrint() {
7392 JSArrayPrint(stdout);
7393 }
7394 void JSArrayPrint(FILE* out);
7395#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007396#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007397 void JSArrayVerify();
7398#endif
7399
7400 // Number of element slots to pre-allocate for an empty array.
7401 static const int kPreallocatedArrayElements = 4;
7402
7403 // Layout description.
7404 static const int kLengthOffset = JSObject::kHeaderSize;
7405 static const int kSize = kLengthOffset + kPointerSize;
7406
7407 private:
7408 // Expand the fixed array backing of a fast-case JSArray to at least
7409 // the requested size.
7410 void Expand(int minimum_size_of_backing_fixed_array);
7411
7412 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
7413};
7414
7415
Steve Block6ded16b2010-05-10 14:33:55 +01007416// JSRegExpResult is just a JSArray with a specific initial map.
7417// This initial map adds in-object properties for "index" and "input"
7418// properties, as assigned by RegExp.prototype.exec, which allows
7419// faster creation of RegExp exec results.
7420// This class just holds constants used when creating the result.
7421// After creation the result must be treated as a JSArray in all regards.
7422class JSRegExpResult: public JSArray {
7423 public:
7424 // Offsets of object fields.
7425 static const int kIndexOffset = JSArray::kSize;
7426 static const int kInputOffset = kIndexOffset + kPointerSize;
7427 static const int kSize = kInputOffset + kPointerSize;
7428 // Indices of in-object properties.
7429 static const int kIndexIndex = 0;
7430 static const int kInputIndex = 1;
7431 private:
7432 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
7433};
7434
7435
Steve Blocka7e24c12009-10-30 11:49:00 +00007436// An accessor must have a getter, but can have no setter.
7437//
7438// When setting a property, V8 searches accessors in prototypes.
7439// If an accessor was found and it does not have a setter,
7440// the request is ignored.
7441//
7442// If the accessor in the prototype has the READ_ONLY property attribute, then
7443// a new value is added to the local object when the property is set.
7444// This shadows the accessor in the prototype.
7445class AccessorInfo: public Struct {
7446 public:
7447 DECL_ACCESSORS(getter, Object)
7448 DECL_ACCESSORS(setter, Object)
7449 DECL_ACCESSORS(data, Object)
7450 DECL_ACCESSORS(name, Object)
7451 DECL_ACCESSORS(flag, Smi)
7452
7453 inline bool all_can_read();
7454 inline void set_all_can_read(bool value);
7455
7456 inline bool all_can_write();
7457 inline void set_all_can_write(bool value);
7458
7459 inline bool prohibits_overwriting();
7460 inline void set_prohibits_overwriting(bool value);
7461
7462 inline PropertyAttributes property_attributes();
7463 inline void set_property_attributes(PropertyAttributes attributes);
7464
7465 static inline AccessorInfo* cast(Object* obj);
7466
Ben Murdochb0fe1622011-05-05 13:52:32 +01007467#ifdef OBJECT_PRINT
7468 inline void AccessorInfoPrint() {
7469 AccessorInfoPrint(stdout);
7470 }
7471 void AccessorInfoPrint(FILE* out);
7472#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007473#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007474 void AccessorInfoVerify();
7475#endif
7476
7477 static const int kGetterOffset = HeapObject::kHeaderSize;
7478 static const int kSetterOffset = kGetterOffset + kPointerSize;
7479 static const int kDataOffset = kSetterOffset + kPointerSize;
7480 static const int kNameOffset = kDataOffset + kPointerSize;
7481 static const int kFlagOffset = kNameOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007482 static const int kSize = kFlagOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007483
7484 private:
7485 // Bit positions in flag.
7486 static const int kAllCanReadBit = 0;
7487 static const int kAllCanWriteBit = 1;
7488 static const int kProhibitsOverwritingBit = 2;
7489 class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
7490
7491 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
7492};
7493
7494
7495class AccessCheckInfo: public Struct {
7496 public:
7497 DECL_ACCESSORS(named_callback, Object)
7498 DECL_ACCESSORS(indexed_callback, Object)
7499 DECL_ACCESSORS(data, Object)
7500
7501 static inline AccessCheckInfo* cast(Object* obj);
7502
Ben Murdochb0fe1622011-05-05 13:52:32 +01007503#ifdef OBJECT_PRINT
7504 inline void AccessCheckInfoPrint() {
7505 AccessCheckInfoPrint(stdout);
7506 }
7507 void AccessCheckInfoPrint(FILE* out);
7508#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007509#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007510 void AccessCheckInfoVerify();
7511#endif
7512
7513 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
7514 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
7515 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
7516 static const int kSize = kDataOffset + kPointerSize;
7517
7518 private:
7519 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
7520};
7521
7522
7523class InterceptorInfo: public Struct {
7524 public:
7525 DECL_ACCESSORS(getter, Object)
7526 DECL_ACCESSORS(setter, Object)
7527 DECL_ACCESSORS(query, Object)
7528 DECL_ACCESSORS(deleter, Object)
7529 DECL_ACCESSORS(enumerator, Object)
7530 DECL_ACCESSORS(data, Object)
7531
7532 static inline InterceptorInfo* cast(Object* obj);
7533
Ben Murdochb0fe1622011-05-05 13:52:32 +01007534#ifdef OBJECT_PRINT
7535 inline void InterceptorInfoPrint() {
7536 InterceptorInfoPrint(stdout);
7537 }
7538 void InterceptorInfoPrint(FILE* out);
7539#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007540#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007541 void InterceptorInfoVerify();
7542#endif
7543
7544 static const int kGetterOffset = HeapObject::kHeaderSize;
7545 static const int kSetterOffset = kGetterOffset + kPointerSize;
7546 static const int kQueryOffset = kSetterOffset + kPointerSize;
7547 static const int kDeleterOffset = kQueryOffset + kPointerSize;
7548 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
7549 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
7550 static const int kSize = kDataOffset + kPointerSize;
7551
7552 private:
7553 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
7554};
7555
7556
7557class CallHandlerInfo: public Struct {
7558 public:
7559 DECL_ACCESSORS(callback, Object)
7560 DECL_ACCESSORS(data, Object)
7561
7562 static inline CallHandlerInfo* cast(Object* obj);
7563
Ben Murdochb0fe1622011-05-05 13:52:32 +01007564#ifdef OBJECT_PRINT
7565 inline void CallHandlerInfoPrint() {
7566 CallHandlerInfoPrint(stdout);
7567 }
7568 void CallHandlerInfoPrint(FILE* out);
7569#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007570#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007571 void CallHandlerInfoVerify();
7572#endif
7573
7574 static const int kCallbackOffset = HeapObject::kHeaderSize;
7575 static const int kDataOffset = kCallbackOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007576 static const int kSize = kDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007577
7578 private:
7579 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
7580};
7581
7582
7583class TemplateInfo: public Struct {
7584 public:
7585 DECL_ACCESSORS(tag, Object)
7586 DECL_ACCESSORS(property_list, Object)
7587
7588#ifdef DEBUG
7589 void TemplateInfoVerify();
7590#endif
7591
7592 static const int kTagOffset = HeapObject::kHeaderSize;
7593 static const int kPropertyListOffset = kTagOffset + kPointerSize;
7594 static const int kHeaderSize = kPropertyListOffset + kPointerSize;
7595 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +00007596 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
7597};
7598
7599
7600class FunctionTemplateInfo: public TemplateInfo {
7601 public:
7602 DECL_ACCESSORS(serial_number, Object)
7603 DECL_ACCESSORS(call_code, Object)
7604 DECL_ACCESSORS(property_accessors, Object)
7605 DECL_ACCESSORS(prototype_template, Object)
7606 DECL_ACCESSORS(parent_template, Object)
7607 DECL_ACCESSORS(named_property_handler, Object)
7608 DECL_ACCESSORS(indexed_property_handler, Object)
7609 DECL_ACCESSORS(instance_template, Object)
7610 DECL_ACCESSORS(class_name, Object)
7611 DECL_ACCESSORS(signature, Object)
7612 DECL_ACCESSORS(instance_call_handler, Object)
7613 DECL_ACCESSORS(access_check_info, Object)
7614 DECL_ACCESSORS(flag, Smi)
7615
7616 // Following properties use flag bits.
7617 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
7618 DECL_BOOLEAN_ACCESSORS(undetectable)
7619 // If the bit is set, object instances created by this function
7620 // requires access check.
7621 DECL_BOOLEAN_ACCESSORS(needs_access_check)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007622 DECL_BOOLEAN_ACCESSORS(read_only_prototype)
Steve Blocka7e24c12009-10-30 11:49:00 +00007623
7624 static inline FunctionTemplateInfo* cast(Object* obj);
7625
Ben Murdochb0fe1622011-05-05 13:52:32 +01007626#ifdef OBJECT_PRINT
7627 inline void FunctionTemplateInfoPrint() {
7628 FunctionTemplateInfoPrint(stdout);
7629 }
7630 void FunctionTemplateInfoPrint(FILE* out);
7631#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007632#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007633 void FunctionTemplateInfoVerify();
7634#endif
7635
7636 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
7637 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
7638 static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
7639 static const int kPrototypeTemplateOffset =
7640 kPropertyAccessorsOffset + kPointerSize;
7641 static const int kParentTemplateOffset =
7642 kPrototypeTemplateOffset + kPointerSize;
7643 static const int kNamedPropertyHandlerOffset =
7644 kParentTemplateOffset + kPointerSize;
7645 static const int kIndexedPropertyHandlerOffset =
7646 kNamedPropertyHandlerOffset + kPointerSize;
7647 static const int kInstanceTemplateOffset =
7648 kIndexedPropertyHandlerOffset + kPointerSize;
7649 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
7650 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
7651 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
7652 static const int kAccessCheckInfoOffset =
7653 kInstanceCallHandlerOffset + kPointerSize;
7654 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007655 static const int kSize = kFlagOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007656
7657 private:
7658 // Bit position in the flag, from least significant bit position.
7659 static const int kHiddenPrototypeBit = 0;
7660 static const int kUndetectableBit = 1;
7661 static const int kNeedsAccessCheckBit = 2;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00007662 static const int kReadOnlyPrototypeBit = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +00007663
7664 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
7665};
7666
7667
7668class ObjectTemplateInfo: public TemplateInfo {
7669 public:
7670 DECL_ACCESSORS(constructor, Object)
7671 DECL_ACCESSORS(internal_field_count, Object)
7672
7673 static inline ObjectTemplateInfo* cast(Object* obj);
7674
Ben Murdochb0fe1622011-05-05 13:52:32 +01007675#ifdef OBJECT_PRINT
7676 inline void ObjectTemplateInfoPrint() {
7677 ObjectTemplateInfoPrint(stdout);
7678 }
7679 void ObjectTemplateInfoPrint(FILE* out);
7680#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007681#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007682 void ObjectTemplateInfoVerify();
7683#endif
7684
7685 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
7686 static const int kInternalFieldCountOffset =
7687 kConstructorOffset + kPointerSize;
7688 static const int kSize = kInternalFieldCountOffset + kPointerSize;
7689};
7690
7691
7692class SignatureInfo: public Struct {
7693 public:
7694 DECL_ACCESSORS(receiver, Object)
7695 DECL_ACCESSORS(args, Object)
7696
7697 static inline SignatureInfo* cast(Object* obj);
7698
Ben Murdochb0fe1622011-05-05 13:52:32 +01007699#ifdef OBJECT_PRINT
7700 inline void SignatureInfoPrint() {
7701 SignatureInfoPrint(stdout);
7702 }
7703 void SignatureInfoPrint(FILE* out);
7704#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007705#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007706 void SignatureInfoVerify();
7707#endif
7708
7709 static const int kReceiverOffset = Struct::kHeaderSize;
7710 static const int kArgsOffset = kReceiverOffset + kPointerSize;
7711 static const int kSize = kArgsOffset + kPointerSize;
7712
7713 private:
7714 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
7715};
7716
7717
7718class TypeSwitchInfo: public Struct {
7719 public:
7720 DECL_ACCESSORS(types, Object)
7721
7722 static inline TypeSwitchInfo* cast(Object* obj);
7723
Ben Murdochb0fe1622011-05-05 13:52:32 +01007724#ifdef OBJECT_PRINT
7725 inline void TypeSwitchInfoPrint() {
7726 TypeSwitchInfoPrint(stdout);
7727 }
7728 void TypeSwitchInfoPrint(FILE* out);
7729#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007730#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007731 void TypeSwitchInfoVerify();
7732#endif
7733
7734 static const int kTypesOffset = Struct::kHeaderSize;
7735 static const int kSize = kTypesOffset + kPointerSize;
7736};
7737
7738
7739#ifdef ENABLE_DEBUGGER_SUPPORT
7740// The DebugInfo class holds additional information for a function being
7741// debugged.
7742class DebugInfo: public Struct {
7743 public:
7744 // The shared function info for the source being debugged.
7745 DECL_ACCESSORS(shared, SharedFunctionInfo)
7746 // Code object for the original code.
7747 DECL_ACCESSORS(original_code, Code)
7748 // Code object for the patched code. This code object is the code object
7749 // currently active for the function.
7750 DECL_ACCESSORS(code, Code)
7751 // Fixed array holding status information for each active break point.
7752 DECL_ACCESSORS(break_points, FixedArray)
7753
7754 // Check if there is a break point at a code position.
7755 bool HasBreakPoint(int code_position);
7756 // Get the break point info object for a code position.
7757 Object* GetBreakPointInfo(int code_position);
7758 // Clear a break point.
7759 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
7760 int code_position,
7761 Handle<Object> break_point_object);
7762 // Set a break point.
7763 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
7764 int source_position, int statement_position,
7765 Handle<Object> break_point_object);
7766 // Get the break point objects for a code position.
7767 Object* GetBreakPointObjects(int code_position);
7768 // Find the break point info holding this break point object.
7769 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
7770 Handle<Object> break_point_object);
7771 // Get the number of break points for this function.
7772 int GetBreakPointCount();
7773
7774 static inline DebugInfo* cast(Object* obj);
7775
Ben Murdochb0fe1622011-05-05 13:52:32 +01007776#ifdef OBJECT_PRINT
7777 inline void DebugInfoPrint() {
7778 DebugInfoPrint(stdout);
7779 }
7780 void DebugInfoPrint(FILE* out);
7781#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007782#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007783 void DebugInfoVerify();
7784#endif
7785
7786 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
7787 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
7788 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
7789 static const int kActiveBreakPointsCountIndex =
7790 kPatchedCodeIndex + kPointerSize;
7791 static const int kBreakPointsStateIndex =
7792 kActiveBreakPointsCountIndex + kPointerSize;
7793 static const int kSize = kBreakPointsStateIndex + kPointerSize;
7794
7795 private:
7796 static const int kNoBreakPointInfo = -1;
7797
7798 // Lookup the index in the break_points array for a code position.
7799 int GetBreakPointInfoIndex(int code_position);
7800
7801 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
7802};
7803
7804
7805// The BreakPointInfo class holds information for break points set in a
7806// function. The DebugInfo object holds a BreakPointInfo object for each code
7807// position with one or more break points.
7808class BreakPointInfo: public Struct {
7809 public:
7810 // The position in the code for the break point.
7811 DECL_ACCESSORS(code_position, Smi)
7812 // The position in the source for the break position.
7813 DECL_ACCESSORS(source_position, Smi)
7814 // The position in the source for the last statement before this break
7815 // position.
7816 DECL_ACCESSORS(statement_position, Smi)
7817 // List of related JavaScript break points.
7818 DECL_ACCESSORS(break_point_objects, Object)
7819
7820 // Removes a break point.
7821 static void ClearBreakPoint(Handle<BreakPointInfo> info,
7822 Handle<Object> break_point_object);
7823 // Set a break point.
7824 static void SetBreakPoint(Handle<BreakPointInfo> info,
7825 Handle<Object> break_point_object);
7826 // Check if break point info has this break point object.
7827 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
7828 Handle<Object> break_point_object);
7829 // Get the number of break points for this code position.
7830 int GetBreakPointCount();
7831
7832 static inline BreakPointInfo* cast(Object* obj);
7833
Ben Murdochb0fe1622011-05-05 13:52:32 +01007834#ifdef OBJECT_PRINT
7835 inline void BreakPointInfoPrint() {
7836 BreakPointInfoPrint(stdout);
7837 }
7838 void BreakPointInfoPrint(FILE* out);
7839#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00007840#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00007841 void BreakPointInfoVerify();
7842#endif
7843
7844 static const int kCodePositionIndex = Struct::kHeaderSize;
7845 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
7846 static const int kStatementPositionIndex =
7847 kSourcePositionIndex + kPointerSize;
7848 static const int kBreakPointObjectsIndex =
7849 kStatementPositionIndex + kPointerSize;
7850 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
7851
7852 private:
7853 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
7854};
7855#endif // ENABLE_DEBUGGER_SUPPORT
7856
7857
7858#undef DECL_BOOLEAN_ACCESSORS
7859#undef DECL_ACCESSORS
7860
7861
7862// Abstract base class for visiting, and optionally modifying, the
7863// pointers contained in Objects. Used in GC and serialization/deserialization.
7864class ObjectVisitor BASE_EMBEDDED {
7865 public:
7866 virtual ~ObjectVisitor() {}
7867
7868 // Visits a contiguous arrays of pointers in the half-open range
7869 // [start, end). Any or all of the values may be modified on return.
7870 virtual void VisitPointers(Object** start, Object** end) = 0;
7871
7872 // To allow lazy clearing of inline caches the visitor has
7873 // a rich interface for iterating over Code objects..
7874
7875 // Visits a code target in the instruction stream.
7876 virtual void VisitCodeTarget(RelocInfo* rinfo);
7877
Steve Block791712a2010-08-27 10:21:07 +01007878 // Visits a code entry in a JS function.
7879 virtual void VisitCodeEntry(Address entry_address);
7880
Ben Murdochb0fe1622011-05-05 13:52:32 +01007881 // Visits a global property cell reference in the instruction stream.
7882 virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
7883
Steve Blocka7e24c12009-10-30 11:49:00 +00007884 // Visits a runtime entry in the instruction stream.
7885 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
7886
Steve Blockd0582a62009-12-15 09:54:21 +00007887 // Visits the resource of an ASCII or two-byte string.
7888 virtual void VisitExternalAsciiString(
7889 v8::String::ExternalAsciiStringResource** resource) {}
7890 virtual void VisitExternalTwoByteString(
7891 v8::String::ExternalStringResource** resource) {}
7892
Steve Blocka7e24c12009-10-30 11:49:00 +00007893 // Visits a debug call target in the instruction stream.
7894 virtual void VisitDebugTarget(RelocInfo* rinfo);
7895
7896 // Handy shorthand for visiting a single pointer.
7897 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
7898
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007899 // Visit pointer embedded into a code object.
7900 virtual void VisitEmbeddedPointer(RelocInfo* rinfo);
7901
Steve Blocka7e24c12009-10-30 11:49:00 +00007902 // Visits a contiguous arrays of external references (references to the C++
7903 // heap) in the half-open range [start, end). Any or all of the values
7904 // may be modified on return.
7905 virtual void VisitExternalReferences(Address* start, Address* end) {}
7906
Ben Murdoch592a9fc2012-03-05 11:04:45 +00007907 virtual void VisitExternalReference(RelocInfo* rinfo);
7908
Steve Blocka7e24c12009-10-30 11:49:00 +00007909 inline void VisitExternalReference(Address* p) {
7910 VisitExternalReferences(p, p + 1);
7911 }
7912
Steve Block44f0eee2011-05-26 01:26:41 +01007913 // Visits a handle that has an embedder-assigned class ID.
7914 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
7915
Steve Blocka7e24c12009-10-30 11:49:00 +00007916#ifdef DEBUG
7917 // Intended for serialization/deserialization checking: insert, or
7918 // check for the presence of, a tag at this position in the stream.
7919 virtual void Synchronize(const char* tag) {}
Steve Blockd0582a62009-12-15 09:54:21 +00007920#else
7921 inline void Synchronize(const char* tag) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00007922#endif
7923};
7924
7925
Iain Merrick75681382010-08-19 15:07:18 +01007926class StructBodyDescriptor : public
7927 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
7928 public:
7929 static inline int SizeOf(Map* map, HeapObject* object) {
7930 return map->instance_size();
7931 }
7932};
7933
7934
Steve Blocka7e24c12009-10-30 11:49:00 +00007935// BooleanBit is a helper class for setting and getting a bit in an
7936// integer or Smi.
7937class BooleanBit : public AllStatic {
7938 public:
7939 static inline bool get(Smi* smi, int bit_position) {
7940 return get(smi->value(), bit_position);
7941 }
7942
7943 static inline bool get(int value, int bit_position) {
7944 return (value & (1 << bit_position)) != 0;
7945 }
7946
7947 static inline Smi* set(Smi* smi, int bit_position, bool v) {
7948 return Smi::FromInt(set(smi->value(), bit_position, v));
7949 }
7950
7951 static inline int set(int value, int bit_position, bool v) {
7952 if (v) {
7953 value |= (1 << bit_position);
7954 } else {
7955 value &= ~(1 << bit_position);
7956 }
7957 return value;
7958 }
7959};
7960
7961} } // namespace v8::internal
7962
7963#endif // V8_OBJECTS_H_