| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1 | // Copyright 2006-2009 the V8 project authors. All rights reserved. | 
 | 2 | // Redistribution and use in source and binary forms, with or without | 
 | 3 | // modification, are permitted provided that the following conditions are | 
 | 4 | // met: | 
 | 5 | // | 
 | 6 | //     * Redistributions of source code must retain the above copyright | 
 | 7 | //       notice, this list of conditions and the following disclaimer. | 
 | 8 | //     * Redistributions in binary form must reproduce the above | 
 | 9 | //       copyright notice, this list of conditions and the following | 
 | 10 | //       disclaimer in the documentation and/or other materials provided | 
 | 11 | //       with the distribution. | 
 | 12 | //     * Neither the name of Google Inc. nor the names of its | 
 | 13 | //       contributors may be used to endorse or promote products derived | 
 | 14 | //       from this software without specific prior written permission. | 
 | 15 | // | 
 | 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 | 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 | 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
 | 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
 | 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
 | 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
 | 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
 | 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
 | 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 | 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
 | 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 | 27 |  | 
 | 28 | #ifndef V8_OBJECTS_H_ | 
 | 29 | #define V8_OBJECTS_H_ | 
 | 30 |  | 
 | 31 | #include "builtins.h" | 
 | 32 | #include "code-stubs.h" | 
 | 33 | #include "smart-pointer.h" | 
 | 34 | #include "unicode-inl.h" | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 35 | #if V8_TARGET_ARCH_ARM | 
 | 36 | #include "arm/constants-arm.h" | 
 | 37 | #endif | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 38 |  | 
 | 39 | // | 
 | 40 | // All object types in the V8 JavaScript are described in this file. | 
 | 41 | // | 
 | 42 | // Inheritance hierarchy: | 
 | 43 | //   - Object | 
 | 44 | //     - Smi          (immediate small integer) | 
 | 45 | //     - Failure      (immediate for marking failed operation) | 
 | 46 | //     - HeapObject   (superclass for everything allocated in the heap) | 
 | 47 | //       - JSObject | 
 | 48 | //         - JSArray | 
 | 49 | //         - JSRegExp | 
 | 50 | //         - JSFunction | 
 | 51 | //         - GlobalObject | 
 | 52 | //           - JSGlobalObject | 
 | 53 | //           - JSBuiltinsObject | 
 | 54 | //         - JSGlobalProxy | 
 | 55 | //         - JSValue | 
 | 56 | //       - Array | 
 | 57 | //         - ByteArray | 
 | 58 | //         - PixelArray | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 59 | //         - ExternalArray | 
 | 60 | //           - ExternalByteArray | 
 | 61 | //           - ExternalUnsignedByteArray | 
 | 62 | //           - ExternalShortArray | 
 | 63 | //           - ExternalUnsignedShortArray | 
 | 64 | //           - ExternalIntArray | 
 | 65 | //           - ExternalUnsignedIntArray | 
 | 66 | //           - ExternalFloatArray | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 67 | //         - FixedArray | 
 | 68 | //           - DescriptorArray | 
 | 69 | //           - HashTable | 
 | 70 | //             - Dictionary | 
 | 71 | //             - SymbolTable | 
 | 72 | //             - CompilationCacheTable | 
 | 73 | //             - MapCache | 
 | 74 | //           - Context | 
 | 75 | //           - GlobalContext | 
 | 76 | //       - String | 
 | 77 | //         - SeqString | 
 | 78 | //           - SeqAsciiString | 
 | 79 | //           - SeqTwoByteString | 
 | 80 | //         - ConsString | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 81 | //         - ExternalString | 
 | 82 | //           - ExternalAsciiString | 
 | 83 | //           - ExternalTwoByteString | 
 | 84 | //       - HeapNumber | 
 | 85 | //       - Code | 
 | 86 | //       - Map | 
 | 87 | //       - Oddball | 
 | 88 | //       - Proxy | 
 | 89 | //       - SharedFunctionInfo | 
 | 90 | //       - Struct | 
 | 91 | //         - AccessorInfo | 
 | 92 | //         - AccessCheckInfo | 
 | 93 | //         - InterceptorInfo | 
 | 94 | //         - CallHandlerInfo | 
 | 95 | //         - TemplateInfo | 
 | 96 | //           - FunctionTemplateInfo | 
 | 97 | //           - ObjectTemplateInfo | 
 | 98 | //         - Script | 
 | 99 | //         - SignatureInfo | 
 | 100 | //         - TypeSwitchInfo | 
 | 101 | //         - DebugInfo | 
 | 102 | //         - BreakPointInfo | 
 | 103 | // | 
 | 104 | // Formats of Object*: | 
 | 105 | //  Smi:        [31 bit signed int] 0 | 
 | 106 | //  HeapObject: [32 bit direct pointer] (4 byte aligned) | 01 | 
 | 107 | //  Failure:    [30 bit signed int] 11 | 
 | 108 |  | 
 | 109 | // Ecma-262 3rd 8.6.1 | 
 | 110 | enum PropertyAttributes { | 
 | 111 |   NONE              = v8::None, | 
 | 112 |   READ_ONLY         = v8::ReadOnly, | 
 | 113 |   DONT_ENUM         = v8::DontEnum, | 
 | 114 |   DONT_DELETE       = v8::DontDelete, | 
 | 115 |   ABSENT            = 16  // Used in runtime to indicate a property is absent. | 
 | 116 |   // ABSENT can never be stored in or returned from a descriptor's attributes | 
 | 117 |   // bitfield.  It is only used as a return value meaning the attributes of | 
 | 118 |   // a non-existent property. | 
 | 119 | }; | 
 | 120 |  | 
 | 121 | namespace v8 { | 
 | 122 | namespace internal { | 
 | 123 |  | 
 | 124 |  | 
 | 125 | // PropertyDetails captures type and attributes for a property. | 
 | 126 | // They are used both in property dictionaries and instance descriptors. | 
 | 127 | class PropertyDetails BASE_EMBEDDED { | 
 | 128 |  public: | 
 | 129 |  | 
 | 130 |   PropertyDetails(PropertyAttributes attributes, | 
 | 131 |                   PropertyType type, | 
 | 132 |                   int index = 0) { | 
 | 133 |     ASSERT(TypeField::is_valid(type)); | 
 | 134 |     ASSERT(AttributesField::is_valid(attributes)); | 
 | 135 |     ASSERT(IndexField::is_valid(index)); | 
 | 136 |  | 
 | 137 |     value_ = TypeField::encode(type) | 
 | 138 |         | AttributesField::encode(attributes) | 
 | 139 |         | IndexField::encode(index); | 
 | 140 |  | 
 | 141 |     ASSERT(type == this->type()); | 
 | 142 |     ASSERT(attributes == this->attributes()); | 
 | 143 |     ASSERT(index == this->index()); | 
 | 144 |   } | 
 | 145 |  | 
 | 146 |   // Conversion for storing details as Object*. | 
 | 147 |   inline PropertyDetails(Smi* smi); | 
 | 148 |   inline Smi* AsSmi(); | 
 | 149 |  | 
 | 150 |   PropertyType type() { return TypeField::decode(value_); } | 
 | 151 |  | 
 | 152 |   bool IsTransition() { | 
 | 153 |     PropertyType t = type(); | 
 | 154 |     ASSERT(t != INTERCEPTOR); | 
 | 155 |     return t == MAP_TRANSITION || t == CONSTANT_TRANSITION; | 
 | 156 |   } | 
 | 157 |  | 
 | 158 |   bool IsProperty() { | 
 | 159 |     return type() < FIRST_PHANTOM_PROPERTY_TYPE; | 
 | 160 |   } | 
 | 161 |  | 
 | 162 |   PropertyAttributes attributes() { return AttributesField::decode(value_); } | 
 | 163 |  | 
 | 164 |   int index() { return IndexField::decode(value_); } | 
 | 165 |  | 
 | 166 |   inline PropertyDetails AsDeleted(); | 
 | 167 |  | 
 | 168 |   static bool IsValidIndex(int index) { return IndexField::is_valid(index); } | 
 | 169 |  | 
 | 170 |   bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; } | 
 | 171 |   bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; } | 
 | 172 |   bool IsDontEnum() { return (attributes() & DONT_ENUM) != 0; } | 
 | 173 |   bool IsDeleted() { return DeletedField::decode(value_) != 0;} | 
 | 174 |  | 
 | 175 |   // Bit fields in value_ (type, shift, size). Must be public so the | 
 | 176 |   // constants can be embedded in generated code. | 
 | 177 |   class TypeField:       public BitField<PropertyType,       0, 3> {}; | 
 | 178 |   class AttributesField: public BitField<PropertyAttributes, 3, 3> {}; | 
 | 179 |   class DeletedField:    public BitField<uint32_t,           6, 1> {}; | 
 | 180 |   class IndexField:      public BitField<uint32_t,           7, 31-7> {}; | 
 | 181 |  | 
 | 182 |   static const int kInitialIndex = 1; | 
 | 183 |  private: | 
 | 184 |   uint32_t value_; | 
 | 185 | }; | 
 | 186 |  | 
 | 187 |  | 
 | 188 | // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER. | 
 | 189 | enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER }; | 
 | 190 |  | 
 | 191 |  | 
 | 192 | // PropertyNormalizationMode is used to specify whether to keep | 
 | 193 | // inobject properties when normalizing properties of a JSObject. | 
 | 194 | enum PropertyNormalizationMode { | 
 | 195 |   CLEAR_INOBJECT_PROPERTIES, | 
 | 196 |   KEEP_INOBJECT_PROPERTIES | 
 | 197 | }; | 
 | 198 |  | 
 | 199 |  | 
 | 200 | // All Maps have a field instance_type containing a InstanceType. | 
 | 201 | // It describes the type of the instances. | 
 | 202 | // | 
 | 203 | // As an example, a JavaScript object is a heap object and its map | 
 | 204 | // instance_type is JS_OBJECT_TYPE. | 
 | 205 | // | 
 | 206 | // The names of the string instance types are intended to systematically | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 207 | // mirror their encoding in the instance_type field of the map.  The default | 
 | 208 | // encoding is considered TWO_BYTE.  It is not mentioned in the name.  ASCII | 
 | 209 | // encoding is mentioned explicitly in the name.  Likewise, the default | 
 | 210 | // representation is considered sequential.  It is not mentioned in the | 
 | 211 | // name.  The other representations (eg, CONS, EXTERNAL) are explicitly | 
 | 212 | // mentioned.  Finally, the string is either a SYMBOL_TYPE (if it is a | 
 | 213 | // symbol) or a STRING_TYPE (if it is not a symbol). | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 214 | // | 
 | 215 | // NOTE: The following things are some that depend on the string types having | 
 | 216 | // instance_types that are less than those of all other types: | 
 | 217 | // HeapObject::Size, HeapObject::IterateBody, the typeof operator, and | 
 | 218 | // Object::IsString. | 
 | 219 | // | 
 | 220 | // NOTE: Everything following JS_VALUE_TYPE is considered a | 
 | 221 | // JSObject for GC purposes. The first four entries here have typeof | 
 | 222 | // 'object', whereas JS_FUNCTION_TYPE has typeof 'function'. | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 223 | #define INSTANCE_TYPE_LIST_ALL(V)                                              \ | 
 | 224 |   V(SYMBOL_TYPE)                                                               \ | 
 | 225 |   V(ASCII_SYMBOL_TYPE)                                                         \ | 
 | 226 |   V(CONS_SYMBOL_TYPE)                                                          \ | 
 | 227 |   V(CONS_ASCII_SYMBOL_TYPE)                                                    \ | 
 | 228 |   V(EXTERNAL_SYMBOL_TYPE)                                                      \ | 
 | 229 |   V(EXTERNAL_ASCII_SYMBOL_TYPE)                                                \ | 
 | 230 |   V(STRING_TYPE)                                                               \ | 
 | 231 |   V(ASCII_STRING_TYPE)                                                         \ | 
 | 232 |   V(CONS_STRING_TYPE)                                                          \ | 
 | 233 |   V(CONS_ASCII_STRING_TYPE)                                                    \ | 
 | 234 |   V(EXTERNAL_STRING_TYPE)                                                      \ | 
 | 235 |   V(EXTERNAL_ASCII_STRING_TYPE)                                                \ | 
 | 236 |   V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE)                                        \ | 
 | 237 |                                                                                \ | 
 | 238 |   V(MAP_TYPE)                                                                  \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 239 |   V(CODE_TYPE)                                                                 \ | 
 | 240 |   V(JS_GLOBAL_PROPERTY_CELL_TYPE)                                              \ | 
 | 241 |   V(ODDBALL_TYPE)                                                              \ | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 242 |                                                                                \ | 
 | 243 |   V(HEAP_NUMBER_TYPE)                                                          \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 244 |   V(PROXY_TYPE)                                                                \ | 
 | 245 |   V(BYTE_ARRAY_TYPE)                                                           \ | 
 | 246 |   V(PIXEL_ARRAY_TYPE)                                                          \ | 
 | 247 |   /* Note: the order of these external array */                                \ | 
 | 248 |   /* types is relied upon in */                                                \ | 
 | 249 |   /* Object::IsExternalArray(). */                                             \ | 
 | 250 |   V(EXTERNAL_BYTE_ARRAY_TYPE)                                                  \ | 
 | 251 |   V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)                                         \ | 
 | 252 |   V(EXTERNAL_SHORT_ARRAY_TYPE)                                                 \ | 
 | 253 |   V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)                                        \ | 
 | 254 |   V(EXTERNAL_INT_ARRAY_TYPE)                                                   \ | 
 | 255 |   V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)                                          \ | 
 | 256 |   V(EXTERNAL_FLOAT_ARRAY_TYPE)                                                 \ | 
 | 257 |   V(FILLER_TYPE)                                                               \ | 
 | 258 |                                                                                \ | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 259 |   V(FIXED_ARRAY_TYPE)                                                          \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 260 |   V(ACCESSOR_INFO_TYPE)                                                        \ | 
 | 261 |   V(ACCESS_CHECK_INFO_TYPE)                                                    \ | 
 | 262 |   V(INTERCEPTOR_INFO_TYPE)                                                     \ | 
 | 263 |   V(SHARED_FUNCTION_INFO_TYPE)                                                 \ | 
 | 264 |   V(CALL_HANDLER_INFO_TYPE)                                                    \ | 
 | 265 |   V(FUNCTION_TEMPLATE_INFO_TYPE)                                               \ | 
 | 266 |   V(OBJECT_TEMPLATE_INFO_TYPE)                                                 \ | 
 | 267 |   V(SIGNATURE_INFO_TYPE)                                                       \ | 
 | 268 |   V(TYPE_SWITCH_INFO_TYPE)                                                     \ | 
 | 269 |   V(SCRIPT_TYPE)                                                               \ | 
 | 270 |                                                                                \ | 
 | 271 |   V(JS_VALUE_TYPE)                                                             \ | 
 | 272 |   V(JS_OBJECT_TYPE)                                                            \ | 
 | 273 |   V(JS_CONTEXT_EXTENSION_OBJECT_TYPE)                                          \ | 
 | 274 |   V(JS_GLOBAL_OBJECT_TYPE)                                                     \ | 
 | 275 |   V(JS_BUILTINS_OBJECT_TYPE)                                                   \ | 
 | 276 |   V(JS_GLOBAL_PROXY_TYPE)                                                      \ | 
 | 277 |   V(JS_ARRAY_TYPE)                                                             \ | 
 | 278 |   V(JS_REGEXP_TYPE)                                                            \ | 
 | 279 |                                                                                \ | 
 | 280 |   V(JS_FUNCTION_TYPE)                                                          \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 281 |  | 
 | 282 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 283 | #define INSTANCE_TYPE_LIST_DEBUGGER(V)                                         \ | 
 | 284 |   V(DEBUG_INFO_TYPE)                                                           \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 285 |   V(BREAK_POINT_INFO_TYPE) | 
 | 286 | #else | 
 | 287 | #define INSTANCE_TYPE_LIST_DEBUGGER(V) | 
 | 288 | #endif | 
 | 289 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 290 | #define INSTANCE_TYPE_LIST(V)                                                  \ | 
 | 291 |   INSTANCE_TYPE_LIST_ALL(V)                                                    \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 292 |   INSTANCE_TYPE_LIST_DEBUGGER(V) | 
 | 293 |  | 
 | 294 |  | 
 | 295 | // Since string types are not consecutive, this macro is used to | 
 | 296 | // iterate over them. | 
 | 297 | #define STRING_TYPE_LIST(V)                                                    \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 298 |   V(SYMBOL_TYPE,                                                               \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 299 |     SeqTwoByteString::kAlignedSize,                                            \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 300 |     symbol,                                                                    \ | 
 | 301 |     Symbol)                                                                    \ | 
 | 302 |   V(ASCII_SYMBOL_TYPE,                                                         \ | 
 | 303 |     SeqAsciiString::kAlignedSize,                                              \ | 
 | 304 |     ascii_symbol,                                                              \ | 
 | 305 |     AsciiSymbol)                                                               \ | 
 | 306 |   V(CONS_SYMBOL_TYPE,                                                          \ | 
 | 307 |     ConsString::kSize,                                                         \ | 
 | 308 |     cons_symbol,                                                               \ | 
 | 309 |     ConsSymbol)                                                                \ | 
 | 310 |   V(CONS_ASCII_SYMBOL_TYPE,                                                    \ | 
 | 311 |     ConsString::kSize,                                                         \ | 
 | 312 |     cons_ascii_symbol,                                                         \ | 
 | 313 |     ConsAsciiSymbol)                                                           \ | 
 | 314 |   V(EXTERNAL_SYMBOL_TYPE,                                                      \ | 
 | 315 |     ExternalTwoByteString::kSize,                                              \ | 
 | 316 |     external_symbol,                                                           \ | 
 | 317 |     ExternalSymbol)                                                            \ | 
 | 318 |   V(EXTERNAL_ASCII_SYMBOL_TYPE,                                                \ | 
 | 319 |     ExternalAsciiString::kSize,                                                \ | 
 | 320 |     external_ascii_symbol,                                                     \ | 
 | 321 |     ExternalAsciiSymbol)                                                       \ | 
 | 322 |   V(STRING_TYPE,                                                               \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 323 |     SeqTwoByteString::kAlignedSize,                                            \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 324 |     string,                                                                    \ | 
 | 325 |     String)                                                                    \ | 
 | 326 |   V(ASCII_STRING_TYPE,                                                         \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 327 |     SeqAsciiString::kAlignedSize,                                              \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 328 |     ascii_string,                                                              \ | 
 | 329 |     AsciiString)                                                               \ | 
 | 330 |   V(CONS_STRING_TYPE,                                                          \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 331 |     ConsString::kSize,                                                         \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 332 |     cons_string,                                                               \ | 
 | 333 |     ConsString)                                                                \ | 
 | 334 |   V(CONS_ASCII_STRING_TYPE,                                                    \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 335 |     ConsString::kSize,                                                         \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 336 |     cons_ascii_string,                                                         \ | 
 | 337 |     ConsAsciiString)                                                           \ | 
 | 338 |   V(EXTERNAL_STRING_TYPE,                                                      \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 339 |     ExternalTwoByteString::kSize,                                              \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 340 |     external_string,                                                           \ | 
 | 341 |     ExternalString)                                                            \ | 
 | 342 |   V(EXTERNAL_ASCII_STRING_TYPE,                                                \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 343 |     ExternalAsciiString::kSize,                                                \ | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 344 |     external_ascii_string,                                                     \ | 
 | 345 |     ExternalAsciiString)                                                       \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 346 |  | 
 | 347 | // A struct is a simple object a set of object-valued fields.  Including an | 
 | 348 | // object type in this causes the compiler to generate most of the boilerplate | 
 | 349 | // code for the class including allocation and garbage collection routines, | 
 | 350 | // casts and predicates.  All you need to define is the class, methods and | 
 | 351 | // object verification routines.  Easy, no? | 
 | 352 | // | 
 | 353 | // Note that for subtle reasons related to the ordering or numerical values of | 
 | 354 | // type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST | 
 | 355 | // manually. | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 356 | #define STRUCT_LIST_ALL(V)                                                     \ | 
 | 357 |   V(ACCESSOR_INFO, AccessorInfo, accessor_info)                                \ | 
 | 358 |   V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info)                     \ | 
 | 359 |   V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info)                       \ | 
 | 360 |   V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info)                     \ | 
 | 361 |   V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info)      \ | 
 | 362 |   V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info)            \ | 
 | 363 |   V(SIGNATURE_INFO, SignatureInfo, signature_info)                             \ | 
 | 364 |   V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info)                        \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 365 |   V(SCRIPT, Script, script) | 
 | 366 |  | 
 | 367 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 368 | #define STRUCT_LIST_DEBUGGER(V)                                                \ | 
 | 369 |   V(DEBUG_INFO, DebugInfo, debug_info)                                         \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 370 |   V(BREAK_POINT_INFO, BreakPointInfo, break_point_info) | 
 | 371 | #else | 
 | 372 | #define STRUCT_LIST_DEBUGGER(V) | 
 | 373 | #endif | 
 | 374 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 375 | #define STRUCT_LIST(V)                                                         \ | 
 | 376 |   STRUCT_LIST_ALL(V)                                                           \ | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 377 |   STRUCT_LIST_DEBUGGER(V) | 
 | 378 |  | 
 | 379 | // We use the full 8 bits of the instance_type field to encode heap object | 
 | 380 | // instance types.  The high-order bit (bit 7) is set if the object is not a | 
 | 381 | // string, and cleared if it is a string. | 
 | 382 | const uint32_t kIsNotStringMask = 0x80; | 
 | 383 | const uint32_t kStringTag = 0x0; | 
 | 384 | const uint32_t kNotStringTag = 0x80; | 
 | 385 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 386 | // Bit 6 indicates that the object is a symbol (if set) or not (if cleared). | 
 | 387 | // There are not enough types that the non-string types (with bit 7 set) can | 
 | 388 | // have bit 6 set too. | 
 | 389 | const uint32_t kIsSymbolMask = 0x40; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 390 | const uint32_t kNotSymbolTag = 0x0; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 391 | const uint32_t kSymbolTag = 0x40; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 392 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 393 | // If bit 7 is clear then bit 2 indicates whether the string consists of | 
 | 394 | // two-byte characters or one-byte characters. | 
 | 395 | const uint32_t kStringEncodingMask = 0x4; | 
 | 396 | const uint32_t kTwoByteStringTag = 0x0; | 
 | 397 | const uint32_t kAsciiStringTag = 0x4; | 
 | 398 |  | 
 | 399 | // If bit 7 is clear, the low-order 2 bits indicate the representation | 
 | 400 | // of the string. | 
 | 401 | const uint32_t kStringRepresentationMask = 0x03; | 
 | 402 | enum StringRepresentationTag { | 
 | 403 |   kSeqStringTag = 0x0, | 
 | 404 |   kConsStringTag = 0x1, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 405 |   kExternalStringTag = 0x3 | 
 | 406 | }; | 
 | 407 |  | 
 | 408 |  | 
 | 409 | // A ConsString with an empty string as the right side is a candidate | 
 | 410 | // for being shortcut by the garbage collector unless it is a | 
 | 411 | // symbol. It's not common to have non-flat symbols, so we do not | 
 | 412 | // shortcut them thereby avoiding turning symbols into strings. See | 
 | 413 | // heap.cc and mark-compact.cc. | 
 | 414 | const uint32_t kShortcutTypeMask = | 
 | 415 |     kIsNotStringMask | | 
 | 416 |     kIsSymbolMask | | 
 | 417 |     kStringRepresentationMask; | 
 | 418 | const uint32_t kShortcutTypeTag = kConsStringTag; | 
 | 419 |  | 
 | 420 |  | 
 | 421 | enum InstanceType { | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 422 |   // String types. | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 423 |   SYMBOL_TYPE = kSymbolTag | kSeqStringTag, | 
 | 424 |   ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag, | 
 | 425 |   CONS_SYMBOL_TYPE = kSymbolTag | kConsStringTag, | 
 | 426 |   CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag, | 
 | 427 |   EXTERNAL_SYMBOL_TYPE = kSymbolTag | kExternalStringTag, | 
 | 428 |   EXTERNAL_ASCII_SYMBOL_TYPE = | 
 | 429 |       kAsciiStringTag | kSymbolTag | kExternalStringTag, | 
 | 430 |   STRING_TYPE = kSeqStringTag, | 
 | 431 |   ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag, | 
 | 432 |   CONS_STRING_TYPE = kConsStringTag, | 
 | 433 |   CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag, | 
 | 434 |   EXTERNAL_STRING_TYPE = kExternalStringTag, | 
 | 435 |   EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag, | 
 | 436 |   PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 437 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 438 |   // Objects allocated in their own spaces (never in new space). | 
 | 439 |   MAP_TYPE = kNotStringTag,  // FIRST_NONSTRING_TYPE | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 440 |   CODE_TYPE, | 
 | 441 |   ODDBALL_TYPE, | 
 | 442 |   JS_GLOBAL_PROPERTY_CELL_TYPE, | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 443 |  | 
 | 444 |   // "Data", objects that cannot contain non-map-word pointers to heap | 
 | 445 |   // objects. | 
 | 446 |   HEAP_NUMBER_TYPE, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 447 |   PROXY_TYPE, | 
 | 448 |   BYTE_ARRAY_TYPE, | 
 | 449 |   PIXEL_ARRAY_TYPE, | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 450 |   EXTERNAL_BYTE_ARRAY_TYPE,  // FIRST_EXTERNAL_ARRAY_TYPE | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 451 |   EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, | 
 | 452 |   EXTERNAL_SHORT_ARRAY_TYPE, | 
 | 453 |   EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE, | 
 | 454 |   EXTERNAL_INT_ARRAY_TYPE, | 
 | 455 |   EXTERNAL_UNSIGNED_INT_ARRAY_TYPE, | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 456 |   EXTERNAL_FLOAT_ARRAY_TYPE,  // LAST_EXTERNAL_ARRAY_TYPE | 
 | 457 |   FILLER_TYPE,  // LAST_DATA_TYPE | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 458 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 459 |   // Structs. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 460 |   ACCESSOR_INFO_TYPE, | 
 | 461 |   ACCESS_CHECK_INFO_TYPE, | 
 | 462 |   INTERCEPTOR_INFO_TYPE, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 463 |   CALL_HANDLER_INFO_TYPE, | 
 | 464 |   FUNCTION_TEMPLATE_INFO_TYPE, | 
 | 465 |   OBJECT_TEMPLATE_INFO_TYPE, | 
 | 466 |   SIGNATURE_INFO_TYPE, | 
 | 467 |   TYPE_SWITCH_INFO_TYPE, | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 468 |   SCRIPT_TYPE, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 469 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
 | 470 |   DEBUG_INFO_TYPE, | 
 | 471 |   BREAK_POINT_INFO_TYPE, | 
 | 472 | #endif | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 473 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 474 |   FIXED_ARRAY_TYPE, | 
 | 475 |   SHARED_FUNCTION_INFO_TYPE, | 
 | 476 |  | 
 | 477 |   JS_VALUE_TYPE,  // FIRST_JS_OBJECT_TYPE | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 478 |   JS_OBJECT_TYPE, | 
 | 479 |   JS_CONTEXT_EXTENSION_OBJECT_TYPE, | 
 | 480 |   JS_GLOBAL_OBJECT_TYPE, | 
 | 481 |   JS_BUILTINS_OBJECT_TYPE, | 
 | 482 |   JS_GLOBAL_PROXY_TYPE, | 
 | 483 |   JS_ARRAY_TYPE, | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 484 |   JS_REGEXP_TYPE,  // LAST_JS_OBJECT_TYPE | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 485 |  | 
 | 486 |   JS_FUNCTION_TYPE, | 
 | 487 |  | 
 | 488 |   // Pseudo-types | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 489 |   FIRST_TYPE = 0x0, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 490 |   LAST_TYPE = JS_FUNCTION_TYPE, | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 491 |   INVALID_TYPE = FIRST_TYPE - 1, | 
 | 492 |   FIRST_NONSTRING_TYPE = MAP_TYPE, | 
 | 493 |   // Boundaries for testing for an external array. | 
 | 494 |   FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE, | 
 | 495 |   LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_FLOAT_ARRAY_TYPE, | 
 | 496 |   // Boundary for promotion to old data space/old pointer space. | 
 | 497 |   LAST_DATA_TYPE = FILLER_TYPE, | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 498 |   // Boundaries for testing the type is a JavaScript "object".  Note that | 
 | 499 |   // function objects are not counted as objects, even though they are | 
 | 500 |   // implemented as such; only values whose typeof is "object" are included. | 
 | 501 |   FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE, | 
 | 502 |   LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE | 
 | 503 | }; | 
 | 504 |  | 
 | 505 |  | 
 | 506 | enum CompareResult { | 
 | 507 |   LESS      = -1, | 
 | 508 |   EQUAL     =  0, | 
 | 509 |   GREATER   =  1, | 
 | 510 |  | 
 | 511 |   NOT_EQUAL = GREATER | 
 | 512 | }; | 
 | 513 |  | 
 | 514 |  | 
 | 515 | #define DECL_BOOLEAN_ACCESSORS(name)   \ | 
 | 516 |   inline bool name();                  \ | 
 | 517 |   inline void set_##name(bool value);  \ | 
 | 518 |  | 
 | 519 |  | 
 | 520 | #define DECL_ACCESSORS(name, type)                                      \ | 
 | 521 |   inline type* name();                                                  \ | 
 | 522 |   inline void set_##name(type* value,                                   \ | 
 | 523 |                          WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \ | 
 | 524 |  | 
 | 525 |  | 
 | 526 | class StringStream; | 
 | 527 | class ObjectVisitor; | 
 | 528 |  | 
 | 529 | struct ValueInfo : public Malloced { | 
 | 530 |   ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { } | 
 | 531 |   InstanceType type; | 
 | 532 |   Object* ptr; | 
 | 533 |   const char* str; | 
 | 534 |   double number; | 
 | 535 | }; | 
 | 536 |  | 
 | 537 |  | 
 | 538 | // A template-ized version of the IsXXX functions. | 
 | 539 | template <class C> static inline bool Is(Object* obj); | 
 | 540 |  | 
 | 541 |  | 
 | 542 | // Object is the abstract superclass for all classes in the | 
 | 543 | // object hierarchy. | 
 | 544 | // Object does not use any virtual functions to avoid the | 
 | 545 | // allocation of the C++ vtable. | 
 | 546 | // Since Smi and Failure are subclasses of Object no | 
 | 547 | // data members can be present in Object. | 
 | 548 | class Object BASE_EMBEDDED { | 
 | 549 |  public: | 
 | 550 |   // Type testing. | 
 | 551 |   inline bool IsSmi(); | 
 | 552 |   inline bool IsHeapObject(); | 
 | 553 |   inline bool IsHeapNumber(); | 
 | 554 |   inline bool IsString(); | 
 | 555 |   inline bool IsSymbol(); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 556 |   // See objects-inl.h for more details | 
 | 557 |   inline bool IsSeqString(); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 558 |   inline bool IsExternalString(); | 
 | 559 |   inline bool IsExternalTwoByteString(); | 
 | 560 |   inline bool IsExternalAsciiString(); | 
 | 561 |   inline bool IsSeqTwoByteString(); | 
 | 562 |   inline bool IsSeqAsciiString(); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 563 |   inline bool IsConsString(); | 
 | 564 |  | 
 | 565 |   inline bool IsNumber(); | 
 | 566 |   inline bool IsByteArray(); | 
 | 567 |   inline bool IsPixelArray(); | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 568 |   inline bool IsExternalArray(); | 
 | 569 |   inline bool IsExternalByteArray(); | 
 | 570 |   inline bool IsExternalUnsignedByteArray(); | 
 | 571 |   inline bool IsExternalShortArray(); | 
 | 572 |   inline bool IsExternalUnsignedShortArray(); | 
 | 573 |   inline bool IsExternalIntArray(); | 
 | 574 |   inline bool IsExternalUnsignedIntArray(); | 
 | 575 |   inline bool IsExternalFloatArray(); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 576 |   inline bool IsFailure(); | 
 | 577 |   inline bool IsRetryAfterGC(); | 
 | 578 |   inline bool IsOutOfMemoryFailure(); | 
 | 579 |   inline bool IsException(); | 
 | 580 |   inline bool IsJSObject(); | 
 | 581 |   inline bool IsJSContextExtensionObject(); | 
 | 582 |   inline bool IsMap(); | 
 | 583 |   inline bool IsFixedArray(); | 
 | 584 |   inline bool IsDescriptorArray(); | 
 | 585 |   inline bool IsContext(); | 
 | 586 |   inline bool IsCatchContext(); | 
 | 587 |   inline bool IsGlobalContext(); | 
 | 588 |   inline bool IsJSFunction(); | 
 | 589 |   inline bool IsCode(); | 
 | 590 |   inline bool IsOddball(); | 
 | 591 |   inline bool IsSharedFunctionInfo(); | 
 | 592 |   inline bool IsJSValue(); | 
 | 593 |   inline bool IsStringWrapper(); | 
 | 594 |   inline bool IsProxy(); | 
 | 595 |   inline bool IsBoolean(); | 
 | 596 |   inline bool IsJSArray(); | 
 | 597 |   inline bool IsJSRegExp(); | 
 | 598 |   inline bool IsHashTable(); | 
 | 599 |   inline bool IsDictionary(); | 
 | 600 |   inline bool IsSymbolTable(); | 
 | 601 |   inline bool IsCompilationCacheTable(); | 
 | 602 |   inline bool IsMapCache(); | 
 | 603 |   inline bool IsPrimitive(); | 
 | 604 |   inline bool IsGlobalObject(); | 
 | 605 |   inline bool IsJSGlobalObject(); | 
 | 606 |   inline bool IsJSBuiltinsObject(); | 
 | 607 |   inline bool IsJSGlobalProxy(); | 
 | 608 |   inline bool IsUndetectableObject(); | 
 | 609 |   inline bool IsAccessCheckNeeded(); | 
 | 610 |   inline bool IsJSGlobalPropertyCell(); | 
 | 611 |  | 
 | 612 |   // Returns true if this object is an instance of the specified | 
 | 613 |   // function template. | 
 | 614 |   inline bool IsInstanceOf(FunctionTemplateInfo* type); | 
 | 615 |  | 
 | 616 |   inline bool IsStruct(); | 
 | 617 | #define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name(); | 
 | 618 |   STRUCT_LIST(DECLARE_STRUCT_PREDICATE) | 
 | 619 | #undef DECLARE_STRUCT_PREDICATE | 
 | 620 |  | 
 | 621 |   // Oddball testing. | 
 | 622 |   INLINE(bool IsUndefined()); | 
 | 623 |   INLINE(bool IsTheHole()); | 
 | 624 |   INLINE(bool IsNull()); | 
 | 625 |   INLINE(bool IsTrue()); | 
 | 626 |   INLINE(bool IsFalse()); | 
 | 627 |  | 
 | 628 |   // Extract the number. | 
 | 629 |   inline double Number(); | 
 | 630 |  | 
 | 631 |   inline bool HasSpecificClassOf(String* name); | 
 | 632 |  | 
 | 633 |   Object* ToObject();             // ECMA-262 9.9. | 
 | 634 |   Object* ToBoolean();            // ECMA-262 9.2. | 
 | 635 |  | 
 | 636 |   // Convert to a JSObject if needed. | 
 | 637 |   // global_context is used when creating wrapper object. | 
 | 638 |   Object* ToObject(Context* global_context); | 
 | 639 |  | 
 | 640 |   // Converts this to a Smi if possible. | 
 | 641 |   // Failure is returned otherwise. | 
 | 642 |   inline Object* ToSmi(); | 
 | 643 |  | 
 | 644 |   void Lookup(String* name, LookupResult* result); | 
 | 645 |  | 
 | 646 |   // Property access. | 
 | 647 |   inline Object* GetProperty(String* key); | 
 | 648 |   inline Object* GetProperty(String* key, PropertyAttributes* attributes); | 
 | 649 |   Object* GetPropertyWithReceiver(Object* receiver, | 
 | 650 |                                   String* key, | 
 | 651 |                                   PropertyAttributes* attributes); | 
 | 652 |   Object* GetProperty(Object* receiver, | 
 | 653 |                       LookupResult* result, | 
 | 654 |                       String* key, | 
 | 655 |                       PropertyAttributes* attributes); | 
 | 656 |   Object* GetPropertyWithCallback(Object* receiver, | 
 | 657 |                                   Object* structure, | 
 | 658 |                                   String* name, | 
 | 659 |                                   Object* holder); | 
 | 660 |   Object* GetPropertyWithDefinedGetter(Object* receiver, | 
 | 661 |                                        JSFunction* getter); | 
 | 662 |  | 
 | 663 |   inline Object* GetElement(uint32_t index); | 
 | 664 |   Object* GetElementWithReceiver(Object* receiver, uint32_t index); | 
 | 665 |  | 
 | 666 |   // Return the object's prototype (might be Heap::null_value()). | 
 | 667 |   Object* GetPrototype(); | 
 | 668 |  | 
 | 669 |   // Returns true if this is a JSValue containing a string and the index is | 
 | 670 |   // < the length of the string.  Used to implement [] on strings. | 
 | 671 |   inline bool IsStringObjectWithCharacterAt(uint32_t index); | 
 | 672 |  | 
 | 673 | #ifdef DEBUG | 
 | 674 |   // Prints this object with details. | 
 | 675 |   void Print(); | 
 | 676 |   void PrintLn(); | 
 | 677 |   // Verifies the object. | 
 | 678 |   void Verify(); | 
 | 679 |  | 
 | 680 |   // Verify a pointer is a valid object pointer. | 
 | 681 |   static void VerifyPointer(Object* p); | 
 | 682 | #endif | 
 | 683 |  | 
 | 684 |   // Prints this object without details. | 
 | 685 |   void ShortPrint(); | 
 | 686 |  | 
 | 687 |   // Prints this object without details to a message accumulator. | 
 | 688 |   void ShortPrint(StringStream* accumulator); | 
 | 689 |  | 
 | 690 |   // Casting: This cast is only needed to satisfy macros in objects-inl.h. | 
 | 691 |   static Object* cast(Object* value) { return value; } | 
 | 692 |  | 
 | 693 |   // Layout description. | 
 | 694 |   static const int kHeaderSize = 0;  // Object does not take up any space. | 
 | 695 |  | 
 | 696 |  private: | 
 | 697 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Object); | 
 | 698 | }; | 
 | 699 |  | 
 | 700 |  | 
 | 701 | // Smi represents integer Numbers that can be stored in 31 bits. | 
 | 702 | // Smis are immediate which means they are NOT allocated in the heap. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 703 | // The this pointer has the following format: [31 bit signed int] 0 | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 704 | // For long smis it has the following format: | 
 | 705 | //     [32 bit signed int] [31 bits zero padding] 0 | 
 | 706 | // Smi stands for small integer. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 707 | class Smi: public Object { | 
 | 708 |  public: | 
 | 709 |   // Returns the integer value. | 
 | 710 |   inline int value(); | 
 | 711 |  | 
 | 712 |   // Convert a value to a Smi object. | 
 | 713 |   static inline Smi* FromInt(int value); | 
 | 714 |  | 
 | 715 |   static inline Smi* FromIntptr(intptr_t value); | 
 | 716 |  | 
 | 717 |   // Returns whether value can be represented in a Smi. | 
 | 718 |   static inline bool IsValid(intptr_t value); | 
 | 719 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 720 |   // Casting. | 
 | 721 |   static inline Smi* cast(Object* object); | 
 | 722 |  | 
 | 723 |   // Dispatched behavior. | 
 | 724 |   void SmiPrint(); | 
 | 725 |   void SmiPrint(StringStream* accumulator); | 
 | 726 | #ifdef DEBUG | 
 | 727 |   void SmiVerify(); | 
 | 728 | #endif | 
 | 729 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 730 |   static const int kMinValue = (-1 << (kSmiValueSize - 1)); | 
 | 731 |   static const int kMaxValue = -(kMinValue + 1); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 732 |  | 
 | 733 |  private: | 
 | 734 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Smi); | 
 | 735 | }; | 
 | 736 |  | 
 | 737 |  | 
 | 738 | // Failure is used for reporting out of memory situations and | 
 | 739 | // propagating exceptions through the runtime system.  Failure objects | 
 | 740 | // are transient and cannot occur as part of the object graph. | 
 | 741 | // | 
 | 742 | // Failures are a single word, encoded as follows: | 
 | 743 | // +-------------------------+---+--+--+ | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 744 | // |...rrrrrrrrrrrrrrrrrrrrrr|sss|tt|11| | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 745 | // +-------------------------+---+--+--+ | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 746 | //                          7 6 4 32 10 | 
 | 747 | // | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 748 | // | 
 | 749 | // The low two bits, 0-1, are the failure tag, 11.  The next two bits, | 
 | 750 | // 2-3, are a failure type tag 'tt' with possible values: | 
 | 751 | //   00 RETRY_AFTER_GC | 
 | 752 | //   01 EXCEPTION | 
 | 753 | //   10 INTERNAL_ERROR | 
 | 754 | //   11 OUT_OF_MEMORY_EXCEPTION | 
 | 755 | // | 
 | 756 | // The next three bits, 4-6, are an allocation space tag 'sss'.  The | 
 | 757 | // allocation space tag is 000 for all failure types except | 
 | 758 | // RETRY_AFTER_GC.  For RETRY_AFTER_GC, the possible values are the | 
 | 759 | // allocation spaces (the encoding is found in globals.h). | 
 | 760 | // | 
 | 761 | // The remaining bits is the size of the allocation request in units | 
 | 762 | // of the pointer size, and is zeroed except for RETRY_AFTER_GC | 
 | 763 | // failures.  The 25 bits (on a 32 bit platform) gives a representable | 
 | 764 | // range of 2^27 bytes (128MB). | 
 | 765 |  | 
 | 766 | // Failure type tag info. | 
 | 767 | const int kFailureTypeTagSize = 2; | 
 | 768 | const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1; | 
 | 769 |  | 
 | 770 | class Failure: public Object { | 
 | 771 |  public: | 
 | 772 |   // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code. | 
 | 773 |   enum Type { | 
 | 774 |     RETRY_AFTER_GC = 0, | 
 | 775 |     EXCEPTION = 1,       // Returning this marker tells the real exception | 
 | 776 |                          // is in Top::pending_exception. | 
 | 777 |     INTERNAL_ERROR = 2, | 
 | 778 |     OUT_OF_MEMORY_EXCEPTION = 3 | 
 | 779 |   }; | 
 | 780 |  | 
 | 781 |   inline Type type() const; | 
 | 782 |  | 
 | 783 |   // Returns the space that needs to be collected for RetryAfterGC failures. | 
 | 784 |   inline AllocationSpace allocation_space() const; | 
 | 785 |  | 
 | 786 |   // Returns the number of bytes requested (up to the representable maximum) | 
 | 787 |   // for RetryAfterGC failures. | 
 | 788 |   inline int requested() const; | 
 | 789 |  | 
 | 790 |   inline bool IsInternalError() const; | 
 | 791 |   inline bool IsOutOfMemoryException() const; | 
 | 792 |  | 
 | 793 |   static Failure* RetryAfterGC(int requested_bytes, AllocationSpace space); | 
 | 794 |   static inline Failure* RetryAfterGC(int requested_bytes);  // NEW_SPACE | 
 | 795 |   static inline Failure* Exception(); | 
 | 796 |   static inline Failure* InternalError(); | 
 | 797 |   static inline Failure* OutOfMemoryException(); | 
 | 798 |   // Casting. | 
 | 799 |   static inline Failure* cast(Object* object); | 
 | 800 |  | 
 | 801 |   // Dispatched behavior. | 
 | 802 |   void FailurePrint(); | 
 | 803 |   void FailurePrint(StringStream* accumulator); | 
 | 804 | #ifdef DEBUG | 
 | 805 |   void FailureVerify(); | 
 | 806 | #endif | 
 | 807 |  | 
 | 808 |  private: | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 809 |   inline intptr_t value() const; | 
 | 810 |   static inline Failure* Construct(Type type, intptr_t value = 0); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 811 |  | 
 | 812 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Failure); | 
 | 813 | }; | 
 | 814 |  | 
 | 815 |  | 
 | 816 | // Heap objects typically have a map pointer in their first word.  However, | 
 | 817 | // during GC other data (eg, mark bits, forwarding addresses) is sometimes | 
 | 818 | // encoded in the first word.  The class MapWord is an abstraction of the | 
 | 819 | // value in a heap object's first word. | 
 | 820 | class MapWord BASE_EMBEDDED { | 
 | 821 |  public: | 
 | 822 |   // Normal state: the map word contains a map pointer. | 
 | 823 |  | 
 | 824 |   // Create a map word from a map pointer. | 
 | 825 |   static inline MapWord FromMap(Map* map); | 
 | 826 |  | 
 | 827 |   // View this map word as a map pointer. | 
 | 828 |   inline Map* ToMap(); | 
 | 829 |  | 
 | 830 |  | 
 | 831 |   // Scavenge collection: the map word of live objects in the from space | 
 | 832 |   // contains a forwarding address (a heap object pointer in the to space). | 
 | 833 |  | 
 | 834 |   // True if this map word is a forwarding address for a scavenge | 
 | 835 |   // collection.  Only valid during a scavenge collection (specifically, | 
 | 836 |   // when all map words are heap object pointers, ie. not during a full GC). | 
 | 837 |   inline bool IsForwardingAddress(); | 
 | 838 |  | 
 | 839 |   // Create a map word from a forwarding address. | 
 | 840 |   static inline MapWord FromForwardingAddress(HeapObject* object); | 
 | 841 |  | 
 | 842 |   // View this map word as a forwarding address. | 
 | 843 |   inline HeapObject* ToForwardingAddress(); | 
 | 844 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 845 |   // Marking phase of full collection: the map word of live objects is | 
 | 846 |   // marked, and may be marked as overflowed (eg, the object is live, its | 
 | 847 |   // children have not been visited, and it does not fit in the marking | 
 | 848 |   // stack). | 
 | 849 |  | 
 | 850 |   // True if this map word's mark bit is set. | 
 | 851 |   inline bool IsMarked(); | 
 | 852 |  | 
 | 853 |   // Return this map word but with its mark bit set. | 
 | 854 |   inline void SetMark(); | 
 | 855 |  | 
 | 856 |   // Return this map word but with its mark bit cleared. | 
 | 857 |   inline void ClearMark(); | 
 | 858 |  | 
 | 859 |   // True if this map word's overflow bit is set. | 
 | 860 |   inline bool IsOverflowed(); | 
 | 861 |  | 
 | 862 |   // Return this map word but with its overflow bit set. | 
 | 863 |   inline void SetOverflow(); | 
 | 864 |  | 
 | 865 |   // Return this map word but with its overflow bit cleared. | 
 | 866 |   inline void ClearOverflow(); | 
 | 867 |  | 
 | 868 |  | 
 | 869 |   // Compacting phase of a full compacting collection: the map word of live | 
 | 870 |   // objects contains an encoding of the original map address along with the | 
 | 871 |   // forwarding address (represented as an offset from the first live object | 
 | 872 |   // in the same page as the (old) object address). | 
 | 873 |  | 
 | 874 |   // Create a map word from a map address and a forwarding address offset. | 
 | 875 |   static inline MapWord EncodeAddress(Address map_address, int offset); | 
 | 876 |  | 
 | 877 |   // Return the map address encoded in this map word. | 
 | 878 |   inline Address DecodeMapAddress(MapSpace* map_space); | 
 | 879 |  | 
 | 880 |   // Return the forwarding offset encoded in this map word. | 
 | 881 |   inline int DecodeOffset(); | 
 | 882 |  | 
 | 883 |  | 
 | 884 |   // During serialization: the map word is used to hold an encoded | 
 | 885 |   // address, and possibly a mark bit (set and cleared with SetMark | 
 | 886 |   // and ClearMark). | 
 | 887 |  | 
 | 888 |   // Create a map word from an encoded address. | 
 | 889 |   static inline MapWord FromEncodedAddress(Address address); | 
 | 890 |  | 
 | 891 |   inline Address ToEncodedAddress(); | 
 | 892 |  | 
 | 893 |   // Bits used by the marking phase of the garbage collector. | 
 | 894 |   // | 
 | 895 |   // The first word of a heap object is normally a map pointer. The last two | 
 | 896 |   // bits are tagged as '01' (kHeapObjectTag). We reuse the last two bits to | 
 | 897 |   // mark an object as live and/or overflowed: | 
 | 898 |   //   last bit = 0, marked as alive | 
 | 899 |   //   second bit = 1, overflowed | 
 | 900 |   // An object is only marked as overflowed when it is marked as live while | 
 | 901 |   // the marking stack is overflowed. | 
 | 902 |   static const int kMarkingBit = 0;  // marking bit | 
 | 903 |   static const int kMarkingMask = (1 << kMarkingBit);  // marking mask | 
 | 904 |   static const int kOverflowBit = 1;  // overflow bit | 
 | 905 |   static const int kOverflowMask = (1 << kOverflowBit);  // overflow mask | 
 | 906 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 907 |   // Forwarding pointers and map pointer encoding. On 32 bit all the bits are | 
 | 908 |   // used. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 909 |   // +-----------------+------------------+-----------------+ | 
 | 910 |   // |forwarding offset|page offset of map|page index of map| | 
 | 911 |   // +-----------------+------------------+-----------------+ | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 912 |   //          ^                 ^                  ^ | 
 | 913 |   //          |                 |                  | | 
 | 914 |   //          |                 |          kMapPageIndexBits | 
 | 915 |   //          |         kMapPageOffsetBits | 
 | 916 |   // kForwardingOffsetBits | 
 | 917 |   static const int kMapPageOffsetBits = kPageSizeBits - kMapAlignmentBits; | 
 | 918 |   static const int kForwardingOffsetBits = kPageSizeBits - kObjectAlignmentBits; | 
 | 919 | #ifdef V8_HOST_ARCH_64_BIT | 
 | 920 |   static const int kMapPageIndexBits = 16; | 
 | 921 | #else | 
 | 922 |   // Use all the 32-bits to encode on a 32-bit platform. | 
 | 923 |   static const int kMapPageIndexBits = | 
 | 924 |       32 - (kMapPageOffsetBits + kForwardingOffsetBits); | 
 | 925 | #endif | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 926 |  | 
 | 927 |   static const int kMapPageIndexShift = 0; | 
 | 928 |   static const int kMapPageOffsetShift = | 
 | 929 |       kMapPageIndexShift + kMapPageIndexBits; | 
 | 930 |   static const int kForwardingOffsetShift = | 
 | 931 |       kMapPageOffsetShift + kMapPageOffsetBits; | 
 | 932 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 933 |   // Bit masks covering the different parts the encoding. | 
 | 934 |   static const uintptr_t kMapPageIndexMask = | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 935 |       (1 << kMapPageOffsetShift) - 1; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 936 |   static const uintptr_t kMapPageOffsetMask = | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 937 |       ((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 938 |   static const uintptr_t kForwardingOffsetMask = | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 939 |       ~(kMapPageIndexMask | kMapPageOffsetMask); | 
 | 940 |  | 
 | 941 |  private: | 
 | 942 |   // HeapObject calls the private constructor and directly reads the value. | 
 | 943 |   friend class HeapObject; | 
 | 944 |  | 
 | 945 |   explicit MapWord(uintptr_t value) : value_(value) {} | 
 | 946 |  | 
 | 947 |   uintptr_t value_; | 
 | 948 | }; | 
 | 949 |  | 
 | 950 |  | 
 | 951 | // HeapObject is the superclass for all classes describing heap allocated | 
 | 952 | // objects. | 
 | 953 | class HeapObject: public Object { | 
 | 954 |  public: | 
 | 955 |   // [map]: Contains a map which contains the object's reflective | 
 | 956 |   // information. | 
 | 957 |   inline Map* map(); | 
 | 958 |   inline void set_map(Map* value); | 
 | 959 |  | 
 | 960 |   // During garbage collection, the map word of a heap object does not | 
 | 961 |   // necessarily contain a map pointer. | 
 | 962 |   inline MapWord map_word(); | 
 | 963 |   inline void set_map_word(MapWord map_word); | 
 | 964 |  | 
 | 965 |   // Converts an address to a HeapObject pointer. | 
 | 966 |   static inline HeapObject* FromAddress(Address address); | 
 | 967 |  | 
 | 968 |   // Returns the address of this HeapObject. | 
 | 969 |   inline Address address(); | 
 | 970 |  | 
 | 971 |   // Iterates over pointers contained in the object (including the Map) | 
 | 972 |   void Iterate(ObjectVisitor* v); | 
 | 973 |  | 
 | 974 |   // Iterates over all pointers contained in the object except the | 
 | 975 |   // first map pointer.  The object type is given in the first | 
 | 976 |   // parameter. This function does not access the map pointer in the | 
 | 977 |   // object, and so is safe to call while the map pointer is modified. | 
 | 978 |   void IterateBody(InstanceType type, int object_size, ObjectVisitor* v); | 
 | 979 |  | 
 | 980 |   // This method only applies to struct objects.  Iterates over all the fields | 
 | 981 |   // of this struct. | 
 | 982 |   void IterateStructBody(int object_size, ObjectVisitor* v); | 
 | 983 |  | 
 | 984 |   // Returns the heap object's size in bytes | 
 | 985 |   inline int Size(); | 
 | 986 |  | 
 | 987 |   // Given a heap object's map pointer, returns the heap size in bytes | 
 | 988 |   // Useful when the map pointer field is used for other purposes. | 
 | 989 |   // GC internal. | 
 | 990 |   inline int SizeFromMap(Map* map); | 
 | 991 |  | 
 | 992 |   // Support for the marking heap objects during the marking phase of GC. | 
 | 993 |   // True if the object is marked live. | 
 | 994 |   inline bool IsMarked(); | 
 | 995 |  | 
 | 996 |   // Mutate this object's map pointer to indicate that the object is live. | 
 | 997 |   inline void SetMark(); | 
 | 998 |  | 
 | 999 |   // Mutate this object's map pointer to remove the indication that the | 
 | 1000 |   // object is live (ie, partially restore the map pointer). | 
 | 1001 |   inline void ClearMark(); | 
 | 1002 |  | 
 | 1003 |   // True if this object is marked as overflowed.  Overflowed objects have | 
 | 1004 |   // been reached and marked during marking of the heap, but their children | 
 | 1005 |   // have not necessarily been marked and they have not been pushed on the | 
 | 1006 |   // marking stack. | 
 | 1007 |   inline bool IsOverflowed(); | 
 | 1008 |  | 
 | 1009 |   // Mutate this object's map pointer to indicate that the object is | 
 | 1010 |   // overflowed. | 
 | 1011 |   inline void SetOverflow(); | 
 | 1012 |  | 
 | 1013 |   // Mutate this object's map pointer to remove the indication that the | 
 | 1014 |   // object is overflowed (ie, partially restore the map pointer). | 
 | 1015 |   inline void ClearOverflow(); | 
 | 1016 |  | 
 | 1017 |   // Returns the field at offset in obj, as a read/write Object* reference. | 
 | 1018 |   // Does no checking, and is safe to use during GC, while maps are invalid. | 
 | 1019 |   // Does not update remembered sets, so should only be assigned to | 
 | 1020 |   // during marking GC. | 
 | 1021 |   static inline Object** RawField(HeapObject* obj, int offset); | 
 | 1022 |  | 
 | 1023 |   // Casting. | 
 | 1024 |   static inline HeapObject* cast(Object* obj); | 
 | 1025 |  | 
 | 1026 |   // Return the write barrier mode for this. | 
 | 1027 |   inline WriteBarrierMode GetWriteBarrierMode(); | 
 | 1028 |  | 
 | 1029 |   // Dispatched behavior. | 
 | 1030 |   void HeapObjectShortPrint(StringStream* accumulator); | 
 | 1031 | #ifdef DEBUG | 
 | 1032 |   void HeapObjectPrint(); | 
 | 1033 |   void HeapObjectVerify(); | 
 | 1034 |   inline void VerifyObjectField(int offset); | 
 | 1035 |  | 
 | 1036 |   void PrintHeader(const char* id); | 
 | 1037 |  | 
 | 1038 |   // Verify a pointer is a valid HeapObject pointer that points to object | 
 | 1039 |   // areas in the heap. | 
 | 1040 |   static void VerifyHeapPointer(Object* p); | 
 | 1041 | #endif | 
 | 1042 |  | 
 | 1043 |   // Layout description. | 
 | 1044 |   // First field in a heap object is map. | 
 | 1045 |   static const int kMapOffset = Object::kHeaderSize; | 
 | 1046 |   static const int kHeaderSize = kMapOffset + kPointerSize; | 
 | 1047 |  | 
 | 1048 |   STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset); | 
 | 1049 |  | 
 | 1050 |  protected: | 
 | 1051 |   // helpers for calling an ObjectVisitor to iterate over pointers in the | 
 | 1052 |   // half-open range [start, end) specified as integer offsets | 
 | 1053 |   inline void IteratePointers(ObjectVisitor* v, int start, int end); | 
 | 1054 |   // as above, for the single element at "offset" | 
 | 1055 |   inline void IteratePointer(ObjectVisitor* v, int offset); | 
 | 1056 |  | 
 | 1057 |   // Computes the object size from the map. | 
 | 1058 |   // Should only be used from SizeFromMap. | 
 | 1059 |   int SlowSizeFromMap(Map* map); | 
 | 1060 |  | 
 | 1061 |  private: | 
 | 1062 |   DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject); | 
 | 1063 | }; | 
 | 1064 |  | 
 | 1065 |  | 
 | 1066 | // The HeapNumber class describes heap allocated numbers that cannot be | 
 | 1067 | // represented in a Smi (small integer) | 
 | 1068 | class HeapNumber: public HeapObject { | 
 | 1069 |  public: | 
 | 1070 |   // [value]: number value. | 
 | 1071 |   inline double value(); | 
 | 1072 |   inline void set_value(double value); | 
 | 1073 |  | 
 | 1074 |   // Casting. | 
 | 1075 |   static inline HeapNumber* cast(Object* obj); | 
 | 1076 |  | 
 | 1077 |   // Dispatched behavior. | 
 | 1078 |   Object* HeapNumberToBoolean(); | 
 | 1079 |   void HeapNumberPrint(); | 
 | 1080 |   void HeapNumberPrint(StringStream* accumulator); | 
 | 1081 | #ifdef DEBUG | 
 | 1082 |   void HeapNumberVerify(); | 
 | 1083 | #endif | 
 | 1084 |  | 
 | 1085 |   // Layout description. | 
 | 1086 |   static const int kValueOffset = HeapObject::kHeaderSize; | 
 | 1087 |   // IEEE doubles are two 32 bit words.  The first is just mantissa, the second | 
 | 1088 |   // is a mixture of sign, exponent and mantissa.  Our current platforms are all | 
 | 1089 |   // little endian apart from non-EABI arm which is little endian with big | 
 | 1090 |   // endian floating point word ordering! | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1091 | #if !defined(V8_HOST_ARCH_ARM) || defined(USE_ARM_EABI) | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1092 |   static const int kMantissaOffset = kValueOffset; | 
 | 1093 |   static const int kExponentOffset = kValueOffset + 4; | 
 | 1094 | #else | 
 | 1095 |   static const int kMantissaOffset = kValueOffset + 4; | 
 | 1096 |   static const int kExponentOffset = kValueOffset; | 
 | 1097 | # define BIG_ENDIAN_FLOATING_POINT 1 | 
 | 1098 | #endif | 
 | 1099 |   static const int kSize = kValueOffset + kDoubleSize; | 
 | 1100 |  | 
 | 1101 |   static const uint32_t kSignMask = 0x80000000u; | 
 | 1102 |   static const uint32_t kExponentMask = 0x7ff00000u; | 
 | 1103 |   static const uint32_t kMantissaMask = 0xfffffu; | 
 | 1104 |   static const int kExponentBias = 1023; | 
 | 1105 |   static const int kExponentShift = 20; | 
 | 1106 |   static const int kMantissaBitsInTopWord = 20; | 
 | 1107 |   static const int kNonMantissaBitsInTopWord = 12; | 
 | 1108 |  | 
 | 1109 |  private: | 
 | 1110 |   DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber); | 
 | 1111 | }; | 
 | 1112 |  | 
 | 1113 |  | 
 | 1114 | // The JSObject describes real heap allocated JavaScript objects with | 
 | 1115 | // properties. | 
 | 1116 | // Note that the map of JSObject changes during execution to enable inline | 
 | 1117 | // caching. | 
 | 1118 | class JSObject: public HeapObject { | 
 | 1119 |  public: | 
 | 1120 |   enum DeleteMode { NORMAL_DELETION, FORCE_DELETION }; | 
 | 1121 |   enum ElementsKind { | 
 | 1122 |     FAST_ELEMENTS, | 
 | 1123 |     DICTIONARY_ELEMENTS, | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1124 |     PIXEL_ELEMENTS, | 
 | 1125 |     EXTERNAL_BYTE_ELEMENTS, | 
 | 1126 |     EXTERNAL_UNSIGNED_BYTE_ELEMENTS, | 
 | 1127 |     EXTERNAL_SHORT_ELEMENTS, | 
 | 1128 |     EXTERNAL_UNSIGNED_SHORT_ELEMENTS, | 
 | 1129 |     EXTERNAL_INT_ELEMENTS, | 
 | 1130 |     EXTERNAL_UNSIGNED_INT_ELEMENTS, | 
 | 1131 |     EXTERNAL_FLOAT_ELEMENTS | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1132 |   }; | 
 | 1133 |  | 
 | 1134 |   // [properties]: Backing storage for properties. | 
 | 1135 |   // properties is a FixedArray in the fast case, and a Dictionary in the | 
 | 1136 |   // slow case. | 
 | 1137 |   DECL_ACCESSORS(properties, FixedArray)  // Get and set fast properties. | 
 | 1138 |   inline void initialize_properties(); | 
 | 1139 |   inline bool HasFastProperties(); | 
 | 1140 |   inline StringDictionary* property_dictionary();  // Gets slow properties. | 
 | 1141 |  | 
 | 1142 |   // [elements]: The elements (properties with names that are integers). | 
 | 1143 |   // elements is a FixedArray in the fast case, and a Dictionary in the slow | 
 | 1144 |   // case or a PixelArray in a special case. | 
 | 1145 |   DECL_ACCESSORS(elements, Array)  // Get and set fast elements. | 
 | 1146 |   inline void initialize_elements(); | 
 | 1147 |   inline ElementsKind GetElementsKind(); | 
 | 1148 |   inline bool HasFastElements(); | 
 | 1149 |   inline bool HasDictionaryElements(); | 
 | 1150 |   inline bool HasPixelElements(); | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1151 |   inline bool HasExternalArrayElements(); | 
 | 1152 |   inline bool HasExternalByteElements(); | 
 | 1153 |   inline bool HasExternalUnsignedByteElements(); | 
 | 1154 |   inline bool HasExternalShortElements(); | 
 | 1155 |   inline bool HasExternalUnsignedShortElements(); | 
 | 1156 |   inline bool HasExternalIntElements(); | 
 | 1157 |   inline bool HasExternalUnsignedIntElements(); | 
 | 1158 |   inline bool HasExternalFloatElements(); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1159 |   inline NumberDictionary* element_dictionary();  // Gets slow elements. | 
 | 1160 |  | 
 | 1161 |   // Collects elements starting at index 0. | 
 | 1162 |   // Undefined values are placed after non-undefined values. | 
 | 1163 |   // Returns the number of non-undefined values. | 
 | 1164 |   Object* PrepareElementsForSort(uint32_t limit); | 
 | 1165 |   // As PrepareElementsForSort, but only on objects where elements is | 
 | 1166 |   // a dictionary, and it will stay a dictionary. | 
 | 1167 |   Object* PrepareSlowElementsForSort(uint32_t limit); | 
 | 1168 |  | 
 | 1169 |   Object* SetProperty(String* key, | 
 | 1170 |                       Object* value, | 
 | 1171 |                       PropertyAttributes attributes); | 
 | 1172 |   Object* SetProperty(LookupResult* result, | 
 | 1173 |                       String* key, | 
 | 1174 |                       Object* value, | 
 | 1175 |                       PropertyAttributes attributes); | 
 | 1176 |   Object* SetPropertyWithFailedAccessCheck(LookupResult* result, | 
 | 1177 |                                            String* name, | 
 | 1178 |                                            Object* value); | 
 | 1179 |   Object* SetPropertyWithCallback(Object* structure, | 
 | 1180 |                                   String* name, | 
 | 1181 |                                   Object* value, | 
 | 1182 |                                   JSObject* holder); | 
 | 1183 |   Object* SetPropertyWithDefinedSetter(JSFunction* setter, | 
 | 1184 |                                        Object* value); | 
 | 1185 |   Object* SetPropertyWithInterceptor(String* name, | 
 | 1186 |                                      Object* value, | 
 | 1187 |                                      PropertyAttributes attributes); | 
 | 1188 |   Object* SetPropertyPostInterceptor(String* name, | 
 | 1189 |                                      Object* value, | 
 | 1190 |                                      PropertyAttributes attributes); | 
 | 1191 |   Object* IgnoreAttributesAndSetLocalProperty(String* key, | 
 | 1192 |                                               Object* value, | 
 | 1193 |                                               PropertyAttributes attributes); | 
 | 1194 |  | 
 | 1195 |   // Retrieve a value in a normalized object given a lookup result. | 
 | 1196 |   // Handles the special representation of JS global objects. | 
 | 1197 |   Object* GetNormalizedProperty(LookupResult* result); | 
 | 1198 |  | 
 | 1199 |   // Sets the property value in a normalized object given a lookup result. | 
 | 1200 |   // Handles the special representation of JS global objects. | 
 | 1201 |   Object* SetNormalizedProperty(LookupResult* result, Object* value); | 
 | 1202 |  | 
 | 1203 |   // Sets the property value in a normalized object given (key, value, details). | 
 | 1204 |   // Handles the special representation of JS global objects. | 
 | 1205 |   Object* SetNormalizedProperty(String* name, | 
 | 1206 |                                 Object* value, | 
 | 1207 |                                 PropertyDetails details); | 
 | 1208 |  | 
 | 1209 |   // Deletes the named property in a normalized object. | 
 | 1210 |   Object* DeleteNormalizedProperty(String* name, DeleteMode mode); | 
 | 1211 |  | 
 | 1212 |   // Sets a property that currently has lazy loading. | 
 | 1213 |   Object* SetLazyProperty(LookupResult* result, | 
 | 1214 |                           String* name, | 
 | 1215 |                           Object* value, | 
 | 1216 |                           PropertyAttributes attributes); | 
 | 1217 |  | 
 | 1218 |   // Returns the class name ([[Class]] property in the specification). | 
 | 1219 |   String* class_name(); | 
 | 1220 |  | 
 | 1221 |   // Returns the constructor name (the name (possibly, inferred name) of the | 
 | 1222 |   // function that was used to instantiate the object). | 
 | 1223 |   String* constructor_name(); | 
 | 1224 |  | 
 | 1225 |   // Retrieve interceptors. | 
 | 1226 |   InterceptorInfo* GetNamedInterceptor(); | 
 | 1227 |   InterceptorInfo* GetIndexedInterceptor(); | 
 | 1228 |  | 
 | 1229 |   inline PropertyAttributes GetPropertyAttribute(String* name); | 
 | 1230 |   PropertyAttributes GetPropertyAttributeWithReceiver(JSObject* receiver, | 
 | 1231 |                                                       String* name); | 
 | 1232 |   PropertyAttributes GetLocalPropertyAttribute(String* name); | 
 | 1233 |  | 
 | 1234 |   Object* DefineAccessor(String* name, bool is_getter, JSFunction* fun, | 
 | 1235 |                          PropertyAttributes attributes); | 
 | 1236 |   Object* LookupAccessor(String* name, bool is_getter); | 
 | 1237 |  | 
 | 1238 |   // Used from Object::GetProperty(). | 
 | 1239 |   Object* GetPropertyWithFailedAccessCheck(Object* receiver, | 
 | 1240 |                                            LookupResult* result, | 
 | 1241 |                                            String* name, | 
 | 1242 |                                            PropertyAttributes* attributes); | 
 | 1243 |   Object* GetPropertyWithInterceptor(JSObject* receiver, | 
 | 1244 |                                      String* name, | 
 | 1245 |                                      PropertyAttributes* attributes); | 
 | 1246 |   Object* GetPropertyPostInterceptor(JSObject* receiver, | 
 | 1247 |                                      String* name, | 
 | 1248 |                                      PropertyAttributes* attributes); | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 1249 |   Object* GetLocalPropertyPostInterceptor(JSObject* receiver, | 
 | 1250 |                                           String* name, | 
 | 1251 |                                           PropertyAttributes* attributes); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1252 |   Object* GetLazyProperty(Object* receiver, | 
 | 1253 |                           LookupResult* result, | 
 | 1254 |                           String* name, | 
 | 1255 |                           PropertyAttributes* attributes); | 
 | 1256 |  | 
 | 1257 |   // Tells whether this object needs to be loaded. | 
 | 1258 |   inline bool IsLoaded(); | 
 | 1259 |  | 
 | 1260 |   // Returns true if this is an instance of an api function and has | 
 | 1261 |   // been modified since it was created.  May give false positives. | 
 | 1262 |   bool IsDirty(); | 
 | 1263 |  | 
 | 1264 |   bool HasProperty(String* name) { | 
 | 1265 |     return GetPropertyAttribute(name) != ABSENT; | 
 | 1266 |   } | 
 | 1267 |  | 
 | 1268 |   // Can cause a GC if it hits an interceptor. | 
 | 1269 |   bool HasLocalProperty(String* name) { | 
 | 1270 |     return GetLocalPropertyAttribute(name) != ABSENT; | 
 | 1271 |   } | 
 | 1272 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 1273 |   // If the receiver is a JSGlobalProxy this method will return its prototype, | 
 | 1274 |   // otherwise the result is the receiver itself. | 
 | 1275 |   inline Object* BypassGlobalProxy(); | 
 | 1276 |  | 
 | 1277 |   // Accessors for hidden properties object. | 
 | 1278 |   // | 
 | 1279 |   // Hidden properties are not local properties of the object itself. | 
 | 1280 |   // Instead they are stored on an auxiliary JSObject stored as a local | 
 | 1281 |   // property with a special name Heap::hidden_symbol(). But if the | 
 | 1282 |   // receiver is a JSGlobalProxy then the auxiliary object is a property | 
 | 1283 |   // of its prototype. | 
 | 1284 |   // | 
 | 1285 |   // Has/Get/SetHiddenPropertiesObject methods don't allow the holder to be | 
 | 1286 |   // a JSGlobalProxy. Use BypassGlobalProxy method above to get to the real | 
 | 1287 |   // holder. | 
 | 1288 |   // | 
 | 1289 |   // These accessors do not touch interceptors or accessors. | 
 | 1290 |   inline bool HasHiddenPropertiesObject(); | 
 | 1291 |   inline Object* GetHiddenPropertiesObject(); | 
 | 1292 |   inline Object* SetHiddenPropertiesObject(Object* hidden_obj); | 
 | 1293 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1294 |   Object* DeleteProperty(String* name, DeleteMode mode); | 
 | 1295 |   Object* DeleteElement(uint32_t index, DeleteMode mode); | 
 | 1296 |   Object* DeleteLazyProperty(LookupResult* result, | 
 | 1297 |                              String* name, | 
 | 1298 |                              DeleteMode mode); | 
 | 1299 |  | 
 | 1300 |   // Tests for the fast common case for property enumeration. | 
 | 1301 |   bool IsSimpleEnum(); | 
 | 1302 |  | 
 | 1303 |   // Do we want to keep the elements in fast case when increasing the | 
 | 1304 |   // capacity? | 
 | 1305 |   bool ShouldConvertToSlowElements(int new_capacity); | 
 | 1306 |   // Returns true if the backing storage for the slow-case elements of | 
 | 1307 |   // this object takes up nearly as much space as a fast-case backing | 
 | 1308 |   // storage would.  In that case the JSObject should have fast | 
 | 1309 |   // elements. | 
 | 1310 |   bool ShouldConvertToFastElements(); | 
 | 1311 |  | 
 | 1312 |   // Return the object's prototype (might be Heap::null_value()). | 
 | 1313 |   inline Object* GetPrototype(); | 
 | 1314 |  | 
 | 1315 |   // Tells whether the index'th element is present. | 
 | 1316 |   inline bool HasElement(uint32_t index); | 
 | 1317 |   bool HasElementWithReceiver(JSObject* receiver, uint32_t index); | 
 | 1318 |   bool HasLocalElement(uint32_t index); | 
 | 1319 |  | 
 | 1320 |   bool HasElementWithInterceptor(JSObject* receiver, uint32_t index); | 
 | 1321 |   bool HasElementPostInterceptor(JSObject* receiver, uint32_t index); | 
 | 1322 |  | 
 | 1323 |   Object* SetFastElement(uint32_t index, Object* value); | 
 | 1324 |  | 
 | 1325 |   // Set the index'th array element. | 
 | 1326 |   // A Failure object is returned if GC is needed. | 
 | 1327 |   Object* SetElement(uint32_t index, Object* value); | 
 | 1328 |  | 
 | 1329 |   // Returns the index'th element. | 
 | 1330 |   // The undefined object if index is out of bounds. | 
 | 1331 |   Object* GetElementWithReceiver(JSObject* receiver, uint32_t index); | 
 | 1332 |  | 
 | 1333 |   void SetFastElements(FixedArray* elements); | 
 | 1334 |   Object* SetSlowElements(Object* length); | 
 | 1335 |  | 
 | 1336 |   // Lookup interceptors are used for handling properties controlled by host | 
 | 1337 |   // objects. | 
 | 1338 |   inline bool HasNamedInterceptor(); | 
 | 1339 |   inline bool HasIndexedInterceptor(); | 
 | 1340 |  | 
 | 1341 |   // Support functions for v8 api (needed for correct interceptor behavior). | 
 | 1342 |   bool HasRealNamedProperty(String* key); | 
 | 1343 |   bool HasRealElementProperty(uint32_t index); | 
 | 1344 |   bool HasRealNamedCallbackProperty(String* key); | 
 | 1345 |  | 
 | 1346 |   // Initializes the array to a certain length | 
 | 1347 |   Object* SetElementsLength(Object* length); | 
 | 1348 |  | 
 | 1349 |   // Get the header size for a JSObject.  Used to compute the index of | 
 | 1350 |   // internal fields as well as the number of internal fields. | 
 | 1351 |   inline int GetHeaderSize(); | 
 | 1352 |  | 
 | 1353 |   inline int GetInternalFieldCount(); | 
 | 1354 |   inline Object* GetInternalField(int index); | 
 | 1355 |   inline void SetInternalField(int index, Object* value); | 
 | 1356 |  | 
 | 1357 |   // Lookup a property.  If found, the result is valid and has | 
 | 1358 |   // detailed information. | 
 | 1359 |   void LocalLookup(String* name, LookupResult* result); | 
 | 1360 |   void Lookup(String* name, LookupResult* result); | 
 | 1361 |  | 
 | 1362 |   // The following lookup functions skip interceptors. | 
 | 1363 |   void LocalLookupRealNamedProperty(String* name, LookupResult* result); | 
 | 1364 |   void LookupRealNamedProperty(String* name, LookupResult* result); | 
 | 1365 |   void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result); | 
 | 1366 |   void LookupCallbackSetterInPrototypes(String* name, LookupResult* result); | 
 | 1367 |   Object* LookupCallbackSetterInPrototypes(uint32_t index); | 
 | 1368 |   void LookupCallback(String* name, LookupResult* result); | 
 | 1369 |  | 
 | 1370 |   // Returns the number of properties on this object filtering out properties | 
 | 1371 |   // with the specified attributes (ignoring interceptors). | 
 | 1372 |   int NumberOfLocalProperties(PropertyAttributes filter); | 
 | 1373 |   // Returns the number of enumerable properties (ignoring interceptors). | 
 | 1374 |   int NumberOfEnumProperties(); | 
 | 1375 |   // Fill in details for properties into storage starting at the specified | 
 | 1376 |   // index. | 
 | 1377 |   void GetLocalPropertyNames(FixedArray* storage, int index); | 
 | 1378 |  | 
 | 1379 |   // Returns the number of properties on this object filtering out properties | 
 | 1380 |   // with the specified attributes (ignoring interceptors). | 
 | 1381 |   int NumberOfLocalElements(PropertyAttributes filter); | 
 | 1382 |   // Returns the number of enumerable elements (ignoring interceptors). | 
 | 1383 |   int NumberOfEnumElements(); | 
 | 1384 |   // Returns the number of elements on this object filtering out elements | 
 | 1385 |   // with the specified attributes (ignoring interceptors). | 
 | 1386 |   int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter); | 
 | 1387 |   // Count and fill in the enumerable elements into storage. | 
 | 1388 |   // (storage->length() == NumberOfEnumElements()). | 
 | 1389 |   // If storage is NULL, will count the elements without adding | 
 | 1390 |   // them to any storage. | 
 | 1391 |   // Returns the number of enumerable elements. | 
 | 1392 |   int GetEnumElementKeys(FixedArray* storage); | 
 | 1393 |  | 
 | 1394 |   // Add a property to a fast-case object using a map transition to | 
 | 1395 |   // new_map. | 
 | 1396 |   Object* AddFastPropertyUsingMap(Map* new_map, | 
 | 1397 |                                   String* name, | 
 | 1398 |                                   Object* value); | 
 | 1399 |  | 
 | 1400 |   // Add a constant function property to a fast-case object. | 
 | 1401 |   // This leaves a CONSTANT_TRANSITION in the old map, and | 
 | 1402 |   // if it is called on a second object with this map, a | 
 | 1403 |   // normal property is added instead, with a map transition. | 
 | 1404 |   // This avoids the creation of many maps with the same constant | 
 | 1405 |   // function, all orphaned. | 
 | 1406 |   Object* AddConstantFunctionProperty(String* name, | 
 | 1407 |                                       JSFunction* function, | 
 | 1408 |                                       PropertyAttributes attributes); | 
 | 1409 |  | 
 | 1410 |   Object* ReplaceSlowProperty(String* name, | 
 | 1411 |                               Object* value, | 
 | 1412 |                               PropertyAttributes attributes); | 
 | 1413 |  | 
 | 1414 |   // Converts a descriptor of any other type to a real field, | 
 | 1415 |   // backed by the properties array.  Descriptors of visible | 
 | 1416 |   // types, such as CONSTANT_FUNCTION, keep their enumeration order. | 
 | 1417 |   // Converts the descriptor on the original object's map to a | 
 | 1418 |   // map transition, and the the new field is on the object's new map. | 
 | 1419 |   Object* ConvertDescriptorToFieldAndMapTransition( | 
 | 1420 |       String* name, | 
 | 1421 |       Object* new_value, | 
 | 1422 |       PropertyAttributes attributes); | 
 | 1423 |  | 
 | 1424 |   // Converts a descriptor of any other type to a real field, | 
 | 1425 |   // backed by the properties array.  Descriptors of visible | 
 | 1426 |   // types, such as CONSTANT_FUNCTION, keep their enumeration order. | 
 | 1427 |   Object* ConvertDescriptorToField(String* name, | 
 | 1428 |                                    Object* new_value, | 
 | 1429 |                                    PropertyAttributes attributes); | 
 | 1430 |  | 
 | 1431 |   // Add a property to a fast-case object. | 
 | 1432 |   Object* AddFastProperty(String* name, | 
 | 1433 |                           Object* value, | 
 | 1434 |                           PropertyAttributes attributes); | 
 | 1435 |  | 
 | 1436 |   // Add a property to a slow-case object. | 
 | 1437 |   Object* AddSlowProperty(String* name, | 
 | 1438 |                           Object* value, | 
 | 1439 |                           PropertyAttributes attributes); | 
 | 1440 |  | 
 | 1441 |   // Add a property to an object. | 
 | 1442 |   Object* AddProperty(String* name, | 
 | 1443 |                       Object* value, | 
 | 1444 |                       PropertyAttributes attributes); | 
 | 1445 |  | 
 | 1446 |   // Convert the object to use the canonical dictionary | 
 | 1447 |   // representation. If the object is expected to have additional properties | 
 | 1448 |   // added this number can be indicated to have the backing store allocated to | 
 | 1449 |   // an initial capacity for holding these properties. | 
 | 1450 |   Object* NormalizeProperties(PropertyNormalizationMode mode, | 
 | 1451 |                               int expected_additional_properties); | 
 | 1452 |   Object* NormalizeElements(); | 
 | 1453 |  | 
 | 1454 |   // Transform slow named properties to fast variants. | 
 | 1455 |   // Returns failure if allocation failed. | 
 | 1456 |   Object* TransformToFastProperties(int unused_property_fields); | 
 | 1457 |  | 
 | 1458 |   // Access fast-case object properties at index. | 
 | 1459 |   inline Object* FastPropertyAt(int index); | 
 | 1460 |   inline Object* FastPropertyAtPut(int index, Object* value); | 
 | 1461 |  | 
 | 1462 |   // Access to in object properties. | 
 | 1463 |   inline Object* InObjectPropertyAt(int index); | 
 | 1464 |   inline Object* InObjectPropertyAtPut(int index, | 
 | 1465 |                                        Object* value, | 
 | 1466 |                                        WriteBarrierMode mode | 
 | 1467 |                                        = UPDATE_WRITE_BARRIER); | 
 | 1468 |  | 
 | 1469 |   // initializes the body after properties slot, properties slot is | 
 | 1470 |   // initialized by set_properties | 
 | 1471 |   // Note: this call does not update write barrier, it is caller's | 
 | 1472 |   // reponsibility to ensure that *v* can be collected without WB here. | 
 | 1473 |   inline void InitializeBody(int object_size); | 
 | 1474 |  | 
 | 1475 |   // Check whether this object references another object | 
 | 1476 |   bool ReferencesObject(Object* obj); | 
 | 1477 |  | 
 | 1478 |   // Casting. | 
 | 1479 |   static inline JSObject* cast(Object* obj); | 
 | 1480 |  | 
 | 1481 |   // Dispatched behavior. | 
 | 1482 |   void JSObjectIterateBody(int object_size, ObjectVisitor* v); | 
 | 1483 |   void JSObjectShortPrint(StringStream* accumulator); | 
 | 1484 | #ifdef DEBUG | 
 | 1485 |   void JSObjectPrint(); | 
 | 1486 |   void JSObjectVerify(); | 
 | 1487 |   void PrintProperties(); | 
 | 1488 |   void PrintElements(); | 
 | 1489 |  | 
 | 1490 |   // Structure for collecting spill information about JSObjects. | 
 | 1491 |   class SpillInformation { | 
 | 1492 |    public: | 
 | 1493 |     void Clear(); | 
 | 1494 |     void Print(); | 
 | 1495 |     int number_of_objects_; | 
 | 1496 |     int number_of_objects_with_fast_properties_; | 
 | 1497 |     int number_of_objects_with_fast_elements_; | 
 | 1498 |     int number_of_fast_used_fields_; | 
 | 1499 |     int number_of_fast_unused_fields_; | 
 | 1500 |     int number_of_slow_used_properties_; | 
 | 1501 |     int number_of_slow_unused_properties_; | 
 | 1502 |     int number_of_fast_used_elements_; | 
 | 1503 |     int number_of_fast_unused_elements_; | 
 | 1504 |     int number_of_slow_used_elements_; | 
 | 1505 |     int number_of_slow_unused_elements_; | 
 | 1506 |   }; | 
 | 1507 |  | 
 | 1508 |   void IncrementSpillStatistics(SpillInformation* info); | 
 | 1509 | #endif | 
 | 1510 |   Object* SlowReverseLookup(Object* value); | 
 | 1511 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1512 |   // Maximal number of elements (numbered 0 .. kMaxElementCount - 1). | 
 | 1513 |   // Also maximal value of JSArray's length property. | 
 | 1514 |   static const uint32_t kMaxElementCount = 0xffffffffu; | 
 | 1515 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1516 |   static const uint32_t kMaxGap = 1024; | 
 | 1517 |   static const int kMaxFastElementsLength = 5000; | 
 | 1518 |   static const int kInitialMaxFastElementArray = 100000; | 
 | 1519 |   static const int kMaxFastProperties = 8; | 
 | 1520 |   static const int kMaxInstanceSize = 255 * kPointerSize; | 
 | 1521 |   // When extending the backing storage for property values, we increase | 
 | 1522 |   // its size by more than the 1 entry necessary, so sequentially adding fields | 
 | 1523 |   // to the same object requires fewer allocations and copies. | 
 | 1524 |   static const int kFieldsAdded = 3; | 
 | 1525 |  | 
 | 1526 |   // Layout description. | 
 | 1527 |   static const int kPropertiesOffset = HeapObject::kHeaderSize; | 
 | 1528 |   static const int kElementsOffset = kPropertiesOffset + kPointerSize; | 
 | 1529 |   static const int kHeaderSize = kElementsOffset + kPointerSize; | 
 | 1530 |  | 
 | 1531 |   STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize); | 
 | 1532 |  | 
 | 1533 |   Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index); | 
 | 1534 |  | 
 | 1535 |  private: | 
 | 1536 |   Object* SetElementWithInterceptor(uint32_t index, Object* value); | 
 | 1537 |   Object* SetElementWithoutInterceptor(uint32_t index, Object* value); | 
 | 1538 |  | 
 | 1539 |   Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index); | 
 | 1540 |  | 
 | 1541 |   Object* DeletePropertyPostInterceptor(String* name, DeleteMode mode); | 
 | 1542 |   Object* DeletePropertyWithInterceptor(String* name); | 
 | 1543 |  | 
 | 1544 |   Object* DeleteElementPostInterceptor(uint32_t index, DeleteMode mode); | 
 | 1545 |   Object* DeleteElementWithInterceptor(uint32_t index); | 
 | 1546 |  | 
 | 1547 |   PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver, | 
 | 1548 |                                                          String* name, | 
 | 1549 |                                                          bool continue_search); | 
 | 1550 |   PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver, | 
 | 1551 |                                                          String* name, | 
 | 1552 |                                                          bool continue_search); | 
 | 1553 |   PropertyAttributes GetPropertyAttributeWithFailedAccessCheck( | 
 | 1554 |       Object* receiver, | 
 | 1555 |       LookupResult* result, | 
 | 1556 |       String* name, | 
 | 1557 |       bool continue_search); | 
 | 1558 |   PropertyAttributes GetPropertyAttribute(JSObject* receiver, | 
 | 1559 |                                           LookupResult* result, | 
 | 1560 |                                           String* name, | 
 | 1561 |                                           bool continue_search); | 
 | 1562 |  | 
 | 1563 |   // Returns true if most of the elements backing storage is used. | 
 | 1564 |   bool HasDenseElements(); | 
 | 1565 |  | 
 | 1566 |   Object* DefineGetterSetter(String* name, PropertyAttributes attributes); | 
 | 1567 |  | 
 | 1568 |   void LookupInDescriptor(String* name, LookupResult* result); | 
 | 1569 |  | 
 | 1570 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject); | 
 | 1571 | }; | 
 | 1572 |  | 
 | 1573 |  | 
 | 1574 | // Abstract super class arrays. It provides length behavior. | 
 | 1575 | class Array: public HeapObject { | 
 | 1576 |  public: | 
 | 1577 |   // [length]: length of the array. | 
 | 1578 |   inline int length(); | 
 | 1579 |   inline void set_length(int value); | 
 | 1580 |  | 
 | 1581 |   // Convert an object to an array index. | 
 | 1582 |   // Returns true if the conversion succeeded. | 
 | 1583 |   static inline bool IndexFromObject(Object* object, uint32_t* index); | 
 | 1584 |  | 
 | 1585 |   // Layout descriptor. | 
 | 1586 |   static const int kLengthOffset = HeapObject::kHeaderSize; | 
 | 1587 |  | 
 | 1588 |  protected: | 
 | 1589 |   // No code should use the Array class directly, only its subclasses. | 
 | 1590 |   // Use the kHeaderSize of the appropriate subclass, which may be aligned. | 
 | 1591 |   static const int kHeaderSize = kLengthOffset + kIntSize; | 
 | 1592 |   static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); | 
 | 1593 |  | 
 | 1594 |  private: | 
 | 1595 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Array); | 
 | 1596 | }; | 
 | 1597 |  | 
 | 1598 |  | 
 | 1599 | // FixedArray describes fixed sized arrays where element | 
 | 1600 | // type is Object*. | 
 | 1601 |  | 
 | 1602 | class FixedArray: public Array { | 
 | 1603 |  public: | 
 | 1604 |  | 
 | 1605 |   // Setter and getter for elements. | 
 | 1606 |   inline Object* get(int index); | 
 | 1607 |   // Setter that uses write barrier. | 
 | 1608 |   inline void set(int index, Object* value); | 
 | 1609 |  | 
 | 1610 |   // Setter that doesn't need write barrier). | 
 | 1611 |   inline void set(int index, Smi* value); | 
 | 1612 |   // Setter with explicit barrier mode. | 
 | 1613 |   inline void set(int index, Object* value, WriteBarrierMode mode); | 
 | 1614 |  | 
 | 1615 |   // Setters for frequently used oddballs located in old space. | 
 | 1616 |   inline void set_undefined(int index); | 
 | 1617 |   inline void set_null(int index); | 
 | 1618 |   inline void set_the_hole(int index); | 
 | 1619 |  | 
 | 1620 |   // Copy operations. | 
 | 1621 |   inline Object* Copy(); | 
 | 1622 |   Object* CopySize(int new_length); | 
 | 1623 |  | 
 | 1624 |   // Add the elements of a JSArray to this FixedArray. | 
 | 1625 |   Object* AddKeysFromJSArray(JSArray* array); | 
 | 1626 |  | 
 | 1627 |   // Compute the union of this and other. | 
 | 1628 |   Object* UnionOfKeys(FixedArray* other); | 
 | 1629 |  | 
 | 1630 |   // Copy a sub array from the receiver to dest. | 
 | 1631 |   void CopyTo(int pos, FixedArray* dest, int dest_pos, int len); | 
 | 1632 |  | 
 | 1633 |   // Garbage collection support. | 
 | 1634 |   static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; } | 
 | 1635 |  | 
 | 1636 |   // Code Generation support. | 
 | 1637 |   static int OffsetOfElementAt(int index) { return SizeFor(index); } | 
 | 1638 |  | 
 | 1639 |   // Casting. | 
 | 1640 |   static inline FixedArray* cast(Object* obj); | 
 | 1641 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1642 |   static const int kHeaderSize = Array::kAlignedSize; | 
 | 1643 |  | 
 | 1644 |   // Maximal allowed size, in bytes, of a single FixedArray. | 
 | 1645 |   // Prevents overflowing size computations, as well as extreme memory | 
 | 1646 |   // consumption. | 
 | 1647 |   static const int kMaxSize = 512 * MB; | 
 | 1648 |   // Maximally allowed length of a FixedArray. | 
 | 1649 |   static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1650 |  | 
 | 1651 |   // Dispatched behavior. | 
 | 1652 |   int FixedArraySize() { return SizeFor(length()); } | 
 | 1653 |   void FixedArrayIterateBody(ObjectVisitor* v); | 
 | 1654 | #ifdef DEBUG | 
 | 1655 |   void FixedArrayPrint(); | 
 | 1656 |   void FixedArrayVerify(); | 
 | 1657 |   // Checks if two FixedArrays have identical contents. | 
 | 1658 |   bool IsEqualTo(FixedArray* other); | 
 | 1659 | #endif | 
 | 1660 |  | 
 | 1661 |   // Swap two elements in a pair of arrays.  If this array and the | 
 | 1662 |   // numbers array are the same object, the elements are only swapped | 
 | 1663 |   // once. | 
 | 1664 |   void SwapPairs(FixedArray* numbers, int i, int j); | 
 | 1665 |  | 
 | 1666 |   // Sort prefix of this array and the numbers array as pairs wrt. the | 
 | 1667 |   // numbers.  If the numbers array and the this array are the same | 
 | 1668 |   // object, the prefix of this array is sorted. | 
 | 1669 |   void SortPairs(FixedArray* numbers, uint32_t len); | 
 | 1670 |  | 
 | 1671 |  protected: | 
 | 1672 |   // Set operation on FixedArray without using write barriers. | 
 | 1673 |   static inline void fast_set(FixedArray* array, int index, Object* value); | 
 | 1674 |  | 
 | 1675 |  private: | 
 | 1676 |   DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray); | 
 | 1677 | }; | 
 | 1678 |  | 
 | 1679 |  | 
 | 1680 | // DescriptorArrays are fixed arrays used to hold instance descriptors. | 
 | 1681 | // The format of the these objects is: | 
 | 1682 | //   [0]: point to a fixed array with (value, detail) pairs. | 
 | 1683 | //   [1]: next enumeration index (Smi), or pointer to small fixed array: | 
 | 1684 | //          [0]: next enumeration index (Smi) | 
 | 1685 | //          [1]: pointer to fixed array with enum cache | 
 | 1686 | //   [2]: first key | 
 | 1687 | //   [length() - 1]: last key | 
 | 1688 | // | 
 | 1689 | class DescriptorArray: public FixedArray { | 
 | 1690 |  public: | 
 | 1691 |   // Is this the singleton empty_descriptor_array? | 
 | 1692 |   inline bool IsEmpty(); | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1693 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1694 |   // Returns the number of descriptors in the array. | 
 | 1695 |   int number_of_descriptors() { | 
 | 1696 |     return IsEmpty() ? 0 : length() - kFirstIndex; | 
 | 1697 |   } | 
 | 1698 |  | 
 | 1699 |   int NextEnumerationIndex() { | 
 | 1700 |     if (IsEmpty()) return PropertyDetails::kInitialIndex; | 
 | 1701 |     Object* obj = get(kEnumerationIndexIndex); | 
 | 1702 |     if (obj->IsSmi()) { | 
 | 1703 |       return Smi::cast(obj)->value(); | 
 | 1704 |     } else { | 
 | 1705 |       Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex); | 
 | 1706 |       return Smi::cast(index)->value(); | 
 | 1707 |     } | 
 | 1708 |   } | 
 | 1709 |  | 
 | 1710 |   // Set next enumeration index and flush any enum cache. | 
 | 1711 |   void SetNextEnumerationIndex(int value) { | 
 | 1712 |     if (!IsEmpty()) { | 
 | 1713 |       fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value)); | 
 | 1714 |     } | 
 | 1715 |   } | 
 | 1716 |   bool HasEnumCache() { | 
 | 1717 |     return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi(); | 
 | 1718 |   } | 
 | 1719 |  | 
 | 1720 |   Object* GetEnumCache() { | 
 | 1721 |     ASSERT(HasEnumCache()); | 
 | 1722 |     FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex)); | 
 | 1723 |     return bridge->get(kEnumCacheBridgeCacheIndex); | 
 | 1724 |   } | 
 | 1725 |  | 
 | 1726 |   // Initialize or change the enum cache, | 
 | 1727 |   // using the supplied storage for the small "bridge". | 
 | 1728 |   void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache); | 
 | 1729 |  | 
 | 1730 |   // Accessors for fetching instance descriptor at descriptor number. | 
 | 1731 |   inline String* GetKey(int descriptor_number); | 
 | 1732 |   inline Object* GetValue(int descriptor_number); | 
 | 1733 |   inline Smi* GetDetails(int descriptor_number); | 
 | 1734 |   inline PropertyType GetType(int descriptor_number); | 
 | 1735 |   inline int GetFieldIndex(int descriptor_number); | 
 | 1736 |   inline JSFunction* GetConstantFunction(int descriptor_number); | 
 | 1737 |   inline Object* GetCallbacksObject(int descriptor_number); | 
 | 1738 |   inline AccessorDescriptor* GetCallbacks(int descriptor_number); | 
 | 1739 |   inline bool IsProperty(int descriptor_number); | 
 | 1740 |   inline bool IsTransition(int descriptor_number); | 
 | 1741 |   inline bool IsNullDescriptor(int descriptor_number); | 
 | 1742 |   inline bool IsDontEnum(int descriptor_number); | 
 | 1743 |  | 
 | 1744 |   // Accessor for complete descriptor. | 
 | 1745 |   inline void Get(int descriptor_number, Descriptor* desc); | 
 | 1746 |   inline void Set(int descriptor_number, Descriptor* desc); | 
 | 1747 |  | 
 | 1748 |   // Transfer complete descriptor from another descriptor array to | 
 | 1749 |   // this one. | 
 | 1750 |   inline void CopyFrom(int index, DescriptorArray* src, int src_index); | 
 | 1751 |  | 
 | 1752 |   // Copy the descriptor array, insert a new descriptor and optionally | 
 | 1753 |   // remove map transitions.  If the descriptor is already present, it is | 
 | 1754 |   // replaced.  If a replaced descriptor is a real property (not a transition | 
 | 1755 |   // or null), its enumeration index is kept as is. | 
 | 1756 |   // If adding a real property, map transitions must be removed.  If adding | 
 | 1757 |   // a transition, they must not be removed.  All null descriptors are removed. | 
 | 1758 |   Object* CopyInsert(Descriptor* descriptor, TransitionFlag transition_flag); | 
 | 1759 |  | 
 | 1760 |   // Remove all transitions.  Return  a copy of the array with all transitions | 
 | 1761 |   // removed, or a Failure object if the new array could not be allocated. | 
 | 1762 |   Object* RemoveTransitions(); | 
 | 1763 |  | 
 | 1764 |   // Sort the instance descriptors by the hash codes of their keys. | 
 | 1765 |   void Sort(); | 
 | 1766 |  | 
 | 1767 |   // Search the instance descriptors for given name. | 
 | 1768 |   inline int Search(String* name); | 
 | 1769 |  | 
 | 1770 |   // Tells whether the name is present int the array. | 
 | 1771 |   bool Contains(String* name) { return kNotFound != Search(name); } | 
 | 1772 |  | 
 | 1773 |   // Perform a binary search in the instance descriptors represented | 
 | 1774 |   // by this fixed array.  low and high are descriptor indices.  If there | 
 | 1775 |   // are three instance descriptors in this array it should be called | 
 | 1776 |   // with low=0 and high=2. | 
 | 1777 |   int BinarySearch(String* name, int low, int high); | 
 | 1778 |  | 
 | 1779 |   // Perform a linear search in the instance descriptors represented | 
 | 1780 |   // by this fixed array.  len is the number of descriptor indices that are | 
 | 1781 |   // valid.  Does not require the descriptors to be sorted. | 
 | 1782 |   int LinearSearch(String* name, int len); | 
 | 1783 |  | 
 | 1784 |   // Allocates a DescriptorArray, but returns the singleton | 
 | 1785 |   // empty descriptor array object if number_of_descriptors is 0. | 
 | 1786 |   static Object* Allocate(int number_of_descriptors); | 
 | 1787 |  | 
 | 1788 |   // Casting. | 
 | 1789 |   static inline DescriptorArray* cast(Object* obj); | 
 | 1790 |  | 
 | 1791 |   // Constant for denoting key was not found. | 
 | 1792 |   static const int kNotFound = -1; | 
 | 1793 |  | 
 | 1794 |   static const int kContentArrayIndex = 0; | 
 | 1795 |   static const int kEnumerationIndexIndex = 1; | 
 | 1796 |   static const int kFirstIndex = 2; | 
 | 1797 |  | 
 | 1798 |   // The length of the "bridge" to the enum cache. | 
 | 1799 |   static const int kEnumCacheBridgeLength = 2; | 
 | 1800 |   static const int kEnumCacheBridgeEnumIndex = 0; | 
 | 1801 |   static const int kEnumCacheBridgeCacheIndex = 1; | 
 | 1802 |  | 
 | 1803 |   // Layout description. | 
 | 1804 |   static const int kContentArrayOffset = FixedArray::kHeaderSize; | 
 | 1805 |   static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize; | 
 | 1806 |   static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize; | 
 | 1807 |  | 
 | 1808 |   // Layout description for the bridge array. | 
 | 1809 |   static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize; | 
 | 1810 |   static const int kEnumCacheBridgeCacheOffset = | 
 | 1811 |     kEnumCacheBridgeEnumOffset + kPointerSize; | 
 | 1812 |  | 
 | 1813 | #ifdef DEBUG | 
 | 1814 |   // Print all the descriptors. | 
 | 1815 |   void PrintDescriptors(); | 
 | 1816 |  | 
 | 1817 |   // Is the descriptor array sorted and without duplicates? | 
 | 1818 |   bool IsSortedNoDuplicates(); | 
 | 1819 |  | 
 | 1820 |   // Are two DescriptorArrays equal? | 
 | 1821 |   bool IsEqualTo(DescriptorArray* other); | 
 | 1822 | #endif | 
 | 1823 |  | 
 | 1824 |   // The maximum number of descriptors we want in a descriptor array (should | 
 | 1825 |   // fit in a page). | 
 | 1826 |   static const int kMaxNumberOfDescriptors = 1024 + 512; | 
 | 1827 |  | 
 | 1828 |  private: | 
 | 1829 |   // Conversion from descriptor number to array indices. | 
 | 1830 |   static int ToKeyIndex(int descriptor_number) { | 
 | 1831 |     return descriptor_number+kFirstIndex; | 
 | 1832 |   } | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1833 |  | 
 | 1834 |   static int ToDetailsIndex(int descriptor_number) { | 
 | 1835 |     return (descriptor_number << 1) + 1; | 
 | 1836 |   } | 
 | 1837 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1838 |   static int ToValueIndex(int descriptor_number) { | 
 | 1839 |     return descriptor_number << 1; | 
 | 1840 |   } | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1841 |  | 
 | 1842 |   bool is_null_descriptor(int descriptor_number) { | 
 | 1843 |     return PropertyDetails(GetDetails(descriptor_number)).type() == | 
 | 1844 |         NULL_DESCRIPTOR; | 
 | 1845 |   } | 
 | 1846 |   // Swap operation on FixedArray without using write barriers. | 
 | 1847 |   static inline void fast_swap(FixedArray* array, int first, int second); | 
 | 1848 |  | 
 | 1849 |   // Swap descriptor first and second. | 
 | 1850 |   inline void Swap(int first, int second); | 
 | 1851 |  | 
 | 1852 |   FixedArray* GetContentArray() { | 
 | 1853 |     return FixedArray::cast(get(kContentArrayIndex)); | 
 | 1854 |   } | 
 | 1855 |   DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); | 
 | 1856 | }; | 
 | 1857 |  | 
 | 1858 |  | 
 | 1859 | // HashTable is a subclass of FixedArray that implements a hash table | 
 | 1860 | // that uses open addressing and quadratic probing. | 
 | 1861 | // | 
 | 1862 | // In order for the quadratic probing to work, elements that have not | 
 | 1863 | // yet been used and elements that have been deleted are | 
 | 1864 | // distinguished.  Probing continues when deleted elements are | 
 | 1865 | // encountered and stops when unused elements are encountered. | 
 | 1866 | // | 
 | 1867 | // - Elements with key == undefined have not been used yet. | 
 | 1868 | // - Elements with key == null have been deleted. | 
 | 1869 | // | 
 | 1870 | // The hash table class is parameterized with a Shape and a Key. | 
 | 1871 | // Shape must be a class with the following interface: | 
 | 1872 | //   class ExampleShape { | 
 | 1873 | //    public: | 
 | 1874 | //      // Tells whether key matches other. | 
 | 1875 | //     static bool IsMatch(Key key, Object* other); | 
 | 1876 | //     // Returns the hash value for key. | 
 | 1877 | //     static uint32_t Hash(Key key); | 
 | 1878 | //     // Returns the hash value for object. | 
 | 1879 | //     static uint32_t HashForObject(Key key, Object* object); | 
 | 1880 | //     // Convert key to an object. | 
 | 1881 | //     static inline Object* AsObject(Key key); | 
 | 1882 | //     // The prefix size indicates number of elements in the beginning | 
 | 1883 | //     // of the backing storage. | 
 | 1884 | //     static const int kPrefixSize = ..; | 
 | 1885 | //     // The Element size indicates number of elements per entry. | 
 | 1886 | //     static const int kEntrySize = ..; | 
 | 1887 | //   }; | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1888 | // The prefix size indicates an amount of memory in the | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1889 | // beginning of the backing storage that can be used for non-element | 
 | 1890 | // information by subclasses. | 
 | 1891 |  | 
 | 1892 | template<typename Shape, typename Key> | 
 | 1893 | class HashTable: public FixedArray { | 
 | 1894 |  public: | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1895 |   // Returns the number of elements in the hash table. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1896 |   int NumberOfElements() { | 
 | 1897 |     return Smi::cast(get(kNumberOfElementsIndex))->value(); | 
 | 1898 |   } | 
 | 1899 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1900 |   // Returns the number of deleted elements in the hash table. | 
 | 1901 |   int NumberOfDeletedElements() { | 
 | 1902 |     return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); | 
 | 1903 |   } | 
 | 1904 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1905 |   // Returns the capacity of the hash table. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1906 |   int Capacity() { | 
 | 1907 |     return Smi::cast(get(kCapacityIndex))->value(); | 
 | 1908 |   } | 
 | 1909 |  | 
 | 1910 |   // ElementAdded should be called whenever an element is added to a | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1911 |   // hash table. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1912 |   void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); } | 
 | 1913 |  | 
 | 1914 |   // ElementRemoved should be called whenever an element is removed from | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1915 |   // a hash table. | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1916 |   void ElementRemoved() { | 
 | 1917 |     SetNumberOfElements(NumberOfElements() - 1); | 
 | 1918 |     SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); | 
 | 1919 |   } | 
 | 1920 |   void ElementsRemoved(int n) { | 
 | 1921 |     SetNumberOfElements(NumberOfElements() - n); | 
 | 1922 |     SetNumberOfDeletedElements(NumberOfDeletedElements() + n); | 
 | 1923 |   } | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1924 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1925 |   // Returns a new HashTable object. Might return Failure. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1926 |   static Object* Allocate(int at_least_space_for); | 
 | 1927 |  | 
 | 1928 |   // Returns the key at entry. | 
 | 1929 |   Object* KeyAt(int entry) { return get(EntryToIndex(entry)); } | 
 | 1930 |  | 
 | 1931 |   // Tells whether k is a real key.  Null and undefined are not allowed | 
 | 1932 |   // as keys and can be used to indicate missing or deleted elements. | 
 | 1933 |   bool IsKey(Object* k) { | 
 | 1934 |     return !k->IsNull() && !k->IsUndefined(); | 
 | 1935 |   } | 
 | 1936 |  | 
 | 1937 |   // Garbage collection support. | 
 | 1938 |   void IteratePrefix(ObjectVisitor* visitor); | 
 | 1939 |   void IterateElements(ObjectVisitor* visitor); | 
 | 1940 |  | 
 | 1941 |   // Casting. | 
 | 1942 |   static inline HashTable* cast(Object* obj); | 
 | 1943 |  | 
 | 1944 |   // Compute the probe offset (quadratic probing). | 
 | 1945 |   INLINE(static uint32_t GetProbeOffset(uint32_t n)) { | 
 | 1946 |     return (n + n * n) >> 1; | 
 | 1947 |   } | 
 | 1948 |  | 
 | 1949 |   static const int kNumberOfElementsIndex = 0; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1950 |   static const int kNumberOfDeletedElementsIndex = 1; | 
 | 1951 |   static const int kCapacityIndex = 2; | 
 | 1952 |   static const int kPrefixStartIndex = 3; | 
 | 1953 |   static const int kElementsStartIndex = | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1954 |       kPrefixStartIndex + Shape::kPrefixSize; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1955 |   static const int kEntrySize = Shape::kEntrySize; | 
 | 1956 |   static const int kElementsStartOffset = | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1957 |       kHeaderSize + kElementsStartIndex * kPointerSize; | 
 | 1958 |  | 
 | 1959 |   // Constant used for denoting a absent entry. | 
 | 1960 |   static const int kNotFound = -1; | 
 | 1961 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1962 |   // Maximal capacity of HashTable. Based on maximal length of underlying | 
 | 1963 |   // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex | 
 | 1964 |   // cannot overflow. | 
 | 1965 |   static const int kMaxCapacity = | 
 | 1966 |       (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize; | 
 | 1967 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1968 |   // Find entry for key otherwise return -1. | 
 | 1969 |   int FindEntry(Key key); | 
 | 1970 |  | 
 | 1971 |  protected: | 
 | 1972 |  | 
 | 1973 |   // Find the entry at which to insert element with the given key that | 
 | 1974 |   // has the given hash value. | 
 | 1975 |   uint32_t FindInsertionEntry(uint32_t hash); | 
 | 1976 |  | 
 | 1977 |   // Returns the index for an entry (of the key) | 
 | 1978 |   static inline int EntryToIndex(int entry) { | 
 | 1979 |     return (entry * kEntrySize) + kElementsStartIndex; | 
 | 1980 |   } | 
 | 1981 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 1982 |   // Update the number of elements in the hash table. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1983 |   void SetNumberOfElements(int nof) { | 
 | 1984 |     fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof)); | 
 | 1985 |   } | 
 | 1986 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1987 |   // Update the number of deleted elements in the hash table. | 
 | 1988 |   void SetNumberOfDeletedElements(int nod) { | 
 | 1989 |     fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); | 
 | 1990 |   } | 
 | 1991 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1992 |   // Sets the capacity of the hash table. | 
 | 1993 |   void SetCapacity(int capacity) { | 
 | 1994 |     // To scale a computed hash code to fit within the hash table, we | 
 | 1995 |     // use bit-wise AND with a mask, so the capacity must be positive | 
 | 1996 |     // and non-zero. | 
 | 1997 |     ASSERT(capacity > 0); | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 1998 |     ASSERT(capacity <= kMaxCapacity); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1999 |     fast_set(this, kCapacityIndex, Smi::FromInt(capacity)); | 
 | 2000 |   } | 
 | 2001 |  | 
 | 2002 |  | 
 | 2003 |   // Returns probe entry. | 
 | 2004 |   static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) { | 
 | 2005 |     ASSERT(IsPowerOf2(size)); | 
 | 2006 |     return (hash + GetProbeOffset(number)) & (size - 1); | 
 | 2007 |   } | 
 | 2008 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 2009 |   static uint32_t FirstProbe(uint32_t hash, uint32_t size) { | 
 | 2010 |     return hash & (size - 1); | 
 | 2011 |   } | 
 | 2012 |  | 
 | 2013 |   static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) { | 
 | 2014 |     return (last + number) & (size - 1); | 
 | 2015 |   } | 
 | 2016 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2017 |   // Ensure enough space for n additional elements. | 
 | 2018 |   Object* EnsureCapacity(int n, Key key); | 
 | 2019 | }; | 
 | 2020 |  | 
 | 2021 |  | 
 | 2022 |  | 
 | 2023 | // HashTableKey is an abstract superclass for virtual key behavior. | 
 | 2024 | class HashTableKey { | 
 | 2025 |  public: | 
 | 2026 |   // Returns whether the other object matches this key. | 
 | 2027 |   virtual bool IsMatch(Object* other) = 0; | 
 | 2028 |   // Returns the hash value for this key. | 
 | 2029 |   virtual uint32_t Hash() = 0; | 
 | 2030 |   // Returns the hash value for object. | 
 | 2031 |   virtual uint32_t HashForObject(Object* key) = 0; | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 2032 |   // Returns the key object for storing into the hash table. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2033 |   // If allocations fails a failure object is returned. | 
 | 2034 |   virtual Object* AsObject() = 0; | 
 | 2035 |   // Required. | 
 | 2036 |   virtual ~HashTableKey() {} | 
 | 2037 | }; | 
 | 2038 |  | 
 | 2039 | class SymbolTableShape { | 
 | 2040 |  public: | 
 | 2041 |   static bool IsMatch(HashTableKey* key, Object* value) { | 
 | 2042 |     return key->IsMatch(value); | 
 | 2043 |   } | 
 | 2044 |   static uint32_t Hash(HashTableKey* key) { | 
 | 2045 |     return key->Hash(); | 
 | 2046 |   } | 
 | 2047 |   static uint32_t HashForObject(HashTableKey* key, Object* object) { | 
 | 2048 |     return key->HashForObject(object); | 
 | 2049 |   } | 
 | 2050 |   static Object* AsObject(HashTableKey* key) { | 
 | 2051 |     return key->AsObject(); | 
 | 2052 |   } | 
 | 2053 |  | 
 | 2054 |   static const int kPrefixSize = 0; | 
 | 2055 |   static const int kEntrySize = 1; | 
 | 2056 | }; | 
 | 2057 |  | 
 | 2058 | // SymbolTable. | 
 | 2059 | // | 
 | 2060 | // No special elements in the prefix and the element size is 1 | 
 | 2061 | // because only the symbol itself (the key) needs to be stored. | 
 | 2062 | class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> { | 
 | 2063 |  public: | 
 | 2064 |   // Find symbol in the symbol table.  If it is not there yet, it is | 
 | 2065 |   // added.  The return value is the symbol table which might have | 
 | 2066 |   // been enlarged.  If the return value is not a failure, the symbol | 
 | 2067 |   // pointer *s is set to the symbol found. | 
 | 2068 |   Object* LookupSymbol(Vector<const char> str, Object** s); | 
 | 2069 |   Object* LookupString(String* key, Object** s); | 
 | 2070 |  | 
 | 2071 |   // Looks up a symbol that is equal to the given string and returns | 
 | 2072 |   // true if it is found, assigning the symbol to the given output | 
 | 2073 |   // parameter. | 
 | 2074 |   bool LookupSymbolIfExists(String* str, String** symbol); | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 2075 |   bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2076 |  | 
 | 2077 |   // Casting. | 
 | 2078 |   static inline SymbolTable* cast(Object* obj); | 
 | 2079 |  | 
 | 2080 |  private: | 
 | 2081 |   Object* LookupKey(HashTableKey* key, Object** s); | 
 | 2082 |  | 
 | 2083 |   DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable); | 
 | 2084 | }; | 
 | 2085 |  | 
 | 2086 |  | 
 | 2087 | class MapCacheShape { | 
 | 2088 |  public: | 
 | 2089 |   static bool IsMatch(HashTableKey* key, Object* value) { | 
 | 2090 |     return key->IsMatch(value); | 
 | 2091 |   } | 
 | 2092 |   static uint32_t Hash(HashTableKey* key) { | 
 | 2093 |     return key->Hash(); | 
 | 2094 |   } | 
 | 2095 |  | 
 | 2096 |   static uint32_t HashForObject(HashTableKey* key, Object* object) { | 
 | 2097 |     return key->HashForObject(object); | 
 | 2098 |   } | 
 | 2099 |  | 
 | 2100 |   static Object* AsObject(HashTableKey* key) { | 
 | 2101 |     return key->AsObject(); | 
 | 2102 |   } | 
 | 2103 |  | 
 | 2104 |   static const int kPrefixSize = 0; | 
 | 2105 |   static const int kEntrySize = 2; | 
 | 2106 | }; | 
 | 2107 |  | 
 | 2108 |  | 
 | 2109 | // MapCache. | 
 | 2110 | // | 
 | 2111 | // Maps keys that are a fixed array of symbols to a map. | 
 | 2112 | // Used for canonicalize maps for object literals. | 
 | 2113 | class MapCache: public HashTable<MapCacheShape, HashTableKey*> { | 
 | 2114 |  public: | 
 | 2115 |   // Find cached value for a string key, otherwise return null. | 
 | 2116 |   Object* Lookup(FixedArray* key); | 
 | 2117 |   Object* Put(FixedArray* key, Map* value); | 
 | 2118 |   static inline MapCache* cast(Object* obj); | 
 | 2119 |  | 
 | 2120 |  private: | 
 | 2121 |   DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache); | 
 | 2122 | }; | 
 | 2123 |  | 
 | 2124 |  | 
 | 2125 | template <typename Shape, typename Key> | 
 | 2126 | class Dictionary: public HashTable<Shape, Key> { | 
 | 2127 |  public: | 
 | 2128 |  | 
 | 2129 |   static inline Dictionary<Shape, Key>* cast(Object* obj) { | 
 | 2130 |     return reinterpret_cast<Dictionary<Shape, Key>*>(obj); | 
 | 2131 |   } | 
 | 2132 |  | 
 | 2133 |   // Returns the value at entry. | 
 | 2134 |   Object* ValueAt(int entry) { | 
 | 2135 |     return get(HashTable<Shape, Key>::EntryToIndex(entry)+1); | 
 | 2136 |   } | 
 | 2137 |  | 
 | 2138 |   // Set the value for entry. | 
 | 2139 |   void ValueAtPut(int entry, Object* value) { | 
 | 2140 |     set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value); | 
 | 2141 |   } | 
 | 2142 |  | 
 | 2143 |   // Returns the property details for the property at entry. | 
 | 2144 |   PropertyDetails DetailsAt(int entry) { | 
 | 2145 |     ASSERT(entry >= 0);  // Not found is -1, which is not caught by get(). | 
 | 2146 |     return PropertyDetails( | 
 | 2147 |         Smi::cast(get(HashTable<Shape, Key>::EntryToIndex(entry) + 2))); | 
 | 2148 |   } | 
 | 2149 |  | 
 | 2150 |   // Set the details for entry. | 
 | 2151 |   void DetailsAtPut(int entry, PropertyDetails value) { | 
 | 2152 |     set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi()); | 
 | 2153 |   } | 
 | 2154 |  | 
 | 2155 |   // Sorting support | 
 | 2156 |   void CopyValuesTo(FixedArray* elements); | 
 | 2157 |  | 
 | 2158 |   // Delete a property from the dictionary. | 
 | 2159 |   Object* DeleteProperty(int entry, JSObject::DeleteMode mode); | 
 | 2160 |  | 
 | 2161 |   // Returns the number of elements in the dictionary filtering out properties | 
 | 2162 |   // with the specified attributes. | 
 | 2163 |   int NumberOfElementsFilterAttributes(PropertyAttributes filter); | 
 | 2164 |  | 
 | 2165 |   // Returns the number of enumerable elements in the dictionary. | 
 | 2166 |   int NumberOfEnumElements(); | 
 | 2167 |  | 
 | 2168 |   // Copies keys to preallocated fixed array. | 
 | 2169 |   void CopyKeysTo(FixedArray* storage, PropertyAttributes filter); | 
 | 2170 |   // Fill in details for properties into storage. | 
 | 2171 |   void CopyKeysTo(FixedArray* storage); | 
 | 2172 |  | 
 | 2173 |   // Accessors for next enumeration index. | 
 | 2174 |   void SetNextEnumerationIndex(int index) { | 
 | 2175 |     fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index)); | 
 | 2176 |   } | 
 | 2177 |  | 
 | 2178 |   int NextEnumerationIndex() { | 
 | 2179 |     return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value(); | 
 | 2180 |   } | 
 | 2181 |  | 
 | 2182 |   // Returns a new array for dictionary usage. Might return Failure. | 
 | 2183 |   static Object* Allocate(int at_least_space_for); | 
 | 2184 |  | 
 | 2185 |   // Ensure enough space for n additional elements. | 
 | 2186 |   Object* EnsureCapacity(int n, Key key); | 
 | 2187 |  | 
 | 2188 | #ifdef DEBUG | 
 | 2189 |   void Print(); | 
 | 2190 | #endif | 
 | 2191 |   // Returns the key (slow). | 
 | 2192 |   Object* SlowReverseLookup(Object* value); | 
 | 2193 |  | 
 | 2194 |   // Sets the entry to (key, value) pair. | 
 | 2195 |   inline void SetEntry(int entry, | 
 | 2196 |                        Object* key, | 
 | 2197 |                        Object* value, | 
 | 2198 |                        PropertyDetails details); | 
 | 2199 |  | 
 | 2200 |   Object* Add(Key key, Object* value, PropertyDetails details); | 
 | 2201 |  | 
 | 2202 |  protected: | 
 | 2203 |   // Generic at put operation. | 
 | 2204 |   Object* AtPut(Key key, Object* value); | 
 | 2205 |  | 
 | 2206 |   // Add entry to dictionary. | 
 | 2207 |   Object* AddEntry(Key key, | 
 | 2208 |                    Object* value, | 
 | 2209 |                    PropertyDetails details, | 
 | 2210 |                    uint32_t hash); | 
 | 2211 |  | 
 | 2212 |   // Generate new enumeration indices to avoid enumeration index overflow. | 
 | 2213 |   Object* GenerateNewEnumerationIndices(); | 
 | 2214 |   static const int kMaxNumberKeyIndex = | 
 | 2215 |       HashTable<Shape, Key>::kPrefixStartIndex; | 
 | 2216 |   static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; | 
 | 2217 | }; | 
 | 2218 |  | 
 | 2219 |  | 
 | 2220 | class StringDictionaryShape { | 
 | 2221 |  public: | 
 | 2222 |   static inline bool IsMatch(String* key, Object* other); | 
 | 2223 |   static inline uint32_t Hash(String* key); | 
 | 2224 |   static inline uint32_t HashForObject(String* key, Object* object); | 
 | 2225 |   static inline Object* AsObject(String* key); | 
 | 2226 |   static const int kPrefixSize = 2; | 
 | 2227 |   static const int kEntrySize = 3; | 
 | 2228 |   static const bool kIsEnumerable = true; | 
 | 2229 | }; | 
 | 2230 |  | 
 | 2231 |  | 
 | 2232 | class StringDictionary: public Dictionary<StringDictionaryShape, String*> { | 
 | 2233 |  public: | 
 | 2234 |   static inline StringDictionary* cast(Object* obj) { | 
 | 2235 |     ASSERT(obj->IsDictionary()); | 
 | 2236 |     return reinterpret_cast<StringDictionary*>(obj); | 
 | 2237 |   } | 
 | 2238 |  | 
 | 2239 |   // Copies enumerable keys to preallocated fixed array. | 
 | 2240 |   void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array); | 
 | 2241 |  | 
 | 2242 |   // For transforming properties of a JSObject. | 
 | 2243 |   Object* TransformPropertiesToFastFor(JSObject* obj, | 
 | 2244 |                                        int unused_property_fields); | 
 | 2245 | }; | 
 | 2246 |  | 
 | 2247 |  | 
 | 2248 | class NumberDictionaryShape { | 
 | 2249 |  public: | 
 | 2250 |   static inline bool IsMatch(uint32_t key, Object* other); | 
 | 2251 |   static inline uint32_t Hash(uint32_t key); | 
 | 2252 |   static inline uint32_t HashForObject(uint32_t key, Object* object); | 
 | 2253 |   static inline Object* AsObject(uint32_t key); | 
 | 2254 |   static const int kPrefixSize = 2; | 
 | 2255 |   static const int kEntrySize = 3; | 
 | 2256 |   static const bool kIsEnumerable = false; | 
 | 2257 | }; | 
 | 2258 |  | 
 | 2259 |  | 
 | 2260 | class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> { | 
 | 2261 |  public: | 
 | 2262 |   static NumberDictionary* cast(Object* obj) { | 
 | 2263 |     ASSERT(obj->IsDictionary()); | 
 | 2264 |     return reinterpret_cast<NumberDictionary*>(obj); | 
 | 2265 |   } | 
 | 2266 |  | 
 | 2267 |   // Type specific at put (default NONE attributes is used when adding). | 
 | 2268 |   Object* AtNumberPut(uint32_t key, Object* value); | 
 | 2269 |   Object* AddNumberEntry(uint32_t key, | 
 | 2270 |                          Object* value, | 
 | 2271 |                          PropertyDetails details); | 
 | 2272 |  | 
 | 2273 |   // Set an existing entry or add a new one if needed. | 
 | 2274 |   Object* Set(uint32_t key, Object* value, PropertyDetails details); | 
 | 2275 |  | 
 | 2276 |   void UpdateMaxNumberKey(uint32_t key); | 
 | 2277 |  | 
 | 2278 |   // If slow elements are required we will never go back to fast-case | 
 | 2279 |   // for the elements kept in this dictionary.  We require slow | 
 | 2280 |   // elements if an element has been added at an index larger than | 
 | 2281 |   // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called | 
 | 2282 |   // when defining a getter or setter with a number key. | 
 | 2283 |   inline bool requires_slow_elements(); | 
 | 2284 |   inline void set_requires_slow_elements(); | 
 | 2285 |  | 
 | 2286 |   // Get the value of the max number key that has been added to this | 
 | 2287 |   // dictionary.  max_number_key can only be called if | 
 | 2288 |   // requires_slow_elements returns false. | 
 | 2289 |   inline uint32_t max_number_key(); | 
 | 2290 |  | 
 | 2291 |   // Remove all entries were key is a number and (from <= key && key < to). | 
 | 2292 |   void RemoveNumberEntries(uint32_t from, uint32_t to); | 
 | 2293 |  | 
 | 2294 |   // Bit masks. | 
 | 2295 |   static const int kRequiresSlowElementsMask = 1; | 
 | 2296 |   static const int kRequiresSlowElementsTagSize = 1; | 
 | 2297 |   static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1; | 
 | 2298 | }; | 
 | 2299 |  | 
 | 2300 |  | 
 | 2301 | // ByteArray represents fixed sized byte arrays.  Used by the outside world, | 
 | 2302 | // such as PCRE, and also by the memory allocator and garbage collector to | 
 | 2303 | // fill in free blocks in the heap. | 
 | 2304 | class ByteArray: public Array { | 
 | 2305 |  public: | 
 | 2306 |   // Setter and getter. | 
 | 2307 |   inline byte get(int index); | 
 | 2308 |   inline void set(int index, byte value); | 
 | 2309 |  | 
 | 2310 |   // Treat contents as an int array. | 
 | 2311 |   inline int get_int(int index); | 
 | 2312 |  | 
 | 2313 |   static int SizeFor(int length) { | 
 | 2314 |     return OBJECT_SIZE_ALIGN(kHeaderSize + length); | 
 | 2315 |   } | 
 | 2316 |   // We use byte arrays for free blocks in the heap.  Given a desired size in | 
 | 2317 |   // bytes that is a multiple of the word size and big enough to hold a byte | 
 | 2318 |   // array, this function returns the number of elements a byte array should | 
 | 2319 |   // have. | 
 | 2320 |   static int LengthFor(int size_in_bytes) { | 
 | 2321 |     ASSERT(IsAligned(size_in_bytes, kPointerSize)); | 
 | 2322 |     ASSERT(size_in_bytes >= kHeaderSize); | 
 | 2323 |     return size_in_bytes - kHeaderSize; | 
 | 2324 |   } | 
 | 2325 |  | 
 | 2326 |   // Returns data start address. | 
 | 2327 |   inline Address GetDataStartAddress(); | 
 | 2328 |  | 
 | 2329 |   // Returns a pointer to the ByteArray object for a given data start address. | 
 | 2330 |   static inline ByteArray* FromDataStartAddress(Address address); | 
 | 2331 |  | 
 | 2332 |   // Casting. | 
 | 2333 |   static inline ByteArray* cast(Object* obj); | 
 | 2334 |  | 
 | 2335 |   // Dispatched behavior. | 
 | 2336 |   int ByteArraySize() { return SizeFor(length()); } | 
 | 2337 | #ifdef DEBUG | 
 | 2338 |   void ByteArrayPrint(); | 
 | 2339 |   void ByteArrayVerify(); | 
 | 2340 | #endif | 
 | 2341 |  | 
 | 2342 |   // ByteArray headers are not quadword aligned. | 
 | 2343 |   static const int kHeaderSize = Array::kHeaderSize; | 
 | 2344 |   static const int kAlignedSize = Array::kAlignedSize; | 
 | 2345 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 2346 |   // Maximal memory consumption for a single ByteArray. | 
 | 2347 |   static const int kMaxSize = 512 * MB; | 
 | 2348 |   // Maximal length of a single ByteArray. | 
 | 2349 |   static const int kMaxLength = kMaxSize - kHeaderSize; | 
 | 2350 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2351 |  private: | 
 | 2352 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray); | 
 | 2353 | }; | 
 | 2354 |  | 
 | 2355 |  | 
 | 2356 | // A PixelArray represents a fixed-size byte array with special semantics | 
 | 2357 | // used for implementing the CanvasPixelArray object. Please see the | 
 | 2358 | // specification at: | 
 | 2359 | // http://www.whatwg.org/specs/web-apps/current-work/ | 
 | 2360 | //                      multipage/the-canvas-element.html#canvaspixelarray | 
 | 2361 | // In particular, write access clamps the value written to 0 or 255 if the | 
 | 2362 | // value written is outside this range. | 
 | 2363 | class PixelArray: public Array { | 
 | 2364 |  public: | 
 | 2365 |   // [external_pointer]: The pointer to the external memory area backing this | 
 | 2366 |   // pixel array. | 
 | 2367 |   DECL_ACCESSORS(external_pointer, uint8_t)  // Pointer to the data store. | 
 | 2368 |  | 
 | 2369 |   // Setter and getter. | 
 | 2370 |   inline uint8_t get(int index); | 
 | 2371 |   inline void set(int index, uint8_t value); | 
 | 2372 |  | 
 | 2373 |   // This accessor applies the correct conversion from Smi, HeapNumber and | 
 | 2374 |   // undefined and clamps the converted value between 0 and 255. | 
 | 2375 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2376 |  | 
 | 2377 |   // Casting. | 
 | 2378 |   static inline PixelArray* cast(Object* obj); | 
 | 2379 |  | 
 | 2380 | #ifdef DEBUG | 
 | 2381 |   void PixelArrayPrint(); | 
 | 2382 |   void PixelArrayVerify(); | 
 | 2383 | #endif  // DEBUG | 
 | 2384 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 2385 |   // Maximal acceptable length for a pixel array. | 
 | 2386 |   static const int kMaxLength = 0x3fffffff; | 
 | 2387 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2388 |   // PixelArray headers are not quadword aligned. | 
 | 2389 |   static const int kExternalPointerOffset = Array::kAlignedSize; | 
 | 2390 |   static const int kHeaderSize = kExternalPointerOffset + kPointerSize; | 
 | 2391 |   static const int kAlignedSize = OBJECT_SIZE_ALIGN(kHeaderSize); | 
 | 2392 |  | 
 | 2393 |  private: | 
 | 2394 |   DISALLOW_IMPLICIT_CONSTRUCTORS(PixelArray); | 
 | 2395 | }; | 
 | 2396 |  | 
 | 2397 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 2398 | // An ExternalArray represents a fixed-size array of primitive values | 
 | 2399 | // which live outside the JavaScript heap. Its subclasses are used to | 
 | 2400 | // implement the CanvasArray types being defined in the WebGL | 
 | 2401 | // specification. As of this writing the first public draft is not yet | 
 | 2402 | // available, but Khronos members can access the draft at: | 
 | 2403 | //   https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html | 
 | 2404 | // | 
 | 2405 | // The semantics of these arrays differ from CanvasPixelArray. | 
 | 2406 | // Out-of-range values passed to the setter are converted via a C | 
 | 2407 | // cast, not clamping. Out-of-range indices cause exceptions to be | 
 | 2408 | // raised rather than being silently ignored. | 
 | 2409 | class ExternalArray: public Array { | 
 | 2410 |  public: | 
 | 2411 |   // [external_pointer]: The pointer to the external memory area backing this | 
 | 2412 |   // external array. | 
 | 2413 |   DECL_ACCESSORS(external_pointer, void)  // Pointer to the data store. | 
 | 2414 |  | 
 | 2415 |   // Casting. | 
 | 2416 |   static inline ExternalArray* cast(Object* obj); | 
 | 2417 |  | 
 | 2418 |   // Maximal acceptable length for an external array. | 
 | 2419 |   static const int kMaxLength = 0x3fffffff; | 
 | 2420 |  | 
 | 2421 |   // ExternalArray headers are not quadword aligned. | 
 | 2422 |   static const int kExternalPointerOffset = Array::kAlignedSize; | 
 | 2423 |   static const int kHeaderSize = kExternalPointerOffset + kPointerSize; | 
 | 2424 |   static const int kAlignedSize = OBJECT_SIZE_ALIGN(kHeaderSize); | 
 | 2425 |  | 
 | 2426 |  private: | 
 | 2427 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray); | 
 | 2428 | }; | 
 | 2429 |  | 
 | 2430 |  | 
 | 2431 | class ExternalByteArray: public ExternalArray { | 
 | 2432 |  public: | 
 | 2433 |   // Setter and getter. | 
 | 2434 |   inline int8_t get(int index); | 
 | 2435 |   inline void set(int index, int8_t value); | 
 | 2436 |  | 
 | 2437 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2438 |   // and undefined. | 
 | 2439 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2440 |  | 
 | 2441 |   // Casting. | 
 | 2442 |   static inline ExternalByteArray* cast(Object* obj); | 
 | 2443 |  | 
 | 2444 | #ifdef DEBUG | 
 | 2445 |   void ExternalByteArrayPrint(); | 
 | 2446 |   void ExternalByteArrayVerify(); | 
 | 2447 | #endif  // DEBUG | 
 | 2448 |  | 
 | 2449 |  private: | 
 | 2450 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray); | 
 | 2451 | }; | 
 | 2452 |  | 
 | 2453 |  | 
 | 2454 | class ExternalUnsignedByteArray: public ExternalArray { | 
 | 2455 |  public: | 
 | 2456 |   // Setter and getter. | 
 | 2457 |   inline uint8_t get(int index); | 
 | 2458 |   inline void set(int index, uint8_t value); | 
 | 2459 |  | 
 | 2460 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2461 |   // and undefined. | 
 | 2462 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2463 |  | 
 | 2464 |   // Casting. | 
 | 2465 |   static inline ExternalUnsignedByteArray* cast(Object* obj); | 
 | 2466 |  | 
 | 2467 | #ifdef DEBUG | 
 | 2468 |   void ExternalUnsignedByteArrayPrint(); | 
 | 2469 |   void ExternalUnsignedByteArrayVerify(); | 
 | 2470 | #endif  // DEBUG | 
 | 2471 |  | 
 | 2472 |  private: | 
 | 2473 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray); | 
 | 2474 | }; | 
 | 2475 |  | 
 | 2476 |  | 
 | 2477 | class ExternalShortArray: public ExternalArray { | 
 | 2478 |  public: | 
 | 2479 |   // Setter and getter. | 
 | 2480 |   inline int16_t get(int index); | 
 | 2481 |   inline void set(int index, int16_t value); | 
 | 2482 |  | 
 | 2483 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2484 |   // and undefined. | 
 | 2485 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2486 |  | 
 | 2487 |   // Casting. | 
 | 2488 |   static inline ExternalShortArray* cast(Object* obj); | 
 | 2489 |  | 
 | 2490 | #ifdef DEBUG | 
 | 2491 |   void ExternalShortArrayPrint(); | 
 | 2492 |   void ExternalShortArrayVerify(); | 
 | 2493 | #endif  // DEBUG | 
 | 2494 |  | 
 | 2495 |  private: | 
 | 2496 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray); | 
 | 2497 | }; | 
 | 2498 |  | 
 | 2499 |  | 
 | 2500 | class ExternalUnsignedShortArray: public ExternalArray { | 
 | 2501 |  public: | 
 | 2502 |   // Setter and getter. | 
 | 2503 |   inline uint16_t get(int index); | 
 | 2504 |   inline void set(int index, uint16_t value); | 
 | 2505 |  | 
 | 2506 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2507 |   // and undefined. | 
 | 2508 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2509 |  | 
 | 2510 |   // Casting. | 
 | 2511 |   static inline ExternalUnsignedShortArray* cast(Object* obj); | 
 | 2512 |  | 
 | 2513 | #ifdef DEBUG | 
 | 2514 |   void ExternalUnsignedShortArrayPrint(); | 
 | 2515 |   void ExternalUnsignedShortArrayVerify(); | 
 | 2516 | #endif  // DEBUG | 
 | 2517 |  | 
 | 2518 |  private: | 
 | 2519 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray); | 
 | 2520 | }; | 
 | 2521 |  | 
 | 2522 |  | 
 | 2523 | class ExternalIntArray: public ExternalArray { | 
 | 2524 |  public: | 
 | 2525 |   // Setter and getter. | 
 | 2526 |   inline int32_t get(int index); | 
 | 2527 |   inline void set(int index, int32_t value); | 
 | 2528 |  | 
 | 2529 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2530 |   // and undefined. | 
 | 2531 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2532 |  | 
 | 2533 |   // Casting. | 
 | 2534 |   static inline ExternalIntArray* cast(Object* obj); | 
 | 2535 |  | 
 | 2536 | #ifdef DEBUG | 
 | 2537 |   void ExternalIntArrayPrint(); | 
 | 2538 |   void ExternalIntArrayVerify(); | 
 | 2539 | #endif  // DEBUG | 
 | 2540 |  | 
 | 2541 |  private: | 
 | 2542 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray); | 
 | 2543 | }; | 
 | 2544 |  | 
 | 2545 |  | 
 | 2546 | class ExternalUnsignedIntArray: public ExternalArray { | 
 | 2547 |  public: | 
 | 2548 |   // Setter and getter. | 
 | 2549 |   inline uint32_t get(int index); | 
 | 2550 |   inline void set(int index, uint32_t value); | 
 | 2551 |  | 
 | 2552 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2553 |   // and undefined. | 
 | 2554 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2555 |  | 
 | 2556 |   // Casting. | 
 | 2557 |   static inline ExternalUnsignedIntArray* cast(Object* obj); | 
 | 2558 |  | 
 | 2559 | #ifdef DEBUG | 
 | 2560 |   void ExternalUnsignedIntArrayPrint(); | 
 | 2561 |   void ExternalUnsignedIntArrayVerify(); | 
 | 2562 | #endif  // DEBUG | 
 | 2563 |  | 
 | 2564 |  private: | 
 | 2565 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray); | 
 | 2566 | }; | 
 | 2567 |  | 
 | 2568 |  | 
 | 2569 | class ExternalFloatArray: public ExternalArray { | 
 | 2570 |  public: | 
 | 2571 |   // Setter and getter. | 
 | 2572 |   inline float get(int index); | 
 | 2573 |   inline void set(int index, float value); | 
 | 2574 |  | 
 | 2575 |   // This accessor applies the correct conversion from Smi, HeapNumber | 
 | 2576 |   // and undefined. | 
 | 2577 |   Object* SetValue(uint32_t index, Object* value); | 
 | 2578 |  | 
 | 2579 |   // Casting. | 
 | 2580 |   static inline ExternalFloatArray* cast(Object* obj); | 
 | 2581 |  | 
 | 2582 | #ifdef DEBUG | 
 | 2583 |   void ExternalFloatArrayPrint(); | 
 | 2584 |   void ExternalFloatArrayVerify(); | 
 | 2585 | #endif  // DEBUG | 
 | 2586 |  | 
 | 2587 |  private: | 
 | 2588 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray); | 
 | 2589 | }; | 
 | 2590 |  | 
 | 2591 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2592 | // Code describes objects with on-the-fly generated machine code. | 
 | 2593 | class Code: public HeapObject { | 
 | 2594 |  public: | 
 | 2595 |   // Opaque data type for encapsulating code flags like kind, inline | 
 | 2596 |   // cache state, and arguments count. | 
 | 2597 |   enum Flags { }; | 
 | 2598 |  | 
 | 2599 |   enum Kind { | 
 | 2600 |     FUNCTION, | 
 | 2601 |     STUB, | 
 | 2602 |     BUILTIN, | 
 | 2603 |     LOAD_IC, | 
 | 2604 |     KEYED_LOAD_IC, | 
 | 2605 |     CALL_IC, | 
 | 2606 |     STORE_IC, | 
 | 2607 |     KEYED_STORE_IC, | 
 | 2608 |     // No more than eight kinds. The value currently encoded in three bits in | 
 | 2609 |     // Flags. | 
 | 2610 |  | 
 | 2611 |     // Pseudo-kinds. | 
 | 2612 |     REGEXP = BUILTIN, | 
 | 2613 |     FIRST_IC_KIND = LOAD_IC, | 
 | 2614 |     LAST_IC_KIND = KEYED_STORE_IC | 
 | 2615 |   }; | 
 | 2616 |  | 
 | 2617 |   enum { | 
 | 2618 |     NUMBER_OF_KINDS = KEYED_STORE_IC + 1 | 
 | 2619 |   }; | 
 | 2620 |  | 
 | 2621 | #ifdef ENABLE_DISASSEMBLER | 
 | 2622 |   // Printing | 
 | 2623 |   static const char* Kind2String(Kind kind); | 
 | 2624 |   static const char* ICState2String(InlineCacheState state); | 
 | 2625 |   static const char* PropertyType2String(PropertyType type); | 
 | 2626 |   void Disassemble(const char* name); | 
 | 2627 | #endif  // ENABLE_DISASSEMBLER | 
 | 2628 |  | 
 | 2629 |   // [instruction_size]: Size of the native instructions | 
 | 2630 |   inline int instruction_size(); | 
 | 2631 |   inline void set_instruction_size(int value); | 
 | 2632 |  | 
 | 2633 |   // [relocation_size]: Size of relocation information. | 
 | 2634 |   inline int relocation_size(); | 
 | 2635 |   inline void set_relocation_size(int value); | 
 | 2636 |  | 
 | 2637 |   // [sinfo_size]: Size of scope information. | 
 | 2638 |   inline int sinfo_size(); | 
 | 2639 |   inline void set_sinfo_size(int value); | 
 | 2640 |  | 
 | 2641 |   // [flags]: Various code flags. | 
 | 2642 |   inline Flags flags(); | 
 | 2643 |   inline void set_flags(Flags flags); | 
 | 2644 |  | 
 | 2645 |   // [flags]: Access to specific code flags. | 
 | 2646 |   inline Kind kind(); | 
 | 2647 |   inline InlineCacheState ic_state();  // Only valid for IC stubs. | 
 | 2648 |   inline InLoopFlag ic_in_loop();  // Only valid for IC stubs. | 
 | 2649 |   inline PropertyType type();  // Only valid for monomorphic IC stubs. | 
 | 2650 |   inline int arguments_count();  // Only valid for call IC stubs. | 
 | 2651 |  | 
 | 2652 |   // Testers for IC stub kinds. | 
 | 2653 |   inline bool is_inline_cache_stub(); | 
 | 2654 |   inline bool is_load_stub() { return kind() == LOAD_IC; } | 
 | 2655 |   inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; } | 
 | 2656 |   inline bool is_store_stub() { return kind() == STORE_IC; } | 
 | 2657 |   inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; } | 
 | 2658 |   inline bool is_call_stub() { return kind() == CALL_IC; } | 
 | 2659 |  | 
 | 2660 |   // [major_key]: For kind STUB, the major key. | 
 | 2661 |   inline CodeStub::Major major_key(); | 
 | 2662 |   inline void set_major_key(CodeStub::Major major); | 
 | 2663 |  | 
 | 2664 |   // Flags operations. | 
 | 2665 |   static inline Flags ComputeFlags(Kind kind, | 
 | 2666 |                                    InLoopFlag in_loop = NOT_IN_LOOP, | 
 | 2667 |                                    InlineCacheState ic_state = UNINITIALIZED, | 
 | 2668 |                                    PropertyType type = NORMAL, | 
 | 2669 |                                    int argc = -1); | 
 | 2670 |  | 
 | 2671 |   static inline Flags ComputeMonomorphicFlags( | 
 | 2672 |       Kind kind, | 
 | 2673 |       PropertyType type, | 
 | 2674 |       InLoopFlag in_loop = NOT_IN_LOOP, | 
 | 2675 |       int argc = -1); | 
 | 2676 |  | 
 | 2677 |   static inline Kind ExtractKindFromFlags(Flags flags); | 
 | 2678 |   static inline InlineCacheState ExtractICStateFromFlags(Flags flags); | 
 | 2679 |   static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags); | 
 | 2680 |   static inline PropertyType ExtractTypeFromFlags(Flags flags); | 
 | 2681 |   static inline int ExtractArgumentsCountFromFlags(Flags flags); | 
 | 2682 |   static inline Flags RemoveTypeFromFlags(Flags flags); | 
 | 2683 |  | 
 | 2684 |   // Convert a target address into a code object. | 
 | 2685 |   static inline Code* GetCodeFromTargetAddress(Address address); | 
 | 2686 |  | 
 | 2687 |   // Returns the address of the first instruction. | 
 | 2688 |   inline byte* instruction_start(); | 
 | 2689 |  | 
 | 2690 |   // Returns the size of the instructions, padding, and relocation information. | 
 | 2691 |   inline int body_size(); | 
 | 2692 |  | 
 | 2693 |   // Returns the address of the first relocation info (read backwards!). | 
 | 2694 |   inline byte* relocation_start(); | 
 | 2695 |  | 
 | 2696 |   // Code entry point. | 
 | 2697 |   inline byte* entry(); | 
 | 2698 |  | 
 | 2699 |   // Returns true if pc is inside this object's instructions. | 
 | 2700 |   inline bool contains(byte* pc); | 
 | 2701 |  | 
 | 2702 |   // Returns the address of the scope information. | 
 | 2703 |   inline byte* sinfo_start(); | 
 | 2704 |  | 
 | 2705 |   // Relocate the code by delta bytes. Called to signal that this code | 
 | 2706 |   // object has been moved by delta bytes. | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 2707 |   void Relocate(intptr_t delta); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2708 |  | 
 | 2709 |   // Migrate code described by desc. | 
 | 2710 |   void CopyFrom(const CodeDesc& desc); | 
 | 2711 |  | 
 | 2712 |   // Returns the object size for a given body and sinfo size (Used for | 
 | 2713 |   // allocation). | 
 | 2714 |   static int SizeFor(int body_size, int sinfo_size) { | 
 | 2715 |     ASSERT_SIZE_TAG_ALIGNED(body_size); | 
 | 2716 |     ASSERT_SIZE_TAG_ALIGNED(sinfo_size); | 
 | 2717 |     return RoundUp(kHeaderSize + body_size + sinfo_size, kCodeAlignment); | 
 | 2718 |   } | 
 | 2719 |  | 
 | 2720 |   // Calculate the size of the code object to report for log events. This takes | 
 | 2721 |   // the layout of the code object into account. | 
 | 2722 |   int ExecutableSize() { | 
 | 2723 |     // Check that the assumptions about the layout of the code object holds. | 
 | 2724 |     ASSERT_EQ(static_cast<int>(instruction_start() - address()), | 
 | 2725 |               Code::kHeaderSize); | 
 | 2726 |     return instruction_size() + Code::kHeaderSize; | 
 | 2727 |   } | 
 | 2728 |  | 
 | 2729 |   // Locating source position. | 
 | 2730 |   int SourcePosition(Address pc); | 
 | 2731 |   int SourceStatementPosition(Address pc); | 
 | 2732 |  | 
 | 2733 |   // Casting. | 
 | 2734 |   static inline Code* cast(Object* obj); | 
 | 2735 |  | 
 | 2736 |   // Dispatched behavior. | 
 | 2737 |   int CodeSize() { return SizeFor(body_size(), sinfo_size()); } | 
 | 2738 |   void CodeIterateBody(ObjectVisitor* v); | 
 | 2739 | #ifdef DEBUG | 
 | 2740 |   void CodePrint(); | 
 | 2741 |   void CodeVerify(); | 
 | 2742 | #endif | 
 | 2743 |   // Code entry points are aligned to 32 bytes. | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 2744 |   static const int kCodeAlignmentBits = 5; | 
 | 2745 |   static const int kCodeAlignment = 1 << kCodeAlignmentBits; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2746 |   static const int kCodeAlignmentMask = kCodeAlignment - 1; | 
 | 2747 |  | 
 | 2748 |   // Layout description. | 
 | 2749 |   static const int kInstructionSizeOffset = HeapObject::kHeaderSize; | 
 | 2750 |   static const int kRelocationSizeOffset = kInstructionSizeOffset + kIntSize; | 
 | 2751 |   static const int kSInfoSizeOffset = kRelocationSizeOffset + kIntSize; | 
 | 2752 |   static const int kFlagsOffset = kSInfoSizeOffset + kIntSize; | 
 | 2753 |   static const int kKindSpecificFlagsOffset  = kFlagsOffset + kIntSize; | 
 | 2754 |   // Add padding to align the instruction start following right after | 
 | 2755 |   // the Code object header. | 
 | 2756 |   static const int kHeaderSize = | 
 | 2757 |       (kKindSpecificFlagsOffset + kIntSize + kCodeAlignmentMask) & | 
 | 2758 |           ~kCodeAlignmentMask; | 
 | 2759 |  | 
 | 2760 |   // Byte offsets within kKindSpecificFlagsOffset. | 
 | 2761 |   static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset + 1; | 
 | 2762 |  | 
 | 2763 |   // Flags layout. | 
 | 2764 |   static const int kFlagsICStateShift        = 0; | 
 | 2765 |   static const int kFlagsICInLoopShift       = 3; | 
 | 2766 |   static const int kFlagsKindShift           = 4; | 
 | 2767 |   static const int kFlagsTypeShift           = 7; | 
 | 2768 |   static const int kFlagsArgumentsCountShift = 10; | 
 | 2769 |  | 
 | 2770 |   static const int kFlagsICStateMask        = 0x00000007;  // 0000000111 | 
 | 2771 |   static const int kFlagsICInLoopMask       = 0x00000008;  // 0000001000 | 
 | 2772 |   static const int kFlagsKindMask           = 0x00000070;  // 0001110000 | 
 | 2773 |   static const int kFlagsTypeMask           = 0x00000380;  // 1110000000 | 
 | 2774 |   static const int kFlagsArgumentsCountMask = 0xFFFFFC00; | 
 | 2775 |  | 
 | 2776 |   static const int kFlagsNotUsedInLookup = | 
 | 2777 |       (kFlagsICInLoopMask | kFlagsTypeMask); | 
 | 2778 |  | 
 | 2779 |  private: | 
 | 2780 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Code); | 
 | 2781 | }; | 
 | 2782 |  | 
 | 2783 |  | 
 | 2784 | // All heap objects have a Map that describes their structure. | 
 | 2785 | //  A Map contains information about: | 
 | 2786 | //  - Size information about the object | 
 | 2787 | //  - How to iterate over an object (for garbage collection) | 
 | 2788 | class Map: public HeapObject { | 
 | 2789 |  public: | 
 | 2790 |   // Instance size. | 
 | 2791 |   inline int instance_size(); | 
 | 2792 |   inline void set_instance_size(int value); | 
 | 2793 |  | 
 | 2794 |   // Count of properties allocated in the object. | 
 | 2795 |   inline int inobject_properties(); | 
 | 2796 |   inline void set_inobject_properties(int value); | 
 | 2797 |  | 
 | 2798 |   // Count of property fields pre-allocated in the object when first allocated. | 
 | 2799 |   inline int pre_allocated_property_fields(); | 
 | 2800 |   inline void set_pre_allocated_property_fields(int value); | 
 | 2801 |  | 
 | 2802 |   // Instance type. | 
 | 2803 |   inline InstanceType instance_type(); | 
 | 2804 |   inline void set_instance_type(InstanceType value); | 
 | 2805 |  | 
 | 2806 |   // Tells how many unused property fields are available in the | 
 | 2807 |   // instance (only used for JSObject in fast mode). | 
 | 2808 |   inline int unused_property_fields(); | 
 | 2809 |   inline void set_unused_property_fields(int value); | 
 | 2810 |  | 
 | 2811 |   // Bit field. | 
 | 2812 |   inline byte bit_field(); | 
 | 2813 |   inline void set_bit_field(byte value); | 
 | 2814 |  | 
 | 2815 |   // Bit field 2. | 
 | 2816 |   inline byte bit_field2(); | 
 | 2817 |   inline void set_bit_field2(byte value); | 
 | 2818 |  | 
 | 2819 |   // Tells whether the object in the prototype property will be used | 
 | 2820 |   // for instances created from this function.  If the prototype | 
 | 2821 |   // property is set to a value that is not a JSObject, the prototype | 
 | 2822 |   // property will not be used to create instances of the function. | 
 | 2823 |   // See ECMA-262, 13.2.2. | 
 | 2824 |   inline void set_non_instance_prototype(bool value); | 
 | 2825 |   inline bool has_non_instance_prototype(); | 
 | 2826 |  | 
 | 2827 |   // Tells whether the instance with this map should be ignored by the | 
 | 2828 |   // __proto__ accessor. | 
 | 2829 |   inline void set_is_hidden_prototype() { | 
 | 2830 |     set_bit_field(bit_field() | (1 << kIsHiddenPrototype)); | 
 | 2831 |   } | 
 | 2832 |  | 
 | 2833 |   inline bool is_hidden_prototype() { | 
 | 2834 |     return ((1 << kIsHiddenPrototype) & bit_field()) != 0; | 
 | 2835 |   } | 
 | 2836 |  | 
 | 2837 |   // Records and queries whether the instance has a named interceptor. | 
 | 2838 |   inline void set_has_named_interceptor() { | 
 | 2839 |     set_bit_field(bit_field() | (1 << kHasNamedInterceptor)); | 
 | 2840 |   } | 
 | 2841 |  | 
 | 2842 |   inline bool has_named_interceptor() { | 
 | 2843 |     return ((1 << kHasNamedInterceptor) & bit_field()) != 0; | 
 | 2844 |   } | 
 | 2845 |  | 
 | 2846 |   // Records and queries whether the instance has an indexed interceptor. | 
 | 2847 |   inline void set_has_indexed_interceptor() { | 
 | 2848 |     set_bit_field(bit_field() | (1 << kHasIndexedInterceptor)); | 
 | 2849 |   } | 
 | 2850 |  | 
 | 2851 |   inline bool has_indexed_interceptor() { | 
 | 2852 |     return ((1 << kHasIndexedInterceptor) & bit_field()) != 0; | 
 | 2853 |   } | 
 | 2854 |  | 
 | 2855 |   // Tells whether the instance is undetectable. | 
 | 2856 |   // An undetectable object is a special class of JSObject: 'typeof' operator | 
 | 2857 |   // returns undefined, ToBoolean returns false. Otherwise it behaves like | 
 | 2858 |   // a normal JS object.  It is useful for implementing undetectable | 
 | 2859 |   // document.all in Firefox & Safari. | 
 | 2860 |   // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549. | 
 | 2861 |   inline void set_is_undetectable() { | 
 | 2862 |     set_bit_field(bit_field() | (1 << kIsUndetectable)); | 
 | 2863 |   } | 
 | 2864 |  | 
 | 2865 |   inline bool is_undetectable() { | 
 | 2866 |     return ((1 << kIsUndetectable) & bit_field()) != 0; | 
 | 2867 |   } | 
 | 2868 |  | 
 | 2869 |   inline void set_needs_loading(bool value) { | 
 | 2870 |     if (value) { | 
 | 2871 |       set_bit_field2(bit_field2() | (1 << kNeedsLoading)); | 
 | 2872 |     } else { | 
 | 2873 |       set_bit_field2(bit_field2() & ~(1 << kNeedsLoading)); | 
 | 2874 |     } | 
 | 2875 |   } | 
 | 2876 |  | 
 | 2877 |   // Does this object or function require a lazily loaded script to be | 
 | 2878 |   // run before being used? | 
 | 2879 |   inline bool needs_loading() { | 
 | 2880 |     return ((1 << kNeedsLoading) & bit_field2()) != 0; | 
 | 2881 |   } | 
 | 2882 |  | 
 | 2883 |   // Tells whether the instance has a call-as-function handler. | 
 | 2884 |   inline void set_has_instance_call_handler() { | 
 | 2885 |     set_bit_field(bit_field() | (1 << kHasInstanceCallHandler)); | 
 | 2886 |   } | 
 | 2887 |  | 
 | 2888 |   inline bool has_instance_call_handler() { | 
 | 2889 |     return ((1 << kHasInstanceCallHandler) & bit_field()) != 0; | 
 | 2890 |   } | 
 | 2891 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 2892 |   inline void set_is_extensible() { | 
 | 2893 |     set_bit_field2(bit_field2() | (1 << kIsExtensible)); | 
 | 2894 |   } | 
 | 2895 |  | 
 | 2896 |   inline bool is_extensible() { | 
 | 2897 |     return ((1 << kIsExtensible) & bit_field2()) != 0; | 
 | 2898 |   } | 
 | 2899 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2900 |   // Tells whether the instance needs security checks when accessing its | 
 | 2901 |   // properties. | 
 | 2902 |   inline void set_is_access_check_needed(bool access_check_needed); | 
 | 2903 |   inline bool is_access_check_needed(); | 
 | 2904 |  | 
 | 2905 |   // [prototype]: implicit prototype object. | 
 | 2906 |   DECL_ACCESSORS(prototype, Object) | 
 | 2907 |  | 
 | 2908 |   // [constructor]: points back to the function responsible for this map. | 
 | 2909 |   DECL_ACCESSORS(constructor, Object) | 
 | 2910 |  | 
 | 2911 |   // [instance descriptors]: describes the object. | 
 | 2912 |   DECL_ACCESSORS(instance_descriptors, DescriptorArray) | 
 | 2913 |  | 
 | 2914 |   // [stub cache]: contains stubs compiled for this map. | 
 | 2915 |   DECL_ACCESSORS(code_cache, FixedArray) | 
 | 2916 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2917 |   Object* CopyDropDescriptors(); | 
 | 2918 |  | 
 | 2919 |   // Returns a copy of the map, with all transitions dropped from the | 
 | 2920 |   // instance descriptors. | 
 | 2921 |   Object* CopyDropTransitions(); | 
 | 2922 |  | 
 | 2923 |   // Returns the property index for name (only valid for FAST MODE). | 
 | 2924 |   int PropertyIndexFor(String* name); | 
 | 2925 |  | 
 | 2926 |   // Returns the next free property index (only valid for FAST MODE). | 
 | 2927 |   int NextFreePropertyIndex(); | 
 | 2928 |  | 
 | 2929 |   // Returns the number of properties described in instance_descriptors. | 
 | 2930 |   int NumberOfDescribedProperties(); | 
 | 2931 |  | 
 | 2932 |   // Casting. | 
 | 2933 |   static inline Map* cast(Object* obj); | 
 | 2934 |  | 
 | 2935 |   // Locate an accessor in the instance descriptor. | 
 | 2936 |   AccessorDescriptor* FindAccessor(String* name); | 
 | 2937 |  | 
 | 2938 |   // Code cache operations. | 
 | 2939 |  | 
 | 2940 |   // Clears the code cache. | 
 | 2941 |   inline void ClearCodeCache(); | 
 | 2942 |  | 
 | 2943 |   // Update code cache. | 
 | 2944 |   Object* UpdateCodeCache(String* name, Code* code); | 
 | 2945 |  | 
 | 2946 |   // Returns the found code or undefined if absent. | 
 | 2947 |   Object* FindInCodeCache(String* name, Code::Flags flags); | 
 | 2948 |  | 
 | 2949 |   // Returns the non-negative index of the code object if it is in the | 
 | 2950 |   // cache and -1 otherwise. | 
 | 2951 |   int IndexInCodeCache(Code* code); | 
 | 2952 |  | 
 | 2953 |   // Removes a code object from the code cache at the given index. | 
 | 2954 |   void RemoveFromCodeCache(int index); | 
 | 2955 |  | 
 | 2956 |   // For every transition in this map, makes the transition's | 
 | 2957 |   // target's prototype pointer point back to this map. | 
 | 2958 |   // This is undone in MarkCompactCollector::ClearNonLiveTransitions(). | 
 | 2959 |   void CreateBackPointers(); | 
 | 2960 |  | 
 | 2961 |   // Set all map transitions from this map to dead maps to null. | 
 | 2962 |   // Also, restore the original prototype on the targets of these | 
 | 2963 |   // transitions, so that we do not process this map again while | 
 | 2964 |   // following back pointers. | 
 | 2965 |   void ClearNonLiveTransitions(Object* real_prototype); | 
 | 2966 |  | 
 | 2967 |   // Dispatched behavior. | 
 | 2968 |   void MapIterateBody(ObjectVisitor* v); | 
 | 2969 | #ifdef DEBUG | 
 | 2970 |   void MapPrint(); | 
 | 2971 |   void MapVerify(); | 
 | 2972 | #endif | 
 | 2973 |  | 
 | 2974 |   static const int kMaxPreAllocatedPropertyFields = 255; | 
 | 2975 |  | 
 | 2976 |   // Layout description. | 
 | 2977 |   static const int kInstanceSizesOffset = HeapObject::kHeaderSize; | 
 | 2978 |   static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize; | 
 | 2979 |   static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize; | 
 | 2980 |   static const int kConstructorOffset = kPrototypeOffset + kPointerSize; | 
 | 2981 |   static const int kInstanceDescriptorsOffset = | 
 | 2982 |       kConstructorOffset + kPointerSize; | 
 | 2983 |   static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 2984 |   static const int kPadStart = kCodeCacheOffset + kPointerSize; | 
 | 2985 |   static const int kSize = MAP_SIZE_ALIGN(kPadStart); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2986 |  | 
 | 2987 |   // Byte offsets within kInstanceSizesOffset. | 
 | 2988 |   static const int kInstanceSizeOffset = kInstanceSizesOffset + 0; | 
 | 2989 |   static const int kInObjectPropertiesByte = 1; | 
 | 2990 |   static const int kInObjectPropertiesOffset = | 
 | 2991 |       kInstanceSizesOffset + kInObjectPropertiesByte; | 
 | 2992 |   static const int kPreAllocatedPropertyFieldsByte = 2; | 
 | 2993 |   static const int kPreAllocatedPropertyFieldsOffset = | 
 | 2994 |       kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte; | 
 | 2995 |   // The byte at position 3 is not in use at the moment. | 
 | 2996 |  | 
 | 2997 |   // Byte offsets within kInstanceAttributesOffset attributes. | 
 | 2998 |   static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0; | 
 | 2999 |   static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1; | 
 | 3000 |   static const int kBitFieldOffset = kInstanceAttributesOffset + 2; | 
 | 3001 |   static const int kBitField2Offset = kInstanceAttributesOffset + 3; | 
 | 3002 |  | 
 | 3003 |   STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset); | 
 | 3004 |  | 
 | 3005 |   // Bit positions for bit field. | 
 | 3006 |   static const int kUnused = 0;  // To be used for marking recently used maps. | 
 | 3007 |   static const int kHasNonInstancePrototype = 1; | 
 | 3008 |   static const int kIsHiddenPrototype = 2; | 
 | 3009 |   static const int kHasNamedInterceptor = 3; | 
 | 3010 |   static const int kHasIndexedInterceptor = 4; | 
 | 3011 |   static const int kIsUndetectable = 5; | 
 | 3012 |   static const int kHasInstanceCallHandler = 6; | 
 | 3013 |   static const int kIsAccessCheckNeeded = 7; | 
 | 3014 |  | 
 | 3015 |   // Bit positions for bit field 2 | 
 | 3016 |   static const int kNeedsLoading = 0; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 3017 |   static const int kIsExtensible = 1; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3018 |  | 
 | 3019 |  private: | 
 | 3020 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Map); | 
 | 3021 | }; | 
 | 3022 |  | 
 | 3023 |  | 
 | 3024 | // An abstract superclass, a marker class really, for simple structure classes. | 
 | 3025 | // It doesn't carry much functionality but allows struct classes to me | 
 | 3026 | // identified in the type system. | 
 | 3027 | class Struct: public HeapObject { | 
 | 3028 |  public: | 
 | 3029 |   inline void InitializeBody(int object_size); | 
 | 3030 |   static inline Struct* cast(Object* that); | 
 | 3031 | }; | 
 | 3032 |  | 
 | 3033 |  | 
 | 3034 | // Script describes a script which has been added to the VM. | 
 | 3035 | class Script: public Struct { | 
 | 3036 |  public: | 
 | 3037 |   // Script types. | 
 | 3038 |   enum Type { | 
 | 3039 |     TYPE_NATIVE = 0, | 
 | 3040 |     TYPE_EXTENSION = 1, | 
 | 3041 |     TYPE_NORMAL = 2 | 
 | 3042 |   }; | 
 | 3043 |  | 
 | 3044 |   // Script compilation types. | 
 | 3045 |   enum CompilationType { | 
 | 3046 |     COMPILATION_TYPE_HOST = 0, | 
 | 3047 |     COMPILATION_TYPE_EVAL = 1, | 
 | 3048 |     COMPILATION_TYPE_JSON = 2 | 
 | 3049 |   }; | 
 | 3050 |  | 
 | 3051 |   // [source]: the script source. | 
 | 3052 |   DECL_ACCESSORS(source, Object) | 
 | 3053 |  | 
 | 3054 |   // [name]: the script name. | 
 | 3055 |   DECL_ACCESSORS(name, Object) | 
 | 3056 |  | 
 | 3057 |   // [id]: the script id. | 
 | 3058 |   DECL_ACCESSORS(id, Object) | 
 | 3059 |  | 
 | 3060 |   // [line_offset]: script line offset in resource from where it was extracted. | 
 | 3061 |   DECL_ACCESSORS(line_offset, Smi) | 
 | 3062 |  | 
 | 3063 |   // [column_offset]: script column offset in resource from where it was | 
 | 3064 |   // extracted. | 
 | 3065 |   DECL_ACCESSORS(column_offset, Smi) | 
 | 3066 |  | 
 | 3067 |   // [data]: additional data associated with this script. | 
 | 3068 |   DECL_ACCESSORS(data, Object) | 
 | 3069 |  | 
 | 3070 |   // [context_data]: context data for the context this script was compiled in. | 
 | 3071 |   DECL_ACCESSORS(context_data, Object) | 
 | 3072 |  | 
 | 3073 |   // [wrapper]: the wrapper cache. | 
 | 3074 |   DECL_ACCESSORS(wrapper, Proxy) | 
 | 3075 |  | 
 | 3076 |   // [type]: the script type. | 
 | 3077 |   DECL_ACCESSORS(type, Smi) | 
 | 3078 |  | 
 | 3079 |   // [compilation]: how the the script was compiled. | 
 | 3080 |   DECL_ACCESSORS(compilation_type, Smi) | 
 | 3081 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3082 |   // [line_ends]: FixedArray of line ends positions. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3083 |   DECL_ACCESSORS(line_ends, Object) | 
 | 3084 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3085 |   // [eval_from_shared]: for eval scripts the shared funcion info for the | 
 | 3086 |   // function from which eval was called. | 
 | 3087 |   DECL_ACCESSORS(eval_from_shared, Object) | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3088 |  | 
 | 3089 |   // [eval_from_instructions_offset]: the instruction offset in the code for the | 
 | 3090 |   // function from which eval was called where eval was called. | 
 | 3091 |   DECL_ACCESSORS(eval_from_instructions_offset, Smi) | 
 | 3092 |  | 
 | 3093 |   static inline Script* cast(Object* obj); | 
 | 3094 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 3095 |   // If script source is an external string, check that the underlying | 
 | 3096 |   // resource is accessible. Otherwise, always return true. | 
 | 3097 |   inline bool HasValidSource(); | 
 | 3098 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3099 | #ifdef DEBUG | 
 | 3100 |   void ScriptPrint(); | 
 | 3101 |   void ScriptVerify(); | 
 | 3102 | #endif | 
 | 3103 |  | 
 | 3104 |   static const int kSourceOffset = HeapObject::kHeaderSize; | 
 | 3105 |   static const int kNameOffset = kSourceOffset + kPointerSize; | 
 | 3106 |   static const int kLineOffsetOffset = kNameOffset + kPointerSize; | 
 | 3107 |   static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize; | 
 | 3108 |   static const int kDataOffset = kColumnOffsetOffset + kPointerSize; | 
 | 3109 |   static const int kContextOffset = kDataOffset + kPointerSize; | 
 | 3110 |   static const int kWrapperOffset = kContextOffset + kPointerSize; | 
 | 3111 |   static const int kTypeOffset = kWrapperOffset + kPointerSize; | 
 | 3112 |   static const int kCompilationTypeOffset = kTypeOffset + kPointerSize; | 
 | 3113 |   static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize; | 
 | 3114 |   static const int kIdOffset = kLineEndsOffset + kPointerSize; | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3115 |   static const int kEvalFromSharedOffset = kIdOffset + kPointerSize; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3116 |   static const int kEvalFrominstructionsOffsetOffset = | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3117 |       kEvalFromSharedOffset + kPointerSize; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3118 |   static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize; | 
 | 3119 |  | 
 | 3120 |  private: | 
 | 3121 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Script); | 
 | 3122 | }; | 
 | 3123 |  | 
 | 3124 |  | 
 | 3125 | // SharedFunctionInfo describes the JSFunction information that can be | 
 | 3126 | // shared by multiple instances of the function. | 
 | 3127 | class SharedFunctionInfo: public HeapObject { | 
 | 3128 |  public: | 
 | 3129 |   // [name]: Function name. | 
 | 3130 |   DECL_ACCESSORS(name, Object) | 
 | 3131 |  | 
 | 3132 |   // [code]: Function code. | 
 | 3133 |   DECL_ACCESSORS(code, Code) | 
 | 3134 |  | 
 | 3135 |   // [construct stub]: Code stub for constructing instances of this function. | 
 | 3136 |   DECL_ACCESSORS(construct_stub, Code) | 
 | 3137 |  | 
 | 3138 |   // Returns if this function has been compiled to native code yet. | 
 | 3139 |   inline bool is_compiled(); | 
 | 3140 |  | 
 | 3141 |   // [length]: The function length - usually the number of declared parameters. | 
 | 3142 |   // Use up to 2^30 parameters. | 
 | 3143 |   inline int length(); | 
 | 3144 |   inline void set_length(int value); | 
 | 3145 |  | 
 | 3146 |   // [formal parameter count]: The declared number of parameters. | 
 | 3147 |   inline int formal_parameter_count(); | 
 | 3148 |   inline void set_formal_parameter_count(int value); | 
 | 3149 |  | 
 | 3150 |   // Set the formal parameter count so the function code will be | 
 | 3151 |   // called without using argument adaptor frames. | 
 | 3152 |   inline void DontAdaptArguments(); | 
 | 3153 |  | 
 | 3154 |   // [expected_nof_properties]: Expected number of properties for the function. | 
 | 3155 |   inline int expected_nof_properties(); | 
 | 3156 |   inline void set_expected_nof_properties(int value); | 
 | 3157 |  | 
 | 3158 |   // [instance class name]: class name for instances. | 
 | 3159 |   DECL_ACCESSORS(instance_class_name, Object) | 
 | 3160 |  | 
 | 3161 |   // [function data]: This field has been added for make benefit the API. | 
 | 3162 |   // In the long run we don't want all functions to have this field but | 
 | 3163 |   // we can fix that when we have a better model for storing hidden data | 
 | 3164 |   // on objects. | 
 | 3165 |   DECL_ACCESSORS(function_data, Object) | 
 | 3166 |  | 
 | 3167 |   // [script info]: Script from which the function originates. | 
 | 3168 |   DECL_ACCESSORS(script, Object) | 
 | 3169 |  | 
 | 3170 |   // [start_position_and_type]: Field used to store both the source code | 
 | 3171 |   // position, whether or not the function is a function expression, | 
 | 3172 |   // and whether or not the function is a toplevel function. The two | 
 | 3173 |   // least significants bit indicates whether the function is an | 
 | 3174 |   // expression and the rest contains the source code position. | 
 | 3175 |   inline int start_position_and_type(); | 
 | 3176 |   inline void set_start_position_and_type(int value); | 
 | 3177 |  | 
 | 3178 |   // [debug info]: Debug information. | 
 | 3179 |   DECL_ACCESSORS(debug_info, Object) | 
 | 3180 |  | 
 | 3181 |   // [inferred name]: Name inferred from variable or property | 
 | 3182 |   // assignment of this function. Used to facilitate debugging and | 
 | 3183 |   // profiling of JavaScript code written in OO style, where almost | 
 | 3184 |   // all functions are anonymous but are assigned to object | 
 | 3185 |   // properties. | 
 | 3186 |   DECL_ACCESSORS(inferred_name, String) | 
 | 3187 |  | 
 | 3188 |   // Position of the 'function' token in the script source. | 
 | 3189 |   inline int function_token_position(); | 
 | 3190 |   inline void set_function_token_position(int function_token_position); | 
 | 3191 |  | 
 | 3192 |   // Position of this function in the script source. | 
 | 3193 |   inline int start_position(); | 
 | 3194 |   inline void set_start_position(int start_position); | 
 | 3195 |  | 
 | 3196 |   // End position of this function in the script source. | 
 | 3197 |   inline int end_position(); | 
 | 3198 |   inline void set_end_position(int end_position); | 
 | 3199 |  | 
 | 3200 |   // Is this function a function expression in the source code. | 
 | 3201 |   inline bool is_expression(); | 
 | 3202 |   inline void set_is_expression(bool value); | 
 | 3203 |  | 
 | 3204 |   // Is this function a top-level function (scripts, evals). | 
 | 3205 |   inline bool is_toplevel(); | 
 | 3206 |   inline void set_is_toplevel(bool value); | 
 | 3207 |  | 
 | 3208 |   // Bit field containing various information collected by the compiler to | 
 | 3209 |   // drive optimization. | 
 | 3210 |   inline int compiler_hints(); | 
 | 3211 |   inline void set_compiler_hints(int value); | 
 | 3212 |  | 
 | 3213 |   // Add information on assignments of the form this.x = ...; | 
 | 3214 |   void SetThisPropertyAssignmentsInfo( | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3215 |       bool has_only_simple_this_property_assignments, | 
 | 3216 |       FixedArray* this_property_assignments); | 
 | 3217 |  | 
 | 3218 |   // Clear information on assignments of the form this.x = ...; | 
 | 3219 |   void ClearThisPropertyAssignmentsInfo(); | 
 | 3220 |  | 
 | 3221 |   // Indicate that this function only consists of assignments of the form | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3222 |   // this.x = y; where y is either a constant or refers to an argument. | 
 | 3223 |   inline bool has_only_simple_this_property_assignments(); | 
 | 3224 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3225 |   inline bool try_fast_codegen(); | 
 | 3226 |   inline void set_try_fast_codegen(bool flag); | 
 | 3227 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3228 |   // For functions which only contains this property assignments this provides | 
 | 3229 |   // access to the names for the properties assigned. | 
 | 3230 |   DECL_ACCESSORS(this_property_assignments, Object) | 
 | 3231 |   inline int this_property_assignments_count(); | 
 | 3232 |   inline void set_this_property_assignments_count(int value); | 
 | 3233 |   String* GetThisPropertyAssignmentName(int index); | 
 | 3234 |   bool IsThisPropertyAssignmentArgument(int index); | 
 | 3235 |   int GetThisPropertyAssignmentArgument(int index); | 
 | 3236 |   Object* GetThisPropertyAssignmentConstant(int index); | 
 | 3237 |  | 
 | 3238 |   // [source code]: Source code for the function. | 
 | 3239 |   bool HasSourceCode(); | 
 | 3240 |   Object* GetSourceCode(); | 
 | 3241 |  | 
 | 3242 |   // Calculate the instance size. | 
 | 3243 |   int CalculateInstanceSize(); | 
 | 3244 |  | 
 | 3245 |   // Calculate the number of in-object properties. | 
 | 3246 |   int CalculateInObjectProperties(); | 
 | 3247 |  | 
 | 3248 |   // Dispatched behavior. | 
 | 3249 |   void SharedFunctionInfoIterateBody(ObjectVisitor* v); | 
 | 3250 |   // Set max_length to -1 for unlimited length. | 
 | 3251 |   void SourceCodePrint(StringStream* accumulator, int max_length); | 
 | 3252 | #ifdef DEBUG | 
 | 3253 |   void SharedFunctionInfoPrint(); | 
 | 3254 |   void SharedFunctionInfoVerify(); | 
 | 3255 | #endif | 
 | 3256 |  | 
 | 3257 |   // Casting. | 
 | 3258 |   static inline SharedFunctionInfo* cast(Object* obj); | 
 | 3259 |  | 
 | 3260 |   // Constants. | 
 | 3261 |   static const int kDontAdaptArgumentsSentinel = -1; | 
 | 3262 |  | 
 | 3263 |   // Layout description. | 
 | 3264 |   // (An even number of integers has a size that is a multiple of a pointer.) | 
 | 3265 |   static const int kNameOffset = HeapObject::kHeaderSize; | 
 | 3266 |   static const int kCodeOffset = kNameOffset + kPointerSize; | 
 | 3267 |   static const int kConstructStubOffset = kCodeOffset + kPointerSize; | 
 | 3268 |   static const int kLengthOffset = kConstructStubOffset + kPointerSize; | 
 | 3269 |   static const int kFormalParameterCountOffset = kLengthOffset + kIntSize; | 
 | 3270 |   static const int kExpectedNofPropertiesOffset = | 
 | 3271 |       kFormalParameterCountOffset + kIntSize; | 
 | 3272 |   static const int kStartPositionAndTypeOffset = | 
 | 3273 |       kExpectedNofPropertiesOffset + kIntSize; | 
 | 3274 |   static const int kEndPositionOffset = kStartPositionAndTypeOffset + kIntSize; | 
 | 3275 |   static const int kFunctionTokenPositionOffset = kEndPositionOffset + kIntSize; | 
 | 3276 |   static const int kInstanceClassNameOffset = | 
 | 3277 |       kFunctionTokenPositionOffset + kIntSize; | 
 | 3278 |   static const int kExternalReferenceDataOffset = | 
 | 3279 |       kInstanceClassNameOffset + kPointerSize; | 
 | 3280 |   static const int kScriptOffset = kExternalReferenceDataOffset + kPointerSize; | 
 | 3281 |   static const int kDebugInfoOffset = kScriptOffset + kPointerSize; | 
 | 3282 |   static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize; | 
 | 3283 |   static const int kCompilerHintsOffset = kInferredNameOffset + kPointerSize; | 
 | 3284 |   static const int kThisPropertyAssignmentsOffset = | 
 | 3285 |       kCompilerHintsOffset + kPointerSize; | 
 | 3286 |   static const int kThisPropertyAssignmentsCountOffset = | 
 | 3287 |       kThisPropertyAssignmentsOffset + kPointerSize; | 
 | 3288 |   static const int kSize = kThisPropertyAssignmentsCountOffset + kPointerSize; | 
 | 3289 |  | 
 | 3290 |  private: | 
 | 3291 |   // Bit positions in length_and_flg. | 
 | 3292 |   // The least significant bit is used as the flag. | 
 | 3293 |   static const int kFlagBit         = 0; | 
 | 3294 |   static const int kLengthShift     = 1; | 
 | 3295 |   static const int kLengthMask      = ~((1 << kLengthShift) - 1); | 
 | 3296 |  | 
 | 3297 |   // Bit positions in start_position_and_type. | 
 | 3298 |   // The source code start position is in the 30 most significant bits of | 
 | 3299 |   // the start_position_and_type field. | 
 | 3300 |   static const int kIsExpressionBit = 0; | 
 | 3301 |   static const int kIsTopLevelBit   = 1; | 
 | 3302 |   static const int kStartPositionShift = 2; | 
 | 3303 |   static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1); | 
 | 3304 |  | 
 | 3305 |   // Bit positions in compiler_hints. | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3306 |   static const int kHasOnlySimpleThisPropertyAssignments = 0; | 
 | 3307 |   static const int kTryFastCodegen = 1; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3308 |  | 
 | 3309 |   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo); | 
 | 3310 | }; | 
 | 3311 |  | 
 | 3312 |  | 
 | 3313 | // JSFunction describes JavaScript functions. | 
 | 3314 | class JSFunction: public JSObject { | 
 | 3315 |  public: | 
 | 3316 |   // [prototype_or_initial_map]: | 
 | 3317 |   DECL_ACCESSORS(prototype_or_initial_map, Object) | 
 | 3318 |  | 
 | 3319 |   // [shared_function_info]: The information about the function that | 
 | 3320 |   // can be shared by instances. | 
 | 3321 |   DECL_ACCESSORS(shared, SharedFunctionInfo) | 
 | 3322 |  | 
 | 3323 |   // [context]: The context for this function. | 
 | 3324 |   inline Context* context(); | 
 | 3325 |   inline Object* unchecked_context(); | 
 | 3326 |   inline void set_context(Object* context); | 
 | 3327 |  | 
 | 3328 |   // [code]: The generated code object for this function.  Executed | 
 | 3329 |   // when the function is invoked, e.g. foo() or new foo(). See | 
 | 3330 |   // [[Call]] and [[Construct]] description in ECMA-262, section | 
 | 3331 |   // 8.6.2, page 27. | 
 | 3332 |   inline Code* code(); | 
 | 3333 |   inline void set_code(Code* value); | 
 | 3334 |  | 
 | 3335 |   // Tells whether this function is a context-independent boilerplate | 
 | 3336 |   // function. | 
 | 3337 |   inline bool IsBoilerplate(); | 
 | 3338 |  | 
 | 3339 |   // Tells whether this function is builtin. | 
 | 3340 |   inline bool IsBuiltin(); | 
 | 3341 |  | 
 | 3342 |   // [literals]: Fixed array holding the materialized literals. | 
 | 3343 |   // | 
 | 3344 |   // If the function contains object, regexp or array literals, the | 
 | 3345 |   // literals array prefix contains the object, regexp, and array | 
 | 3346 |   // function to be used when creating these literals.  This is | 
 | 3347 |   // necessary so that we do not dynamically lookup the object, regexp | 
 | 3348 |   // or array functions.  Performing a dynamic lookup, we might end up | 
 | 3349 |   // using the functions from a new context that we should not have | 
 | 3350 |   // access to. | 
 | 3351 |   DECL_ACCESSORS(literals, FixedArray) | 
 | 3352 |  | 
 | 3353 |   // The initial map for an object created by this constructor. | 
 | 3354 |   inline Map* initial_map(); | 
 | 3355 |   inline void set_initial_map(Map* value); | 
 | 3356 |   inline bool has_initial_map(); | 
 | 3357 |  | 
 | 3358 |   // Get and set the prototype property on a JSFunction. If the | 
 | 3359 |   // function has an initial map the prototype is set on the initial | 
 | 3360 |   // map. Otherwise, the prototype is put in the initial map field | 
 | 3361 |   // until an initial map is needed. | 
 | 3362 |   inline bool has_prototype(); | 
 | 3363 |   inline bool has_instance_prototype(); | 
 | 3364 |   inline Object* prototype(); | 
 | 3365 |   inline Object* instance_prototype(); | 
 | 3366 |   Object* SetInstancePrototype(Object* value); | 
 | 3367 |   Object* SetPrototype(Object* value); | 
 | 3368 |  | 
 | 3369 |   // Accessor for this function's initial map's [[class]] | 
 | 3370 |   // property. This is primarily used by ECMA native functions.  This | 
 | 3371 |   // method sets the class_name field of this function's initial map | 
 | 3372 |   // to a given value. It creates an initial map if this function does | 
 | 3373 |   // not have one. Note that this method does not copy the initial map | 
 | 3374 |   // if it has one already, but simply replaces it with the new value. | 
 | 3375 |   // Instances created afterwards will have a map whose [[class]] is | 
 | 3376 |   // set to 'value', but there is no guarantees on instances created | 
 | 3377 |   // before. | 
 | 3378 |   Object* SetInstanceClassName(String* name); | 
 | 3379 |  | 
 | 3380 |   // Returns if this function has been compiled to native code yet. | 
 | 3381 |   inline bool is_compiled(); | 
 | 3382 |  | 
 | 3383 |   // Casting. | 
 | 3384 |   static inline JSFunction* cast(Object* obj); | 
 | 3385 |  | 
 | 3386 |   // Dispatched behavior. | 
 | 3387 | #ifdef DEBUG | 
 | 3388 |   void JSFunctionPrint(); | 
 | 3389 |   void JSFunctionVerify(); | 
 | 3390 | #endif | 
 | 3391 |  | 
 | 3392 |   // Returns the number of allocated literals. | 
 | 3393 |   inline int NumberOfLiterals(); | 
 | 3394 |  | 
 | 3395 |   // Retrieve the global context from a function's literal array. | 
 | 3396 |   static Context* GlobalContextFromLiterals(FixedArray* literals); | 
 | 3397 |  | 
 | 3398 |   // Layout descriptors. | 
 | 3399 |   static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize; | 
 | 3400 |   static const int kSharedFunctionInfoOffset = | 
 | 3401 |       kPrototypeOrInitialMapOffset + kPointerSize; | 
 | 3402 |   static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize; | 
 | 3403 |   static const int kLiteralsOffset = kContextOffset + kPointerSize; | 
 | 3404 |   static const int kSize = kLiteralsOffset + kPointerSize; | 
 | 3405 |  | 
 | 3406 |   // Layout of the literals array. | 
 | 3407 |   static const int kLiteralsPrefixSize = 1; | 
 | 3408 |   static const int kLiteralGlobalContextIndex = 0; | 
 | 3409 |  private: | 
 | 3410 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction); | 
 | 3411 | }; | 
 | 3412 |  | 
 | 3413 |  | 
 | 3414 | // JSGlobalProxy's prototype must be a JSGlobalObject or null, | 
 | 3415 | // and the prototype is hidden. JSGlobalProxy always delegates | 
 | 3416 | // property accesses to its prototype if the prototype is not null. | 
 | 3417 | // | 
 | 3418 | // A JSGlobalProxy can be reinitialized which will preserve its identity. | 
 | 3419 | // | 
 | 3420 | // Accessing a JSGlobalProxy requires security check. | 
 | 3421 |  | 
 | 3422 | class JSGlobalProxy : public JSObject { | 
 | 3423 |  public: | 
 | 3424 |   // [context]: the owner global context of this proxy object. | 
 | 3425 |   // It is null value if this object is not used by any context. | 
 | 3426 |   DECL_ACCESSORS(context, Object) | 
 | 3427 |  | 
 | 3428 |   // Casting. | 
 | 3429 |   static inline JSGlobalProxy* cast(Object* obj); | 
 | 3430 |  | 
 | 3431 |   // Dispatched behavior. | 
 | 3432 | #ifdef DEBUG | 
 | 3433 |   void JSGlobalProxyPrint(); | 
 | 3434 |   void JSGlobalProxyVerify(); | 
 | 3435 | #endif | 
 | 3436 |  | 
 | 3437 |   // Layout description. | 
 | 3438 |   static const int kContextOffset = JSObject::kHeaderSize; | 
 | 3439 |   static const int kSize = kContextOffset + kPointerSize; | 
 | 3440 |  | 
 | 3441 |  private: | 
 | 3442 |  | 
 | 3443 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy); | 
 | 3444 | }; | 
 | 3445 |  | 
 | 3446 |  | 
 | 3447 | // Forward declaration. | 
 | 3448 | class JSBuiltinsObject; | 
 | 3449 |  | 
 | 3450 | // Common super class for JavaScript global objects and the special | 
 | 3451 | // builtins global objects. | 
 | 3452 | class GlobalObject: public JSObject { | 
 | 3453 |  public: | 
 | 3454 |   // [builtins]: the object holding the runtime routines written in JS. | 
 | 3455 |   DECL_ACCESSORS(builtins, JSBuiltinsObject) | 
 | 3456 |  | 
 | 3457 |   // [global context]: the global context corresponding to this global object. | 
 | 3458 |   DECL_ACCESSORS(global_context, Context) | 
 | 3459 |  | 
 | 3460 |   // [global receiver]: the global receiver object of the context | 
 | 3461 |   DECL_ACCESSORS(global_receiver, JSObject) | 
 | 3462 |  | 
 | 3463 |   // Retrieve the property cell used to store a property. | 
 | 3464 |   Object* GetPropertyCell(LookupResult* result); | 
 | 3465 |  | 
 | 3466 |   // Ensure that the global object has a cell for the given property name. | 
 | 3467 |   Object* EnsurePropertyCell(String* name); | 
 | 3468 |  | 
 | 3469 |   // Casting. | 
 | 3470 |   static inline GlobalObject* cast(Object* obj); | 
 | 3471 |  | 
 | 3472 |   // Layout description. | 
 | 3473 |   static const int kBuiltinsOffset = JSObject::kHeaderSize; | 
 | 3474 |   static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize; | 
 | 3475 |   static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize; | 
 | 3476 |   static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize; | 
 | 3477 |  | 
 | 3478 |  private: | 
 | 3479 |   friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs; | 
 | 3480 |  | 
 | 3481 |   DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject); | 
 | 3482 | }; | 
 | 3483 |  | 
 | 3484 |  | 
 | 3485 | // JavaScript global object. | 
 | 3486 | class JSGlobalObject: public GlobalObject { | 
 | 3487 |  public: | 
 | 3488 |  | 
 | 3489 |   // Casting. | 
 | 3490 |   static inline JSGlobalObject* cast(Object* obj); | 
 | 3491 |  | 
 | 3492 |   // Dispatched behavior. | 
 | 3493 | #ifdef DEBUG | 
 | 3494 |   void JSGlobalObjectPrint(); | 
 | 3495 |   void JSGlobalObjectVerify(); | 
 | 3496 | #endif | 
 | 3497 |  | 
 | 3498 |   // Layout description. | 
 | 3499 |   static const int kSize = GlobalObject::kHeaderSize; | 
 | 3500 |  | 
 | 3501 |  private: | 
 | 3502 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject); | 
 | 3503 | }; | 
 | 3504 |  | 
 | 3505 |  | 
 | 3506 | // Builtins global object which holds the runtime routines written in | 
 | 3507 | // JavaScript. | 
 | 3508 | class JSBuiltinsObject: public GlobalObject { | 
 | 3509 |  public: | 
 | 3510 |   // Accessors for the runtime routines written in JavaScript. | 
 | 3511 |   inline Object* javascript_builtin(Builtins::JavaScript id); | 
 | 3512 |   inline void set_javascript_builtin(Builtins::JavaScript id, Object* value); | 
 | 3513 |  | 
 | 3514 |   // Casting. | 
 | 3515 |   static inline JSBuiltinsObject* cast(Object* obj); | 
 | 3516 |  | 
 | 3517 |   // Dispatched behavior. | 
 | 3518 | #ifdef DEBUG | 
 | 3519 |   void JSBuiltinsObjectPrint(); | 
 | 3520 |   void JSBuiltinsObjectVerify(); | 
 | 3521 | #endif | 
 | 3522 |  | 
 | 3523 |   // Layout description.  The size of the builtins object includes | 
 | 3524 |   // room for one pointer per runtime routine written in javascript. | 
 | 3525 |   static const int kJSBuiltinsCount = Builtins::id_count; | 
 | 3526 |   static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize; | 
 | 3527 |   static const int kSize = | 
 | 3528 |       kJSBuiltinsOffset + (kJSBuiltinsCount * kPointerSize); | 
 | 3529 |  private: | 
 | 3530 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject); | 
 | 3531 | }; | 
 | 3532 |  | 
 | 3533 |  | 
 | 3534 | // Representation for JS Wrapper objects, String, Number, Boolean, Date, etc. | 
 | 3535 | class JSValue: public JSObject { | 
 | 3536 |  public: | 
 | 3537 |   // [value]: the object being wrapped. | 
 | 3538 |   DECL_ACCESSORS(value, Object) | 
 | 3539 |  | 
 | 3540 |   // Casting. | 
 | 3541 |   static inline JSValue* cast(Object* obj); | 
 | 3542 |  | 
 | 3543 |   // Dispatched behavior. | 
 | 3544 | #ifdef DEBUG | 
 | 3545 |   void JSValuePrint(); | 
 | 3546 |   void JSValueVerify(); | 
 | 3547 | #endif | 
 | 3548 |  | 
 | 3549 |   // Layout description. | 
 | 3550 |   static const int kValueOffset = JSObject::kHeaderSize; | 
 | 3551 |   static const int kSize = kValueOffset + kPointerSize; | 
 | 3552 |  | 
 | 3553 |  private: | 
 | 3554 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue); | 
 | 3555 | }; | 
 | 3556 |  | 
 | 3557 | // Regular expressions | 
 | 3558 | // The regular expression holds a single reference to a FixedArray in | 
 | 3559 | // the kDataOffset field. | 
 | 3560 | // The FixedArray contains the following data: | 
 | 3561 | // - tag : type of regexp implementation (not compiled yet, atom or irregexp) | 
 | 3562 | // - reference to the original source string | 
 | 3563 | // - reference to the original flag string | 
 | 3564 | // If it is an atom regexp | 
 | 3565 | // - a reference to a literal string to search for | 
 | 3566 | // If it is an irregexp regexp: | 
 | 3567 | // - a reference to code for ASCII inputs (bytecode or compiled). | 
 | 3568 | // - a reference to code for UC16 inputs (bytecode or compiled). | 
 | 3569 | // - max number of registers used by irregexp implementations. | 
 | 3570 | // - number of capture registers (output values) of the regexp. | 
 | 3571 | class JSRegExp: public JSObject { | 
 | 3572 |  public: | 
 | 3573 |   // Meaning of Type: | 
 | 3574 |   // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet. | 
 | 3575 |   // ATOM: A simple string to match against using an indexOf operation. | 
 | 3576 |   // IRREGEXP: Compiled with Irregexp. | 
 | 3577 |   // IRREGEXP_NATIVE: Compiled to native code with Irregexp. | 
 | 3578 |   enum Type { NOT_COMPILED, ATOM, IRREGEXP }; | 
 | 3579 |   enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 }; | 
 | 3580 |  | 
 | 3581 |   class Flags { | 
 | 3582 |    public: | 
 | 3583 |     explicit Flags(uint32_t value) : value_(value) { } | 
 | 3584 |     bool is_global() { return (value_ & GLOBAL) != 0; } | 
 | 3585 |     bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; } | 
 | 3586 |     bool is_multiline() { return (value_ & MULTILINE) != 0; } | 
 | 3587 |     uint32_t value() { return value_; } | 
 | 3588 |    private: | 
 | 3589 |     uint32_t value_; | 
 | 3590 |   }; | 
 | 3591 |  | 
 | 3592 |   DECL_ACCESSORS(data, Object) | 
 | 3593 |  | 
 | 3594 |   inline Type TypeTag(); | 
 | 3595 |   inline int CaptureCount(); | 
 | 3596 |   inline Flags GetFlags(); | 
 | 3597 |   inline String* Pattern(); | 
 | 3598 |   inline Object* DataAt(int index); | 
 | 3599 |   // Set implementation data after the object has been prepared. | 
 | 3600 |   inline void SetDataAt(int index, Object* value); | 
 | 3601 |   static int code_index(bool is_ascii) { | 
 | 3602 |     if (is_ascii) { | 
 | 3603 |       return kIrregexpASCIICodeIndex; | 
 | 3604 |     } else { | 
 | 3605 |       return kIrregexpUC16CodeIndex; | 
 | 3606 |     } | 
 | 3607 |   } | 
 | 3608 |  | 
 | 3609 |   static inline JSRegExp* cast(Object* obj); | 
 | 3610 |  | 
 | 3611 |   // Dispatched behavior. | 
 | 3612 | #ifdef DEBUG | 
 | 3613 |   void JSRegExpVerify(); | 
 | 3614 | #endif | 
 | 3615 |  | 
 | 3616 |   static const int kDataOffset = JSObject::kHeaderSize; | 
 | 3617 |   static const int kSize = kDataOffset + kPointerSize; | 
 | 3618 |  | 
 | 3619 |   // Indices in the data array. | 
 | 3620 |   static const int kTagIndex = 0; | 
 | 3621 |   static const int kSourceIndex = kTagIndex + 1; | 
 | 3622 |   static const int kFlagsIndex = kSourceIndex + 1; | 
 | 3623 |   static const int kDataIndex = kFlagsIndex + 1; | 
 | 3624 |   // The data fields are used in different ways depending on the | 
 | 3625 |   // value of the tag. | 
 | 3626 |   // Atom regexps (literal strings). | 
 | 3627 |   static const int kAtomPatternIndex = kDataIndex; | 
 | 3628 |  | 
 | 3629 |   static const int kAtomDataSize = kAtomPatternIndex + 1; | 
 | 3630 |  | 
 | 3631 |   // Irregexp compiled code or bytecode for ASCII. If compilation | 
 | 3632 |   // fails, this fields hold an exception object that should be | 
 | 3633 |   // thrown if the regexp is used again. | 
 | 3634 |   static const int kIrregexpASCIICodeIndex = kDataIndex; | 
 | 3635 |   // Irregexp compiled code or bytecode for UC16.  If compilation | 
 | 3636 |   // fails, this fields hold an exception object that should be | 
 | 3637 |   // thrown if the regexp is used again. | 
 | 3638 |   static const int kIrregexpUC16CodeIndex = kDataIndex + 1; | 
 | 3639 |   // Maximal number of registers used by either ASCII or UC16. | 
 | 3640 |   // Only used to check that there is enough stack space | 
 | 3641 |   static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 2; | 
 | 3642 |   // Number of captures in the compiled regexp. | 
 | 3643 |   static const int kIrregexpCaptureCountIndex = kDataIndex + 3; | 
 | 3644 |  | 
 | 3645 |   static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1; | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 3646 |  | 
 | 3647 |   // Offsets directly into the data fixed array. | 
 | 3648 |   static const int kDataTagOffset = | 
 | 3649 |       FixedArray::kHeaderSize + kTagIndex * kPointerSize; | 
 | 3650 |   static const int kDataAsciiCodeOffset = | 
 | 3651 |       FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize; | 
 | 3652 |   static const int kIrregexpCaptureCountOffset = | 
 | 3653 |       FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3654 | }; | 
 | 3655 |  | 
 | 3656 |  | 
 | 3657 | class CompilationCacheShape { | 
 | 3658 |  public: | 
 | 3659 |   static inline bool IsMatch(HashTableKey* key, Object* value) { | 
 | 3660 |     return key->IsMatch(value); | 
 | 3661 |   } | 
 | 3662 |  | 
 | 3663 |   static inline uint32_t Hash(HashTableKey* key) { | 
 | 3664 |     return key->Hash(); | 
 | 3665 |   } | 
 | 3666 |  | 
 | 3667 |   static inline uint32_t HashForObject(HashTableKey* key, Object* object) { | 
 | 3668 |     return key->HashForObject(object); | 
 | 3669 |   } | 
 | 3670 |  | 
 | 3671 |   static Object* AsObject(HashTableKey* key) { | 
 | 3672 |     return key->AsObject(); | 
 | 3673 |   } | 
 | 3674 |  | 
 | 3675 |   static const int kPrefixSize = 0; | 
 | 3676 |   static const int kEntrySize = 2; | 
 | 3677 | }; | 
 | 3678 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 3679 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3680 | class CompilationCacheTable: public HashTable<CompilationCacheShape, | 
 | 3681 |                                               HashTableKey*> { | 
 | 3682 |  public: | 
 | 3683 |   // Find cached value for a string key, otherwise return null. | 
 | 3684 |   Object* Lookup(String* src); | 
 | 3685 |   Object* LookupEval(String* src, Context* context); | 
 | 3686 |   Object* LookupRegExp(String* source, JSRegExp::Flags flags); | 
 | 3687 |   Object* Put(String* src, Object* value); | 
 | 3688 |   Object* PutEval(String* src, Context* context, Object* value); | 
 | 3689 |   Object* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value); | 
 | 3690 |  | 
 | 3691 |   static inline CompilationCacheTable* cast(Object* obj); | 
 | 3692 |  | 
 | 3693 |  private: | 
 | 3694 |   DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable); | 
 | 3695 | }; | 
 | 3696 |  | 
 | 3697 |  | 
 | 3698 | enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS}; | 
 | 3699 | enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL}; | 
 | 3700 |  | 
 | 3701 |  | 
 | 3702 | class StringHasher { | 
 | 3703 |  public: | 
 | 3704 |   inline StringHasher(int length); | 
 | 3705 |  | 
 | 3706 |   // Returns true if the hash of this string can be computed without | 
 | 3707 |   // looking at the contents. | 
 | 3708 |   inline bool has_trivial_hash(); | 
 | 3709 |  | 
 | 3710 |   // Add a character to the hash and update the array index calculation. | 
 | 3711 |   inline void AddCharacter(uc32 c); | 
 | 3712 |  | 
 | 3713 |   // Adds a character to the hash but does not update the array index | 
 | 3714 |   // calculation.  This can only be called when it has been verified | 
 | 3715 |   // that the input is not an array index. | 
 | 3716 |   inline void AddCharacterNoIndex(uc32 c); | 
 | 3717 |  | 
 | 3718 |   // Returns the value to store in the hash field of a string with | 
 | 3719 |   // the given length and contents. | 
 | 3720 |   uint32_t GetHashField(); | 
 | 3721 |  | 
 | 3722 |   // Returns true if the characters seen so far make up a legal array | 
 | 3723 |   // index. | 
 | 3724 |   bool is_array_index() { return is_array_index_; } | 
 | 3725 |  | 
 | 3726 |   bool is_valid() { return is_valid_; } | 
 | 3727 |  | 
 | 3728 |   void invalidate() { is_valid_ = false; } | 
 | 3729 |  | 
 | 3730 |  private: | 
 | 3731 |  | 
 | 3732 |   uint32_t array_index() { | 
 | 3733 |     ASSERT(is_array_index()); | 
 | 3734 |     return array_index_; | 
 | 3735 |   } | 
 | 3736 |  | 
 | 3737 |   inline uint32_t GetHash(); | 
 | 3738 |  | 
 | 3739 |   int length_; | 
 | 3740 |   uint32_t raw_running_hash_; | 
 | 3741 |   uint32_t array_index_; | 
 | 3742 |   bool is_array_index_; | 
 | 3743 |   bool is_first_char_; | 
 | 3744 |   bool is_valid_; | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3745 |   friend class TwoCharHashTableKey; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3746 | }; | 
 | 3747 |  | 
 | 3748 |  | 
 | 3749 | // The characteristics of a string are stored in its map.  Retrieving these | 
 | 3750 | // few bits of information is moderately expensive, involving two memory | 
 | 3751 | // loads where the second is dependent on the first.  To improve efficiency | 
 | 3752 | // the shape of the string is given its own class so that it can be retrieved | 
 | 3753 | // once and used for several string operations.  A StringShape is small enough | 
 | 3754 | // to be passed by value and is immutable, but be aware that flattening a | 
 | 3755 | // string can potentially alter its shape.  Also be aware that a GC caused by | 
 | 3756 | // something else can alter the shape of a string due to ConsString | 
 | 3757 | // shortcutting.  Keeping these restrictions in mind has proven to be error- | 
 | 3758 | // prone and so we no longer put StringShapes in variables unless there is a | 
 | 3759 | // concrete performance benefit at that particular point in the code. | 
 | 3760 | class StringShape BASE_EMBEDDED { | 
 | 3761 |  public: | 
 | 3762 |   inline explicit StringShape(String* s); | 
 | 3763 |   inline explicit StringShape(Map* s); | 
 | 3764 |   inline explicit StringShape(InstanceType t); | 
 | 3765 |   inline bool IsSequential(); | 
 | 3766 |   inline bool IsExternal(); | 
 | 3767 |   inline bool IsCons(); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3768 |   inline bool IsExternalAscii(); | 
 | 3769 |   inline bool IsExternalTwoByte(); | 
 | 3770 |   inline bool IsSequentialAscii(); | 
 | 3771 |   inline bool IsSequentialTwoByte(); | 
 | 3772 |   inline bool IsSymbol(); | 
 | 3773 |   inline StringRepresentationTag representation_tag(); | 
 | 3774 |   inline uint32_t full_representation_tag(); | 
 | 3775 |   inline uint32_t size_tag(); | 
 | 3776 | #ifdef DEBUG | 
 | 3777 |   inline uint32_t type() { return type_; } | 
 | 3778 |   inline void invalidate() { valid_ = false; } | 
 | 3779 |   inline bool valid() { return valid_; } | 
 | 3780 | #else | 
 | 3781 |   inline void invalidate() { } | 
 | 3782 | #endif | 
 | 3783 |  private: | 
 | 3784 |   uint32_t type_; | 
 | 3785 | #ifdef DEBUG | 
 | 3786 |   inline void set_valid() { valid_ = true; } | 
 | 3787 |   bool valid_; | 
 | 3788 | #else | 
 | 3789 |   inline void set_valid() { } | 
 | 3790 | #endif | 
 | 3791 | }; | 
 | 3792 |  | 
 | 3793 |  | 
 | 3794 | // The String abstract class captures JavaScript string values: | 
 | 3795 | // | 
 | 3796 | // Ecma-262: | 
 | 3797 | //  4.3.16 String Value | 
 | 3798 | //    A string value is a member of the type String and is a finite | 
 | 3799 | //    ordered sequence of zero or more 16-bit unsigned integer values. | 
 | 3800 | // | 
 | 3801 | // All string values have a length field. | 
 | 3802 | class String: public HeapObject { | 
 | 3803 |  public: | 
 | 3804 |   // Get and set the length of the string. | 
 | 3805 |   inline int length(); | 
 | 3806 |   inline void set_length(int value); | 
 | 3807 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3808 |   // Get and set the hash field of the string. | 
 | 3809 |   inline uint32_t hash_field(); | 
 | 3810 |   inline void set_hash_field(uint32_t value); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3811 |  | 
 | 3812 |   inline bool IsAsciiRepresentation(); | 
 | 3813 |   inline bool IsTwoByteRepresentation(); | 
 | 3814 |  | 
 | 3815 |   // Get and set individual two byte chars in the string. | 
 | 3816 |   inline void Set(int index, uint16_t value); | 
 | 3817 |   // Get individual two byte char in the string.  Repeated calls | 
 | 3818 |   // to this method are not efficient unless the string is flat. | 
 | 3819 |   inline uint16_t Get(int index); | 
 | 3820 |  | 
 | 3821 |   // Try to flatten the top level ConsString that is hiding behind this | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3822 |   // string.  This is a no-op unless the string is a ConsString.  Flatten | 
 | 3823 |   // mutates the ConsString and might return a failure. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3824 |   Object* TryFlatten(); | 
 | 3825 |  | 
 | 3826 |   // Try to flatten the string.  Checks first inline to see if it is necessary. | 
 | 3827 |   // Do not handle allocation failures.  After calling TryFlattenIfNotFlat, the | 
 | 3828 |   // string could still be a ConsString, in which case a failure is returned. | 
 | 3829 |   // Use FlattenString from Handles.cc to be sure to flatten. | 
 | 3830 |   inline Object* TryFlattenIfNotFlat(); | 
 | 3831 |  | 
 | 3832 |   Vector<const char> ToAsciiVector(); | 
 | 3833 |   Vector<const uc16> ToUC16Vector(); | 
 | 3834 |  | 
 | 3835 |   // Mark the string as an undetectable object. It only applies to | 
 | 3836 |   // ascii and two byte string types. | 
 | 3837 |   bool MarkAsUndetectable(); | 
 | 3838 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3839 |   // Return a substring. | 
 | 3840 |   Object* SubString(int from, int to); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3841 |  | 
 | 3842 |   // String equality operations. | 
 | 3843 |   inline bool Equals(String* other); | 
 | 3844 |   bool IsEqualTo(Vector<const char> str); | 
 | 3845 |  | 
 | 3846 |   // Return a UTF8 representation of the string.  The string is null | 
 | 3847 |   // terminated but may optionally contain nulls.  Length is returned | 
 | 3848 |   // in length_output if length_output is not a null pointer  The string | 
 | 3849 |   // should be nearly flat, otherwise the performance of this method may | 
 | 3850 |   // be very slow (quadratic in the length).  Setting robustness_flag to | 
 | 3851 |   // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust  This means it | 
 | 3852 |   // handles unexpected data without causing assert failures and it does not | 
 | 3853 |   // do any heap allocations.  This is useful when printing stack traces. | 
 | 3854 |   SmartPointer<char> ToCString(AllowNullsFlag allow_nulls, | 
 | 3855 |                                RobustnessFlag robustness_flag, | 
 | 3856 |                                int offset, | 
 | 3857 |                                int length, | 
 | 3858 |                                int* length_output = 0); | 
 | 3859 |   SmartPointer<char> ToCString( | 
 | 3860 |       AllowNullsFlag allow_nulls = DISALLOW_NULLS, | 
 | 3861 |       RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL, | 
 | 3862 |       int* length_output = 0); | 
 | 3863 |  | 
 | 3864 |   int Utf8Length(); | 
 | 3865 |  | 
 | 3866 |   // Return a 16 bit Unicode representation of the string. | 
 | 3867 |   // The string should be nearly flat, otherwise the performance of | 
 | 3868 |   // of this method may be very bad.  Setting robustness_flag to | 
 | 3869 |   // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust  This means it | 
 | 3870 |   // handles unexpected data without causing assert failures and it does not | 
 | 3871 |   // do any heap allocations.  This is useful when printing stack traces. | 
 | 3872 |   SmartPointer<uc16> ToWideCString( | 
 | 3873 |       RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL); | 
 | 3874 |  | 
 | 3875 |   // Tells whether the hash code has been computed. | 
 | 3876 |   inline bool HasHashCode(); | 
 | 3877 |  | 
 | 3878 |   // Returns a hash value used for the property table | 
 | 3879 |   inline uint32_t Hash(); | 
 | 3880 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3881 |   static uint32_t ComputeHashField(unibrow::CharacterStream* buffer, | 
 | 3882 |                                    int length); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3883 |  | 
 | 3884 |   static bool ComputeArrayIndex(unibrow::CharacterStream* buffer, | 
 | 3885 |                                 uint32_t* index, | 
 | 3886 |                                 int length); | 
 | 3887 |  | 
 | 3888 |   // Externalization. | 
 | 3889 |   bool MakeExternal(v8::String::ExternalStringResource* resource); | 
 | 3890 |   bool MakeExternal(v8::String::ExternalAsciiStringResource* resource); | 
 | 3891 |  | 
 | 3892 |   // Conversion. | 
 | 3893 |   inline bool AsArrayIndex(uint32_t* index); | 
 | 3894 |  | 
 | 3895 |   // Casting. | 
 | 3896 |   static inline String* cast(Object* obj); | 
 | 3897 |  | 
 | 3898 |   void PrintOn(FILE* out); | 
 | 3899 |  | 
 | 3900 |   // For use during stack traces.  Performs rudimentary sanity check. | 
 | 3901 |   bool LooksValid(); | 
 | 3902 |  | 
 | 3903 |   // Dispatched behavior. | 
 | 3904 |   void StringShortPrint(StringStream* accumulator); | 
 | 3905 | #ifdef DEBUG | 
 | 3906 |   void StringPrint(); | 
 | 3907 |   void StringVerify(); | 
 | 3908 | #endif | 
 | 3909 |   inline bool IsFlat(); | 
 | 3910 |  | 
 | 3911 |   // Layout description. | 
 | 3912 |   static const int kLengthOffset = HeapObject::kHeaderSize; | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3913 |   static const int kHashFieldOffset = kLengthOffset + kIntSize; | 
 | 3914 |   static const int kSize = kHashFieldOffset + kIntSize; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3915 |   // Notice: kSize is not pointer-size aligned if pointers are 64-bit. | 
 | 3916 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3917 |   // Maximum number of characters to consider when trying to convert a string | 
 | 3918 |   // value into an array index. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3919 |   static const int kMaxArrayIndexSize = 10; | 
 | 3920 |  | 
 | 3921 |   // Max ascii char code. | 
 | 3922 |   static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar; | 
 | 3923 |   static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar; | 
 | 3924 |   static const int kMaxUC16CharCode = 0xffff; | 
 | 3925 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3926 |   // Minimum length for a cons string. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3927 |   static const int kMinNonFlatLength = 13; | 
 | 3928 |  | 
 | 3929 |   // Mask constant for checking if a string has a computed hash code | 
 | 3930 |   // and if it is an array index.  The least significant bit indicates | 
 | 3931 |   // whether a hash code has been computed.  If the hash code has been | 
 | 3932 |   // computed the 2nd bit tells whether the string can be used as an | 
 | 3933 |   // array index. | 
 | 3934 |   static const int kHashComputedMask = 1; | 
 | 3935 |   static const int kIsArrayIndexMask = 1 << 1; | 
 | 3936 |   static const int kNofLengthBitFields = 2; | 
 | 3937 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3938 |   // Shift constant retrieving hash code from hash field. | 
 | 3939 |   static const int kHashShift = kNofLengthBitFields; | 
 | 3940 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3941 |   // Array index strings this short can keep their index in the hash | 
 | 3942 |   // field. | 
 | 3943 |   static const int kMaxCachedArrayIndexLength = 7; | 
 | 3944 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 3945 |   // For strings which are array indexes the hash value has the string length | 
 | 3946 |   // mixed into the hash, mainly to avoid a hash value of zero which would be | 
 | 3947 |   // the case for the string '0'. 24 bits are used for the array index value. | 
 | 3948 |   static const int kArrayIndexHashLengthShift = 24 + kNofLengthBitFields; | 
 | 3949 |   static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1; | 
 | 3950 |   static const int kArrayIndexValueBits = | 
 | 3951 |       kArrayIndexHashLengthShift - kHashShift; | 
 | 3952 |  | 
 | 3953 |   // Value of empty hash field indicating that the hash is not computed. | 
 | 3954 |   static const int kEmptyHashField = 0; | 
 | 3955 |  | 
 | 3956 |   // Maximal string length. | 
 | 3957 |   static const int kMaxLength = (1 << (32 - 2)) - 1; | 
 | 3958 |  | 
 | 3959 |   // Max length for computing hash. For strings longer than this limit the | 
 | 3960 |   // string length is used as the hash value. | 
 | 3961 |   static const int kMaxHashCalcLength = 16383; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 3962 |  | 
 | 3963 |   // Limit for truncation in short printing. | 
 | 3964 |   static const int kMaxShortPrintLength = 1024; | 
 | 3965 |  | 
 | 3966 |   // Support for regular expressions. | 
 | 3967 |   const uc16* GetTwoByteData(); | 
 | 3968 |   const uc16* GetTwoByteData(unsigned start); | 
 | 3969 |  | 
 | 3970 |   // Support for StringInputBuffer | 
 | 3971 |   static const unibrow::byte* ReadBlock(String* input, | 
 | 3972 |                                         unibrow::byte* util_buffer, | 
 | 3973 |                                         unsigned capacity, | 
 | 3974 |                                         unsigned* remaining, | 
 | 3975 |                                         unsigned* offset); | 
 | 3976 |   static const unibrow::byte* ReadBlock(String** input, | 
 | 3977 |                                         unibrow::byte* util_buffer, | 
 | 3978 |                                         unsigned capacity, | 
 | 3979 |                                         unsigned* remaining, | 
 | 3980 |                                         unsigned* offset); | 
 | 3981 |  | 
 | 3982 |   // Helper function for flattening strings. | 
 | 3983 |   template <typename sinkchar> | 
 | 3984 |   static void WriteToFlat(String* source, | 
 | 3985 |                           sinkchar* sink, | 
 | 3986 |                           int from, | 
 | 3987 |                           int to); | 
 | 3988 |  | 
 | 3989 |  protected: | 
 | 3990 |   class ReadBlockBuffer { | 
 | 3991 |    public: | 
 | 3992 |     ReadBlockBuffer(unibrow::byte* util_buffer_, | 
 | 3993 |                     unsigned cursor_, | 
 | 3994 |                     unsigned capacity_, | 
 | 3995 |                     unsigned remaining_) : | 
 | 3996 |       util_buffer(util_buffer_), | 
 | 3997 |       cursor(cursor_), | 
 | 3998 |       capacity(capacity_), | 
 | 3999 |       remaining(remaining_) { | 
 | 4000 |     } | 
 | 4001 |     unibrow::byte* util_buffer; | 
 | 4002 |     unsigned       cursor; | 
 | 4003 |     unsigned       capacity; | 
 | 4004 |     unsigned       remaining; | 
 | 4005 |   }; | 
 | 4006 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4007 |   static inline const unibrow::byte* ReadBlock(String* input, | 
 | 4008 |                                                ReadBlockBuffer* buffer, | 
 | 4009 |                                                unsigned* offset, | 
 | 4010 |                                                unsigned max_chars); | 
 | 4011 |   static void ReadBlockIntoBuffer(String* input, | 
 | 4012 |                                   ReadBlockBuffer* buffer, | 
 | 4013 |                                   unsigned* offset_ptr, | 
 | 4014 |                                   unsigned max_chars); | 
 | 4015 |  | 
 | 4016 |  private: | 
 | 4017 |   // Slow case of String::Equals.  This implementation works on any strings | 
 | 4018 |   // but it is most efficient on strings that are almost flat. | 
 | 4019 |   bool SlowEquals(String* other); | 
 | 4020 |  | 
 | 4021 |   // Slow case of AsArrayIndex. | 
 | 4022 |   bool SlowAsArrayIndex(uint32_t* index); | 
 | 4023 |  | 
 | 4024 |   // Compute and set the hash code. | 
 | 4025 |   uint32_t ComputeAndSetHash(); | 
 | 4026 |  | 
 | 4027 |   DISALLOW_IMPLICIT_CONSTRUCTORS(String); | 
 | 4028 | }; | 
 | 4029 |  | 
 | 4030 |  | 
 | 4031 | // The SeqString abstract class captures sequential string values. | 
 | 4032 | class SeqString: public String { | 
 | 4033 |  public: | 
 | 4034 |  | 
 | 4035 |   // Casting. | 
 | 4036 |   static inline SeqString* cast(Object* obj); | 
 | 4037 |  | 
 | 4038 |   // Dispatched behaviour. | 
 | 4039 |   // For regexp code. | 
 | 4040 |   uint16_t* SeqStringGetTwoByteAddress(); | 
 | 4041 |  | 
 | 4042 |  private: | 
 | 4043 |   DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString); | 
 | 4044 | }; | 
 | 4045 |  | 
 | 4046 |  | 
 | 4047 | // The AsciiString class captures sequential ascii string objects. | 
 | 4048 | // Each character in the AsciiString is an ascii character. | 
 | 4049 | class SeqAsciiString: public SeqString { | 
 | 4050 |  public: | 
 | 4051 |   // Dispatched behavior. | 
 | 4052 |   inline uint16_t SeqAsciiStringGet(int index); | 
 | 4053 |   inline void SeqAsciiStringSet(int index, uint16_t value); | 
 | 4054 |  | 
 | 4055 |   // Get the address of the characters in this string. | 
 | 4056 |   inline Address GetCharsAddress(); | 
 | 4057 |  | 
 | 4058 |   inline char* GetChars(); | 
 | 4059 |  | 
 | 4060 |   // Casting | 
 | 4061 |   static inline SeqAsciiString* cast(Object* obj); | 
 | 4062 |  | 
 | 4063 |   // Garbage collection support.  This method is called by the | 
 | 4064 |   // garbage collector to compute the actual size of an AsciiString | 
 | 4065 |   // instance. | 
 | 4066 |   inline int SeqAsciiStringSize(InstanceType instance_type); | 
 | 4067 |  | 
 | 4068 |   // Computes the size for an AsciiString instance of a given length. | 
 | 4069 |   static int SizeFor(int length) { | 
 | 4070 |     return OBJECT_SIZE_ALIGN(kHeaderSize + length * kCharSize); | 
 | 4071 |   } | 
 | 4072 |  | 
 | 4073 |   // Layout description. | 
 | 4074 |   static const int kHeaderSize = String::kSize; | 
 | 4075 |   static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); | 
 | 4076 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 4077 |   // Maximal memory usage for a single sequential ASCII string. | 
 | 4078 |   static const int kMaxSize = 512 * MB; | 
 | 4079 |   // Maximal length of a single sequential ASCII string. | 
 | 4080 |   // Q.v. String::kMaxLength which is the maximal size of concatenated strings. | 
 | 4081 |   static const int kMaxLength = (kMaxSize - kHeaderSize); | 
 | 4082 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4083 |   // Support for StringInputBuffer. | 
 | 4084 |   inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer, | 
 | 4085 |                                                 unsigned* offset, | 
 | 4086 |                                                 unsigned chars); | 
 | 4087 |   inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining, | 
 | 4088 |                                                       unsigned* offset, | 
 | 4089 |                                                       unsigned chars); | 
 | 4090 |  | 
 | 4091 |  private: | 
 | 4092 |   DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString); | 
 | 4093 | }; | 
 | 4094 |  | 
 | 4095 |  | 
 | 4096 | // The TwoByteString class captures sequential unicode string objects. | 
 | 4097 | // Each character in the TwoByteString is a two-byte uint16_t. | 
 | 4098 | class SeqTwoByteString: public SeqString { | 
 | 4099 |  public: | 
 | 4100 |   // Dispatched behavior. | 
 | 4101 |   inline uint16_t SeqTwoByteStringGet(int index); | 
 | 4102 |   inline void SeqTwoByteStringSet(int index, uint16_t value); | 
 | 4103 |  | 
 | 4104 |   // Get the address of the characters in this string. | 
 | 4105 |   inline Address GetCharsAddress(); | 
 | 4106 |  | 
 | 4107 |   inline uc16* GetChars(); | 
 | 4108 |  | 
 | 4109 |   // For regexp code. | 
 | 4110 |   const uint16_t* SeqTwoByteStringGetData(unsigned start); | 
 | 4111 |  | 
 | 4112 |   // Casting | 
 | 4113 |   static inline SeqTwoByteString* cast(Object* obj); | 
 | 4114 |  | 
 | 4115 |   // Garbage collection support.  This method is called by the | 
 | 4116 |   // garbage collector to compute the actual size of a TwoByteString | 
 | 4117 |   // instance. | 
 | 4118 |   inline int SeqTwoByteStringSize(InstanceType instance_type); | 
 | 4119 |  | 
 | 4120 |   // Computes the size for a TwoByteString instance of a given length. | 
 | 4121 |   static int SizeFor(int length) { | 
 | 4122 |     return OBJECT_SIZE_ALIGN(kHeaderSize + length * kShortSize); | 
 | 4123 |   } | 
 | 4124 |  | 
 | 4125 |   // Layout description. | 
 | 4126 |   static const int kHeaderSize = String::kSize; | 
 | 4127 |   static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); | 
 | 4128 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 4129 |   // Maximal memory usage for a single sequential two-byte string. | 
 | 4130 |   static const int kMaxSize = 512 * MB; | 
 | 4131 |   // Maximal length of a single sequential two-byte string. | 
 | 4132 |   // Q.v. String::kMaxLength which is the maximal size of concatenated strings. | 
 | 4133 |   static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t); | 
 | 4134 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4135 |   // Support for StringInputBuffer. | 
 | 4136 |   inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer, | 
 | 4137 |                                                   unsigned* offset_ptr, | 
 | 4138 |                                                   unsigned chars); | 
 | 4139 |  | 
 | 4140 |  private: | 
 | 4141 |   DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString); | 
 | 4142 | }; | 
 | 4143 |  | 
 | 4144 |  | 
 | 4145 | // The ConsString class describes string values built by using the | 
 | 4146 | // addition operator on strings.  A ConsString is a pair where the | 
 | 4147 | // first and second components are pointers to other string values. | 
 | 4148 | // One or both components of a ConsString can be pointers to other | 
 | 4149 | // ConsStrings, creating a binary tree of ConsStrings where the leaves | 
 | 4150 | // are non-ConsString string values.  The string value represented by | 
 | 4151 | // a ConsString can be obtained by concatenating the leaf string | 
 | 4152 | // values in a left-to-right depth-first traversal of the tree. | 
 | 4153 | class ConsString: public String { | 
 | 4154 |  public: | 
 | 4155 |   // First string of the cons cell. | 
 | 4156 |   inline String* first(); | 
 | 4157 |   // Doesn't check that the result is a string, even in debug mode.  This is | 
 | 4158 |   // useful during GC where the mark bits confuse the checks. | 
 | 4159 |   inline Object* unchecked_first(); | 
 | 4160 |   inline void set_first(String* first, | 
 | 4161 |                         WriteBarrierMode mode = UPDATE_WRITE_BARRIER); | 
 | 4162 |  | 
 | 4163 |   // Second string of the cons cell. | 
 | 4164 |   inline String* second(); | 
 | 4165 |   // Doesn't check that the result is a string, even in debug mode.  This is | 
 | 4166 |   // useful during GC where the mark bits confuse the checks. | 
 | 4167 |   inline Object* unchecked_second(); | 
 | 4168 |   inline void set_second(String* second, | 
 | 4169 |                          WriteBarrierMode mode = UPDATE_WRITE_BARRIER); | 
 | 4170 |  | 
 | 4171 |   // Dispatched behavior. | 
 | 4172 |   uint16_t ConsStringGet(int index); | 
 | 4173 |  | 
 | 4174 |   // Casting. | 
 | 4175 |   static inline ConsString* cast(Object* obj); | 
 | 4176 |  | 
 | 4177 |   // Garbage collection support.  This method is called during garbage | 
 | 4178 |   // collection to iterate through the heap pointers in the body of | 
 | 4179 |   // the ConsString. | 
 | 4180 |   void ConsStringIterateBody(ObjectVisitor* v); | 
 | 4181 |  | 
 | 4182 |   // Layout description. | 
 | 4183 |   static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize); | 
 | 4184 |   static const int kSecondOffset = kFirstOffset + kPointerSize; | 
 | 4185 |   static const int kSize = kSecondOffset + kPointerSize; | 
 | 4186 |  | 
 | 4187 |   // Support for StringInputBuffer. | 
 | 4188 |   inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer, | 
 | 4189 |                                                   unsigned* offset_ptr, | 
 | 4190 |                                                   unsigned chars); | 
 | 4191 |   inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer, | 
 | 4192 |                                             unsigned* offset_ptr, | 
 | 4193 |                                             unsigned chars); | 
 | 4194 |  | 
 | 4195 |   // Minimum length for a cons string. | 
 | 4196 |   static const int kMinLength = 13; | 
 | 4197 |  | 
 | 4198 |  private: | 
 | 4199 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString); | 
 | 4200 | }; | 
 | 4201 |  | 
 | 4202 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4203 | // The ExternalString class describes string values that are backed by | 
 | 4204 | // a string resource that lies outside the V8 heap.  ExternalStrings | 
 | 4205 | // consist of the length field common to all strings, a pointer to the | 
 | 4206 | // external resource.  It is important to ensure (externally) that the | 
 | 4207 | // resource is not deallocated while the ExternalString is live in the | 
 | 4208 | // V8 heap. | 
 | 4209 | // | 
 | 4210 | // The API expects that all ExternalStrings are created through the | 
 | 4211 | // API.  Therefore, ExternalStrings should not be used internally. | 
 | 4212 | class ExternalString: public String { | 
 | 4213 |  public: | 
 | 4214 |   // Casting | 
 | 4215 |   static inline ExternalString* cast(Object* obj); | 
 | 4216 |  | 
 | 4217 |   // Layout description. | 
 | 4218 |   static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize); | 
 | 4219 |   static const int kSize = kResourceOffset + kPointerSize; | 
 | 4220 |  | 
 | 4221 |   STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset); | 
 | 4222 |  | 
 | 4223 |  private: | 
 | 4224 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString); | 
 | 4225 | }; | 
 | 4226 |  | 
 | 4227 |  | 
 | 4228 | // The ExternalAsciiString class is an external string backed by an | 
 | 4229 | // ASCII string. | 
 | 4230 | class ExternalAsciiString: public ExternalString { | 
 | 4231 |  public: | 
 | 4232 |   typedef v8::String::ExternalAsciiStringResource Resource; | 
 | 4233 |  | 
 | 4234 |   // The underlying resource. | 
 | 4235 |   inline Resource* resource(); | 
 | 4236 |   inline void set_resource(Resource* buffer); | 
 | 4237 |  | 
 | 4238 |   // Dispatched behavior. | 
 | 4239 |   uint16_t ExternalAsciiStringGet(int index); | 
 | 4240 |  | 
 | 4241 |   // Casting. | 
 | 4242 |   static inline ExternalAsciiString* cast(Object* obj); | 
 | 4243 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 4244 |   // Garbage collection support. | 
 | 4245 |   void ExternalAsciiStringIterateBody(ObjectVisitor* v); | 
 | 4246 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4247 |   // Support for StringInputBuffer. | 
 | 4248 |   const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining, | 
 | 4249 |                                                     unsigned* offset, | 
 | 4250 |                                                     unsigned chars); | 
 | 4251 |   inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer, | 
 | 4252 |                                                      unsigned* offset, | 
 | 4253 |                                                      unsigned chars); | 
 | 4254 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4255 |  private: | 
 | 4256 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString); | 
 | 4257 | }; | 
 | 4258 |  | 
 | 4259 |  | 
 | 4260 | // The ExternalTwoByteString class is an external string backed by a UTF-16 | 
 | 4261 | // encoded string. | 
 | 4262 | class ExternalTwoByteString: public ExternalString { | 
 | 4263 |  public: | 
 | 4264 |   typedef v8::String::ExternalStringResource Resource; | 
 | 4265 |  | 
 | 4266 |   // The underlying string resource. | 
 | 4267 |   inline Resource* resource(); | 
 | 4268 |   inline void set_resource(Resource* buffer); | 
 | 4269 |  | 
 | 4270 |   // Dispatched behavior. | 
 | 4271 |   uint16_t ExternalTwoByteStringGet(int index); | 
 | 4272 |  | 
 | 4273 |   // For regexp code. | 
 | 4274 |   const uint16_t* ExternalTwoByteStringGetData(unsigned start); | 
 | 4275 |  | 
 | 4276 |   // Casting. | 
 | 4277 |   static inline ExternalTwoByteString* cast(Object* obj); | 
 | 4278 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 4279 |   // Garbage collection support. | 
 | 4280 |   void ExternalTwoByteStringIterateBody(ObjectVisitor* v); | 
 | 4281 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4282 |   // Support for StringInputBuffer. | 
 | 4283 |   void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer, | 
 | 4284 |                                                 unsigned* offset_ptr, | 
 | 4285 |                                                 unsigned chars); | 
 | 4286 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4287 |  private: | 
 | 4288 |   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString); | 
 | 4289 | }; | 
 | 4290 |  | 
 | 4291 |  | 
 | 4292 | // Utility superclass for stack-allocated objects that must be updated | 
 | 4293 | // on gc.  It provides two ways for the gc to update instances, either | 
 | 4294 | // iterating or updating after gc. | 
 | 4295 | class Relocatable BASE_EMBEDDED { | 
 | 4296 |  public: | 
 | 4297 |   inline Relocatable() : prev_(top_) { top_ = this; } | 
 | 4298 |   virtual ~Relocatable() { | 
 | 4299 |     ASSERT_EQ(top_, this); | 
 | 4300 |     top_ = prev_; | 
 | 4301 |   } | 
 | 4302 |   virtual void IterateInstance(ObjectVisitor* v) { } | 
 | 4303 |   virtual void PostGarbageCollection() { } | 
 | 4304 |  | 
 | 4305 |   static void PostGarbageCollectionProcessing(); | 
 | 4306 |   static int ArchiveSpacePerThread(); | 
 | 4307 |   static char* ArchiveState(char* to); | 
 | 4308 |   static char* RestoreState(char* from); | 
 | 4309 |   static void Iterate(ObjectVisitor* v); | 
 | 4310 |   static void Iterate(ObjectVisitor* v, Relocatable* top); | 
 | 4311 |   static char* Iterate(ObjectVisitor* v, char* t); | 
 | 4312 |  private: | 
 | 4313 |   static Relocatable* top_; | 
 | 4314 |   Relocatable* prev_; | 
 | 4315 | }; | 
 | 4316 |  | 
 | 4317 |  | 
 | 4318 | // A flat string reader provides random access to the contents of a | 
 | 4319 | // string independent of the character width of the string.  The handle | 
 | 4320 | // must be valid as long as the reader is being used. | 
 | 4321 | class FlatStringReader : public Relocatable { | 
 | 4322 |  public: | 
 | 4323 |   explicit FlatStringReader(Handle<String> str); | 
 | 4324 |   explicit FlatStringReader(Vector<const char> input); | 
 | 4325 |   void PostGarbageCollection(); | 
 | 4326 |   inline uc32 Get(int index); | 
 | 4327 |   int length() { return length_; } | 
 | 4328 |  private: | 
 | 4329 |   String** str_; | 
 | 4330 |   bool is_ascii_; | 
 | 4331 |   int length_; | 
 | 4332 |   const void* start_; | 
 | 4333 | }; | 
 | 4334 |  | 
 | 4335 |  | 
 | 4336 | // Note that StringInputBuffers are not valid across a GC!  To fix this | 
 | 4337 | // it would have to store a String Handle instead of a String* and | 
 | 4338 | // AsciiStringReadBlock would have to be modified to use memcpy. | 
 | 4339 | // | 
 | 4340 | // StringInputBuffer is able to traverse any string regardless of how | 
 | 4341 | // deeply nested a sequence of ConsStrings it is made of.  However, | 
 | 4342 | // performance will be better if deep strings are flattened before they | 
 | 4343 | // are traversed.  Since flattening requires memory allocation this is | 
 | 4344 | // not always desirable, however (esp. in debugging situations). | 
 | 4345 | class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> { | 
 | 4346 |  public: | 
 | 4347 |   virtual void Seek(unsigned pos); | 
 | 4348 |   inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {} | 
 | 4349 |   inline StringInputBuffer(String* backing): | 
 | 4350 |       unibrow::InputBuffer<String, String*, 1024>(backing) {} | 
 | 4351 | }; | 
 | 4352 |  | 
 | 4353 |  | 
 | 4354 | class SafeStringInputBuffer | 
 | 4355 |   : public unibrow::InputBuffer<String, String**, 256> { | 
 | 4356 |  public: | 
 | 4357 |   virtual void Seek(unsigned pos); | 
 | 4358 |   inline SafeStringInputBuffer() | 
 | 4359 |       : unibrow::InputBuffer<String, String**, 256>() {} | 
 | 4360 |   inline SafeStringInputBuffer(String** backing) | 
 | 4361 |       : unibrow::InputBuffer<String, String**, 256>(backing) {} | 
 | 4362 | }; | 
 | 4363 |  | 
 | 4364 |  | 
 | 4365 | template <typename T> | 
 | 4366 | class VectorIterator { | 
 | 4367 |  public: | 
 | 4368 |   VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { } | 
 | 4369 |   explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { } | 
 | 4370 |   T GetNext() { return data_[index_++]; } | 
 | 4371 |   bool has_more() { return index_ < data_.length(); } | 
 | 4372 |  private: | 
 | 4373 |   Vector<const T> data_; | 
 | 4374 |   int index_; | 
 | 4375 | }; | 
 | 4376 |  | 
 | 4377 |  | 
 | 4378 | // The Oddball describes objects null, undefined, true, and false. | 
 | 4379 | class Oddball: public HeapObject { | 
 | 4380 |  public: | 
 | 4381 |   // [to_string]: Cached to_string computed at startup. | 
 | 4382 |   DECL_ACCESSORS(to_string, String) | 
 | 4383 |  | 
 | 4384 |   // [to_number]: Cached to_number computed at startup. | 
 | 4385 |   DECL_ACCESSORS(to_number, Object) | 
 | 4386 |  | 
 | 4387 |   // Casting. | 
 | 4388 |   static inline Oddball* cast(Object* obj); | 
 | 4389 |  | 
 | 4390 |   // Dispatched behavior. | 
 | 4391 |   void OddballIterateBody(ObjectVisitor* v); | 
 | 4392 | #ifdef DEBUG | 
 | 4393 |   void OddballVerify(); | 
 | 4394 | #endif | 
 | 4395 |  | 
 | 4396 |   // Initialize the fields. | 
 | 4397 |   Object* Initialize(const char* to_string, Object* to_number); | 
 | 4398 |  | 
 | 4399 |   // Layout description. | 
 | 4400 |   static const int kToStringOffset = HeapObject::kHeaderSize; | 
 | 4401 |   static const int kToNumberOffset = kToStringOffset + kPointerSize; | 
 | 4402 |   static const int kSize = kToNumberOffset + kPointerSize; | 
 | 4403 |  | 
 | 4404 |  private: | 
 | 4405 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball); | 
 | 4406 | }; | 
 | 4407 |  | 
 | 4408 |  | 
 | 4409 | class JSGlobalPropertyCell: public HeapObject { | 
 | 4410 |  public: | 
 | 4411 |   // [value]: value of the global property. | 
 | 4412 |   DECL_ACCESSORS(value, Object) | 
 | 4413 |  | 
 | 4414 |   // Casting. | 
 | 4415 |   static inline JSGlobalPropertyCell* cast(Object* obj); | 
 | 4416 |  | 
 | 4417 |   // Dispatched behavior. | 
 | 4418 |   void JSGlobalPropertyCellIterateBody(ObjectVisitor* v); | 
 | 4419 | #ifdef DEBUG | 
 | 4420 |   void JSGlobalPropertyCellVerify(); | 
 | 4421 |   void JSGlobalPropertyCellPrint(); | 
 | 4422 | #endif | 
 | 4423 |  | 
 | 4424 |   // Layout description. | 
 | 4425 |   static const int kValueOffset = HeapObject::kHeaderSize; | 
 | 4426 |   static const int kSize = kValueOffset + kPointerSize; | 
 | 4427 |  | 
 | 4428 |  private: | 
 | 4429 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell); | 
 | 4430 | }; | 
 | 4431 |  | 
 | 4432 |  | 
 | 4433 |  | 
 | 4434 | // Proxy describes objects pointing from JavaScript to C structures. | 
 | 4435 | // Since they cannot contain references to JS HeapObjects they can be | 
 | 4436 | // placed in old_data_space. | 
 | 4437 | class Proxy: public HeapObject { | 
 | 4438 |  public: | 
 | 4439 |   // [proxy]: field containing the address. | 
 | 4440 |   inline Address proxy(); | 
 | 4441 |   inline void set_proxy(Address value); | 
 | 4442 |  | 
 | 4443 |   // Casting. | 
 | 4444 |   static inline Proxy* cast(Object* obj); | 
 | 4445 |  | 
 | 4446 |   // Dispatched behavior. | 
 | 4447 |   inline void ProxyIterateBody(ObjectVisitor* v); | 
 | 4448 | #ifdef DEBUG | 
 | 4449 |   void ProxyPrint(); | 
 | 4450 |   void ProxyVerify(); | 
 | 4451 | #endif | 
 | 4452 |  | 
 | 4453 |   // Layout description. | 
 | 4454 |  | 
 | 4455 |   static const int kProxyOffset = HeapObject::kHeaderSize; | 
 | 4456 |   static const int kSize = kProxyOffset + kPointerSize; | 
 | 4457 |  | 
 | 4458 |   STATIC_CHECK(kProxyOffset == Internals::kProxyProxyOffset); | 
 | 4459 |  | 
 | 4460 |  private: | 
 | 4461 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy); | 
 | 4462 | }; | 
 | 4463 |  | 
 | 4464 |  | 
 | 4465 | // The JSArray describes JavaScript Arrays | 
 | 4466 | //  Such an array can be in one of two modes: | 
 | 4467 | //    - fast, backing storage is a FixedArray and length <= elements.length(); | 
 | 4468 | //       Please note: push and pop can be used to grow and shrink the array. | 
 | 4469 | //    - slow, backing storage is a HashTable with numbers as keys. | 
 | 4470 | class JSArray: public JSObject { | 
 | 4471 |  public: | 
 | 4472 |   // [length]: The length property. | 
 | 4473 |   DECL_ACCESSORS(length, Object) | 
 | 4474 |  | 
 | 4475 |   Object* JSArrayUpdateLengthFromIndex(uint32_t index, Object* value); | 
 | 4476 |  | 
 | 4477 |   // Initialize the array with the given capacity. The function may | 
 | 4478 |   // fail due to out-of-memory situations, but only if the requested | 
 | 4479 |   // capacity is non-zero. | 
 | 4480 |   Object* Initialize(int capacity); | 
 | 4481 |  | 
 | 4482 |   // Set the content of the array to the content of storage. | 
 | 4483 |   inline void SetContent(FixedArray* storage); | 
 | 4484 |  | 
 | 4485 |   // Casting. | 
 | 4486 |   static inline JSArray* cast(Object* obj); | 
 | 4487 |  | 
 | 4488 |   // Uses handles.  Ensures that the fixed array backing the JSArray has at | 
 | 4489 |   // least the stated size. | 
 | 4490 |   inline void EnsureSize(int minimum_size_of_backing_fixed_array); | 
 | 4491 |  | 
 | 4492 |   // Dispatched behavior. | 
 | 4493 | #ifdef DEBUG | 
 | 4494 |   void JSArrayPrint(); | 
 | 4495 |   void JSArrayVerify(); | 
 | 4496 | #endif | 
 | 4497 |  | 
 | 4498 |   // Number of element slots to pre-allocate for an empty array. | 
 | 4499 |   static const int kPreallocatedArrayElements = 4; | 
 | 4500 |  | 
 | 4501 |   // Layout description. | 
 | 4502 |   static const int kLengthOffset = JSObject::kHeaderSize; | 
 | 4503 |   static const int kSize = kLengthOffset + kPointerSize; | 
 | 4504 |  | 
 | 4505 |  private: | 
 | 4506 |   // Expand the fixed array backing of a fast-case JSArray to at least | 
 | 4507 |   // the requested size. | 
 | 4508 |   void Expand(int minimum_size_of_backing_fixed_array); | 
 | 4509 |  | 
 | 4510 |   DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray); | 
 | 4511 | }; | 
 | 4512 |  | 
 | 4513 |  | 
 | 4514 | // An accessor must have a getter, but can have no setter. | 
 | 4515 | // | 
 | 4516 | // When setting a property, V8 searches accessors in prototypes. | 
 | 4517 | // If an accessor was found and it does not have a setter, | 
 | 4518 | // the request is ignored. | 
 | 4519 | // | 
 | 4520 | // If the accessor in the prototype has the READ_ONLY property attribute, then | 
 | 4521 | // a new value is added to the local object when the property is set. | 
 | 4522 | // This shadows the accessor in the prototype. | 
 | 4523 | class AccessorInfo: public Struct { | 
 | 4524 |  public: | 
 | 4525 |   DECL_ACCESSORS(getter, Object) | 
 | 4526 |   DECL_ACCESSORS(setter, Object) | 
 | 4527 |   DECL_ACCESSORS(data, Object) | 
 | 4528 |   DECL_ACCESSORS(name, Object) | 
 | 4529 |   DECL_ACCESSORS(flag, Smi) | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 4530 |   DECL_ACCESSORS(load_stub_cache, Object) | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4531 |  | 
 | 4532 |   inline bool all_can_read(); | 
 | 4533 |   inline void set_all_can_read(bool value); | 
 | 4534 |  | 
 | 4535 |   inline bool all_can_write(); | 
 | 4536 |   inline void set_all_can_write(bool value); | 
 | 4537 |  | 
 | 4538 |   inline bool prohibits_overwriting(); | 
 | 4539 |   inline void set_prohibits_overwriting(bool value); | 
 | 4540 |  | 
 | 4541 |   inline PropertyAttributes property_attributes(); | 
 | 4542 |   inline void set_property_attributes(PropertyAttributes attributes); | 
 | 4543 |  | 
 | 4544 |   static inline AccessorInfo* cast(Object* obj); | 
 | 4545 |  | 
 | 4546 | #ifdef DEBUG | 
 | 4547 |   void AccessorInfoPrint(); | 
 | 4548 |   void AccessorInfoVerify(); | 
 | 4549 | #endif | 
 | 4550 |  | 
 | 4551 |   static const int kGetterOffset = HeapObject::kHeaderSize; | 
 | 4552 |   static const int kSetterOffset = kGetterOffset + kPointerSize; | 
 | 4553 |   static const int kDataOffset = kSetterOffset + kPointerSize; | 
 | 4554 |   static const int kNameOffset = kDataOffset + kPointerSize; | 
 | 4555 |   static const int kFlagOffset = kNameOffset + kPointerSize; | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 4556 |   static const int kLoadStubCacheOffset = kFlagOffset + kPointerSize; | 
 | 4557 |   static const int kSize = kLoadStubCacheOffset + kPointerSize; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4558 |  | 
 | 4559 |  private: | 
 | 4560 |   // Bit positions in flag. | 
 | 4561 |   static const int kAllCanReadBit = 0; | 
 | 4562 |   static const int kAllCanWriteBit = 1; | 
 | 4563 |   static const int kProhibitsOverwritingBit = 2; | 
 | 4564 |   class AttributesField: public BitField<PropertyAttributes, 3, 3> {}; | 
 | 4565 |  | 
 | 4566 |   DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo); | 
 | 4567 | }; | 
 | 4568 |  | 
 | 4569 |  | 
 | 4570 | class AccessCheckInfo: public Struct { | 
 | 4571 |  public: | 
 | 4572 |   DECL_ACCESSORS(named_callback, Object) | 
 | 4573 |   DECL_ACCESSORS(indexed_callback, Object) | 
 | 4574 |   DECL_ACCESSORS(data, Object) | 
 | 4575 |  | 
 | 4576 |   static inline AccessCheckInfo* cast(Object* obj); | 
 | 4577 |  | 
 | 4578 | #ifdef DEBUG | 
 | 4579 |   void AccessCheckInfoPrint(); | 
 | 4580 |   void AccessCheckInfoVerify(); | 
 | 4581 | #endif | 
 | 4582 |  | 
 | 4583 |   static const int kNamedCallbackOffset   = HeapObject::kHeaderSize; | 
 | 4584 |   static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize; | 
 | 4585 |   static const int kDataOffset = kIndexedCallbackOffset + kPointerSize; | 
 | 4586 |   static const int kSize = kDataOffset + kPointerSize; | 
 | 4587 |  | 
 | 4588 |  private: | 
 | 4589 |   DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo); | 
 | 4590 | }; | 
 | 4591 |  | 
 | 4592 |  | 
 | 4593 | class InterceptorInfo: public Struct { | 
 | 4594 |  public: | 
 | 4595 |   DECL_ACCESSORS(getter, Object) | 
 | 4596 |   DECL_ACCESSORS(setter, Object) | 
 | 4597 |   DECL_ACCESSORS(query, Object) | 
 | 4598 |   DECL_ACCESSORS(deleter, Object) | 
 | 4599 |   DECL_ACCESSORS(enumerator, Object) | 
 | 4600 |   DECL_ACCESSORS(data, Object) | 
 | 4601 |  | 
 | 4602 |   static inline InterceptorInfo* cast(Object* obj); | 
 | 4603 |  | 
 | 4604 | #ifdef DEBUG | 
 | 4605 |   void InterceptorInfoPrint(); | 
 | 4606 |   void InterceptorInfoVerify(); | 
 | 4607 | #endif | 
 | 4608 |  | 
 | 4609 |   static const int kGetterOffset = HeapObject::kHeaderSize; | 
 | 4610 |   static const int kSetterOffset = kGetterOffset + kPointerSize; | 
 | 4611 |   static const int kQueryOffset = kSetterOffset + kPointerSize; | 
 | 4612 |   static const int kDeleterOffset = kQueryOffset + kPointerSize; | 
 | 4613 |   static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; | 
 | 4614 |   static const int kDataOffset = kEnumeratorOffset + kPointerSize; | 
 | 4615 |   static const int kSize = kDataOffset + kPointerSize; | 
 | 4616 |  | 
 | 4617 |  private: | 
 | 4618 |   DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); | 
 | 4619 | }; | 
 | 4620 |  | 
 | 4621 |  | 
 | 4622 | class CallHandlerInfo: public Struct { | 
 | 4623 |  public: | 
 | 4624 |   DECL_ACCESSORS(callback, Object) | 
 | 4625 |   DECL_ACCESSORS(data, Object) | 
 | 4626 |  | 
 | 4627 |   static inline CallHandlerInfo* cast(Object* obj); | 
 | 4628 |  | 
 | 4629 | #ifdef DEBUG | 
 | 4630 |   void CallHandlerInfoPrint(); | 
 | 4631 |   void CallHandlerInfoVerify(); | 
 | 4632 | #endif | 
 | 4633 |  | 
 | 4634 |   static const int kCallbackOffset = HeapObject::kHeaderSize; | 
 | 4635 |   static const int kDataOffset = kCallbackOffset + kPointerSize; | 
 | 4636 |   static const int kSize = kDataOffset + kPointerSize; | 
 | 4637 |  | 
 | 4638 |  private: | 
 | 4639 |   DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo); | 
 | 4640 | }; | 
 | 4641 |  | 
 | 4642 |  | 
 | 4643 | class TemplateInfo: public Struct { | 
 | 4644 |  public: | 
 | 4645 |   DECL_ACCESSORS(tag, Object) | 
 | 4646 |   DECL_ACCESSORS(property_list, Object) | 
 | 4647 |  | 
 | 4648 | #ifdef DEBUG | 
 | 4649 |   void TemplateInfoVerify(); | 
 | 4650 | #endif | 
 | 4651 |  | 
 | 4652 |   static const int kTagOffset          = HeapObject::kHeaderSize; | 
 | 4653 |   static const int kPropertyListOffset = kTagOffset + kPointerSize; | 
 | 4654 |   static const int kHeaderSize         = kPropertyListOffset + kPointerSize; | 
 | 4655 |  protected: | 
 | 4656 |   friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs; | 
 | 4657 |   DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo); | 
 | 4658 | }; | 
 | 4659 |  | 
 | 4660 |  | 
 | 4661 | class FunctionTemplateInfo: public TemplateInfo { | 
 | 4662 |  public: | 
 | 4663 |   DECL_ACCESSORS(serial_number, Object) | 
 | 4664 |   DECL_ACCESSORS(call_code, Object) | 
 | 4665 |   DECL_ACCESSORS(property_accessors, Object) | 
 | 4666 |   DECL_ACCESSORS(prototype_template, Object) | 
 | 4667 |   DECL_ACCESSORS(parent_template, Object) | 
 | 4668 |   DECL_ACCESSORS(named_property_handler, Object) | 
 | 4669 |   DECL_ACCESSORS(indexed_property_handler, Object) | 
 | 4670 |   DECL_ACCESSORS(instance_template, Object) | 
 | 4671 |   DECL_ACCESSORS(class_name, Object) | 
 | 4672 |   DECL_ACCESSORS(signature, Object) | 
 | 4673 |   DECL_ACCESSORS(instance_call_handler, Object) | 
 | 4674 |   DECL_ACCESSORS(access_check_info, Object) | 
 | 4675 |   DECL_ACCESSORS(flag, Smi) | 
 | 4676 |  | 
 | 4677 |   // Following properties use flag bits. | 
 | 4678 |   DECL_BOOLEAN_ACCESSORS(hidden_prototype) | 
 | 4679 |   DECL_BOOLEAN_ACCESSORS(undetectable) | 
 | 4680 |   // If the bit is set, object instances created by this function | 
 | 4681 |   // requires access check. | 
 | 4682 |   DECL_BOOLEAN_ACCESSORS(needs_access_check) | 
 | 4683 |  | 
 | 4684 |   static inline FunctionTemplateInfo* cast(Object* obj); | 
 | 4685 |  | 
 | 4686 | #ifdef DEBUG | 
 | 4687 |   void FunctionTemplateInfoPrint(); | 
 | 4688 |   void FunctionTemplateInfoVerify(); | 
 | 4689 | #endif | 
 | 4690 |  | 
 | 4691 |   static const int kSerialNumberOffset = TemplateInfo::kHeaderSize; | 
 | 4692 |   static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize; | 
 | 4693 |   static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize; | 
 | 4694 |   static const int kPrototypeTemplateOffset = | 
 | 4695 |       kPropertyAccessorsOffset + kPointerSize; | 
 | 4696 |   static const int kParentTemplateOffset = | 
 | 4697 |       kPrototypeTemplateOffset + kPointerSize; | 
 | 4698 |   static const int kNamedPropertyHandlerOffset = | 
 | 4699 |       kParentTemplateOffset + kPointerSize; | 
 | 4700 |   static const int kIndexedPropertyHandlerOffset = | 
 | 4701 |       kNamedPropertyHandlerOffset + kPointerSize; | 
 | 4702 |   static const int kInstanceTemplateOffset = | 
 | 4703 |       kIndexedPropertyHandlerOffset + kPointerSize; | 
 | 4704 |   static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize; | 
 | 4705 |   static const int kSignatureOffset = kClassNameOffset + kPointerSize; | 
 | 4706 |   static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize; | 
 | 4707 |   static const int kAccessCheckInfoOffset = | 
 | 4708 |       kInstanceCallHandlerOffset + kPointerSize; | 
 | 4709 |   static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize; | 
 | 4710 |   static const int kSize = kFlagOffset + kPointerSize; | 
 | 4711 |  | 
 | 4712 |  private: | 
 | 4713 |   // Bit position in the flag, from least significant bit position. | 
 | 4714 |   static const int kHiddenPrototypeBit   = 0; | 
 | 4715 |   static const int kUndetectableBit      = 1; | 
 | 4716 |   static const int kNeedsAccessCheckBit  = 2; | 
 | 4717 |  | 
 | 4718 |   DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo); | 
 | 4719 | }; | 
 | 4720 |  | 
 | 4721 |  | 
 | 4722 | class ObjectTemplateInfo: public TemplateInfo { | 
 | 4723 |  public: | 
 | 4724 |   DECL_ACCESSORS(constructor, Object) | 
 | 4725 |   DECL_ACCESSORS(internal_field_count, Object) | 
 | 4726 |  | 
 | 4727 |   static inline ObjectTemplateInfo* cast(Object* obj); | 
 | 4728 |  | 
 | 4729 | #ifdef DEBUG | 
 | 4730 |   void ObjectTemplateInfoPrint(); | 
 | 4731 |   void ObjectTemplateInfoVerify(); | 
 | 4732 | #endif | 
 | 4733 |  | 
 | 4734 |   static const int kConstructorOffset = TemplateInfo::kHeaderSize; | 
 | 4735 |   static const int kInternalFieldCountOffset = | 
 | 4736 |       kConstructorOffset + kPointerSize; | 
 | 4737 |   static const int kSize = kInternalFieldCountOffset + kPointerSize; | 
 | 4738 | }; | 
 | 4739 |  | 
 | 4740 |  | 
 | 4741 | class SignatureInfo: public Struct { | 
 | 4742 |  public: | 
 | 4743 |   DECL_ACCESSORS(receiver, Object) | 
 | 4744 |   DECL_ACCESSORS(args, Object) | 
 | 4745 |  | 
 | 4746 |   static inline SignatureInfo* cast(Object* obj); | 
 | 4747 |  | 
 | 4748 | #ifdef DEBUG | 
 | 4749 |   void SignatureInfoPrint(); | 
 | 4750 |   void SignatureInfoVerify(); | 
 | 4751 | #endif | 
 | 4752 |  | 
 | 4753 |   static const int kReceiverOffset = Struct::kHeaderSize; | 
 | 4754 |   static const int kArgsOffset     = kReceiverOffset + kPointerSize; | 
 | 4755 |   static const int kSize           = kArgsOffset + kPointerSize; | 
 | 4756 |  | 
 | 4757 |  private: | 
 | 4758 |   DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo); | 
 | 4759 | }; | 
 | 4760 |  | 
 | 4761 |  | 
 | 4762 | class TypeSwitchInfo: public Struct { | 
 | 4763 |  public: | 
 | 4764 |   DECL_ACCESSORS(types, Object) | 
 | 4765 |  | 
 | 4766 |   static inline TypeSwitchInfo* cast(Object* obj); | 
 | 4767 |  | 
 | 4768 | #ifdef DEBUG | 
 | 4769 |   void TypeSwitchInfoPrint(); | 
 | 4770 |   void TypeSwitchInfoVerify(); | 
 | 4771 | #endif | 
 | 4772 |  | 
 | 4773 |   static const int kTypesOffset = Struct::kHeaderSize; | 
 | 4774 |   static const int kSize        = kTypesOffset + kPointerSize; | 
 | 4775 | }; | 
 | 4776 |  | 
 | 4777 |  | 
 | 4778 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
 | 4779 | // The DebugInfo class holds additional information for a function being | 
 | 4780 | // debugged. | 
 | 4781 | class DebugInfo: public Struct { | 
 | 4782 |  public: | 
 | 4783 |   // The shared function info for the source being debugged. | 
 | 4784 |   DECL_ACCESSORS(shared, SharedFunctionInfo) | 
 | 4785 |   // Code object for the original code. | 
 | 4786 |   DECL_ACCESSORS(original_code, Code) | 
 | 4787 |   // Code object for the patched code. This code object is the code object | 
 | 4788 |   // currently active for the function. | 
 | 4789 |   DECL_ACCESSORS(code, Code) | 
 | 4790 |   // Fixed array holding status information for each active break point. | 
 | 4791 |   DECL_ACCESSORS(break_points, FixedArray) | 
 | 4792 |  | 
 | 4793 |   // Check if there is a break point at a code position. | 
 | 4794 |   bool HasBreakPoint(int code_position); | 
 | 4795 |   // Get the break point info object for a code position. | 
 | 4796 |   Object* GetBreakPointInfo(int code_position); | 
 | 4797 |   // Clear a break point. | 
 | 4798 |   static void ClearBreakPoint(Handle<DebugInfo> debug_info, | 
 | 4799 |                               int code_position, | 
 | 4800 |                               Handle<Object> break_point_object); | 
 | 4801 |   // Set a break point. | 
 | 4802 |   static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position, | 
 | 4803 |                             int source_position, int statement_position, | 
 | 4804 |                             Handle<Object> break_point_object); | 
 | 4805 |   // Get the break point objects for a code position. | 
 | 4806 |   Object* GetBreakPointObjects(int code_position); | 
 | 4807 |   // Find the break point info holding this break point object. | 
 | 4808 |   static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info, | 
 | 4809 |                                     Handle<Object> break_point_object); | 
 | 4810 |   // Get the number of break points for this function. | 
 | 4811 |   int GetBreakPointCount(); | 
 | 4812 |  | 
 | 4813 |   static inline DebugInfo* cast(Object* obj); | 
 | 4814 |  | 
 | 4815 | #ifdef DEBUG | 
 | 4816 |   void DebugInfoPrint(); | 
 | 4817 |   void DebugInfoVerify(); | 
 | 4818 | #endif | 
 | 4819 |  | 
 | 4820 |   static const int kSharedFunctionInfoIndex = Struct::kHeaderSize; | 
 | 4821 |   static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize; | 
 | 4822 |   static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize; | 
 | 4823 |   static const int kActiveBreakPointsCountIndex = | 
 | 4824 |       kPatchedCodeIndex + kPointerSize; | 
 | 4825 |   static const int kBreakPointsStateIndex = | 
 | 4826 |       kActiveBreakPointsCountIndex + kPointerSize; | 
 | 4827 |   static const int kSize = kBreakPointsStateIndex + kPointerSize; | 
 | 4828 |  | 
 | 4829 |  private: | 
 | 4830 |   static const int kNoBreakPointInfo = -1; | 
 | 4831 |  | 
 | 4832 |   // Lookup the index in the break_points array for a code position. | 
 | 4833 |   int GetBreakPointInfoIndex(int code_position); | 
 | 4834 |  | 
 | 4835 |   DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo); | 
 | 4836 | }; | 
 | 4837 |  | 
 | 4838 |  | 
 | 4839 | // The BreakPointInfo class holds information for break points set in a | 
 | 4840 | // function. The DebugInfo object holds a BreakPointInfo object for each code | 
 | 4841 | // position with one or more break points. | 
 | 4842 | class BreakPointInfo: public Struct { | 
 | 4843 |  public: | 
 | 4844 |   // The position in the code for the break point. | 
 | 4845 |   DECL_ACCESSORS(code_position, Smi) | 
 | 4846 |   // The position in the source for the break position. | 
 | 4847 |   DECL_ACCESSORS(source_position, Smi) | 
 | 4848 |   // The position in the source for the last statement before this break | 
 | 4849 |   // position. | 
 | 4850 |   DECL_ACCESSORS(statement_position, Smi) | 
 | 4851 |   // List of related JavaScript break points. | 
 | 4852 |   DECL_ACCESSORS(break_point_objects, Object) | 
 | 4853 |  | 
 | 4854 |   // Removes a break point. | 
 | 4855 |   static void ClearBreakPoint(Handle<BreakPointInfo> info, | 
 | 4856 |                               Handle<Object> break_point_object); | 
 | 4857 |   // Set a break point. | 
 | 4858 |   static void SetBreakPoint(Handle<BreakPointInfo> info, | 
 | 4859 |                             Handle<Object> break_point_object); | 
 | 4860 |   // Check if break point info has this break point object. | 
 | 4861 |   static bool HasBreakPointObject(Handle<BreakPointInfo> info, | 
 | 4862 |                                   Handle<Object> break_point_object); | 
 | 4863 |   // Get the number of break points for this code position. | 
 | 4864 |   int GetBreakPointCount(); | 
 | 4865 |  | 
 | 4866 |   static inline BreakPointInfo* cast(Object* obj); | 
 | 4867 |  | 
 | 4868 | #ifdef DEBUG | 
 | 4869 |   void BreakPointInfoPrint(); | 
 | 4870 |   void BreakPointInfoVerify(); | 
 | 4871 | #endif | 
 | 4872 |  | 
 | 4873 |   static const int kCodePositionIndex = Struct::kHeaderSize; | 
 | 4874 |   static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize; | 
 | 4875 |   static const int kStatementPositionIndex = | 
 | 4876 |       kSourcePositionIndex + kPointerSize; | 
 | 4877 |   static const int kBreakPointObjectsIndex = | 
 | 4878 |       kStatementPositionIndex + kPointerSize; | 
 | 4879 |   static const int kSize = kBreakPointObjectsIndex + kPointerSize; | 
 | 4880 |  | 
 | 4881 |  private: | 
 | 4882 |   DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo); | 
 | 4883 | }; | 
 | 4884 | #endif  // ENABLE_DEBUGGER_SUPPORT | 
 | 4885 |  | 
 | 4886 |  | 
 | 4887 | #undef DECL_BOOLEAN_ACCESSORS | 
 | 4888 | #undef DECL_ACCESSORS | 
 | 4889 |  | 
 | 4890 |  | 
 | 4891 | // Abstract base class for visiting, and optionally modifying, the | 
 | 4892 | // pointers contained in Objects. Used in GC and serialization/deserialization. | 
 | 4893 | class ObjectVisitor BASE_EMBEDDED { | 
 | 4894 |  public: | 
 | 4895 |   virtual ~ObjectVisitor() {} | 
 | 4896 |  | 
 | 4897 |   // Visits a contiguous arrays of pointers in the half-open range | 
 | 4898 |   // [start, end). Any or all of the values may be modified on return. | 
 | 4899 |   virtual void VisitPointers(Object** start, Object** end) = 0; | 
 | 4900 |  | 
 | 4901 |   // To allow lazy clearing of inline caches the visitor has | 
 | 4902 |   // a rich interface for iterating over Code objects.. | 
 | 4903 |  | 
 | 4904 |   // Visits a code target in the instruction stream. | 
 | 4905 |   virtual void VisitCodeTarget(RelocInfo* rinfo); | 
 | 4906 |  | 
 | 4907 |   // Visits a runtime entry in the instruction stream. | 
 | 4908 |   virtual void VisitRuntimeEntry(RelocInfo* rinfo) {} | 
 | 4909 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 4910 |   // Visits the resource of an ASCII or two-byte string. | 
 | 4911 |   virtual void VisitExternalAsciiString( | 
 | 4912 |       v8::String::ExternalAsciiStringResource** resource) {} | 
 | 4913 |   virtual void VisitExternalTwoByteString( | 
 | 4914 |       v8::String::ExternalStringResource** resource) {} | 
 | 4915 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4916 |   // Visits a debug call target in the instruction stream. | 
 | 4917 |   virtual void VisitDebugTarget(RelocInfo* rinfo); | 
 | 4918 |  | 
 | 4919 |   // Handy shorthand for visiting a single pointer. | 
 | 4920 |   virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); } | 
 | 4921 |  | 
 | 4922 |   // Visits a contiguous arrays of external references (references to the C++ | 
 | 4923 |   // heap) in the half-open range [start, end). Any or all of the values | 
 | 4924 |   // may be modified on return. | 
 | 4925 |   virtual void VisitExternalReferences(Address* start, Address* end) {} | 
 | 4926 |  | 
 | 4927 |   inline void VisitExternalReference(Address* p) { | 
 | 4928 |     VisitExternalReferences(p, p + 1); | 
 | 4929 |   } | 
 | 4930 |  | 
 | 4931 | #ifdef DEBUG | 
 | 4932 |   // Intended for serialization/deserialization checking: insert, or | 
 | 4933 |   // check for the presence of, a tag at this position in the stream. | 
 | 4934 |   virtual void Synchronize(const char* tag) {} | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 4935 | #else | 
 | 4936 |   inline void Synchronize(const char* tag) {} | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4937 | #endif | 
 | 4938 | }; | 
 | 4939 |  | 
 | 4940 |  | 
 | 4941 | // BooleanBit is a helper class for setting and getting a bit in an | 
 | 4942 | // integer or Smi. | 
 | 4943 | class BooleanBit : public AllStatic { | 
 | 4944 |  public: | 
 | 4945 |   static inline bool get(Smi* smi, int bit_position) { | 
 | 4946 |     return get(smi->value(), bit_position); | 
 | 4947 |   } | 
 | 4948 |  | 
 | 4949 |   static inline bool get(int value, int bit_position) { | 
 | 4950 |     return (value & (1 << bit_position)) != 0; | 
 | 4951 |   } | 
 | 4952 |  | 
 | 4953 |   static inline Smi* set(Smi* smi, int bit_position, bool v) { | 
 | 4954 |     return Smi::FromInt(set(smi->value(), bit_position, v)); | 
 | 4955 |   } | 
 | 4956 |  | 
 | 4957 |   static inline int set(int value, int bit_position, bool v) { | 
 | 4958 |     if (v) { | 
 | 4959 |       value |= (1 << bit_position); | 
 | 4960 |     } else { | 
 | 4961 |       value &= ~(1 << bit_position); | 
 | 4962 |     } | 
 | 4963 |     return value; | 
 | 4964 |   } | 
 | 4965 | }; | 
 | 4966 |  | 
 | 4967 | } }  // namespace v8::internal | 
 | 4968 |  | 
 | 4969 | #endif  // V8_OBJECTS_H_ |