| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/ast.h" | 9 #include "src/ast.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 | 50 |
| 51 // Make sure that the code type and cache holder are not included in the hash. | 51 // Make sure that the code type and cache holder are not included in the hash. |
| 52 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 52 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
| 53 ASSERT(Code::ExtractCacheHolderFromFlags(flags) == 0); | 53 ASSERT(Code::ExtractCacheHolderFromFlags(flags) == 0); |
| 54 | 54 |
| 55 return flags; | 55 return flags; |
| 56 } | 56 } |
| 57 | 57 |
| 58 | 58 |
| 59 Code* StubCache::Set(Name* name, Map* map, Code* code) { | 59 Code* StubCache::Set(Name* name, Map* map, Code* code) { |
| 60 Code::Flags flags = CommonStubCacheChecks(name, map, code->flags(), heap()); | 60 Code::Flags flags = |
| 61 CommonStubCacheChecks(name, map, code->flags(), isolate()->heap()); |
| 61 | 62 |
| 62 // Compute the primary entry. | 63 // Compute the primary entry. |
| 63 int primary_offset = PrimaryOffset(name, flags, map); | 64 int primary_offset = PrimaryOffset(name, flags, map); |
| 64 Entry* primary = entry(primary_, primary_offset); | 65 Entry* primary = entry(primary_, primary_offset); |
| 65 Code* old_code = primary->value; | 66 Code* old_code = primary->value; |
| 66 | 67 |
| 67 // If the primary entry has useful data in it, we retire it to the | 68 // If the primary entry has useful data in it, we retire it to the |
| 68 // secondary cache before overwriting it. | 69 // secondary cache before overwriting it. |
| 69 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { | 70 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { |
| 70 Map* old_map = primary->map; | 71 Map* old_map = primary->map; |
| 71 Code::Flags old_flags = | 72 Code::Flags old_flags = |
| 72 Code::RemoveTypeAndHolderFromFlags(old_code->flags()); | 73 Code::RemoveTypeAndHolderFromFlags(old_code->flags()); |
| 73 int seed = PrimaryOffset(primary->key, old_flags, old_map); | 74 int seed = PrimaryOffset(primary->key, old_flags, old_map); |
| 74 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); | 75 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); |
| 75 Entry* secondary = entry(secondary_, secondary_offset); | 76 Entry* secondary = entry(secondary_, secondary_offset); |
| 76 *secondary = *primary; | 77 *secondary = *primary; |
| 77 } | 78 } |
| 78 | 79 |
| 79 // Update primary cache. | 80 // Update primary cache. |
| 80 primary->key = name; | 81 primary->key = name; |
| 81 primary->value = code; | 82 primary->value = code; |
| 82 primary->map = map; | 83 primary->map = map; |
| 83 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); | 84 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); |
| 84 return code; | 85 return code; |
| 85 } | 86 } |
| 86 | 87 |
| 87 | 88 |
| 88 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { | 89 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { |
| 89 flags = CommonStubCacheChecks(name, map, flags, heap()); | 90 flags = CommonStubCacheChecks(name, map, flags, isolate()->heap()); |
| 90 int primary_offset = PrimaryOffset(name, flags, map); | 91 int primary_offset = PrimaryOffset(name, flags, map); |
| 91 Entry* primary = entry(primary_, primary_offset); | 92 Entry* primary = entry(primary_, primary_offset); |
| 92 if (primary->key == name && primary->map == map) { | 93 if (primary->key == name && primary->map == map) { |
| 93 return primary->value; | 94 return primary->value; |
| 94 } | 95 } |
| 95 int secondary_offset = SecondaryOffset(name, flags, primary_offset); | 96 int secondary_offset = SecondaryOffset(name, flags, primary_offset); |
| 96 Entry* secondary = entry(secondary_, secondary_offset); | 97 Entry* secondary = entry(secondary_, secondary_offset); |
| 97 if (secondary->key == name && secondary->map == map) { | 98 if (secondary->key == name && secondary->map == map) { |
| 98 return secondary->value; | 99 return secondary->value; |
| 99 } | 100 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 121 Code::StubType type) { | 122 Code::StubType type) { |
| 122 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); | 123 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); |
| 123 | 124 |
| 124 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), | 125 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), |
| 125 name->GetIsolate()); | 126 name->GetIsolate()); |
| 126 if (probe->IsCode()) return Handle<Code>::cast(probe); | 127 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 127 return Handle<Code>::null(); | 128 return Handle<Code>::null(); |
| 128 } | 129 } |
| 129 | 130 |
| 130 | 131 |
| 131 Handle<Code> StubCache::ComputeMonomorphicIC( | 132 Handle<Code> PropertyICCompiler::ComputeMonomorphicIC( |
| 132 Code::Kind kind, | 133 Code::Kind kind, Handle<Name> name, Handle<HeapType> type, |
| 133 Handle<Name> name, | 134 Handle<Code> handler, ExtraICState extra_ic_state) { |
| 134 Handle<HeapType> type, | |
| 135 Handle<Code> handler, | |
| 136 ExtraICState extra_ic_state) { | |
| 137 CacheHolderFlag flag; | 135 CacheHolderFlag flag; |
| 138 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate(), &flag); | 136 Isolate* isolate = name->GetIsolate(); |
| 137 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag); |
| 139 | 138 |
| 140 Handle<Code> ic; | 139 Handle<Code> ic; |
| 141 // There are multiple string maps that all use the same prototype. That | 140 // There are multiple string maps that all use the same prototype. That |
| 142 // prototype cannot hold multiple handlers, one for each of the string maps, | 141 // prototype cannot hold multiple handlers, one for each of the string maps, |
| 143 // for a single name. Hence, turn off caching of the IC. | 142 // for a single name. Hence, turn off caching of the IC. |
| 144 bool can_be_cached = !type->Is(HeapType::String()); | 143 bool can_be_cached = !type->Is(HeapType::String()); |
| 145 if (can_be_cached) { | 144 if (can_be_cached) { |
| 146 ic = | 145 ic = Find(name, stub_holder, kind, extra_ic_state, flag); |
| 147 PropertyICCompiler::Find(name, stub_holder, kind, extra_ic_state, flag); | |
| 148 if (!ic.is_null()) return ic; | 146 if (!ic.is_null()) return ic; |
| 149 } | 147 } |
| 150 | 148 |
| 151 #ifdef DEBUG | 149 #ifdef DEBUG |
| 152 if (kind == Code::KEYED_STORE_IC) { | 150 if (kind == Code::KEYED_STORE_IC) { |
| 153 ASSERT(STANDARD_STORE == | 151 ASSERT(STANDARD_STORE == |
| 154 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | 152 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); |
| 155 } | 153 } |
| 156 #endif | 154 #endif |
| 157 | 155 |
| 158 PropertyICCompiler ic_compiler(isolate(), kind, extra_ic_state, flag); | 156 PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag); |
| 159 ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY); | 157 ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY); |
| 160 | 158 |
| 161 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 159 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
| 162 return ic; | 160 return ic; |
| 163 } | 161 } |
| 164 | 162 |
| 165 | 163 |
| 166 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 164 Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( |
| 167 Handle<HeapType> type) { | 165 Handle<Name> name, Handle<HeapType> type) { |
| 168 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate()); | 166 Isolate* isolate = name->GetIsolate(); |
| 167 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate); |
| 169 if (receiver_map->prototype()->IsNull()) { | 168 if (receiver_map->prototype()->IsNull()) { |
| 170 // TODO(jkummerow/verwaest): If there is no prototype and the property | 169 // TODO(jkummerow/verwaest): If there is no prototype and the property |
| 171 // is nonexistent, introduce a builtin to handle this (fast properties | 170 // is nonexistent, introduce a builtin to handle this (fast properties |
| 172 // -> return undefined, dictionary properties -> do negative lookup). | 171 // -> return undefined, dictionary properties -> do negative lookup). |
| 173 return Handle<Code>(); | 172 return Handle<Code>(); |
| 174 } | 173 } |
| 175 CacheHolderFlag flag; | 174 CacheHolderFlag flag; |
| 176 Handle<Map> stub_holder_map = | 175 Handle<Map> stub_holder_map = |
| 177 IC::GetHandlerCacheHolder(*type, false, isolate(), &flag); | 176 IC::GetHandlerCacheHolder(*type, false, isolate, &flag); |
| 178 | 177 |
| 179 // If no dictionary mode objects are present in the prototype chain, the load | 178 // If no dictionary mode objects are present in the prototype chain, the load |
| 180 // nonexistent IC stub can be shared for all names for a given map and we use | 179 // nonexistent IC stub can be shared for all names for a given map and we use |
| 181 // the empty string for the map cache in that case. If there are dictionary | 180 // the empty string for the map cache in that case. If there are dictionary |
| 182 // mode objects involved, we need to do negative lookups in the stub and | 181 // mode objects involved, we need to do negative lookups in the stub and |
| 183 // therefore the stub will be specific to the name. | 182 // therefore the stub will be specific to the name. |
| 184 Handle<Name> cache_name = | 183 Handle<Name> cache_name = |
| 185 receiver_map->is_dictionary_map() | 184 receiver_map->is_dictionary_map() |
| 186 ? name | 185 ? name |
| 187 : Handle<Name>::cast(isolate()->factory()->nonexistent_symbol()); | 186 : Handle<Name>::cast(isolate->factory()->nonexistent_symbol()); |
| 188 Handle<Map> current_map = stub_holder_map; | 187 Handle<Map> current_map = stub_holder_map; |
| 189 Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); | 188 Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); |
| 190 while (true) { | 189 while (true) { |
| 191 if (current_map->is_dictionary_map()) cache_name = name; | 190 if (current_map->is_dictionary_map()) cache_name = name; |
| 192 if (current_map->prototype()->IsNull()) break; | 191 if (current_map->prototype()->IsNull()) break; |
| 193 last = handle(JSObject::cast(current_map->prototype())); | 192 last = handle(JSObject::cast(current_map->prototype())); |
| 194 current_map = handle(last->map()); | 193 current_map = handle(last->map()); |
| 195 } | 194 } |
| 196 // Compile the stub that is either shared for all names or | 195 // Compile the stub that is either shared for all names or |
| 197 // name specific if there are global objects involved. | 196 // name specific if there are global objects involved. |
| 198 Handle<Code> handler = PropertyHandlerCompiler::Find( | 197 Handle<Code> handler = PropertyHandlerCompiler::Find( |
| 199 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); | 198 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); |
| 200 if (!handler.is_null()) return handler; | 199 if (!handler.is_null()) return handler; |
| 201 | 200 |
| 202 NamedLoadHandlerCompiler compiler(isolate_, flag); | 201 NamedLoadHandlerCompiler compiler(isolate, flag); |
| 203 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 202 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
| 204 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); | 203 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
| 205 return handler; | 204 return handler; |
| 206 } | 205 } |
| 207 | 206 |
| 208 | 207 |
| 209 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 208 Handle<Code> PropertyICCompiler::ComputeKeyedLoadElement( |
| 209 Handle<Map> receiver_map) { |
| 210 Isolate* isolate = receiver_map->GetIsolate(); |
| 210 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 211 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
| 211 Handle<Name> name = | 212 Handle<Name> name = isolate->factory()->KeyedLoadElementMonomorphic_string(); |
| 212 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | |
| 213 | 213 |
| 214 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 214 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
| 215 if (probe->IsCode()) return Handle<Code>::cast(probe); | 215 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 216 | 216 |
| 217 ElementsKind elements_kind = receiver_map->elements_kind(); | 217 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 218 Handle<Code> stub; | 218 Handle<Code> stub; |
| 219 if (receiver_map->has_fast_elements() || | 219 if (receiver_map->has_fast_elements() || |
| 220 receiver_map->has_external_array_elements() || | 220 receiver_map->has_external_array_elements() || |
| 221 receiver_map->has_fixed_typed_array_elements()) { | 221 receiver_map->has_fixed_typed_array_elements()) { |
| 222 stub = KeyedLoadFastElementStub( | 222 stub = KeyedLoadFastElementStub( |
| 223 isolate(), receiver_map->instance_type() == JS_ARRAY_TYPE, | 223 isolate, receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 224 elements_kind).GetCode(); | 224 elements_kind).GetCode(); |
| 225 } else { | 225 } else { |
| 226 stub = FLAG_compiled_keyed_dictionary_loads | 226 stub = FLAG_compiled_keyed_dictionary_loads |
| 227 ? KeyedLoadDictionaryElementStub(isolate()).GetCode() | 227 ? KeyedLoadDictionaryElementStub(isolate).GetCode() |
| 228 : KeyedLoadDictionaryElementPlatformStub(isolate()).GetCode(); | 228 : KeyedLoadDictionaryElementPlatformStub(isolate).GetCode(); |
| 229 } | 229 } |
| 230 PropertyICCompiler compiler(isolate(), Code::KEYED_LOAD_IC); | 230 PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); |
| 231 Handle<Code> code = | 231 Handle<Code> code = |
| 232 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate()), | 232 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate), stub, |
| 233 stub, factory()->empty_string(), ELEMENT); | 233 isolate->factory()->empty_string(), ELEMENT); |
| 234 | 234 |
| 235 Map::UpdateCodeCache(receiver_map, name, code); | 235 Map::UpdateCodeCache(receiver_map, name, code); |
| 236 return code; | 236 return code; |
| 237 } | 237 } |
| 238 | 238 |
| 239 | 239 |
| 240 Handle<Code> StubCache::ComputeKeyedStoreElement( | 240 Handle<Code> PropertyICCompiler::ComputeKeyedStoreElement( |
| 241 Handle<Map> receiver_map, | 241 Handle<Map> receiver_map, StrictMode strict_mode, |
| 242 StrictMode strict_mode, | |
| 243 KeyedAccessStoreMode store_mode) { | 242 KeyedAccessStoreMode store_mode) { |
| 243 Isolate* isolate = receiver_map->GetIsolate(); |
| 244 ExtraICState extra_state = | 244 ExtraICState extra_state = |
| 245 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); | 245 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); |
| 246 Code::Flags flags = | 246 Code::Flags flags = |
| 247 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); | 247 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); |
| 248 | 248 |
| 249 ASSERT(store_mode == STANDARD_STORE || | 249 ASSERT(store_mode == STANDARD_STORE || |
| 250 store_mode == STORE_AND_GROW_NO_TRANSITION || | 250 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 251 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 251 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 252 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 252 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
| 253 | 253 |
| 254 Handle<String> name = | 254 Handle<String> name = |
| 255 isolate()->factory()->KeyedStoreElementMonomorphic_string(); | 255 isolate->factory()->KeyedStoreElementMonomorphic_string(); |
| 256 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 256 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
| 257 if (probe->IsCode()) return Handle<Code>::cast(probe); | 257 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 258 | 258 |
| 259 PropertyICCompiler compiler(isolate(), Code::KEYED_STORE_IC, extra_state); | 259 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
| 260 Handle<Code> code = | 260 Handle<Code> code = |
| 261 compiler.CompileIndexedStoreMonomorphic(receiver_map, store_mode); | 261 compiler.CompileIndexedStoreMonomorphic(receiver_map, store_mode); |
| 262 | 262 |
| 263 Map::UpdateCodeCache(receiver_map, name, code); | 263 Map::UpdateCodeCache(receiver_map, name, code); |
| 264 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 264 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
| 265 == store_mode); | 265 == store_mode); |
| 266 return code; | 266 return code; |
| 267 } | 267 } |
| 268 | 268 |
| 269 | 269 |
| 270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
| 271 | 271 |
| 272 static void FillCache(Isolate* isolate, Handle<Code> code) { | 272 static void FillCache(Isolate* isolate, Handle<Code> code) { |
| 273 Handle<UnseededNumberDictionary> dictionary = | 273 Handle<UnseededNumberDictionary> dictionary = |
| 274 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 274 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
| 275 code->flags(), | 275 code->flags(), |
| 276 code); | 276 code); |
| 277 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 277 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
| 278 } | 278 } |
| 279 | 279 |
| 280 | 280 |
| 281 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { | 281 Code* PropertyICCompiler::FindPreMonomorphicIC(Isolate* isolate, |
| 282 Code::Kind kind, |
| 283 ExtraICState state) { |
| 282 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 284 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
| 283 UnseededNumberDictionary* dictionary = | 285 UnseededNumberDictionary* dictionary = |
| 284 isolate()->heap()->non_monomorphic_cache(); | 286 isolate->heap()->non_monomorphic_cache(); |
| 285 int entry = dictionary->FindEntry(isolate(), flags); | 287 int entry = dictionary->FindEntry(isolate, flags); |
| 286 ASSERT(entry != -1); | 288 ASSERT(entry != -1); |
| 287 Object* code = dictionary->ValueAt(entry); | 289 Object* code = dictionary->ValueAt(entry); |
| 288 // This might be called during the marking phase of the collector | 290 // This might be called during the marking phase of the collector |
| 289 // hence the unchecked cast. | 291 // hence the unchecked cast. |
| 290 return reinterpret_cast<Code*>(code); | 292 return reinterpret_cast<Code*>(code); |
| 291 } | 293 } |
| 292 | 294 |
| 293 | 295 |
| 294 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, | 296 Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, |
| 295 ExtraICState extra_state) { | 297 InlineCacheState ic_state, |
| 298 ExtraICState extra_state) { |
| 296 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 299 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
| 297 Handle<UnseededNumberDictionary> cache = | 300 Handle<UnseededNumberDictionary> cache = |
| 298 isolate_->factory()->non_monomorphic_cache(); | 301 isolate->factory()->non_monomorphic_cache(); |
| 299 int entry = cache->FindEntry(isolate_, flags); | 302 int entry = cache->FindEntry(isolate, flags); |
| 300 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 303 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 301 | 304 |
| 302 PropertyICCompiler compiler(isolate_, Code::LOAD_IC); | 305 PropertyICCompiler compiler(isolate, Code::LOAD_IC); |
| 303 Handle<Code> code; | 306 Handle<Code> code; |
| 304 if (ic_state == UNINITIALIZED) { | 307 if (ic_state == UNINITIALIZED) { |
| 305 code = compiler.CompileLoadInitialize(flags); | 308 code = compiler.CompileLoadInitialize(flags); |
| 306 } else if (ic_state == PREMONOMORPHIC) { | 309 } else if (ic_state == PREMONOMORPHIC) { |
| 307 code = compiler.CompileLoadPreMonomorphic(flags); | 310 code = compiler.CompileLoadPreMonomorphic(flags); |
| 308 } else if (ic_state == MEGAMORPHIC) { | 311 } else if (ic_state == MEGAMORPHIC) { |
| 309 code = compiler.CompileLoadMegamorphic(flags); | 312 code = compiler.CompileLoadMegamorphic(flags); |
| 310 } else { | 313 } else { |
| 311 UNREACHABLE(); | 314 UNREACHABLE(); |
| 312 } | 315 } |
| 313 FillCache(isolate_, code); | 316 FillCache(isolate, code); |
| 314 return code; | 317 return code; |
| 315 } | 318 } |
| 316 | 319 |
| 317 | 320 |
| 318 Handle<Code> StubCache::ComputeStore(InlineCacheState ic_state, | 321 Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate, |
| 319 ExtraICState extra_state) { | 322 InlineCacheState ic_state, |
| 323 ExtraICState extra_state) { |
| 320 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); | 324 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); |
| 321 Handle<UnseededNumberDictionary> cache = | 325 Handle<UnseededNumberDictionary> cache = |
| 322 isolate_->factory()->non_monomorphic_cache(); | 326 isolate->factory()->non_monomorphic_cache(); |
| 323 int entry = cache->FindEntry(isolate_, flags); | 327 int entry = cache->FindEntry(isolate, flags); |
| 324 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 328 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 325 | 329 |
| 326 PropertyICCompiler compiler(isolate_, Code::STORE_IC); | 330 PropertyICCompiler compiler(isolate, Code::STORE_IC); |
| 327 Handle<Code> code; | 331 Handle<Code> code; |
| 328 if (ic_state == UNINITIALIZED) { | 332 if (ic_state == UNINITIALIZED) { |
| 329 code = compiler.CompileStoreInitialize(flags); | 333 code = compiler.CompileStoreInitialize(flags); |
| 330 } else if (ic_state == PREMONOMORPHIC) { | 334 } else if (ic_state == PREMONOMORPHIC) { |
| 331 code = compiler.CompileStorePreMonomorphic(flags); | 335 code = compiler.CompileStorePreMonomorphic(flags); |
| 332 } else if (ic_state == GENERIC) { | 336 } else if (ic_state == GENERIC) { |
| 333 code = compiler.CompileStoreGeneric(flags); | 337 code = compiler.CompileStoreGeneric(flags); |
| 334 } else if (ic_state == MEGAMORPHIC) { | 338 } else if (ic_state == MEGAMORPHIC) { |
| 335 code = compiler.CompileStoreMegamorphic(flags); | 339 code = compiler.CompileStoreMegamorphic(flags); |
| 336 } else { | 340 } else { |
| 337 UNREACHABLE(); | 341 UNREACHABLE(); |
| 338 } | 342 } |
| 339 | 343 |
| 340 FillCache(isolate_, code); | 344 FillCache(isolate, code); |
| 341 return code; | 345 return code; |
| 342 } | 346 } |
| 343 | 347 |
| 344 | 348 |
| 345 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, | 349 Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map, |
| 346 CompareNilICStub* stub) { | 350 CompareNilICStub* stub) { |
| 347 Handle<String> name(isolate_->heap()->empty_string()); | 351 Isolate* isolate = receiver_map->GetIsolate(); |
| 352 Handle<String> name(isolate->heap()->empty_string()); |
| 348 if (!receiver_map->is_shared()) { | 353 if (!receiver_map->is_shared()) { |
| 349 Handle<Code> cached_ic = PropertyICCompiler::Find( | 354 Handle<Code> cached_ic = |
| 350 name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState()); | 355 Find(name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState()); |
| 351 if (!cached_ic.is_null()) return cached_ic; | 356 if (!cached_ic.is_null()) return cached_ic; |
| 352 } | 357 } |
| 353 | 358 |
| 354 Code::FindAndReplacePattern pattern; | 359 Code::FindAndReplacePattern pattern; |
| 355 pattern.Add(isolate_->factory()->meta_map(), receiver_map); | 360 pattern.Add(isolate->factory()->meta_map(), receiver_map); |
| 356 Handle<Code> ic = stub->GetCodeCopy(pattern); | 361 Handle<Code> ic = stub->GetCodeCopy(pattern); |
| 357 | 362 |
| 358 if (!receiver_map->is_shared()) { | 363 if (!receiver_map->is_shared()) { |
| 359 Map::UpdateCodeCache(receiver_map, name, ic); | 364 Map::UpdateCodeCache(receiver_map, name, ic); |
| 360 } | 365 } |
| 361 | 366 |
| 362 return ic; | 367 return ic; |
| 363 } | 368 } |
| 364 | 369 |
| 365 | 370 |
| 366 // TODO(verwaest): Change this method so it takes in a TypeHandleList. | 371 // TODO(verwaest): Change this method so it takes in a TypeHandleList. |
| 367 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 372 Handle<Code> PropertyICCompiler::ComputeLoadElementPolymorphic( |
| 368 MapHandleList* receiver_maps) { | 373 MapHandleList* receiver_maps) { |
| 374 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
| 369 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 375 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 370 Handle<PolymorphicCodeCache> cache = | 376 Handle<PolymorphicCodeCache> cache = |
| 371 isolate_->factory()->polymorphic_code_cache(); | 377 isolate->factory()->polymorphic_code_cache(); |
| 372 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 378 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 373 if (probe->IsCode()) return Handle<Code>::cast(probe); | 379 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 374 | 380 |
| 375 TypeHandleList types(receiver_maps->length()); | 381 TypeHandleList types(receiver_maps->length()); |
| 376 for (int i = 0; i < receiver_maps->length(); i++) { | 382 for (int i = 0; i < receiver_maps->length(); i++) { |
| 377 types.Add(HeapType::Class(receiver_maps->at(i), isolate())); | 383 types.Add(HeapType::Class(receiver_maps->at(i), isolate)); |
| 378 } | 384 } |
| 379 CodeHandleList handlers(receiver_maps->length()); | 385 CodeHandleList handlers(receiver_maps->length()); |
| 380 IndexedHandlerCompiler compiler(isolate_); | 386 IndexedHandlerCompiler compiler(isolate); |
| 381 compiler.CompileElementHandlers(receiver_maps, &handlers); | 387 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 382 PropertyICCompiler ic_compiler(isolate_, Code::KEYED_LOAD_IC); | 388 PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); |
| 383 Handle<Code> code = ic_compiler.CompilePolymorphic( | 389 Handle<Code> code = ic_compiler.CompilePolymorphic( |
| 384 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); | 390 &types, &handlers, isolate->factory()->empty_string(), Code::NORMAL, |
| 391 ELEMENT); |
| 385 | 392 |
| 386 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 393 isolate->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 387 | 394 |
| 388 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 395 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 389 return code; | 396 return code; |
| 390 } | 397 } |
| 391 | 398 |
| 392 | 399 |
| 393 Handle<Code> StubCache::ComputePolymorphicIC( | 400 Handle<Code> PropertyICCompiler::ComputePolymorphicIC( |
| 394 Code::Kind kind, | 401 Code::Kind kind, TypeHandleList* types, CodeHandleList* handlers, |
| 395 TypeHandleList* types, | 402 int valid_types, Handle<Name> name, ExtraICState extra_ic_state) { |
| 396 CodeHandleList* handlers, | |
| 397 int number_of_valid_types, | |
| 398 Handle<Name> name, | |
| 399 ExtraICState extra_ic_state) { | |
| 400 Handle<Code> handler = handlers->at(0); | 403 Handle<Code> handler = handlers->at(0); |
| 401 Code::StubType type = number_of_valid_types == 1 ? handler->type() | 404 Code::StubType type = valid_types == 1 ? handler->type() : Code::NORMAL; |
| 402 : Code::NORMAL; | |
| 403 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); | 405 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); |
| 404 PropertyICCompiler ic_compiler(isolate_, kind, extra_ic_state); | 406 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); |
| 405 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); | 407 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); |
| 406 } | 408 } |
| 407 | 409 |
| 408 | 410 |
| 409 Handle<Code> StubCache::ComputeStoreElementPolymorphic( | 411 Handle<Code> PropertyICCompiler::ComputeStoreElementPolymorphic( |
| 410 MapHandleList* receiver_maps, | 412 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, |
| 411 KeyedAccessStoreMode store_mode, | |
| 412 StrictMode strict_mode) { | 413 StrictMode strict_mode) { |
| 414 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
| 413 ASSERT(store_mode == STANDARD_STORE || | 415 ASSERT(store_mode == STANDARD_STORE || |
| 414 store_mode == STORE_AND_GROW_NO_TRANSITION || | 416 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 415 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 417 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 416 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 418 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
| 417 Handle<PolymorphicCodeCache> cache = | 419 Handle<PolymorphicCodeCache> cache = |
| 418 isolate_->factory()->polymorphic_code_cache(); | 420 isolate->factory()->polymorphic_code_cache(); |
| 419 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( | 421 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( |
| 420 strict_mode, store_mode); | 422 strict_mode, store_mode); |
| 421 Code::Flags flags = | 423 Code::Flags flags = |
| 422 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 424 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
| 423 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 425 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 424 if (probe->IsCode()) return Handle<Code>::cast(probe); | 426 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 425 | 427 |
| 426 PropertyICCompiler compiler(isolate_, Code::KEYED_STORE_IC, extra_state); | 428 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
| 427 Handle<Code> code = | 429 Handle<Code> code = |
| 428 compiler.CompileIndexedStorePolymorphic(receiver_maps, store_mode); | 430 compiler.CompileIndexedStorePolymorphic(receiver_maps, store_mode); |
| 429 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 431 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 430 return code; | 432 return code; |
| 431 } | 433 } |
| 432 | 434 |
| 433 | 435 |
| 434 void StubCache::Clear() { | 436 void StubCache::Clear() { |
| 435 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 437 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
| 436 for (int i = 0; i < kPrimaryTableSize; i++) { | 438 for (int i = 0; i < kPrimaryTableSize; i++) { |
| 437 primary_[i].key = heap()->empty_string(); | 439 primary_[i].key = isolate()->heap()->empty_string(); |
| 438 primary_[i].map = NULL; | 440 primary_[i].map = NULL; |
| 439 primary_[i].value = empty; | 441 primary_[i].value = empty; |
| 440 } | 442 } |
| 441 for (int j = 0; j < kSecondaryTableSize; j++) { | 443 for (int j = 0; j < kSecondaryTableSize; j++) { |
| 442 secondary_[j].key = heap()->empty_string(); | 444 secondary_[j].key = isolate()->heap()->empty_string(); |
| 443 secondary_[j].map = NULL; | 445 secondary_[j].map = NULL; |
| 444 secondary_[j].value = empty; | 446 secondary_[j].value = empty; |
| 445 } | 447 } |
| 446 } | 448 } |
| 447 | 449 |
| 448 | 450 |
| 449 void StubCache::CollectMatchingMaps(SmallMapList* types, | 451 void StubCache::CollectMatchingMaps(SmallMapList* types, |
| 450 Handle<Name> name, | 452 Handle<Name> name, |
| 451 Code::Flags flags, | 453 Code::Flags flags, |
| 452 Handle<Context> native_context, | 454 Handle<Context> native_context, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 | 520 |
| 519 | 521 |
| 520 /** | 522 /** |
| 521 * Attempts to load a property with an interceptor (which must be present), | 523 * Attempts to load a property with an interceptor (which must be present), |
| 522 * but doesn't search the prototype chain. | 524 * but doesn't search the prototype chain. |
| 523 * | 525 * |
| 524 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't | 526 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't |
| 525 * provide any value for the given name. | 527 * provide any value for the given name. |
| 526 */ | 528 */ |
| 527 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { | 529 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { |
| 528 ASSERT(args.length() == StubCache::kInterceptorArgsLength); | 530 ASSERT(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |
| 529 Handle<Name> name_handle = | 531 Handle<Name> name_handle = |
| 530 args.at<Name>(StubCache::kInterceptorArgsNameIndex); | 532 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |
| 531 Handle<InterceptorInfo> interceptor_info = | 533 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>( |
| 532 args.at<InterceptorInfo>(StubCache::kInterceptorArgsInfoIndex); | 534 NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex); |
| 533 | 535 |
| 534 // TODO(rossberg): Support symbols in the API. | 536 // TODO(rossberg): Support symbols in the API. |
| 535 if (name_handle->IsSymbol()) | 537 if (name_handle->IsSymbol()) |
| 536 return isolate->heap()->no_interceptor_result_sentinel(); | 538 return isolate->heap()->no_interceptor_result_sentinel(); |
| 537 Handle<String> name = Handle<String>::cast(name_handle); | 539 Handle<String> name = Handle<String>::cast(name_handle); |
| 538 | 540 |
| 539 Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); | 541 Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); |
| 540 v8::NamedPropertyGetterCallback getter = | 542 v8::NamedPropertyGetterCallback getter = |
| 541 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address); | 543 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address); |
| 542 ASSERT(getter != NULL); | 544 ASSERT(getter != NULL); |
| 543 | 545 |
| 544 Handle<JSObject> receiver = | 546 Handle<JSObject> receiver = |
| 545 args.at<JSObject>(StubCache::kInterceptorArgsThisIndex); | 547 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |
| 546 Handle<JSObject> holder = | 548 Handle<JSObject> holder = |
| 547 args.at<JSObject>(StubCache::kInterceptorArgsHolderIndex); | 549 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |
| 548 PropertyCallbackArguments callback_args( | 550 PropertyCallbackArguments callback_args( |
| 549 isolate, interceptor_info->data(), *receiver, *holder); | 551 isolate, interceptor_info->data(), *receiver, *holder); |
| 550 { | 552 { |
| 551 // Use the interceptor getter. | 553 // Use the interceptor getter. |
| 552 HandleScope scope(isolate); | 554 HandleScope scope(isolate); |
| 553 v8::Handle<v8::Value> r = | 555 v8::Handle<v8::Value> r = |
| 554 callback_args.Call(getter, v8::Utils::ToLocal(name)); | 556 callback_args.Call(getter, v8::Utils::ToLocal(name)); |
| 555 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 557 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 556 if (!r.IsEmpty()) { | 558 if (!r.IsEmpty()) { |
| 557 Handle<Object> result = v8::Utils::OpenHandle(*r); | 559 Handle<Object> result = v8::Utils::OpenHandle(*r); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 581 return isolate->Throw(*error); | 583 return isolate->Throw(*error); |
| 582 } | 584 } |
| 583 | 585 |
| 584 | 586 |
| 585 /** | 587 /** |
| 586 * Loads a property with an interceptor performing post interceptor | 588 * Loads a property with an interceptor performing post interceptor |
| 587 * lookup if interceptor failed. | 589 * lookup if interceptor failed. |
| 588 */ | 590 */ |
| 589 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { | 591 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { |
| 590 HandleScope scope(isolate); | 592 HandleScope scope(isolate); |
| 591 ASSERT(args.length() == StubCache::kInterceptorArgsLength); | 593 ASSERT(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |
| 592 Handle<Name> name = | 594 Handle<Name> name = |
| 593 args.at<Name>(StubCache::kInterceptorArgsNameIndex); | 595 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |
| 594 Handle<JSObject> receiver = | 596 Handle<JSObject> receiver = |
| 595 args.at<JSObject>(StubCache::kInterceptorArgsThisIndex); | 597 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |
| 596 Handle<JSObject> holder = | 598 Handle<JSObject> holder = |
| 597 args.at<JSObject>(StubCache::kInterceptorArgsHolderIndex); | 599 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |
| 598 | 600 |
| 599 Handle<Object> result; | 601 Handle<Object> result; |
| 600 LookupIterator it(receiver, name, holder); | 602 LookupIterator it(receiver, name, holder); |
| 601 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 603 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 602 isolate, result, JSObject::GetProperty(&it)); | 604 isolate, result, JSObject::GetProperty(&it)); |
| 603 | 605 |
| 604 if (it.IsFound()) return *result; | 606 if (it.IsFound()) return *result; |
| 605 | 607 |
| 606 return ThrowReferenceError(isolate, Name::cast(args[0])); | 608 return ThrowReferenceError(isolate, Name::cast(args[0])); |
| 607 } | 609 } |
| (...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 Handle<FunctionTemplateInfo>( | 1357 Handle<FunctionTemplateInfo>( |
| 1356 FunctionTemplateInfo::cast(signature->receiver())); | 1358 FunctionTemplateInfo::cast(signature->receiver())); |
| 1357 } | 1359 } |
| 1358 } | 1360 } |
| 1359 | 1361 |
| 1360 is_simple_api_call_ = true; | 1362 is_simple_api_call_ = true; |
| 1361 } | 1363 } |
| 1362 | 1364 |
| 1363 | 1365 |
| 1364 } } // namespace v8::internal | 1366 } } // namespace v8::internal |
| OLD | NEW |