Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 148223002: Remove CallICs (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update test262 status file Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 __ push(scratch1); 490 __ push(scratch1);
491 // Stack now matches JSFunction abi. 491 // Stack now matches JSFunction abi.
492 GenerateFastApiCallBody(masm, 492 GenerateFastApiCallBody(masm,
493 optimization, 493 optimization,
494 argc, 494 argc,
495 receiver, 495 receiver,
496 true); 496 true);
497 } 497 }
498 498
499 499
500 class CallInterceptorCompiler BASE_EMBEDDED {
501 public:
502 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
503 Register name)
504 : stub_compiler_(stub_compiler),
505 name_(name) {}
506
507 void Compile(MacroAssembler* masm,
508 Handle<JSObject> object,
509 Handle<JSObject> holder,
510 Handle<Name> name,
511 LookupResult* lookup,
512 Register receiver,
513 Register scratch1,
514 Register scratch2,
515 Register scratch3,
516 Label* miss) {
517 ASSERT(holder->HasNamedInterceptor());
518 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
519
520 // Check that the receiver isn't a smi.
521 __ JumpIfSmi(receiver, miss);
522
523 CallOptimization optimization(lookup);
524 if (optimization.is_constant_call()) {
525 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
526 holder, lookup, name, optimization, miss);
527 } else {
528 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
529 name, holder, miss);
530 }
531 }
532
533 private:
534 void CompileCacheable(MacroAssembler* masm,
535 Handle<JSObject> object,
536 Register receiver,
537 Register scratch1,
538 Register scratch2,
539 Register scratch3,
540 Handle<JSObject> interceptor_holder,
541 LookupResult* lookup,
542 Handle<Name> name,
543 const CallOptimization& optimization,
544 Label* miss_label) {
545 ASSERT(optimization.is_constant_call());
546 ASSERT(!lookup->holder()->IsGlobalObject());
547
548 Counters* counters = masm->isolate()->counters();
549 __ IncrementCounter(counters->call_const_interceptor(), 1);
550
551 // Check that the maps from receiver to interceptor's holder
552 // haven't changed and thus we can invoke interceptor.
553 Register holder =
554 stub_compiler_->CheckPrototypes(
555 IC::CurrentTypeOf(object, masm->isolate()), receiver,
556 interceptor_holder, scratch1, scratch2, scratch3,
557 name, miss_label);
558
559 // Invoke an interceptor and if it provides a value,
560 // branch to |regular_invoke|.
561 Label regular_invoke;
562 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
563 &regular_invoke);
564
565 // Interceptor returned nothing for this property. Try to use cached
566 // constant function.
567
568 // Check that the maps from interceptor's holder to constant function's
569 // holder haven't changed and thus we can use cached constant function.
570 if (*interceptor_holder != lookup->holder()) {
571 stub_compiler_->CheckPrototypes(
572 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
573 handle(lookup->holder()), scratch1, scratch2, scratch3,
574 name, miss_label);
575 }
576
577 Handle<JSFunction> fun = optimization.constant_function();
578 stub_compiler_->GenerateJumpFunction(object, fun);
579
580 // Invoke a regular function.
581 __ bind(&regular_invoke);
582 }
583
584 void CompileRegular(MacroAssembler* masm,
585 Handle<JSObject> object,
586 Register receiver,
587 Register scratch1,
588 Register scratch2,
589 Register scratch3,
590 Handle<Name> name,
591 Handle<JSObject> interceptor_holder,
592 Label* miss_label) {
593 Register holder =
594 stub_compiler_->CheckPrototypes(
595 IC::CurrentTypeOf(object, masm->isolate()), receiver,
596 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
597
598 FrameScope scope(masm, StackFrame::INTERNAL);
599 // Save the name_ register across the call.
600 __ push(name_);
601
602 CompileCallLoadPropertyWithInterceptor(
603 masm, receiver, holder, name_, interceptor_holder,
604 IC::kLoadPropertyWithInterceptorForCall);
605
606 // Restore the name_ register.
607 __ pop(name_);
608
609 // Leave the internal frame.
610 }
611
612 void LoadWithInterceptor(MacroAssembler* masm,
613 Register receiver,
614 Register holder,
615 Handle<JSObject> holder_obj,
616 Label* interceptor_succeeded) {
617 {
618 FrameScope scope(masm, StackFrame::INTERNAL);
619 __ push(receiver);
620 __ push(holder);
621 __ push(name_);
622
623 CompileCallLoadPropertyWithInterceptor(
624 masm, receiver, holder, name_, holder_obj,
625 IC::kLoadPropertyWithInterceptorOnly);
626
627 __ pop(name_);
628 __ pop(holder);
629 __ pop(receiver);
630 // Leave the internal frame.
631 }
632
633 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
634 __ j(not_equal, interceptor_succeeded);
635 }
636
637 CallStubCompiler* stub_compiler_;
638 Register name_;
639 };
640
641
642 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, 500 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
643 Label* label, 501 Label* label,
644 Handle<Name> name) { 502 Handle<Name> name) {
645 if (!label->is_unused()) { 503 if (!label->is_unused()) {
646 __ bind(label); 504 __ bind(label);
647 __ mov(this->name(), Immediate(name)); 505 __ mov(this->name(), Immediate(name));
648 } 506 }
649 } 507 }
650 508
651 509
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 __ push(scratch2()); // restore old return address 1217 __ push(scratch2()); // restore old return address
1360 1218
1361 ExternalReference ref = 1219 ExternalReference ref =
1362 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1220 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1363 isolate()); 1221 isolate());
1364 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1222 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1365 } 1223 }
1366 } 1224 }
1367 1225
1368 1226
1369 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1370 if (kind_ == Code::KEYED_CALL_IC) {
1371 __ cmp(ecx, Immediate(name));
1372 __ j(not_equal, miss);
1373 }
1374 }
1375
1376
1377 void CallStubCompiler::GenerateFunctionCheck(Register function,
1378 Register scratch,
1379 Label* miss) {
1380 __ JumpIfSmi(function, miss);
1381 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
1382 __ j(not_equal, miss);
1383 }
1384
1385
1386 void CallStubCompiler::GenerateLoadFunctionFromCell(
1387 Handle<Cell> cell,
1388 Handle<JSFunction> function,
1389 Label* miss) {
1390 // Get the value from the cell.
1391 if (Serializer::enabled()) {
1392 __ mov(edi, Immediate(cell));
1393 __ mov(edi, FieldOperand(edi, Cell::kValueOffset));
1394 } else {
1395 __ mov(edi, Operand::ForCell(cell));
1396 }
1397
1398 // Check that the cell contains the same function.
1399 if (isolate()->heap()->InNewSpace(*function)) {
1400 // We can't embed a pointer to a function in new space so we have
1401 // to verify that the shared function info is unchanged. This has
1402 // the nice side effect that multiple closures based on the same
1403 // function can all use this call IC. Before we load through the
1404 // function, we have to verify that it still is a function.
1405 GenerateFunctionCheck(edi, ebx, miss);
1406
1407 // Check the shared function info. Make sure it hasn't changed.
1408 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
1409 Immediate(Handle<SharedFunctionInfo>(function->shared())));
1410 } else {
1411 __ cmp(edi, Immediate(function));
1412 }
1413 __ j(not_equal, miss);
1414 }
1415
1416
1417 void CallStubCompiler::GenerateMissBranch() {
1418 Handle<Code> code =
1419 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1420 kind_,
1421 extra_state());
1422 __ jmp(code, RelocInfo::CODE_TARGET);
1423 }
1424
1425
1426 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1427 Handle<JSObject> holder,
1428 PropertyIndex index,
1429 Handle<Name> name) {
1430 Label miss;
1431
1432 Register reg = HandlerFrontendHeader(
1433 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1434
1435 GenerateFastPropertyLoad(
1436 masm(), edi, reg, index.is_inobject(holder),
1437 index.translate(holder), Representation::Tagged());
1438 GenerateJumpFunction(object, edi, &miss);
1439
1440 HandlerFrontendFooter(&miss);
1441
1442 // Return the generated code.
1443 return GetCode(Code::FAST, name);
1444 }
1445
1446
1447 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1227 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1448 Label success; 1228 Label success;
1449 // Check that the object is a boolean. 1229 // Check that the object is a boolean.
1450 __ cmp(object, factory()->true_value()); 1230 __ cmp(object, factory()->true_value());
1451 __ j(equal, &success); 1231 __ j(equal, &success);
1452 __ cmp(object, factory()->false_value()); 1232 __ cmp(object, factory()->false_value());
1453 __ j(not_equal, miss); 1233 __ j(not_equal, miss);
1454 __ bind(&success); 1234 __ bind(&success);
1455 } 1235 }
1456 1236
1457 1237
1458 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1459 if (object->IsGlobalObject()) {
1460 const int argc = arguments().immediate();
1461 const int receiver_offset = (argc + 1) * kPointerSize;
1462 __ mov(Operand(esp, receiver_offset),
1463 isolate()->factory()->undefined_value());
1464 }
1465 }
1466
1467
1468 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1469 Handle<JSObject> holder,
1470 Handle<Name> name,
1471 CheckType check,
1472 Label* miss) {
1473 GenerateNameCheck(name, miss);
1474
1475 Register reg = edx;
1476
1477 const int argc = arguments().immediate();
1478 const int receiver_offset = (argc + 1) * kPointerSize;
1479 __ mov(reg, Operand(esp, receiver_offset));
1480
1481 // Check that the receiver isn't a smi.
1482 if (check != NUMBER_CHECK) {
1483 __ JumpIfSmi(reg, miss);
1484 }
1485
1486 // Make sure that it's okay not to patch the on stack receiver
1487 // unless we're doing a receiver map check.
1488 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1489 switch (check) {
1490 case RECEIVER_MAP_CHECK:
1491 __ IncrementCounter(isolate()->counters()->call_const(), 1);
1492
1493 // Check that the maps haven't changed.
1494 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
1495 ebx, eax, edi, name, miss);
1496
1497 break;
1498
1499 case STRING_CHECK: {
1500 // Check that the object is a string.
1501 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax);
1502 __ j(above_equal, miss);
1503 // Check that the maps starting from the prototype haven't changed.
1504 GenerateDirectLoadGlobalFunctionPrototype(
1505 masm(), Context::STRING_FUNCTION_INDEX, eax, miss);
1506 break;
1507 }
1508 case SYMBOL_CHECK: {
1509 // Check that the object is a symbol.
1510 __ CmpObjectType(reg, SYMBOL_TYPE, eax);
1511 __ j(not_equal, miss);
1512 // Check that the maps starting from the prototype haven't changed.
1513 GenerateDirectLoadGlobalFunctionPrototype(
1514 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss);
1515 break;
1516 }
1517 case NUMBER_CHECK: {
1518 Label fast;
1519 // Check that the object is a smi or a heap number.
1520 __ JumpIfSmi(reg, &fast);
1521 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax);
1522 __ j(not_equal, miss);
1523 __ bind(&fast);
1524 // Check that the maps starting from the prototype haven't changed.
1525 GenerateDirectLoadGlobalFunctionPrototype(
1526 masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss);
1527 break;
1528 }
1529 case BOOLEAN_CHECK: {
1530 GenerateBooleanCheck(reg, miss);
1531 // Check that the maps starting from the prototype haven't changed.
1532 GenerateDirectLoadGlobalFunctionPrototype(
1533 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss);
1534 break;
1535 }
1536 }
1537
1538 if (check != RECEIVER_MAP_CHECK) {
1539 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
1540 reg = CheckPrototypes(
1541 IC::CurrentTypeOf(prototype, isolate()),
1542 eax, holder, ebx, edx, edi, name, miss);
1543 }
1544
1545 return reg;
1546 }
1547
1548
1549 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1550 Register function,
1551 Label* miss) {
1552 // Check that the function really is a function.
1553 GenerateFunctionCheck(function, ebx, miss);
1554
1555 if (!function.is(edi)) __ mov(edi, function);
1556 PatchImplicitReceiver(object);
1557
1558 // Invoke the function.
1559 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, NullCallWrapper());
1560 }
1561
1562
1563 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
1564 Handle<JSObject> holder,
1565 Handle<Name> name) {
1566 Label miss;
1567
1568 GenerateNameCheck(name, &miss);
1569
1570 // Get the number of arguments.
1571 const int argc = arguments().immediate();
1572
1573 LookupResult lookup(isolate());
1574 LookupPostInterceptor(holder, name, &lookup);
1575
1576 // Get the receiver from the stack.
1577 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1578
1579 CallInterceptorCompiler compiler(this, ecx);
1580 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
1581 &miss);
1582
1583 // Restore receiver.
1584 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1585
1586 GenerateJumpFunction(object, eax, &miss);
1587
1588 HandlerFrontendFooter(&miss);
1589
1590 // Return the generated code.
1591 return GetCode(Code::FAST, name);
1592 }
1593
1594
1595 Handle<Code> CallStubCompiler::CompileCallGlobal(
1596 Handle<JSObject> object,
1597 Handle<GlobalObject> holder,
1598 Handle<PropertyCell> cell,
1599 Handle<JSFunction> function,
1600 Handle<Name> name) {
1601 Label miss;
1602 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1603 // Potentially loads a closure that matches the shared function info of the
1604 // function, rather than function.
1605 GenerateLoadFunctionFromCell(cell, function, &miss);
1606 GenerateJumpFunction(object, edi, function);
1607
1608 HandlerFrontendFooter(&miss);
1609
1610 // Return the generated code.
1611 return GetCode(Code::NORMAL, name);
1612 }
1613
1614
1615 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1238 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1616 Handle<JSObject> object, 1239 Handle<JSObject> object,
1617 Handle<JSObject> holder, 1240 Handle<JSObject> holder,
1618 Handle<Name> name, 1241 Handle<Name> name,
1619 Handle<ExecutableAccessorInfo> callback) { 1242 Handle<ExecutableAccessorInfo> callback) {
1620 Register holder_reg = HandlerFrontend( 1243 Register holder_reg = HandlerFrontend(
1621 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1244 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1622 1245
1623 __ pop(scratch1()); // remove the return address 1246 __ pop(scratch1()); // remove the return address
1624 __ push(receiver()); 1247 __ push(receiver());
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1846 1469
1847 // Check for deleted property if property can actually be deleted. 1470 // Check for deleted property if property can actually be deleted.
1848 if (!is_dont_delete) { 1471 if (!is_dont_delete) {
1849 __ cmp(eax, factory()->the_hole_value()); 1472 __ cmp(eax, factory()->the_hole_value());
1850 __ j(equal, &miss); 1473 __ j(equal, &miss);
1851 } else if (FLAG_debug_code) { 1474 } else if (FLAG_debug_code) {
1852 __ cmp(eax, factory()->the_hole_value()); 1475 __ cmp(eax, factory()->the_hole_value());
1853 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 1476 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
1854 } 1477 }
1855 1478
1856 HandlerFrontendFooter(name, &miss);
1857
1858 Counters* counters = isolate()->counters(); 1479 Counters* counters = isolate()->counters();
1859 __ IncrementCounter(counters->named_load_global_stub(), 1); 1480 __ IncrementCounter(counters->named_load_global_stub(), 1);
1860 // The code above already loads the result into the return register. 1481 // The code above already loads the result into the return register.
1861 __ ret(0); 1482 __ ret(0);
1862 1483
1484 HandlerFrontendFooter(name, &miss);
1485
1863 // Return the generated code. 1486 // Return the generated code.
1864 return GetCode(kind(), Code::NORMAL, name); 1487 return GetCode(kind(), Code::NORMAL, name);
1865 } 1488 }
1866 1489
1867 1490
1868 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1491 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
1869 TypeHandleList* types, 1492 TypeHandleList* types,
1870 CodeHandleList* handlers, 1493 CodeHandleList* handlers,
1871 Handle<Name> name, 1494 Handle<Name> name,
1872 Code::StubType type, 1495 Code::StubType type,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1958 // ----------------------------------- 1581 // -----------------------------------
1959 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1582 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
1960 } 1583 }
1961 1584
1962 1585
1963 #undef __ 1586 #undef __
1964 1587
1965 } } // namespace v8::internal 1588 } } // namespace v8::internal
1966 1589
1967 #endif // V8_TARGET_ARCH_IA32 1590 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698