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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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); |
196 if (!handler.is_null()) return handler; | 196 if (!handler.is_null()) return handler; |
197 | 197 |
198 LoadStubCompiler compiler(isolate_, flag); | 198 LoadStubCompiler compiler(isolate_, kNoExtraICState, flag); |
199 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 199 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
200 Map::UpdateCodeCache(stub_holder, cache_name, handler); | 200 Map::UpdateCodeCache(stub_holder, cache_name, handler); |
201 return handler; | 201 return handler; |
202 } | 202 } |
203 | 203 |
204 | 204 |
205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
207 Handle<Name> name = | 207 Handle<Name> name = |
208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 KeyedStoreStubCompiler compiler(isolate(), extra_state); | 240 KeyedStoreStubCompiler compiler(isolate(), extra_state); |
241 Handle<Code> code = compiler.CompileStoreElement(receiver_map); | 241 Handle<Code> code = compiler.CompileStoreElement(receiver_map); |
242 | 242 |
243 Map::UpdateCodeCache(receiver_map, name, code); | 243 Map::UpdateCodeCache(receiver_map, name, code); |
244 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 244 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
245 == store_mode); | 245 == store_mode); |
246 return code; | 246 return code; |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 #define CALL_LOGGER_TAG(kind, type) \ | 250 #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 | 251 |
408 static void FillCache(Isolate* isolate, Handle<Code> code) { | 252 static void FillCache(Isolate* isolate, Handle<Code> code) { |
409 Handle<UnseededNumberDictionary> dictionary = | 253 Handle<UnseededNumberDictionary> dictionary = |
410 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 254 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
411 code->flags(), | 255 code->flags(), |
412 code); | 256 code); |
413 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 257 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
414 } | 258 } |
415 | 259 |
416 | 260 |
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) { | 261 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { |
432 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 262 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
433 UnseededNumberDictionary* dictionary = | 263 UnseededNumberDictionary* dictionary = |
434 isolate()->heap()->non_monomorphic_cache(); | 264 isolate()->heap()->non_monomorphic_cache(); |
435 int entry = dictionary->FindEntry(isolate(), flags); | 265 int entry = dictionary->FindEntry(isolate(), flags); |
436 ASSERT(entry != -1); | 266 ASSERT(entry != -1); |
437 Object* code = dictionary->ValueAt(entry); | 267 Object* code = dictionary->ValueAt(entry); |
438 // This might be called during the marking phase of the collector | 268 // This might be called during the marking phase of the collector |
439 // hence the unchecked cast. | 269 // hence the unchecked cast. |
440 return reinterpret_cast<Code*>(code); | 270 return reinterpret_cast<Code*>(code); |
441 } | 271 } |
442 | 272 |
443 | 273 |
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, | 274 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, |
540 ExtraICState extra_state) { | 275 ExtraICState extra_state) { |
541 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 276 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
542 Handle<UnseededNumberDictionary> cache = | 277 Handle<UnseededNumberDictionary> cache = |
543 isolate_->factory()->non_monomorphic_cache(); | 278 isolate_->factory()->non_monomorphic_cache(); |
544 int entry = cache->FindEntry(isolate_, flags); | 279 int entry = cache->FindEntry(isolate_, flags); |
545 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 280 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
546 | 281 |
547 StubCompiler compiler(isolate_); | 282 StubCompiler compiler(isolate_); |
548 Handle<Code> code; | 283 Handle<Code> code; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 code = compiler.CompileStoreMegamorphic(flags); | 315 code = compiler.CompileStoreMegamorphic(flags); |
581 } else { | 316 } else { |
582 UNREACHABLE(); | 317 UNREACHABLE(); |
583 } | 318 } |
584 | 319 |
585 FillCache(isolate_, code); | 320 FillCache(isolate_, code); |
586 return code; | 321 return code; |
587 } | 322 } |
588 | 323 |
589 | 324 |
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, | 325 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, |
611 CompareNilICStub& stub) { | 326 CompareNilICStub& stub) { |
612 Handle<String> name(isolate_->heap()->empty_string()); | 327 Handle<String> name(isolate_->heap()->empty_string()); |
613 if (!receiver_map->is_shared()) { | 328 if (!receiver_map->is_shared()) { |
614 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, | 329 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, |
615 stub.GetExtraICState()); | 330 stub.GetExtraICState()); |
616 if (!cached_ic.is_null()) return cached_ic; | 331 if (!cached_ic.is_null()) return cached_ic; |
617 } | 332 } |
618 | 333 |
619 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); | 334 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 409 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
695 if (probe->IsCode()) return Handle<Code>::cast(probe); | 410 if (probe->IsCode()) return Handle<Code>::cast(probe); |
696 | 411 |
697 KeyedStoreStubCompiler compiler(isolate_, extra_state); | 412 KeyedStoreStubCompiler compiler(isolate_, extra_state); |
698 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); | 413 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); |
699 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 414 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
700 return code; | 415 return code; |
701 } | 416 } |
702 | 417 |
703 | 418 |
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() { | 419 void StubCache::Clear() { |
745 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 420 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
746 for (int i = 0; i < kPrimaryTableSize; i++) { | 421 for (int i = 0; i < kPrimaryTableSize; i++) { |
747 primary_[i].key = heap()->empty_string(); | 422 primary_[i].key = heap()->empty_string(); |
748 primary_[i].map = NULL; | 423 primary_[i].map = NULL; |
749 primary_[i].value = empty; | 424 primary_[i].value = empty; |
750 } | 425 } |
751 for (int j = 0; j < kSecondaryTableSize; j++) { | 426 for (int j = 0; j < kSecondaryTableSize; j++) { |
752 secondary_[j].key = heap()->empty_string(); | 427 secondary_[j].key = heap()->empty_string(); |
753 secondary_[j].map = NULL; | 428 secondary_[j].map = NULL; |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 | 662 |
988 | 663 |
989 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { | 664 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { |
990 JSObject* receiver = JSObject::cast(args[0]); | 665 JSObject* receiver = JSObject::cast(args[0]); |
991 ASSERT(args.smi_at(1) >= 0); | 666 ASSERT(args.smi_at(1) >= 0); |
992 uint32_t index = args.smi_at(1); | 667 uint32_t index = args.smi_at(1); |
993 return receiver->GetElementWithInterceptor(receiver, index); | 668 return receiver->GetElementWithInterceptor(receiver, index); |
994 } | 669 } |
995 | 670 |
996 | 671 |
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) { | 672 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { |
1075 LoadIC::GenerateInitialize(masm()); | 673 LoadIC::GenerateInitialize(masm()); |
1076 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 674 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); |
1077 PROFILE(isolate(), | 675 PROFILE(isolate(), |
1078 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | 676 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |
1079 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 677 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
1080 return code; | 678 return code; |
1081 } | 679 } |
1082 | 680 |
1083 | 681 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 737 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
1140 StoreIC::GenerateMegamorphic(masm(), extra_state); | 738 StoreIC::GenerateMegamorphic(masm(), extra_state); |
1141 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 739 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); |
1142 PROFILE(isolate(), | 740 PROFILE(isolate(), |
1143 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); | 741 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); |
1144 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); | 742 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); |
1145 return code; | 743 return code; |
1146 } | 744 } |
1147 | 745 |
1148 | 746 |
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 | 747 #undef CALL_LOGGER_TAG |
1215 | 748 |
1216 | 749 |
1217 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 750 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
1218 const char* name) { | 751 const char* name) { |
1219 // Create code object in the heap. | 752 // Create code object in the heap. |
1220 CodeDesc desc; | 753 CodeDesc desc; |
1221 masm_.GetCode(&desc); | 754 masm_.GetCode(&desc); |
1222 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); | 755 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); |
1223 if (code->has_major_key()) { | 756 if (code->has_major_key()) { |
(...skipping 20 matching lines...) Expand all Loading... |
1244 holder->LocalLookupRealNamedProperty(*name, lookup); | 777 holder->LocalLookupRealNamedProperty(*name, lookup); |
1245 if (lookup->IsFound()) return; | 778 if (lookup->IsFound()) return; |
1246 if (holder->GetPrototype()->IsNull()) return; | 779 if (holder->GetPrototype()->IsNull()) return; |
1247 holder->GetPrototype()->Lookup(*name, lookup); | 780 holder->GetPrototype()->Lookup(*name, lookup); |
1248 } | 781 } |
1249 | 782 |
1250 | 783 |
1251 #define __ ACCESS_MASM(masm()) | 784 #define __ ACCESS_MASM(masm()) |
1252 | 785 |
1253 | 786 |
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 Label miss; | |
1292 HandlerFrontendHeader(object, holder, name, check, &miss); | |
1293 GenerateJumpFunction(object, function); | |
1294 HandlerFrontendFooter(&miss); | |
1295 | |
1296 // Return the generated code. | |
1297 return GetCode(function); | |
1298 } | |
1299 | |
1300 | |
1301 Register LoadStubCompiler::HandlerFrontendHeader( | 787 Register LoadStubCompiler::HandlerFrontendHeader( |
1302 Handle<HeapType> type, | 788 Handle<HeapType> type, |
1303 Register object_reg, | 789 Register object_reg, |
1304 Handle<JSObject> holder, | 790 Handle<JSObject> holder, |
1305 Handle<Name> name, | 791 Handle<Name> name, |
1306 Label* miss) { | 792 Label* miss) { |
1307 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 793 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
1308 int function_index = -1; | 794 int function_index = -1; |
1309 if (type->Is(HeapType::String())) { | 795 if (type->Is(HeapType::String())) { |
1310 function_index = Context::STRING_FUNCTION_INDEX; | 796 function_index = Context::STRING_FUNCTION_INDEX; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 HandlerFrontendFooter(name, &miss); | 901 HandlerFrontendFooter(name, &miss); |
1416 } | 902 } |
1417 | 903 |
1418 | 904 |
1419 Handle<Code> LoadStubCompiler::CompileLoadField( | 905 Handle<Code> LoadStubCompiler::CompileLoadField( |
1420 Handle<HeapType> type, | 906 Handle<HeapType> type, |
1421 Handle<JSObject> holder, | 907 Handle<JSObject> holder, |
1422 Handle<Name> name, | 908 Handle<Name> name, |
1423 PropertyIndex field, | 909 PropertyIndex field, |
1424 Representation representation) { | 910 Representation representation) { |
1425 Label miss; | 911 Register reg = HandlerFrontend(type, receiver(), holder, name); |
1426 | |
1427 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss); | |
1428 | |
1429 GenerateLoadField(reg, holder, field, representation); | 912 GenerateLoadField(reg, holder, field, representation); |
1430 | 913 |
1431 __ bind(&miss); | |
1432 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
1433 | |
1434 // Return the generated code. | 914 // Return the generated code. |
1435 return GetCode(kind(), Code::FAST, name); | 915 return GetCode(kind(), Code::FAST, name); |
1436 } | 916 } |
1437 | 917 |
1438 | 918 |
1439 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 919 Handle<Code> LoadStubCompiler::CompileLoadConstant( |
1440 Handle<HeapType> type, | 920 Handle<HeapType> type, |
1441 Handle<JSObject> holder, | 921 Handle<JSObject> holder, |
1442 Handle<Name> name, | 922 Handle<Name> name, |
1443 Handle<Object> value) { | 923 Handle<Object> value) { |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1849 return code; | 1329 return code; |
1850 } | 1330 } |
1851 | 1331 |
1852 | 1332 |
1853 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1333 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
1854 MacroAssembler* masm) { | 1334 MacroAssembler* masm) { |
1855 KeyedStoreIC::GenerateSlow(masm); | 1335 KeyedStoreIC::GenerateSlow(masm); |
1856 } | 1336 } |
1857 | 1337 |
1858 | 1338 |
1859 CallStubCompiler::CallStubCompiler(Isolate* isolate, | |
1860 int argc, | |
1861 Code::Kind kind, | |
1862 ExtraICState extra_state, | |
1863 InlineCacheHolderFlag cache_holder) | |
1864 : StubCompiler(isolate, extra_state), | |
1865 arguments_(argc), | |
1866 kind_(kind), | |
1867 cache_holder_(cache_holder) { | |
1868 } | |
1869 | |
1870 | |
1871 Handle<Code> CallStubCompiler::GetCode(Code::StubType type, | |
1872 Handle<Name> name) { | |
1873 int argc = arguments_.immediate(); | |
1874 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
1875 kind_, extra_state(), cache_holder_, type, argc); | |
1876 return GetCodeWithFlags(flags, name); | |
1877 } | |
1878 | |
1879 | |
1880 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { | |
1881 Handle<String> function_name; | |
1882 if (function->shared()->name()->IsString()) { | |
1883 function_name = Handle<String>(String::cast(function->shared()->name())); | |
1884 } | |
1885 return GetCode(Code::FAST, function_name); | |
1886 } | |
1887 | |
1888 | |
1889 CallOptimization::CallOptimization(LookupResult* lookup) { | 1339 CallOptimization::CallOptimization(LookupResult* lookup) { |
1890 if (lookup->IsFound() && | 1340 if (lookup->IsFound() && |
1891 lookup->IsCacheable() && | 1341 lookup->IsCacheable() && |
1892 lookup->IsConstantFunction()) { | 1342 lookup->IsConstantFunction()) { |
1893 // We only optimize constant function calls. | 1343 // We only optimize constant function calls. |
1894 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); | 1344 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); |
1895 } else { | 1345 } else { |
1896 Initialize(Handle<JSFunction>::null()); | 1346 Initialize(Handle<JSFunction>::null()); |
1897 } | 1347 } |
1898 } | 1348 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 Handle<FunctionTemplateInfo>( | 1415 Handle<FunctionTemplateInfo>( |
1966 FunctionTemplateInfo::cast(signature->receiver())); | 1416 FunctionTemplateInfo::cast(signature->receiver())); |
1967 } | 1417 } |
1968 } | 1418 } |
1969 | 1419 |
1970 is_simple_api_call_ = true; | 1420 is_simple_api_call_ = true; |
1971 } | 1421 } |
1972 | 1422 |
1973 | 1423 |
1974 } } // namespace v8::internal | 1424 } } // namespace v8::internal |
OLD | NEW |