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

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

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

Powered by Google App Engine
This is Rietveld 408576698