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

Side by Side Diff: src/arm/stub-cache-arm.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/arm/lithium-codegen-arm.cc ('k') | src/ast.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 840 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 } 851 }
852 // Stack now matches JSFunction abi. 852 // Stack now matches JSFunction abi.
853 GenerateFastApiCallBody(masm, 853 GenerateFastApiCallBody(masm,
854 optimization, 854 optimization,
855 argc, 855 argc,
856 receiver, 856 receiver,
857 true); 857 true);
858 } 858 }
859 859
860 860
861 class CallInterceptorCompiler BASE_EMBEDDED {
862 public:
863 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
864 Register name)
865 : stub_compiler_(stub_compiler),
866 name_(name) {}
867
868 void Compile(MacroAssembler* masm,
869 Handle<JSObject> object,
870 Handle<JSObject> holder,
871 Handle<Name> name,
872 LookupResult* lookup,
873 Register receiver,
874 Register scratch1,
875 Register scratch2,
876 Register scratch3,
877 Label* miss) {
878 ASSERT(holder->HasNamedInterceptor());
879 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
880
881 // Check that the receiver isn't a smi.
882 __ JumpIfSmi(receiver, miss);
883 CallOptimization optimization(lookup);
884 if (optimization.is_constant_call()) {
885 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
886 holder, lookup, name, optimization, miss);
887 } else {
888 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
889 name, holder, miss);
890 }
891 }
892
893 private:
894 void CompileCacheable(MacroAssembler* masm,
895 Handle<JSObject> object,
896 Register receiver,
897 Register scratch1,
898 Register scratch2,
899 Register scratch3,
900 Handle<JSObject> interceptor_holder,
901 LookupResult* lookup,
902 Handle<Name> name,
903 const CallOptimization& optimization,
904 Label* miss_label) {
905 ASSERT(optimization.is_constant_call());
906 ASSERT(!lookup->holder()->IsGlobalObject());
907 Counters* counters = masm->isolate()->counters();
908 __ IncrementCounter(counters->call_const_interceptor(), 1,
909 scratch1, scratch2);
910
911 // Check that the maps from receiver to interceptor's holder
912 // haven't changed and thus we can invoke interceptor.
913 Label miss_cleanup;
914 Register holder =
915 stub_compiler_->CheckPrototypes(
916 IC::CurrentTypeOf(object, masm->isolate()), receiver,
917 interceptor_holder, scratch1, scratch2, scratch3,
918 name, miss_label);
919
920 // Invoke an interceptor and if it provides a value,
921 // branch to |regular_invoke|.
922 Label regular_invoke;
923 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
924 &regular_invoke);
925
926 // Interceptor returned nothing for this property. Try to use cached
927 // constant function.
928
929 // Check that the maps from interceptor's holder to constant function's
930 // holder haven't changed and thus we can use cached constant function.
931 if (*interceptor_holder != lookup->holder()) {
932 stub_compiler_->CheckPrototypes(
933 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
934 handle(lookup->holder()), scratch1, scratch2, scratch3,
935 name, miss_label);
936 }
937
938 Handle<JSFunction> function = optimization.constant_function();
939 __ Move(r0, receiver);
940 stub_compiler_->GenerateJumpFunction(object, function);
941
942 // Invoke a regular function.
943 __ bind(&regular_invoke);
944 }
945
946 void CompileRegular(MacroAssembler* masm,
947 Handle<JSObject> object,
948 Register receiver,
949 Register scratch1,
950 Register scratch2,
951 Register scratch3,
952 Handle<Name> name,
953 Handle<JSObject> interceptor_holder,
954 Label* miss_label) {
955 Register holder =
956 stub_compiler_->CheckPrototypes(
957 IC::CurrentTypeOf(object, masm->isolate()), receiver,
958 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
959
960 // Call a runtime function to load the interceptor property.
961 FrameScope scope(masm, StackFrame::INTERNAL);
962 // Save the name_ register across the call.
963 __ push(name_);
964
965 CompileCallLoadPropertyWithInterceptor(
966 masm, receiver, holder, name_, interceptor_holder,
967 IC::kLoadPropertyWithInterceptorForCall);
968
969 // Restore the name_ register.
970 __ pop(name_);
971 // Leave the internal frame.
972 }
973
974 void LoadWithInterceptor(MacroAssembler* masm,
975 Register receiver,
976 Register holder,
977 Handle<JSObject> holder_obj,
978 Register scratch,
979 Label* interceptor_succeeded) {
980 {
981 FrameScope scope(masm, StackFrame::INTERNAL);
982 __ Push(receiver);
983 __ Push(holder, name_);
984 CompileCallLoadPropertyWithInterceptor(
985 masm, receiver, holder, name_, holder_obj,
986 IC::kLoadPropertyWithInterceptorOnly);
987 __ pop(name_);
988 __ pop(holder);
989 __ pop(receiver);
990 }
991 // If interceptor returns no-result sentinel, call the constant function.
992 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
993 __ cmp(r0, scratch);
994 __ b(ne, interceptor_succeeded);
995 }
996
997 CallStubCompiler* stub_compiler_;
998 Register name_;
999 };
1000
1001
1002 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 861 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1003 __ Jump(code, RelocInfo::CODE_TARGET); 862 __ Jump(code, RelocInfo::CODE_TARGET);
1004 } 863 }
1005 864
1006 865
1007 #undef __ 866 #undef __
1008 #define __ ACCESS_MASM(masm()) 867 #define __ ACCESS_MASM(masm())
1009 868
1010 869
1011 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, 870 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
1350 this->name(), interceptor_holder); 1209 this->name(), interceptor_holder);
1351 1210
1352 ExternalReference ref = 1211 ExternalReference ref =
1353 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1212 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1354 isolate()); 1213 isolate());
1355 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1214 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1356 } 1215 }
1357 } 1216 }
1358 1217
1359 1218
1360 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1361 if (kind_ == Code::KEYED_CALL_IC) {
1362 __ cmp(r2, Operand(name));
1363 __ b(ne, miss);
1364 }
1365 }
1366
1367
1368 void CallStubCompiler::GenerateFunctionCheck(Register function,
1369 Register scratch,
1370 Label* miss) {
1371 __ JumpIfSmi(function, miss);
1372 __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE);
1373 __ b(ne, miss);
1374 }
1375
1376
1377 void CallStubCompiler::GenerateLoadFunctionFromCell(
1378 Handle<Cell> cell,
1379 Handle<JSFunction> function,
1380 Label* miss) {
1381 // Get the value from the cell.
1382 __ mov(r3, Operand(cell));
1383 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset));
1384
1385 // Check that the cell contains the same function.
1386 if (heap()->InNewSpace(*function)) {
1387 // We can't embed a pointer to a function in new space so we have
1388 // to verify that the shared function info is unchanged. This has
1389 // the nice side effect that multiple closures based on the same
1390 // function can all use this call IC. Before we load through the
1391 // function, we have to verify that it still is a function.
1392 GenerateFunctionCheck(r1, r3, miss);
1393
1394 // Check the shared function info. Make sure it hasn't changed.
1395 __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
1396 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1397 __ cmp(r4, r3);
1398 } else {
1399 __ cmp(r1, Operand(function));
1400 }
1401 __ b(ne, miss);
1402 }
1403
1404
1405 void CallStubCompiler::GenerateMissBranch() {
1406 Handle<Code> code =
1407 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1408 kind_,
1409 extra_state());
1410 __ Jump(code, RelocInfo::CODE_TARGET);
1411 }
1412
1413
1414 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1415 Handle<JSObject> holder,
1416 PropertyIndex index,
1417 Handle<Name> name) {
1418 Label miss;
1419
1420 Register reg = HandlerFrontendHeader(
1421 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1422 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
1423 index.translate(holder), Representation::Tagged());
1424 GenerateJumpFunction(object, r1, &miss);
1425
1426 HandlerFrontendFooter(&miss);
1427
1428 // Return the generated code.
1429 return GetCode(Code::FAST, name);
1430 }
1431
1432
1433 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1219 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1434 Label success; 1220 Label success;
1435 // Check that the object is a boolean. 1221 // Check that the object is a boolean.
1436 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1222 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1437 __ cmp(object, ip); 1223 __ cmp(object, ip);
1438 __ b(eq, &success); 1224 __ b(eq, &success);
1439 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 1225 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1440 __ cmp(object, ip); 1226 __ cmp(object, ip);
1441 __ b(ne, miss); 1227 __ b(ne, miss);
1442 __ bind(&success); 1228 __ bind(&success);
1443 } 1229 }
1444 1230
1445 1231
1446 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1447 if (object->IsGlobalObject()) {
1448 const int argc = arguments().immediate();
1449 const int receiver_offset = argc * kPointerSize;
1450 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1451 __ str(r3, MemOperand(sp, receiver_offset));
1452 }
1453 }
1454
1455
1456 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1457 Handle<JSObject> holder,
1458 Handle<Name> name,
1459 CheckType check,
1460 Label* miss) {
1461 // ----------- S t a t e -------------
1462 // -- r2 : name
1463 // -- lr : return address
1464 // -----------------------------------
1465 GenerateNameCheck(name, miss);
1466
1467 Register reg = r0;
1468
1469 // Get the receiver from the stack
1470 const int argc = arguments().immediate();
1471 const int receiver_offset = argc * kPointerSize;
1472 __ ldr(r0, MemOperand(sp, receiver_offset));
1473
1474 // Check that the receiver isn't a smi.
1475 if (check != NUMBER_CHECK) {
1476 __ JumpIfSmi(r0, miss);
1477 }
1478
1479 // Make sure that it's okay not to patch the on stack receiver
1480 // unless we're doing a receiver map check.
1481 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1482 switch (check) {
1483 case RECEIVER_MAP_CHECK:
1484 __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3);
1485
1486 // Check that the maps haven't changed.
1487 reg = CheckPrototypes(
1488 IC::CurrentTypeOf(object, isolate()),
1489 reg, holder, r1, r3, r4, name, miss);
1490 break;
1491
1492 case STRING_CHECK: {
1493 // Check that the object is a string.
1494 __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE);
1495 __ b(ge, miss);
1496 // Check that the maps starting from the prototype haven't changed.
1497 GenerateDirectLoadGlobalFunctionPrototype(
1498 masm(), Context::STRING_FUNCTION_INDEX, r1, miss);
1499 break;
1500 }
1501 case SYMBOL_CHECK: {
1502 // Check that the object is a symbol.
1503 __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE);
1504 __ b(ne, miss);
1505 // Check that the maps starting from the prototype haven't changed.
1506 GenerateDirectLoadGlobalFunctionPrototype(
1507 masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss);
1508 break;
1509 }
1510 case NUMBER_CHECK: {
1511 Label fast;
1512 // Check that the object is a smi or a heap number.
1513 __ JumpIfSmi(reg, &fast);
1514 __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE);
1515 __ b(ne, miss);
1516 __ bind(&fast);
1517 // Check that the maps starting from the prototype haven't changed.
1518 GenerateDirectLoadGlobalFunctionPrototype(
1519 masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss);
1520 break;
1521 }
1522 case BOOLEAN_CHECK: {
1523 GenerateBooleanCheck(reg, miss);
1524
1525 // Check that the maps starting from the prototype haven't changed.
1526 GenerateDirectLoadGlobalFunctionPrototype(
1527 masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss);
1528 break;
1529 }
1530 }
1531
1532 if (check != RECEIVER_MAP_CHECK) {
1533 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
1534 reg = CheckPrototypes(
1535 IC::CurrentTypeOf(prototype, isolate()),
1536 r1, holder, r1, r3, r4, name, miss);
1537 }
1538
1539 return reg;
1540 }
1541
1542
1543 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1544 Register function,
1545 Label* miss) {
1546 ASSERT(function.is(r1));
1547 // Check that the function really is a function.
1548 GenerateFunctionCheck(function, r3, miss);
1549 PatchImplicitReceiver(object);
1550
1551 // Invoke the function.
1552 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, NullCallWrapper());
1553 }
1554
1555
1556 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
1557 Handle<JSObject> holder,
1558 Handle<Name> name) {
1559 Label miss;
1560 GenerateNameCheck(name, &miss);
1561
1562 // Get the number of arguments.
1563 const int argc = arguments().immediate();
1564 LookupResult lookup(isolate());
1565 LookupPostInterceptor(holder, name, &lookup);
1566
1567 // Get the receiver from the stack.
1568 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1569
1570 CallInterceptorCompiler compiler(this, r2);
1571 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0,
1572 &miss);
1573
1574 // Move returned value, the function to call, to r1.
1575 __ mov(r1, r0);
1576 // Restore receiver.
1577 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1578
1579 GenerateJumpFunction(object, r1, &miss);
1580
1581 HandlerFrontendFooter(&miss);
1582
1583 // Return the generated code.
1584 return GetCode(Code::FAST, name);
1585 }
1586
1587
1588 Handle<Code> CallStubCompiler::CompileCallGlobal(
1589 Handle<JSObject> object,
1590 Handle<GlobalObject> holder,
1591 Handle<PropertyCell> cell,
1592 Handle<JSFunction> function,
1593 Handle<Name> name) {
1594 Label miss;
1595 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1596 // Potentially loads a closure that matches the shared function info of the
1597 // function, rather than function.
1598 GenerateLoadFunctionFromCell(cell, function, &miss);
1599
1600 Counters* counters = isolate()->counters();
1601 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
1602 GenerateJumpFunction(object, r1, function);
1603 HandlerFrontendFooter(&miss);
1604
1605 // Return the generated code.
1606 return GetCode(Code::NORMAL, name);
1607 }
1608
1609
1610 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1232 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1611 Handle<JSObject> object, 1233 Handle<JSObject> object,
1612 Handle<JSObject> holder, 1234 Handle<JSObject> holder,
1613 Handle<Name> name, 1235 Handle<Name> name,
1614 Handle<ExecutableAccessorInfo> callback) { 1236 Handle<ExecutableAccessorInfo> callback) {
1615 Register holder_reg = HandlerFrontend( 1237 Register holder_reg = HandlerFrontend(
1616 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1238 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1617 1239
1618 // Stub never generated for non-global objects that require access checks. 1240 // Stub never generated for non-global objects that require access checks.
1619 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1241 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 #define __ ACCESS_MASM(masm()) 1436 #define __ ACCESS_MASM(masm())
1815 1437
1816 1438
1817 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 1439 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
1818 Handle<HeapType> type, 1440 Handle<HeapType> type,
1819 Handle<GlobalObject> global, 1441 Handle<GlobalObject> global,
1820 Handle<PropertyCell> cell, 1442 Handle<PropertyCell> cell,
1821 Handle<Name> name, 1443 Handle<Name> name,
1822 bool is_dont_delete) { 1444 bool is_dont_delete) {
1823 Label miss; 1445 Label miss;
1824
1825 HandlerFrontendHeader(type, receiver(), global, name, &miss); 1446 HandlerFrontendHeader(type, receiver(), global, name, &miss);
1826 1447
1827 // Get the value from the cell. 1448 // Get the value from the cell.
1828 __ mov(r3, Operand(cell)); 1449 __ mov(r3, Operand(cell));
1829 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); 1450 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
1830 1451
1831 // Check for deleted property if property can actually be deleted. 1452 // Check for deleted property if property can actually be deleted.
1832 if (!is_dont_delete) { 1453 if (!is_dont_delete) {
1833 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1454 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1834 __ cmp(r4, ip); 1455 __ cmp(r4, ip);
1835 __ b(eq, &miss); 1456 __ b(eq, &miss);
1836 } 1457 }
1837 1458
1838 HandlerFrontendFooter(name, &miss);
1839
1840 Counters* counters = isolate()->counters(); 1459 Counters* counters = isolate()->counters();
1841 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 1460 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
1842 __ mov(r0, r4); 1461 __ mov(r0, r4);
1843 __ Ret(); 1462 __ Ret();
1844 1463
1464 HandlerFrontendFooter(name, &miss);
1465
1845 // Return the generated code. 1466 // Return the generated code.
1846 return GetCode(kind(), Code::NORMAL, name); 1467 return GetCode(kind(), Code::NORMAL, name);
1847 } 1468 }
1848 1469
1849 1470
1850 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1471 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
1851 TypeHandleList* types, 1472 TypeHandleList* types,
1852 CodeHandleList* handlers, 1473 CodeHandleList* handlers,
1853 Handle<Name> name, 1474 Handle<Name> name,
1854 Code::StubType type, 1475 Code::StubType type,
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 // ----------------------------------- 1592 // -----------------------------------
1972 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1593 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
1973 } 1594 }
1974 1595
1975 1596
1976 #undef __ 1597 #undef __
1977 1598
1978 } } // namespace v8::internal 1599 } } // namespace v8::internal
1979 1600
1980 #endif // V8_TARGET_ARCH_ARM 1601 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.cc ('k') | src/ast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698