| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 kind, extra_state, cache_holder); | 109 kind, extra_state, cache_holder); |
| 110 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); | 110 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); |
| 111 if (probe->IsCode()) return Handle<Code>::cast(probe); | 111 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 112 return Handle<Code>::null(); | 112 return Handle<Code>::null(); |
| 113 } | 113 } |
| 114 | 114 |
| 115 | 115 |
| 116 Handle<Code> StubCache::FindHandler(Handle<Name> name, | 116 Handle<Code> StubCache::FindHandler(Handle<Name> name, |
| 117 Handle<Map> stub_holder, | 117 Handle<Map> stub_holder, |
| 118 Code::Kind kind, | 118 Code::Kind kind, |
| 119 InlineCacheHolderFlag cache_holder) { | 119 InlineCacheHolderFlag cache_holder, |
| 120 Code::Flags flags = Code::ComputeMonomorphicFlags( | 120 Code::StubType type) { |
| 121 Code::HANDLER, kNoExtraICState, cache_holder, Code::NORMAL, kind); | 121 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); |
| 122 | 122 |
| 123 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); | 123 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); |
| 124 if (probe->IsCode()) return Handle<Code>::cast(probe); | 124 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 125 return Handle<Code>::null(); | 125 return Handle<Code>::null(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 Handle<Code> StubCache::ComputeMonomorphicIC( | 129 Handle<Code> StubCache::ComputeMonomorphicIC( |
| 130 Code::Kind kind, |
| 130 Handle<Name> name, | 131 Handle<Name> name, |
| 131 Handle<Type> type, | 132 Handle<HeapType> type, |
| 132 Handle<Code> handler, | 133 Handle<Code> handler, |
| 133 ExtraICState extra_ic_state) { | 134 ExtraICState extra_ic_state) { |
| 134 Code::Kind kind = handler->handler_kind(); | |
| 135 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); | 135 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); |
| 136 | 136 |
| 137 Handle<Map> stub_holder; | 137 Handle<Map> stub_holder; |
| 138 Handle<Code> ic; | 138 Handle<Code> ic; |
| 139 // There are multiple string maps that all use the same prototype. That | 139 // There are multiple string maps that all use the same prototype. That |
| 140 // prototype cannot hold multiple handlers, one for each of the string maps, | 140 // prototype cannot hold multiple handlers, one for each of the string maps, |
| 141 // for a single name. Hence, turn off caching of the IC. | 141 // for a single name. Hence, turn off caching of the IC. |
| 142 bool can_be_cached = !type->Is(Type::String()); | 142 bool can_be_cached = !type->Is(HeapType::String()); |
| 143 if (can_be_cached) { | 143 if (can_be_cached) { |
| 144 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); | 144 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); |
| 145 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); | 145 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); |
| 146 if (!ic.is_null()) return ic; | 146 if (!ic.is_null()) return ic; |
| 147 } | 147 } |
| 148 | 148 |
| 149 if (kind == Code::LOAD_IC) { | 149 if (kind == Code::LOAD_IC) { |
| 150 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); | 150 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); |
| 151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 152 } else if (kind == Code::KEYED_LOAD_IC) { | 152 } else if (kind == Code::KEYED_LOAD_IC) { |
| 153 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); | 153 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); |
| 154 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 154 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 155 } else if (kind == Code::STORE_IC) { | 155 } else if (kind == Code::STORE_IC) { |
| 156 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); | 156 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); |
| 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 158 } else { | 158 } else { |
| 159 ASSERT(kind == Code::KEYED_STORE_IC); | 159 ASSERT(kind == Code::KEYED_STORE_IC); |
| 160 ASSERT(STANDARD_STORE == | 160 ASSERT(STANDARD_STORE == |
| 161 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | 161 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); |
| 162 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); | 162 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); |
| 163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 164 } | 164 } |
| 165 | 165 |
| 166 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 166 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
| 167 return ic; | 167 return ic; |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 171 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
| 172 Handle<Type> type) { | 172 Handle<HeapType> type) { |
| 173 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); | 173 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); |
| 174 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); | 174 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); |
| 175 // If no dictionary mode objects are present in the prototype chain, the load | 175 // If no dictionary mode objects are present in the prototype chain, the load |
| 176 // nonexistent IC stub can be shared for all names for a given map and we use | 176 // nonexistent IC stub can be shared for all names for a given map and we use |
| 177 // the empty string for the map cache in that case. If there are dictionary | 177 // the empty string for the map cache in that case. If there are dictionary |
| 178 // mode objects involved, we need to do negative lookups in the stub and | 178 // mode objects involved, we need to do negative lookups in the stub and |
| 179 // therefore the stub will be specific to the name. | 179 // therefore the stub will be specific to the name. |
| 180 Handle<Map> current_map = stub_holder; | 180 Handle<Map> current_map = stub_holder; |
| 181 Handle<Name> cache_name = current_map->is_dictionary_map() | 181 Handle<Name> cache_name = current_map->is_dictionary_map() |
| 182 ? name : Handle<Name>::cast(isolate()->factory()->empty_string()); | 182 ? name : Handle<Name>::cast(isolate()->factory()->empty_string()); |
| 183 Handle<Object> next(current_map->prototype(), isolate()); | 183 Handle<Object> next(current_map->prototype(), isolate()); |
| 184 Handle<JSObject> last = Handle<JSObject>::null(); | 184 Handle<JSObject> last = Handle<JSObject>::null(); |
| 185 while (!next->IsNull()) { | 185 while (!next->IsNull()) { |
| 186 last = Handle<JSObject>::cast(next); | 186 last = Handle<JSObject>::cast(next); |
| 187 next = handle(current_map->prototype(), isolate()); | 187 next = handle(current_map->prototype(), isolate()); |
| 188 current_map = handle(Handle<HeapObject>::cast(next)->map()); | 188 current_map = handle(Handle<HeapObject>::cast(next)->map()); |
| 189 if (current_map->is_dictionary_map()) cache_name = name; | 189 if (current_map->is_dictionary_map()) cache_name = name; |
| 190 } | 190 } |
| 191 | 191 |
| 192 // Compile the stub that is either shared for all names or | 192 // Compile the stub that is either shared for all names or |
| 193 // name specific if there are global objects involved. | 193 // name specific if there are global objects involved. |
| 194 Handle<Code> handler = FindHandler( | 194 Handle<Code> handler = FindHandler( |
| 195 cache_name, stub_holder, Code::LOAD_IC, flag); | 195 cache_name, stub_holder, Code::LOAD_IC, flag, Code::FAST); |
| 196 if (!handler.is_null()) return handler; | 196 if (!handler.is_null()) { |
| 197 return handler; |
| 198 } |
| 197 | 199 |
| 198 LoadStubCompiler compiler(isolate_, flag); | 200 LoadStubCompiler compiler(isolate_, kNoExtraICState, flag); |
| 199 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 201 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
| 200 Map::UpdateCodeCache(stub_holder, cache_name, handler); | 202 Map::UpdateCodeCache(stub_holder, cache_name, handler); |
| 201 return handler; | 203 return handler; |
| 202 } | 204 } |
| 203 | 205 |
| 204 | 206 |
| 205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 207 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
| 206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 208 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
| 207 Handle<Name> name = | 209 Handle<Name> name = |
| 208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 210 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 KeyedStoreStubCompiler compiler(isolate(), extra_state); | 242 KeyedStoreStubCompiler compiler(isolate(), extra_state); |
| 241 Handle<Code> code = compiler.CompileStoreElement(receiver_map); | 243 Handle<Code> code = compiler.CompileStoreElement(receiver_map); |
| 242 | 244 |
| 243 Map::UpdateCodeCache(receiver_map, name, code); | 245 Map::UpdateCodeCache(receiver_map, name, code); |
| 244 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 246 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
| 245 == store_mode); | 247 == store_mode); |
| 246 return code; | 248 return code; |
| 247 } | 249 } |
| 248 | 250 |
| 249 | 251 |
| 250 #define CALL_LOGGER_TAG(kind, type) \ | 252 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
| 251 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | |
| 252 | |
| 253 Handle<Code> StubCache::ComputeCallConstant(int argc, | |
| 254 Code::Kind kind, | |
| 255 ExtraICState extra_state, | |
| 256 Handle<Name> name, | |
| 257 Handle<Object> object, | |
| 258 Handle<JSObject> holder, | |
| 259 Handle<JSFunction> function) { | |
| 260 // Compute the check type and the map. | |
| 261 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | |
| 262 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | |
| 263 isolate_, *object, cache_holder)); | |
| 264 | |
| 265 // Compute check type based on receiver/holder. | |
| 266 CheckType check = RECEIVER_MAP_CHECK; | |
| 267 if (object->IsString()) { | |
| 268 check = STRING_CHECK; | |
| 269 } else if (object->IsSymbol()) { | |
| 270 check = SYMBOL_CHECK; | |
| 271 } else if (object->IsNumber()) { | |
| 272 check = NUMBER_CHECK; | |
| 273 } else if (object->IsBoolean()) { | |
| 274 check = BOOLEAN_CHECK; | |
| 275 } | |
| 276 | |
| 277 if (check != RECEIVER_MAP_CHECK && | |
| 278 !function->IsBuiltin() && | |
| 279 function->shared()->is_classic_mode()) { | |
| 280 // Calling non-strict non-builtins with a value as the receiver | |
| 281 // requires boxing. | |
| 282 return Handle<Code>::null(); | |
| 283 } | |
| 284 | |
| 285 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 286 kind, extra_state, cache_holder, Code::FAST, argc); | |
| 287 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | |
| 288 isolate_); | |
| 289 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
| 290 | |
| 291 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | |
| 292 Handle<Code> code = | |
| 293 compiler.CompileCallConstant(object, holder, name, check, function); | |
| 294 code->set_check_type(check); | |
| 295 ASSERT(flags == code->flags()); | |
| 296 PROFILE(isolate_, | |
| 297 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
| 298 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
| 299 | |
| 300 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
| 301 return code; | |
| 302 } | |
| 303 | |
| 304 | |
| 305 Handle<Code> StubCache::ComputeCallField(int argc, | |
| 306 Code::Kind kind, | |
| 307 ExtraICState extra_state, | |
| 308 Handle<Name> name, | |
| 309 Handle<Object> object, | |
| 310 Handle<JSObject> holder, | |
| 311 PropertyIndex index) { | |
| 312 // Compute the check type and the map. | |
| 313 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | |
| 314 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | |
| 315 isolate_, *object, cache_holder)); | |
| 316 | |
| 317 // TODO(1233596): We cannot do receiver map check for non-JS objects | |
| 318 // because they may be represented as immediates without a | |
| 319 // map. Instead, we check against the map in the holder. | |
| 320 if (object->IsNumber() || object->IsSymbol() || | |
| 321 object->IsBoolean() || object->IsString()) { | |
| 322 object = holder; | |
| 323 } | |
| 324 | |
| 325 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 326 kind, extra_state, cache_holder, Code::FAST, argc); | |
| 327 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | |
| 328 isolate_); | |
| 329 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
| 330 | |
| 331 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | |
| 332 Handle<Code> code = | |
| 333 compiler.CompileCallField(Handle<JSObject>::cast(object), | |
| 334 holder, index, name); | |
| 335 ASSERT(flags == code->flags()); | |
| 336 PROFILE(isolate_, | |
| 337 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
| 338 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
| 339 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
| 340 return code; | |
| 341 } | |
| 342 | |
| 343 | |
| 344 Handle<Code> StubCache::ComputeCallInterceptor(int argc, | |
| 345 Code::Kind kind, | |
| 346 ExtraICState extra_state, | |
| 347 Handle<Name> name, | |
| 348 Handle<Object> object, | |
| 349 Handle<JSObject> holder) { | |
| 350 // Compute the check type and the map. | |
| 351 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | |
| 352 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | |
| 353 isolate_, *object, cache_holder)); | |
| 354 | |
| 355 // TODO(1233596): We cannot do receiver map check for non-JS objects | |
| 356 // because they may be represented as immediates without a | |
| 357 // map. Instead, we check against the map in the holder. | |
| 358 if (object->IsNumber() || object->IsSymbol() || | |
| 359 object->IsBoolean() || object->IsString()) { | |
| 360 object = holder; | |
| 361 } | |
| 362 | |
| 363 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 364 kind, extra_state, cache_holder, Code::FAST, argc); | |
| 365 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | |
| 366 isolate_); | |
| 367 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
| 368 | |
| 369 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); | |
| 370 Handle<Code> code = | |
| 371 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), | |
| 372 holder, name); | |
| 373 ASSERT(flags == code->flags()); | |
| 374 PROFILE(isolate(), | |
| 375 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
| 376 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
| 377 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
| 378 return code; | |
| 379 } | |
| 380 | |
| 381 | |
| 382 Handle<Code> StubCache::ComputeCallGlobal(int argc, | |
| 383 Code::Kind kind, | |
| 384 ExtraICState extra_state, | |
| 385 Handle<Name> name, | |
| 386 Handle<JSObject> receiver, | |
| 387 Handle<GlobalObject> holder, | |
| 388 Handle<PropertyCell> cell, | |
| 389 Handle<JSFunction> function) { | |
| 390 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 391 kind, extra_state, OWN_MAP, Code::NORMAL, argc); | |
| 392 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | |
| 393 isolate_); | |
| 394 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
| 395 | |
| 396 CallStubCompiler compiler(isolate(), argc, kind, extra_state); | |
| 397 Handle<Code> code = | |
| 398 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | |
| 399 ASSERT(flags == code->flags()); | |
| 400 PROFILE(isolate(), | |
| 401 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
| 402 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
| 403 HeapObject::UpdateMapCodeCache(receiver, name, code); | |
| 404 return code; | |
| 405 } | |
| 406 | |
| 407 | 253 |
| 408 static void FillCache(Isolate* isolate, Handle<Code> code) { | 254 static void FillCache(Isolate* isolate, Handle<Code> code) { |
| 409 Handle<UnseededNumberDictionary> dictionary = | 255 Handle<UnseededNumberDictionary> dictionary = |
| 410 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 256 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
| 411 code->flags(), | 257 code->flags(), |
| 412 code); | 258 code); |
| 413 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 259 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
| 414 } | 260 } |
| 415 | 261 |
| 416 | 262 |
| 417 Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) { | |
| 418 Code::Flags flags = Code::ComputeFlags( | |
| 419 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc); | |
| 420 UnseededNumberDictionary* dictionary = | |
| 421 isolate()->heap()->non_monomorphic_cache(); | |
| 422 int entry = dictionary->FindEntry(isolate(), flags); | |
| 423 ASSERT(entry != -1); | |
| 424 Object* code = dictionary->ValueAt(entry); | |
| 425 // This might be called during the marking phase of the collector | |
| 426 // hence the unchecked cast. | |
| 427 return reinterpret_cast<Code*>(code); | |
| 428 } | |
| 429 | |
| 430 | |
| 431 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { | 263 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { |
| 432 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 264 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
| 433 UnseededNumberDictionary* dictionary = | 265 UnseededNumberDictionary* dictionary = |
| 434 isolate()->heap()->non_monomorphic_cache(); | 266 isolate()->heap()->non_monomorphic_cache(); |
| 435 int entry = dictionary->FindEntry(isolate(), flags); | 267 int entry = dictionary->FindEntry(isolate(), flags); |
| 436 ASSERT(entry != -1); | 268 ASSERT(entry != -1); |
| 437 Object* code = dictionary->ValueAt(entry); | 269 Object* code = dictionary->ValueAt(entry); |
| 438 // This might be called during the marking phase of the collector | 270 // This might be called during the marking phase of the collector |
| 439 // hence the unchecked cast. | 271 // hence the unchecked cast. |
| 440 return reinterpret_cast<Code*>(code); | 272 return reinterpret_cast<Code*>(code); |
| 441 } | 273 } |
| 442 | 274 |
| 443 | 275 |
| 444 Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) { | |
| 445 Code::Flags flags = Code::ComputeFlags( | |
| 446 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc); | |
| 447 Handle<UnseededNumberDictionary> cache = | |
| 448 isolate_->factory()->non_monomorphic_cache(); | |
| 449 int entry = cache->FindEntry(isolate_, flags); | |
| 450 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 451 | |
| 452 StubCompiler compiler(isolate_); | |
| 453 Handle<Code> code = compiler.CompileCallInitialize(flags); | |
| 454 FillCache(isolate_, code); | |
| 455 return code; | |
| 456 } | |
| 457 | |
| 458 | |
| 459 Handle<Code> StubCache::ComputeCallInitialize(int argc) { | |
| 460 return ComputeCallInitialize(argc, Code::CALL_IC); | |
| 461 } | |
| 462 | |
| 463 | |
| 464 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) { | |
| 465 return ComputeCallInitialize(argc, Code::KEYED_CALL_IC); | |
| 466 } | |
| 467 | |
| 468 | |
| 469 Handle<Code> StubCache::ComputeCallPreMonomorphic( | |
| 470 int argc, | |
| 471 Code::Kind kind, | |
| 472 ExtraICState extra_state) { | |
| 473 Code::Flags flags = | |
| 474 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc); | |
| 475 Handle<UnseededNumberDictionary> cache = | |
| 476 isolate_->factory()->non_monomorphic_cache(); | |
| 477 int entry = cache->FindEntry(isolate_, flags); | |
| 478 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 479 | |
| 480 StubCompiler compiler(isolate_); | |
| 481 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags); | |
| 482 FillCache(isolate_, code); | |
| 483 return code; | |
| 484 } | |
| 485 | |
| 486 | |
| 487 Handle<Code> StubCache::ComputeCallNormal(int argc, | |
| 488 Code::Kind kind, | |
| 489 ExtraICState extra_state) { | |
| 490 Code::Flags flags = | |
| 491 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc); | |
| 492 Handle<UnseededNumberDictionary> cache = | |
| 493 isolate_->factory()->non_monomorphic_cache(); | |
| 494 int entry = cache->FindEntry(isolate_, flags); | |
| 495 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 496 | |
| 497 StubCompiler compiler(isolate_); | |
| 498 Handle<Code> code = compiler.CompileCallNormal(flags); | |
| 499 FillCache(isolate_, code); | |
| 500 return code; | |
| 501 } | |
| 502 | |
| 503 | |
| 504 Handle<Code> StubCache::ComputeCallArguments(int argc) { | |
| 505 Code::Flags flags = | |
| 506 Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC, | |
| 507 kNoExtraICState, Code::NORMAL, argc); | |
| 508 Handle<UnseededNumberDictionary> cache = | |
| 509 isolate_->factory()->non_monomorphic_cache(); | |
| 510 int entry = cache->FindEntry(isolate_, flags); | |
| 511 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 512 | |
| 513 StubCompiler compiler(isolate_); | |
| 514 Handle<Code> code = compiler.CompileCallArguments(flags); | |
| 515 FillCache(isolate_, code); | |
| 516 return code; | |
| 517 } | |
| 518 | |
| 519 | |
| 520 Handle<Code> StubCache::ComputeCallMegamorphic( | |
| 521 int argc, | |
| 522 Code::Kind kind, | |
| 523 ExtraICState extra_state) { | |
| 524 Code::Flags flags = | |
| 525 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state, | |
| 526 Code::NORMAL, argc); | |
| 527 Handle<UnseededNumberDictionary> cache = | |
| 528 isolate_->factory()->non_monomorphic_cache(); | |
| 529 int entry = cache->FindEntry(isolate_, flags); | |
| 530 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 531 | |
| 532 StubCompiler compiler(isolate_); | |
| 533 Handle<Code> code = compiler.CompileCallMegamorphic(flags); | |
| 534 FillCache(isolate_, code); | |
| 535 return code; | |
| 536 } | |
| 537 | |
| 538 | |
| 539 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, | 276 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, |
| 540 ExtraICState extra_state) { | 277 ExtraICState extra_state) { |
| 541 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 278 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
| 542 Handle<UnseededNumberDictionary> cache = | 279 Handle<UnseededNumberDictionary> cache = |
| 543 isolate_->factory()->non_monomorphic_cache(); | 280 isolate_->factory()->non_monomorphic_cache(); |
| 544 int entry = cache->FindEntry(isolate_, flags); | 281 int entry = cache->FindEntry(isolate_, flags); |
| 545 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 282 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 546 | 283 |
| 547 StubCompiler compiler(isolate_); | 284 StubCompiler compiler(isolate_); |
| 548 Handle<Code> code; | 285 Handle<Code> code; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 code = compiler.CompileStoreMegamorphic(flags); | 317 code = compiler.CompileStoreMegamorphic(flags); |
| 581 } else { | 318 } else { |
| 582 UNREACHABLE(); | 319 UNREACHABLE(); |
| 583 } | 320 } |
| 584 | 321 |
| 585 FillCache(isolate_, code); | 322 FillCache(isolate_, code); |
| 586 return code; | 323 return code; |
| 587 } | 324 } |
| 588 | 325 |
| 589 | 326 |
| 590 Handle<Code> StubCache::ComputeCallMiss(int argc, | |
| 591 Code::Kind kind, | |
| 592 ExtraICState extra_state) { | |
| 593 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs | |
| 594 // and monomorphic stubs are not mixed up together in the stub cache. | |
| 595 Code::Flags flags = | |
| 596 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, | |
| 597 Code::NORMAL, argc, OWN_MAP); | |
| 598 Handle<UnseededNumberDictionary> cache = | |
| 599 isolate_->factory()->non_monomorphic_cache(); | |
| 600 int entry = cache->FindEntry(isolate_, flags); | |
| 601 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 602 | |
| 603 StubCompiler compiler(isolate_); | |
| 604 Handle<Code> code = compiler.CompileCallMiss(flags); | |
| 605 FillCache(isolate_, code); | |
| 606 return code; | |
| 607 } | |
| 608 | |
| 609 | |
| 610 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, | 327 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, |
| 611 CompareNilICStub& stub) { | 328 CompareNilICStub& stub) { |
| 612 Handle<String> name(isolate_->heap()->empty_string()); | 329 Handle<String> name(isolate_->heap()->empty_string()); |
| 613 if (!receiver_map->is_shared()) { | 330 if (!receiver_map->is_shared()) { |
| 614 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, | 331 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, |
| 615 stub.GetExtraICState()); | 332 stub.GetExtraICState()); |
| 616 if (!cached_ic.is_null()) return cached_ic; | 333 if (!cached_ic.is_null()) return cached_ic; |
| 617 } | 334 } |
| 618 | 335 |
| 619 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); | 336 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 631 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 348 Handle<Code> StubCache::ComputeLoadElementPolymorphic( |
| 632 MapHandleList* receiver_maps) { | 349 MapHandleList* receiver_maps) { |
| 633 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 350 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 634 Handle<PolymorphicCodeCache> cache = | 351 Handle<PolymorphicCodeCache> cache = |
| 635 isolate_->factory()->polymorphic_code_cache(); | 352 isolate_->factory()->polymorphic_code_cache(); |
| 636 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 353 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 637 if (probe->IsCode()) return Handle<Code>::cast(probe); | 354 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 638 | 355 |
| 639 TypeHandleList types(receiver_maps->length()); | 356 TypeHandleList types(receiver_maps->length()); |
| 640 for (int i = 0; i < receiver_maps->length(); i++) { | 357 for (int i = 0; i < receiver_maps->length(); i++) { |
| 641 types.Add(Type::Class(receiver_maps->at(i), isolate())); | 358 types.Add(HeapType::Class(receiver_maps->at(i), isolate())); |
| 642 } | 359 } |
| 643 CodeHandleList handlers(receiver_maps->length()); | 360 CodeHandleList handlers(receiver_maps->length()); |
| 644 KeyedLoadStubCompiler compiler(isolate_); | 361 KeyedLoadStubCompiler compiler(isolate_); |
| 645 compiler.CompileElementHandlers(receiver_maps, &handlers); | 362 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 646 Handle<Code> code = compiler.CompilePolymorphicIC( | 363 Handle<Code> code = compiler.CompilePolymorphicIC( |
| 647 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); | 364 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); |
| 648 | 365 |
| 649 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 366 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 650 | 367 |
| 651 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 368 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 652 return code; | 369 return code; |
| 653 } | 370 } |
| 654 | 371 |
| 655 | 372 |
| 656 Handle<Code> StubCache::ComputePolymorphicIC( | 373 Handle<Code> StubCache::ComputePolymorphicIC( |
| 374 Code::Kind kind, |
| 657 TypeHandleList* types, | 375 TypeHandleList* types, |
| 658 CodeHandleList* handlers, | 376 CodeHandleList* handlers, |
| 659 int number_of_valid_types, | 377 int number_of_valid_types, |
| 660 Handle<Name> name, | 378 Handle<Name> name, |
| 661 ExtraICState extra_ic_state) { | 379 ExtraICState extra_ic_state) { |
| 662 | |
| 663 Handle<Code> handler = handlers->at(0); | 380 Handle<Code> handler = handlers->at(0); |
| 664 Code::Kind kind = handler->handler_kind(); | |
| 665 Code::StubType type = number_of_valid_types == 1 ? handler->type() | 381 Code::StubType type = number_of_valid_types == 1 ? handler->type() |
| 666 : Code::NORMAL; | 382 : Code::NORMAL; |
| 667 if (kind == Code::LOAD_IC) { | 383 if (kind == Code::LOAD_IC) { |
| 668 LoadStubCompiler ic_compiler(isolate_, extra_ic_state); | 384 LoadStubCompiler ic_compiler(isolate_, extra_ic_state); |
| 669 return ic_compiler.CompilePolymorphicIC( | 385 return ic_compiler.CompilePolymorphicIC( |
| 670 types, handlers, name, type, PROPERTY); | 386 types, handlers, name, type, PROPERTY); |
| 671 } else { | 387 } else { |
| 672 ASSERT(kind == Code::STORE_IC); | 388 ASSERT(kind == Code::STORE_IC); |
| 673 StoreStubCompiler ic_compiler(isolate_, extra_ic_state); | 389 StoreStubCompiler ic_compiler(isolate_, extra_ic_state); |
| 674 return ic_compiler.CompilePolymorphicIC( | 390 return ic_compiler.CompilePolymorphicIC( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 694 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 410 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 695 if (probe->IsCode()) return Handle<Code>::cast(probe); | 411 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 696 | 412 |
| 697 KeyedStoreStubCompiler compiler(isolate_, extra_state); | 413 KeyedStoreStubCompiler compiler(isolate_, extra_state); |
| 698 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); | 414 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); |
| 699 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 415 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 700 return code; | 416 return code; |
| 701 } | 417 } |
| 702 | 418 |
| 703 | 419 |
| 704 #ifdef ENABLE_DEBUGGER_SUPPORT | |
| 705 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, | |
| 706 Code::Kind kind) { | |
| 707 // Extra IC state is irrelevant for debug break ICs. They jump to | |
| 708 // the actual call ic to carry out the work. | |
| 709 Code::Flags flags = | |
| 710 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK, | |
| 711 Code::NORMAL, argc); | |
| 712 Handle<UnseededNumberDictionary> cache = | |
| 713 isolate_->factory()->non_monomorphic_cache(); | |
| 714 int entry = cache->FindEntry(isolate_, flags); | |
| 715 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 716 | |
| 717 StubCompiler compiler(isolate_); | |
| 718 Handle<Code> code = compiler.CompileCallDebugBreak(flags); | |
| 719 FillCache(isolate_, code); | |
| 720 return code; | |
| 721 } | |
| 722 | |
| 723 | |
| 724 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc, | |
| 725 Code::Kind kind) { | |
| 726 // Extra IC state is irrelevant for debug break ICs. They jump to | |
| 727 // the actual call ic to carry out the work. | |
| 728 Code::Flags flags = | |
| 729 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN, | |
| 730 Code::NORMAL, argc); | |
| 731 Handle<UnseededNumberDictionary> cache = | |
| 732 isolate_->factory()->non_monomorphic_cache(); | |
| 733 int entry = cache->FindEntry(isolate_, flags); | |
| 734 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
| 735 | |
| 736 StubCompiler compiler(isolate_); | |
| 737 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags); | |
| 738 FillCache(isolate_, code); | |
| 739 return code; | |
| 740 } | |
| 741 #endif | |
| 742 | |
| 743 | |
| 744 void StubCache::Clear() { | 420 void StubCache::Clear() { |
| 745 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 421 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
| 746 for (int i = 0; i < kPrimaryTableSize; i++) { | 422 for (int i = 0; i < kPrimaryTableSize; i++) { |
| 747 primary_[i].key = heap()->empty_string(); | 423 primary_[i].key = heap()->empty_string(); |
| 748 primary_[i].map = NULL; | 424 primary_[i].map = NULL; |
| 749 primary_[i].value = empty; | 425 primary_[i].value = empty; |
| 750 } | 426 } |
| 751 for (int j = 0; j < kSecondaryTableSize; j++) { | 427 for (int j = 0; j < kSecondaryTableSize; j++) { |
| 752 secondary_[j].key = heap()->empty_string(); | 428 secondary_[j].key = heap()->empty_string(); |
| 753 secondary_[j].map = NULL; | 429 secondary_[j].map = NULL; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 | 663 |
| 988 | 664 |
| 989 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { | 665 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { |
| 990 JSObject* receiver = JSObject::cast(args[0]); | 666 JSObject* receiver = JSObject::cast(args[0]); |
| 991 ASSERT(args.smi_at(1) >= 0); | 667 ASSERT(args.smi_at(1) >= 0); |
| 992 uint32_t index = args.smi_at(1); | 668 uint32_t index = args.smi_at(1); |
| 993 return receiver->GetElementWithInterceptor(receiver, index); | 669 return receiver->GetElementWithInterceptor(receiver, index); |
| 994 } | 670 } |
| 995 | 671 |
| 996 | 672 |
| 997 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) { | |
| 998 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 999 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1000 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
| 1001 if (kind == Code::CALL_IC) { | |
| 1002 CallIC::GenerateInitialize(masm(), argc, extra_state); | |
| 1003 } else { | |
| 1004 KeyedCallIC::GenerateInitialize(masm(), argc); | |
| 1005 } | |
| 1006 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize"); | |
| 1007 isolate()->counters()->call_initialize_stubs()->Increment(); | |
| 1008 PROFILE(isolate(), | |
| 1009 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), | |
| 1010 *code, code->arguments_count())); | |
| 1011 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code)); | |
| 1012 return code; | |
| 1013 } | |
| 1014 | |
| 1015 | |
| 1016 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | |
| 1017 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1018 // The code of the PreMonomorphic stub is the same as the code | |
| 1019 // of the Initialized stub. They just differ on the code object flags. | |
| 1020 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1021 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
| 1022 if (kind == Code::CALL_IC) { | |
| 1023 CallIC::GenerateInitialize(masm(), argc, extra_state); | |
| 1024 } else { | |
| 1025 KeyedCallIC::GenerateInitialize(masm(), argc); | |
| 1026 } | |
| 1027 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | |
| 1028 isolate()->counters()->call_premonomorphic_stubs()->Increment(); | |
| 1029 PROFILE(isolate(), | |
| 1030 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), | |
| 1031 *code, code->arguments_count())); | |
| 1032 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code)); | |
| 1033 return code; | |
| 1034 } | |
| 1035 | |
| 1036 | |
| 1037 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) { | |
| 1038 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1039 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1040 if (kind == Code::CALL_IC) { | |
| 1041 CallIC::GenerateNormal(masm(), argc); | |
| 1042 } else { | |
| 1043 KeyedCallIC::GenerateNormal(masm(), argc); | |
| 1044 } | |
| 1045 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal"); | |
| 1046 isolate()->counters()->call_normal_stubs()->Increment(); | |
| 1047 PROFILE(isolate(), | |
| 1048 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), | |
| 1049 *code, code->arguments_count())); | |
| 1050 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code)); | |
| 1051 return code; | |
| 1052 } | |
| 1053 | |
| 1054 | |
| 1055 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | |
| 1056 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1057 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1058 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
| 1059 if (kind == Code::CALL_IC) { | |
| 1060 CallIC::GenerateMegamorphic(masm(), argc, extra_state); | |
| 1061 } else { | |
| 1062 KeyedCallIC::GenerateMegamorphic(masm(), argc); | |
| 1063 } | |
| 1064 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic"); | |
| 1065 isolate()->counters()->call_megamorphic_stubs()->Increment(); | |
| 1066 PROFILE(isolate(), | |
| 1067 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), | |
| 1068 *code, code->arguments_count())); | |
| 1069 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code)); | |
| 1070 return code; | |
| 1071 } | |
| 1072 | |
| 1073 | |
| 1074 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { | 673 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { |
| 1075 LoadIC::GenerateInitialize(masm()); | 674 LoadIC::GenerateInitialize(masm()); |
| 1076 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 675 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); |
| 1077 PROFILE(isolate(), | 676 PROFILE(isolate(), |
| 1078 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | 677 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |
| 1079 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 678 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
| 1080 return code; | 679 return code; |
| 1081 } | 680 } |
| 1082 | 681 |
| 1083 | 682 |
| 1084 Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { | 683 Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { |
| 1085 LoadIC::GeneratePreMonomorphic(masm()); | 684 LoadIC::GeneratePreMonomorphic(masm()); |
| 1086 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); | 685 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); |
| 1087 PROFILE(isolate(), | 686 PROFILE(isolate(), |
| 1088 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); | 687 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); |
| 1089 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 688 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
| 1090 return code; | 689 return code; |
| 1091 } | 690 } |
| 1092 | 691 |
| 1093 | 692 |
| 1094 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { | 693 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { |
| 1095 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 694 LoadIC::GenerateMegamorphic(masm()); |
| 1096 ContextualMode mode = LoadIC::GetContextualMode(extra_state); | |
| 1097 LoadIC::GenerateMegamorphic(masm(), mode); | |
| 1098 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); | 695 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); |
| 1099 PROFILE(isolate(), | 696 PROFILE(isolate(), |
| 1100 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); | 697 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); |
| 1101 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 698 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
| 1102 return code; | 699 return code; |
| 1103 } | 700 } |
| 1104 | 701 |
| 1105 | 702 |
| 1106 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) { | 703 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) { |
| 1107 StoreIC::GenerateInitialize(masm()); | 704 StoreIC::GenerateInitialize(masm()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1129 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); | 726 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); |
| 1130 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); | 727 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); |
| 1131 PROFILE(isolate(), | 728 PROFILE(isolate(), |
| 1132 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); | 729 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); |
| 1133 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); | 730 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); |
| 1134 return code; | 731 return code; |
| 1135 } | 732 } |
| 1136 | 733 |
| 1137 | 734 |
| 1138 Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) { | 735 Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) { |
| 1139 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 736 StoreIC::GenerateMegamorphic(masm()); |
| 1140 StoreIC::GenerateMegamorphic(masm(), extra_state); | |
| 1141 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 737 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); |
| 1142 PROFILE(isolate(), | 738 PROFILE(isolate(), |
| 1143 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); | 739 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); |
| 1144 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); | 740 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); |
| 1145 return code; | 741 return code; |
| 1146 } | 742 } |
| 1147 | 743 |
| 1148 | 744 |
| 1149 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) { | |
| 1150 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1151 KeyedCallIC::GenerateNonStrictArguments(masm(), argc); | |
| 1152 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments"); | |
| 1153 PROFILE(isolate(), | |
| 1154 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), | |
| 1155 CALL_MEGAMORPHIC_TAG), | |
| 1156 *code, code->arguments_count())); | |
| 1157 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code)); | |
| 1158 return code; | |
| 1159 } | |
| 1160 | |
| 1161 | |
| 1162 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) { | |
| 1163 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1164 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1165 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
| 1166 if (kind == Code::CALL_IC) { | |
| 1167 CallIC::GenerateMiss(masm(), argc, extra_state); | |
| 1168 } else { | |
| 1169 KeyedCallIC::GenerateMiss(masm(), argc); | |
| 1170 } | |
| 1171 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss"); | |
| 1172 isolate()->counters()->call_megamorphic_stubs()->Increment(); | |
| 1173 PROFILE(isolate(), | |
| 1174 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), | |
| 1175 *code, code->arguments_count())); | |
| 1176 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code)); | |
| 1177 return code; | |
| 1178 } | |
| 1179 | |
| 1180 | |
| 1181 #ifdef ENABLE_DEBUGGER_SUPPORT | |
| 1182 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | |
| 1183 Debug::GenerateCallICDebugBreak(masm()); | |
| 1184 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | |
| 1185 PROFILE(isolate(), | |
| 1186 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), | |
| 1187 CALL_DEBUG_BREAK_TAG), | |
| 1188 *code, code->arguments_count())); | |
| 1189 return code; | |
| 1190 } | |
| 1191 | |
| 1192 | |
| 1193 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | |
| 1194 // Use the same code for the the step in preparations as we do for the | |
| 1195 // miss case. | |
| 1196 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1197 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1198 if (kind == Code::CALL_IC) { | |
| 1199 // For the debugger extra ic state is irrelevant. | |
| 1200 CallIC::GenerateMiss(masm(), argc, kNoExtraICState); | |
| 1201 } else { | |
| 1202 KeyedCallIC::GenerateMiss(masm(), argc); | |
| 1203 } | |
| 1204 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | |
| 1205 PROFILE(isolate(), | |
| 1206 CodeCreateEvent( | |
| 1207 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), | |
| 1208 *code, | |
| 1209 code->arguments_count())); | |
| 1210 return code; | |
| 1211 } | |
| 1212 #endif // ENABLE_DEBUGGER_SUPPORT | |
| 1213 | |
| 1214 #undef CALL_LOGGER_TAG | 745 #undef CALL_LOGGER_TAG |
| 1215 | 746 |
| 1216 | 747 |
| 1217 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 748 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
| 1218 const char* name) { | 749 const char* name) { |
| 1219 // Create code object in the heap. | 750 // Create code object in the heap. |
| 1220 CodeDesc desc; | 751 CodeDesc desc; |
| 1221 masm_.GetCode(&desc); | 752 masm_.GetCode(&desc); |
| 1222 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); | 753 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); |
| 1223 if (code->has_major_key()) { | 754 if (code->has_major_key()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1244 holder->LocalLookupRealNamedProperty(*name, lookup); | 775 holder->LocalLookupRealNamedProperty(*name, lookup); |
| 1245 if (lookup->IsFound()) return; | 776 if (lookup->IsFound()) return; |
| 1246 if (holder->GetPrototype()->IsNull()) return; | 777 if (holder->GetPrototype()->IsNull()) return; |
| 1247 holder->GetPrototype()->Lookup(*name, lookup); | 778 holder->GetPrototype()->Lookup(*name, lookup); |
| 1248 } | 779 } |
| 1249 | 780 |
| 1250 | 781 |
| 1251 #define __ ACCESS_MASM(masm()) | 782 #define __ ACCESS_MASM(masm()) |
| 1252 | 783 |
| 1253 | 784 |
| 1254 void CallStubCompiler::HandlerFrontendFooter(Label* miss) { | |
| 1255 __ bind(miss); | |
| 1256 GenerateMissBranch(); | |
| 1257 } | |
| 1258 | |
| 1259 | |
| 1260 void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver( | |
| 1261 Handle<JSFunction> function) { | |
| 1262 ParameterCount expected(function); | |
| 1263 __ InvokeFunction(function, expected, arguments(), | |
| 1264 JUMP_FUNCTION, NullCallWrapper()); | |
| 1265 } | |
| 1266 | |
| 1267 | |
| 1268 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | |
| 1269 Handle<JSFunction> function) { | |
| 1270 PatchImplicitReceiver(object); | |
| 1271 GenerateJumpFunctionIgnoreReceiver(function); | |
| 1272 } | |
| 1273 | |
| 1274 | |
| 1275 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | |
| 1276 Register actual_closure, | |
| 1277 Handle<JSFunction> function) { | |
| 1278 PatchImplicitReceiver(object); | |
| 1279 ParameterCount expected(function); | |
| 1280 __ InvokeFunction(actual_closure, expected, arguments(), | |
| 1281 JUMP_FUNCTION, NullCallWrapper()); | |
| 1282 } | |
| 1283 | |
| 1284 | |
| 1285 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 1286 Handle<Object> object, | |
| 1287 Handle<JSObject> holder, | |
| 1288 Handle<Name> name, | |
| 1289 CheckType check, | |
| 1290 Handle<JSFunction> function) { | |
| 1291 if (HasCustomCallGenerator(function)) { | |
| 1292 Handle<Code> code = CompileCustomCall(object, holder, | |
| 1293 Handle<Cell>::null(), | |
| 1294 function, Handle<String>::cast(name), | |
| 1295 Code::FAST); | |
| 1296 // A null handle means bail out to the regular compiler code below. | |
| 1297 if (!code.is_null()) return code; | |
| 1298 } | |
| 1299 | |
| 1300 Label miss; | |
| 1301 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 1302 GenerateJumpFunction(object, function); | |
| 1303 HandlerFrontendFooter(&miss); | |
| 1304 | |
| 1305 // Return the generated code. | |
| 1306 return GetCode(function); | |
| 1307 } | |
| 1308 | |
| 1309 | |
| 1310 Register LoadStubCompiler::HandlerFrontendHeader( | 785 Register LoadStubCompiler::HandlerFrontendHeader( |
| 1311 Handle<Type> type, | 786 Handle<HeapType> type, |
| 1312 Register object_reg, | 787 Register object_reg, |
| 1313 Handle<JSObject> holder, | 788 Handle<JSObject> holder, |
| 1314 Handle<Name> name, | 789 Handle<Name> name, |
| 1315 Label* miss) { | 790 Label* miss) { |
| 1316 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 791 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
| 1317 int function_index = -1; | 792 int function_index = -1; |
| 1318 if (type->Is(Type::String())) { | 793 if (type->Is(HeapType::String())) { |
| 1319 function_index = Context::STRING_FUNCTION_INDEX; | 794 function_index = Context::STRING_FUNCTION_INDEX; |
| 1320 } else if (type->Is(Type::Symbol())) { | 795 } else if (type->Is(HeapType::Symbol())) { |
| 1321 function_index = Context::SYMBOL_FUNCTION_INDEX; | 796 function_index = Context::SYMBOL_FUNCTION_INDEX; |
| 1322 } else if (type->Is(Type::Number())) { | 797 } else if (type->Is(HeapType::Number())) { |
| 1323 function_index = Context::NUMBER_FUNCTION_INDEX; | 798 function_index = Context::NUMBER_FUNCTION_INDEX; |
| 1324 } else if (type->Is(Type::Boolean())) { | 799 } else if (type->Is(HeapType::Boolean())) { |
| 1325 // Booleans use the generic oddball map, so an additional check is needed to | 800 // Booleans use the generic oddball map, so an additional check is needed to |
| 1326 // ensure the receiver is really a boolean. | 801 // ensure the receiver is really a boolean. |
| 1327 GenerateBooleanCheck(object_reg, miss); | 802 GenerateBooleanCheck(object_reg, miss); |
| 1328 function_index = Context::BOOLEAN_FUNCTION_INDEX; | 803 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
| 1329 } else { | 804 } else { |
| 1330 check_type = SKIP_RECEIVER; | 805 check_type = SKIP_RECEIVER; |
| 1331 } | 806 } |
| 1332 | 807 |
| 1333 if (check_type == CHECK_ALL_MAPS) { | 808 if (check_type == CHECK_ALL_MAPS) { |
| 1334 GenerateDirectLoadGlobalFunctionPrototype( | 809 GenerateDirectLoadGlobalFunctionPrototype( |
| 1335 masm(), function_index, scratch1(), miss); | 810 masm(), function_index, scratch1(), miss); |
| 1336 Object* function = isolate()->native_context()->get(function_index); | 811 Object* function = isolate()->native_context()->get(function_index); |
| 1337 Object* prototype = JSFunction::cast(function)->instance_prototype(); | 812 Object* prototype = JSFunction::cast(function)->instance_prototype(); |
| 1338 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); | 813 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); |
| 1339 object_reg = scratch1(); | 814 object_reg = scratch1(); |
| 1340 } | 815 } |
| 1341 | 816 |
| 1342 // Check that the maps starting from the prototype haven't changed. | 817 // Check that the maps starting from the prototype haven't changed. |
| 1343 return CheckPrototypes( | 818 return CheckPrototypes( |
| 1344 type, object_reg, holder, scratch1(), scratch2(), scratch3(), | 819 type, object_reg, holder, scratch1(), scratch2(), scratch3(), |
| 1345 name, miss, check_type); | 820 name, miss, check_type); |
| 1346 } | 821 } |
| 1347 | 822 |
| 1348 | 823 |
| 1349 // HandlerFrontend for store uses the name register. It has to be restored | 824 // HandlerFrontend for store uses the name register. It has to be restored |
| 1350 // before a miss. | 825 // before a miss. |
| 1351 Register StoreStubCompiler::HandlerFrontendHeader( | 826 Register StoreStubCompiler::HandlerFrontendHeader( |
| 1352 Handle<Type> type, | 827 Handle<HeapType> type, |
| 1353 Register object_reg, | 828 Register object_reg, |
| 1354 Handle<JSObject> holder, | 829 Handle<JSObject> holder, |
| 1355 Handle<Name> name, | 830 Handle<Name> name, |
| 1356 Label* miss) { | 831 Label* miss) { |
| 1357 return CheckPrototypes(type, object_reg, holder, this->name(), | 832 return CheckPrototypes(type, object_reg, holder, this->name(), |
| 1358 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); | 833 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); |
| 1359 } | 834 } |
| 1360 | 835 |
| 1361 | 836 |
| 1362 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { | 837 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { |
| 1363 for (int i = 0; i < types->length(); ++i) { | 838 for (int i = 0; i < types->length(); ++i) { |
| 1364 if (types->at(i)->Is(Type::Number())) return true; | 839 if (types->at(i)->Is(HeapType::Number())) return true; |
| 1365 } | 840 } |
| 1366 return false; | 841 return false; |
| 1367 } | 842 } |
| 1368 | 843 |
| 1369 | 844 |
| 1370 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Type> type, | 845 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<HeapType> type, |
| 1371 Register object_reg, | 846 Register object_reg, |
| 1372 Handle<JSObject> holder, | 847 Handle<JSObject> holder, |
| 1373 Handle<Name> name) { | 848 Handle<Name> name) { |
| 1374 Label miss; | 849 Label miss; |
| 1375 | 850 |
| 1376 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 851 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1377 | 852 |
| 1378 HandlerFrontendFooter(name, &miss); | 853 HandlerFrontendFooter(name, &miss); |
| 1379 | 854 |
| 1380 return reg; | 855 return reg; |
| 1381 } | 856 } |
| 1382 | 857 |
| 1383 | 858 |
| 1384 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<Type> type, | 859 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<HeapType> type, |
| 1385 Handle<JSObject> last, | 860 Handle<JSObject> last, |
| 1386 Handle<Name> name) { | 861 Handle<Name> name) { |
| 1387 Label miss; | 862 Label miss; |
| 1388 | 863 |
| 1389 Register holder; | 864 Register holder; |
| 1390 Handle<Map> last_map; | 865 Handle<Map> last_map; |
| 1391 if (last.is_null()) { | 866 if (last.is_null()) { |
| 1392 holder = receiver(); | 867 holder = receiver(); |
| 1393 last_map = IC::TypeToMap(*type, isolate()); | 868 last_map = IC::TypeToMap(*type, isolate()); |
| 1394 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). | 869 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1419 ? Handle<JSGlobalObject>::cast(type->AsConstant()) | 894 ? Handle<JSGlobalObject>::cast(type->AsConstant()) |
| 1420 : Handle<JSGlobalObject>::cast(last); | 895 : Handle<JSGlobalObject>::cast(last); |
| 1421 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 896 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1422 } | 897 } |
| 1423 | 898 |
| 1424 HandlerFrontendFooter(name, &miss); | 899 HandlerFrontendFooter(name, &miss); |
| 1425 } | 900 } |
| 1426 | 901 |
| 1427 | 902 |
| 1428 Handle<Code> LoadStubCompiler::CompileLoadField( | 903 Handle<Code> LoadStubCompiler::CompileLoadField( |
| 1429 Handle<Type> type, | 904 Handle<HeapType> type, |
| 1430 Handle<JSObject> holder, | 905 Handle<JSObject> holder, |
| 1431 Handle<Name> name, | 906 Handle<Name> name, |
| 1432 PropertyIndex field, | 907 PropertyIndex field, |
| 1433 Representation representation) { | 908 Representation representation) { |
| 1434 Label miss; | 909 Register reg = HandlerFrontend(type, receiver(), holder, name); |
| 1435 | |
| 1436 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss); | |
| 1437 | |
| 1438 GenerateLoadField(reg, holder, field, representation); | 910 GenerateLoadField(reg, holder, field, representation); |
| 1439 | 911 |
| 1440 __ bind(&miss); | |
| 1441 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 1442 | |
| 1443 // Return the generated code. | 912 // Return the generated code. |
| 1444 return GetCode(kind(), Code::FAST, name); | 913 return GetCode(kind(), Code::FAST, name); |
| 1445 } | 914 } |
| 1446 | 915 |
| 1447 | 916 |
| 1448 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 917 Handle<Code> LoadStubCompiler::CompileLoadConstant( |
| 1449 Handle<Type> type, | 918 Handle<HeapType> type, |
| 1450 Handle<JSObject> holder, | 919 Handle<JSObject> holder, |
| 1451 Handle<Name> name, | 920 Handle<Name> name, |
| 1452 Handle<Object> value) { | 921 Handle<Object> value) { |
| 1453 HandlerFrontend(type, receiver(), holder, name); | 922 HandlerFrontend(type, receiver(), holder, name); |
| 1454 GenerateLoadConstant(value); | 923 GenerateLoadConstant(value); |
| 1455 | 924 |
| 1456 // Return the generated code. | 925 // Return the generated code. |
| 1457 return GetCode(kind(), Code::FAST, name); | 926 return GetCode(kind(), Code::FAST, name); |
| 1458 } | 927 } |
| 1459 | 928 |
| 1460 | 929 |
| 1461 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 930 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1462 Handle<Type> type, | 931 Handle<HeapType> type, |
| 1463 Handle<JSObject> holder, | 932 Handle<JSObject> holder, |
| 1464 Handle<Name> name, | 933 Handle<Name> name, |
| 1465 Handle<ExecutableAccessorInfo> callback) { | 934 Handle<ExecutableAccessorInfo> callback) { |
| 1466 Register reg = CallbackHandlerFrontend( | 935 Register reg = CallbackHandlerFrontend( |
| 1467 type, receiver(), holder, name, callback); | 936 type, receiver(), holder, name, callback); |
| 1468 GenerateLoadCallback(reg, callback); | 937 GenerateLoadCallback(reg, callback); |
| 1469 | 938 |
| 1470 // Return the generated code. | 939 // Return the generated code. |
| 1471 return GetCode(kind(), Code::FAST, name); | 940 return GetCode(kind(), Code::FAST, name); |
| 1472 } | 941 } |
| 1473 | 942 |
| 1474 | 943 |
| 1475 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 944 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1476 Handle<Type> type, | 945 Handle<HeapType> type, |
| 1477 Handle<JSObject> holder, | 946 Handle<JSObject> holder, |
| 1478 Handle<Name> name, | 947 Handle<Name> name, |
| 1479 const CallOptimization& call_optimization) { | 948 const CallOptimization& call_optimization) { |
| 1480 ASSERT(call_optimization.is_simple_api_call()); | 949 ASSERT(call_optimization.is_simple_api_call()); |
| 1481 Handle<JSFunction> callback = call_optimization.constant_function(); | 950 Handle<JSFunction> callback = call_optimization.constant_function(); |
| 1482 CallbackHandlerFrontend(type, receiver(), holder, name, callback); | 951 CallbackHandlerFrontend(type, receiver(), holder, name, callback); |
| 1483 GenerateLoadCallback(call_optimization); | 952 Handle<Map>receiver_map = IC::TypeToMap(*type, isolate()); |
| 1484 | 953 GenerateFastApiCall( |
| 954 masm(), call_optimization, receiver_map, |
| 955 receiver(), scratch1(), false, 0, NULL); |
| 1485 // Return the generated code. | 956 // Return the generated code. |
| 1486 return GetCode(kind(), Code::FAST, name); | 957 return GetCode(kind(), Code::FAST, name); |
| 1487 } | 958 } |
| 1488 | 959 |
| 1489 | 960 |
| 1490 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( | 961 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( |
| 1491 Handle<Type> type, | 962 Handle<HeapType> type, |
| 1492 Handle<JSObject> holder, | 963 Handle<JSObject> holder, |
| 1493 Handle<Name> name) { | 964 Handle<Name> name) { |
| 1494 LookupResult lookup(isolate()); | 965 LookupResult lookup(isolate()); |
| 1495 LookupPostInterceptor(holder, name, &lookup); | 966 LookupPostInterceptor(holder, name, &lookup); |
| 1496 | 967 |
| 1497 Register reg = HandlerFrontend(type, receiver(), holder, name); | 968 Register reg = HandlerFrontend(type, receiver(), holder, name); |
| 1498 // TODO(368): Compile in the whole chain: all the interceptors in | 969 // TODO(368): Compile in the whole chain: all the interceptors in |
| 1499 // prototypes and ultimate answer. | 970 // prototypes and ultimate answer. |
| 1500 GenerateLoadInterceptor(reg, type, holder, &lookup, name); | 971 GenerateLoadInterceptor(reg, type, holder, &lookup, name); |
| 1501 | 972 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 | 1005 |
| 1535 Register reg = CallbackHandlerFrontend( | 1006 Register reg = CallbackHandlerFrontend( |
| 1536 IC::CurrentTypeOf(interceptor_holder, isolate()), | 1007 IC::CurrentTypeOf(interceptor_holder, isolate()), |
| 1537 interceptor_reg, holder, name, callback); | 1008 interceptor_reg, holder, name, callback); |
| 1538 GenerateLoadCallback(reg, callback); | 1009 GenerateLoadCallback(reg, callback); |
| 1539 } | 1010 } |
| 1540 } | 1011 } |
| 1541 | 1012 |
| 1542 | 1013 |
| 1543 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( | 1014 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( |
| 1544 Handle<Type> type, | 1015 Handle<HeapType> type, |
| 1545 Handle<Code> handler, | 1016 Handle<Code> handler, |
| 1546 Handle<Name> name) { | 1017 Handle<Name> name) { |
| 1547 TypeHandleList types(1); | 1018 TypeHandleList types(1); |
| 1548 CodeHandleList handlers(1); | 1019 CodeHandleList handlers(1); |
| 1549 types.Add(type); | 1020 types.Add(type); |
| 1550 handlers.Add(handler); | 1021 handlers.Add(handler); |
| 1551 Code::StubType stub_type = handler->type(); | 1022 Code::StubType stub_type = handler->type(); |
| 1552 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); | 1023 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); |
| 1553 } | 1024 } |
| 1554 | 1025 |
| 1555 | 1026 |
| 1556 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( | 1027 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( |
| 1557 Handle<Type> type, | 1028 Handle<HeapType> type, |
| 1558 Handle<JSObject> holder, | 1029 Handle<JSObject> holder, |
| 1559 Handle<Name> name, | 1030 Handle<Name> name, |
| 1560 Handle<JSFunction> getter) { | 1031 Handle<JSFunction> getter) { |
| 1561 HandlerFrontend(type, receiver(), holder, name); | 1032 HandlerFrontend(type, receiver(), holder, name); |
| 1562 GenerateLoadViaGetter(masm(), receiver(), getter); | 1033 GenerateLoadViaGetter(masm(), type, receiver(), getter); |
| 1563 | 1034 |
| 1564 // Return the generated code. | 1035 // Return the generated code. |
| 1565 return GetCode(kind(), Code::FAST, name); | 1036 return GetCode(kind(), Code::FAST, name); |
| 1566 } | 1037 } |
| 1567 | 1038 |
| 1568 | 1039 |
| 1569 Handle<Code> StoreStubCompiler::CompileStoreTransition( | 1040 Handle<Code> StoreStubCompiler::CompileStoreTransition( |
| 1570 Handle<JSObject> object, | 1041 Handle<JSObject> object, |
| 1571 LookupResult* lookup, | 1042 LookupResult* lookup, |
| 1572 Handle<Map> transition, | 1043 Handle<Map> transition, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 // Return the generated code. | 1116 // Return the generated code. |
| 1646 return GetCode(kind(), Code::FAST, name); | 1117 return GetCode(kind(), Code::FAST, name); |
| 1647 } | 1118 } |
| 1648 | 1119 |
| 1649 | 1120 |
| 1650 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( | 1121 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( |
| 1651 Handle<JSObject> object, | 1122 Handle<JSObject> object, |
| 1652 Handle<JSObject> holder, | 1123 Handle<JSObject> holder, |
| 1653 Handle<Name> name, | 1124 Handle<Name> name, |
| 1654 Handle<JSFunction> setter) { | 1125 Handle<JSFunction> setter) { |
| 1655 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), | 1126 Handle<HeapType> type = IC::CurrentTypeOf(object, isolate()); |
| 1656 receiver(), holder, name); | 1127 HandlerFrontend(type, receiver(), holder, name); |
| 1657 GenerateStoreViaSetter(masm(), setter); | 1128 GenerateStoreViaSetter(masm(), type, setter); |
| 1658 | 1129 |
| 1659 return GetCode(kind(), Code::FAST, name); | 1130 return GetCode(kind(), Code::FAST, name); |
| 1660 } | 1131 } |
| 1661 | 1132 |
| 1133 |
| 1134 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 1135 Handle<JSObject> object, |
| 1136 Handle<JSObject> holder, |
| 1137 Handle<Name> name, |
| 1138 const CallOptimization& call_optimization) { |
| 1139 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 1140 receiver(), holder, name); |
| 1141 Register values[] = { value() }; |
| 1142 GenerateFastApiCall( |
| 1143 masm(), call_optimization, handle(object->map()), |
| 1144 receiver(), scratch1(), true, 1, values); |
| 1145 // Return the generated code. |
| 1146 return GetCode(kind(), Code::FAST, name); |
| 1147 } |
| 1148 |
| 1662 | 1149 |
| 1663 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 1150 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 1664 Handle<Map> receiver_map) { | 1151 Handle<Map> receiver_map) { |
| 1665 ElementsKind elements_kind = receiver_map->elements_kind(); | 1152 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1666 if (receiver_map->has_fast_elements() || | 1153 if (receiver_map->has_fast_elements() || |
| 1667 receiver_map->has_external_array_elements() || | 1154 receiver_map->has_external_array_elements() || |
| 1668 receiver_map->has_fixed_typed_array_elements()) { | 1155 receiver_map->has_fixed_typed_array_elements()) { |
| 1669 Handle<Code> stub = KeyedLoadFastElementStub( | 1156 Handle<Code> stub = KeyedLoadFastElementStub( |
| 1670 receiver_map->instance_type() == JS_ARRAY_TYPE, | 1157 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 1671 elements_kind).GetCode(isolate()); | 1158 elements_kind).GetCode(isolate()); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 Handle<Code> code = GetCodeWithFlags(flags, name); | 1245 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1759 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); | 1246 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
| 1760 JitEvent(name, code); | 1247 JitEvent(name, code); |
| 1761 return code; | 1248 return code; |
| 1762 } | 1249 } |
| 1763 | 1250 |
| 1764 | 1251 |
| 1765 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, | 1252 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, |
| 1766 Code::StubType type, | 1253 Code::StubType type, |
| 1767 Handle<Name> name) { | 1254 Handle<Name> name) { |
| 1768 Code::Flags flags = Code::ComputeFlags( | 1255 ASSERT_EQ(kNoExtraICState, extra_state()); |
| 1769 Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_); | 1256 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder_); |
| 1770 Handle<Code> code = GetCodeWithFlags(flags, name); | 1257 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1771 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); | 1258 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
| 1772 JitEvent(name, code); | 1259 JitEvent(name, code); |
| 1773 return code; | 1260 return code; |
| 1774 } | 1261 } |
| 1775 | 1262 |
| 1776 | 1263 |
| 1777 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, | 1264 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, |
| 1778 CodeHandleList* handlers) { | 1265 CodeHandleList* handlers) { |
| 1779 for (int i = 0; i < receiver_maps->length(); ++i) { | 1266 for (int i = 0; i < receiver_maps->length(); ++i) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 return code; | 1345 return code; |
| 1859 } | 1346 } |
| 1860 | 1347 |
| 1861 | 1348 |
| 1862 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1349 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
| 1863 MacroAssembler* masm) { | 1350 MacroAssembler* masm) { |
| 1864 KeyedStoreIC::GenerateSlow(masm); | 1351 KeyedStoreIC::GenerateSlow(masm); |
| 1865 } | 1352 } |
| 1866 | 1353 |
| 1867 | 1354 |
| 1868 CallStubCompiler::CallStubCompiler(Isolate* isolate, | |
| 1869 int argc, | |
| 1870 Code::Kind kind, | |
| 1871 ExtraICState extra_state, | |
| 1872 InlineCacheHolderFlag cache_holder) | |
| 1873 : StubCompiler(isolate, extra_state), | |
| 1874 arguments_(argc), | |
| 1875 kind_(kind), | |
| 1876 cache_holder_(cache_holder) { | |
| 1877 } | |
| 1878 | |
| 1879 | |
| 1880 bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) { | |
| 1881 if (function->shared()->HasBuiltinFunctionId()) { | |
| 1882 BuiltinFunctionId id = function->shared()->builtin_function_id(); | |
| 1883 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; | |
| 1884 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | |
| 1885 #undef CALL_GENERATOR_CASE | |
| 1886 } | |
| 1887 | |
| 1888 CallOptimization optimization(function); | |
| 1889 return optimization.is_simple_api_call(); | |
| 1890 } | |
| 1891 | |
| 1892 | |
| 1893 Handle<Code> CallStubCompiler::CompileCustomCall( | |
| 1894 Handle<Object> object, | |
| 1895 Handle<JSObject> holder, | |
| 1896 Handle<Cell> cell, | |
| 1897 Handle<JSFunction> function, | |
| 1898 Handle<String> fname, | |
| 1899 Code::StubType type) { | |
| 1900 ASSERT(HasCustomCallGenerator(function)); | |
| 1901 | |
| 1902 if (function->shared()->HasBuiltinFunctionId()) { | |
| 1903 BuiltinFunctionId id = function->shared()->builtin_function_id(); | |
| 1904 #define CALL_GENERATOR_CASE(name) \ | |
| 1905 if (id == k##name) { \ | |
| 1906 return CallStubCompiler::Compile##name##Call(object, \ | |
| 1907 holder, \ | |
| 1908 cell, \ | |
| 1909 function, \ | |
| 1910 fname, \ | |
| 1911 type); \ | |
| 1912 } | |
| 1913 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | |
| 1914 #undef CALL_GENERATOR_CASE | |
| 1915 } | |
| 1916 CallOptimization optimization(function); | |
| 1917 ASSERT(optimization.is_simple_api_call()); | |
| 1918 return CompileFastApiCall(optimization, | |
| 1919 object, | |
| 1920 holder, | |
| 1921 cell, | |
| 1922 function, | |
| 1923 fname); | |
| 1924 } | |
| 1925 | |
| 1926 | |
| 1927 Handle<Code> CallStubCompiler::GetCode(Code::StubType type, | |
| 1928 Handle<Name> name) { | |
| 1929 int argc = arguments_.immediate(); | |
| 1930 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 1931 kind_, extra_state(), cache_holder_, type, argc); | |
| 1932 return GetCodeWithFlags(flags, name); | |
| 1933 } | |
| 1934 | |
| 1935 | |
| 1936 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { | |
| 1937 Handle<String> function_name; | |
| 1938 if (function->shared()->name()->IsString()) { | |
| 1939 function_name = Handle<String>(String::cast(function->shared()->name())); | |
| 1940 } | |
| 1941 return GetCode(Code::FAST, function_name); | |
| 1942 } | |
| 1943 | |
| 1944 | |
| 1945 CallOptimization::CallOptimization(LookupResult* lookup) { | 1355 CallOptimization::CallOptimization(LookupResult* lookup) { |
| 1946 if (lookup->IsFound() && | 1356 if (lookup->IsFound() && |
| 1947 lookup->IsCacheable() && | 1357 lookup->IsCacheable() && |
| 1948 lookup->IsConstantFunction()) { | 1358 lookup->IsConstantFunction()) { |
| 1949 // We only optimize constant function calls. | 1359 // We only optimize constant function calls. |
| 1950 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); | 1360 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); |
| 1951 } else { | 1361 } else { |
| 1952 Initialize(Handle<JSFunction>::null()); | 1362 Initialize(Handle<JSFunction>::null()); |
| 1953 } | 1363 } |
| 1954 } | 1364 } |
| 1955 | 1365 |
| 1956 | 1366 |
| 1957 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 1367 CallOptimization::CallOptimization(Handle<JSFunction> function) { |
| 1958 Initialize(function); | 1368 Initialize(function); |
| 1959 } | 1369 } |
| 1960 | 1370 |
| 1961 | 1371 |
| 1962 int CallOptimization::GetPrototypeDepthOfExpectedType( | 1372 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType( |
| 1963 Handle<JSObject> object, | 1373 Handle<Map> object_map, |
| 1964 Handle<JSObject> holder) const { | 1374 HolderLookup* holder_lookup) const { |
| 1965 ASSERT(is_simple_api_call()); | 1375 ASSERT(is_simple_api_call()); |
| 1966 if (expected_receiver_type_.is_null()) return 0; | 1376 if (!object_map->IsJSObjectMap()) { |
| 1967 int depth = 0; | 1377 *holder_lookup = kHolderNotFound; |
| 1968 while (!object.is_identical_to(holder)) { | 1378 return Handle<JSObject>::null(); |
| 1969 if (expected_receiver_type_->IsTemplateFor(object->map())) return depth; | |
| 1970 object = Handle<JSObject>(JSObject::cast(object->GetPrototype())); | |
| 1971 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth; | |
| 1972 ++depth; | |
| 1973 } | 1379 } |
| 1974 if (expected_receiver_type_->IsTemplateFor(holder->map())) return depth; | 1380 if (expected_receiver_type_.is_null() || |
| 1975 return kInvalidProtoDepth; | 1381 expected_receiver_type_->IsTemplateFor(*object_map)) { |
| 1382 *holder_lookup = kHolderIsReceiver; |
| 1383 return Handle<JSObject>::null(); |
| 1384 } |
| 1385 while (true) { |
| 1386 if (!object_map->prototype()->IsJSObject()) break; |
| 1387 Handle<JSObject> prototype(JSObject::cast(object_map->prototype())); |
| 1388 if (!prototype->map()->is_hidden_prototype()) break; |
| 1389 object_map = handle(prototype->map()); |
| 1390 if (expected_receiver_type_->IsTemplateFor(*object_map)) { |
| 1391 *holder_lookup = kHolderFound; |
| 1392 return prototype; |
| 1393 } |
| 1394 } |
| 1395 *holder_lookup = kHolderNotFound; |
| 1396 return Handle<JSObject>::null(); |
| 1976 } | 1397 } |
| 1977 | 1398 |
| 1978 | 1399 |
| 1400 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver, |
| 1401 Handle<JSObject> holder) const { |
| 1402 ASSERT(is_simple_api_call()); |
| 1403 if (!receiver->IsJSObject()) return false; |
| 1404 Handle<Map> map(JSObject::cast(*receiver)->map()); |
| 1405 HolderLookup holder_lookup; |
| 1406 Handle<JSObject> api_holder = |
| 1407 LookupHolderOfExpectedType(map, &holder_lookup); |
| 1408 switch (holder_lookup) { |
| 1409 case kHolderNotFound: |
| 1410 return false; |
| 1411 case kHolderIsReceiver: |
| 1412 return true; |
| 1413 case kHolderFound: |
| 1414 if (api_holder.is_identical_to(holder)) return true; |
| 1415 // Check if holder is in prototype chain of api_holder. |
| 1416 { |
| 1417 JSObject* object = *api_holder; |
| 1418 while (true) { |
| 1419 Object* prototype = object->map()->prototype(); |
| 1420 if (!prototype->IsJSObject()) return false; |
| 1421 if (prototype == *holder) return true; |
| 1422 object = JSObject::cast(prototype); |
| 1423 } |
| 1424 } |
| 1425 break; |
| 1426 } |
| 1427 UNREACHABLE(); |
| 1428 return false; |
| 1429 } |
| 1430 |
| 1431 |
| 1979 void CallOptimization::Initialize(Handle<JSFunction> function) { | 1432 void CallOptimization::Initialize(Handle<JSFunction> function) { |
| 1980 constant_function_ = Handle<JSFunction>::null(); | 1433 constant_function_ = Handle<JSFunction>::null(); |
| 1981 is_simple_api_call_ = false; | 1434 is_simple_api_call_ = false; |
| 1982 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); | 1435 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); |
| 1983 api_call_info_ = Handle<CallHandlerInfo>::null(); | 1436 api_call_info_ = Handle<CallHandlerInfo>::null(); |
| 1984 | 1437 |
| 1985 if (function.is_null() || !function->is_compiled()) return; | 1438 if (function.is_null() || !function->is_compiled()) return; |
| 1986 | 1439 |
| 1987 constant_function_ = function; | 1440 constant_function_ = function; |
| 1988 AnalyzePossibleApiFunction(function); | 1441 AnalyzePossibleApiFunction(function); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2009 Handle<FunctionTemplateInfo>( | 1462 Handle<FunctionTemplateInfo>( |
| 2010 FunctionTemplateInfo::cast(signature->receiver())); | 1463 FunctionTemplateInfo::cast(signature->receiver())); |
| 2011 } | 1464 } |
| 2012 } | 1465 } |
| 2013 | 1466 |
| 2014 is_simple_api_call_ = true; | 1467 is_simple_api_call_ = true; |
| 2015 } | 1468 } |
| 2016 | 1469 |
| 2017 | 1470 |
| 2018 } } // namespace v8::internal | 1471 } } // namespace v8::internal |
| OLD | NEW |