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

Side by Side Diff: src/x64/stub-cache-x64.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/x64/lithium-x64.cc ('k') | test/cctest/test-api.cc » ('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 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 __ PushReturnAddressFrom(scratch1); 461 __ PushReturnAddressFrom(scratch1);
462 // Stack now matches JSFunction abi. 462 // Stack now matches JSFunction abi.
463 GenerateFastApiCallBody(masm, 463 GenerateFastApiCallBody(masm,
464 optimization, 464 optimization,
465 argc, 465 argc,
466 receiver, 466 receiver,
467 true); 467 true);
468 } 468 }
469 469
470 470
471 class CallInterceptorCompiler BASE_EMBEDDED {
472 public:
473 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
474 Register name)
475 : stub_compiler_(stub_compiler),
476 name_(name) {}
477
478 void Compile(MacroAssembler* masm,
479 Handle<JSObject> object,
480 Handle<JSObject> holder,
481 Handle<Name> name,
482 LookupResult* lookup,
483 Register receiver,
484 Register scratch1,
485 Register scratch2,
486 Register scratch3,
487 Label* miss) {
488 ASSERT(holder->HasNamedInterceptor());
489 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
490
491 // Check that the receiver isn't a smi.
492 __ JumpIfSmi(receiver, miss);
493
494 CallOptimization optimization(lookup);
495 if (optimization.is_constant_call()) {
496 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
497 holder, lookup, name, optimization, miss);
498 } else {
499 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
500 name, holder, miss);
501 }
502 }
503
504 private:
505 void CompileCacheable(MacroAssembler* masm,
506 Handle<JSObject> object,
507 Register receiver,
508 Register scratch1,
509 Register scratch2,
510 Register scratch3,
511 Handle<JSObject> interceptor_holder,
512 LookupResult* lookup,
513 Handle<Name> name,
514 const CallOptimization& optimization,
515 Label* miss_label) {
516 ASSERT(optimization.is_constant_call());
517 ASSERT(!lookup->holder()->IsGlobalObject());
518
519 Counters* counters = masm->isolate()->counters();
520 __ IncrementCounter(counters->call_const_interceptor(), 1);
521
522 // Check that the maps from receiver to interceptor's holder
523 // haven't changed and thus we can invoke interceptor.
524 Label miss_cleanup;
525 Register holder =
526 stub_compiler_->CheckPrototypes(
527 IC::CurrentTypeOf(object, masm->isolate()), receiver,
528 interceptor_holder, scratch1, scratch2, scratch3,
529 name, miss_label);
530
531 // Invoke an interceptor and if it provides a value,
532 // branch to |regular_invoke|.
533 Label regular_invoke;
534 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
535 &regular_invoke);
536
537 // Interceptor returned nothing for this property. Try to use cached
538 // constant function.
539
540 // Check that the maps from interceptor's holder to constant function's
541 // holder haven't changed and thus we can use cached constant function.
542 if (*interceptor_holder != lookup->holder()) {
543 stub_compiler_->CheckPrototypes(
544 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
545 handle(lookup->holder()), scratch1, scratch2, scratch3,
546 name, miss_label);
547 }
548
549 Handle<JSFunction> fun = optimization.constant_function();
550 stub_compiler_->GenerateJumpFunction(object, fun);
551
552 // Invoke a regular function.
553 __ bind(&regular_invoke);
554 }
555
556 void CompileRegular(MacroAssembler* masm,
557 Handle<JSObject> object,
558 Register receiver,
559 Register scratch1,
560 Register scratch2,
561 Register scratch3,
562 Handle<Name> name,
563 Handle<JSObject> interceptor_holder,
564 Label* miss_label) {
565 Register holder =
566 stub_compiler_->CheckPrototypes(
567 IC::CurrentTypeOf(object, masm->isolate()), receiver,
568 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
569
570 FrameScope scope(masm, StackFrame::INTERNAL);
571 // Save the name_ register across the call.
572 __ push(name_);
573
574 CompileCallLoadPropertyWithInterceptor(
575 masm, receiver, holder, name_, interceptor_holder,
576 IC::kLoadPropertyWithInterceptorForCall);
577
578 // Restore the name_ register.
579 __ pop(name_);
580
581 // Leave the internal frame.
582 }
583
584 void LoadWithInterceptor(MacroAssembler* masm,
585 Register receiver,
586 Register holder,
587 Handle<JSObject> holder_obj,
588 Label* interceptor_succeeded) {
589 {
590 FrameScope scope(masm, StackFrame::INTERNAL);
591 __ push(receiver);
592 __ push(holder);
593 __ push(name_);
594
595 CompileCallLoadPropertyWithInterceptor(
596 masm, receiver, holder, name_, holder_obj,
597 IC::kLoadPropertyWithInterceptorOnly);
598
599 __ pop(name_);
600 __ pop(holder);
601 __ pop(receiver);
602 // Leave the internal frame.
603 }
604
605 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
606 __ j(not_equal, interceptor_succeeded);
607 }
608
609 CallStubCompiler* stub_compiler_;
610 Register name_;
611 };
612
613
614 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, 471 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
615 Label* label, 472 Label* label,
616 Handle<Name> name) { 473 Handle<Name> name) {
617 if (!label->is_unused()) { 474 if (!label->is_unused()) {
618 __ bind(label); 475 __ bind(label);
619 __ Move(this->name(), name); 476 __ Move(this->name(), name);
620 } 477 }
621 } 478 }
622 479
623 480
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 this->name(), interceptor_holder); 1111 this->name(), interceptor_holder);
1255 __ PushReturnAddressFrom(scratch2()); 1112 __ PushReturnAddressFrom(scratch2());
1256 1113
1257 ExternalReference ref = ExternalReference( 1114 ExternalReference ref = ExternalReference(
1258 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); 1115 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
1259 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1116 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1260 } 1117 }
1261 } 1118 }
1262 1119
1263 1120
1264 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1265 if (kind_ == Code::KEYED_CALL_IC) {
1266 __ Cmp(rcx, name);
1267 __ j(not_equal, miss);
1268 }
1269 }
1270
1271
1272 void CallStubCompiler::GenerateFunctionCheck(Register function,
1273 Register scratch,
1274 Label* miss) {
1275 __ JumpIfSmi(function, miss);
1276 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
1277 __ j(not_equal, miss);
1278 }
1279
1280
1281 void CallStubCompiler::GenerateLoadFunctionFromCell(
1282 Handle<Cell> cell,
1283 Handle<JSFunction> function,
1284 Label* miss) {
1285 // Get the value from the cell.
1286 __ Move(rdi, cell);
1287 __ movp(rdi, FieldOperand(rdi, Cell::kValueOffset));
1288
1289 // Check that the cell contains the same function.
1290 if (heap()->InNewSpace(*function)) {
1291 // We can't embed a pointer to a function in new space so we have
1292 // to verify that the shared function info is unchanged. This has
1293 // the nice side effect that multiple closures based on the same
1294 // function can all use this call IC. Before we load through the
1295 // function, we have to verify that it still is a function.
1296 GenerateFunctionCheck(rdi, rax, miss);
1297
1298 // Check the shared function info. Make sure it hasn't changed.
1299 __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
1300 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
1301 } else {
1302 __ Cmp(rdi, function);
1303 }
1304 __ j(not_equal, miss);
1305 }
1306
1307
1308 void CallStubCompiler::GenerateMissBranch() {
1309 Handle<Code> code =
1310 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1311 kind_,
1312 extra_state());
1313 __ Jump(code, RelocInfo::CODE_TARGET);
1314 }
1315
1316
1317 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1318 Handle<JSObject> holder,
1319 PropertyIndex index,
1320 Handle<Name> name) {
1321 Label miss;
1322
1323 Register reg = HandlerFrontendHeader(
1324 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1325
1326 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
1327 index.translate(holder), Representation::Tagged());
1328 GenerateJumpFunction(object, rdi, &miss);
1329
1330 HandlerFrontendFooter(&miss);
1331
1332 // Return the generated code.
1333 return GetCode(Code::FAST, name);
1334 }
1335
1336
1337 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1121 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1338 Label success; 1122 Label success;
1339 // Check that the object is a boolean. 1123 // Check that the object is a boolean.
1340 __ CompareRoot(object, Heap::kTrueValueRootIndex); 1124 __ Cmp(object, factory()->true_value());
1341 __ j(equal, &success); 1125 __ j(equal, &success);
1342 __ CompareRoot(object, Heap::kFalseValueRootIndex); 1126 __ Cmp(object, factory()->false_value());
1343 __ j(not_equal, miss); 1127 __ j(not_equal, miss);
1344 __ bind(&success); 1128 __ bind(&success);
1345 } 1129 }
1346 1130
1347 1131
1348 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1349 if (object->IsGlobalObject()) {
1350 StackArgumentsAccessor args(rsp, arguments());
1351 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
1352 __ movp(args.GetReceiverOperand(), rdx);
1353 }
1354 }
1355
1356
1357 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1358 Handle<JSObject> holder,
1359 Handle<Name> name,
1360 CheckType check,
1361 Label* miss) {
1362 GenerateNameCheck(name, miss);
1363
1364 Register reg = rdx;
1365
1366 StackArgumentsAccessor args(rsp, arguments());
1367 __ movp(reg, args.GetReceiverOperand());
1368
1369 // Check that the receiver isn't a smi.
1370 if (check != NUMBER_CHECK) {
1371 __ JumpIfSmi(reg, miss);
1372 }
1373
1374 // Make sure that it's okay not to patch the on stack receiver
1375 // unless we're doing a receiver map check.
1376 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1377
1378 Counters* counters = isolate()->counters();
1379 switch (check) {
1380 case RECEIVER_MAP_CHECK:
1381 __ IncrementCounter(counters->call_const(), 1);
1382
1383 // Check that the maps haven't changed.
1384 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
1385 rbx, rax, rdi, name, miss);
1386 break;
1387
1388 case STRING_CHECK: {
1389 // Check that the object is a string.
1390 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
1391 __ j(above_equal, miss);
1392 // Check that the maps starting from the prototype haven't changed.
1393 GenerateDirectLoadGlobalFunctionPrototype(
1394 masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
1395 break;
1396 }
1397 case SYMBOL_CHECK: {
1398 // Check that the object is a symbol.
1399 __ CmpObjectType(reg, SYMBOL_TYPE, rax);
1400 __ j(not_equal, miss);
1401 // Check that the maps starting from the prototype haven't changed.
1402 GenerateDirectLoadGlobalFunctionPrototype(
1403 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
1404 break;
1405 }
1406 case NUMBER_CHECK: {
1407 Label fast;
1408 // Check that the object is a smi or a heap number.
1409 __ JumpIfSmi(reg, &fast);
1410 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
1411 __ j(not_equal, miss);
1412 __ bind(&fast);
1413 // Check that the maps starting from the prototype haven't changed.
1414 GenerateDirectLoadGlobalFunctionPrototype(
1415 masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
1416 break;
1417 }
1418 case BOOLEAN_CHECK: {
1419 GenerateBooleanCheck(reg, miss);
1420 // Check that the maps starting from the prototype haven't changed.
1421 GenerateDirectLoadGlobalFunctionPrototype(
1422 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
1423 break;
1424 }
1425 }
1426
1427 if (check != RECEIVER_MAP_CHECK) {
1428 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
1429 reg = CheckPrototypes(
1430 IC::CurrentTypeOf(prototype, isolate()),
1431 rax, holder, rbx, rdx, rdi, name, miss);
1432 }
1433
1434 return reg;
1435 }
1436
1437
1438 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1439 Register function,
1440 Label* miss) {
1441 // Check that the function really is a function.
1442 GenerateFunctionCheck(function, rbx, miss);
1443
1444 if (!function.is(rdi)) __ movp(rdi, function);
1445 PatchImplicitReceiver(object);
1446
1447 // Invoke the function.
1448 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, NullCallWrapper());
1449 }
1450
1451
1452 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
1453 Handle<JSObject> holder,
1454 Handle<Name> name) {
1455 Label miss;
1456 GenerateNameCheck(name, &miss);
1457
1458 LookupResult lookup(isolate());
1459 LookupPostInterceptor(holder, name, &lookup);
1460
1461 // Get the receiver from the stack.
1462 StackArgumentsAccessor args(rsp, arguments());
1463 __ movp(rdx, args.GetReceiverOperand());
1464
1465 CallInterceptorCompiler compiler(this, rcx);
1466 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
1467 &miss);
1468
1469 // Restore receiver.
1470 __ movp(rdx, args.GetReceiverOperand());
1471
1472 GenerateJumpFunction(object, rax, &miss);
1473
1474 HandlerFrontendFooter(&miss);
1475
1476 // Return the generated code.
1477 return GetCode(Code::FAST, name);
1478 }
1479
1480
1481 Handle<Code> CallStubCompiler::CompileCallGlobal(
1482 Handle<JSObject> object,
1483 Handle<GlobalObject> holder,
1484 Handle<PropertyCell> cell,
1485 Handle<JSFunction> function,
1486 Handle<Name> name) {
1487 Label miss;
1488 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1489 // Potentially loads a closure that matches the shared function info of the
1490 // function, rather than function.
1491 GenerateLoadFunctionFromCell(cell, function, &miss);
1492 Counters* counters = isolate()->counters();
1493 __ IncrementCounter(counters->call_global_inline(), 1);
1494 GenerateJumpFunction(object, rdi, function);
1495 HandlerFrontendFooter(&miss);
1496
1497 // Return the generated code.
1498 return GetCode(Code::NORMAL, name);
1499 }
1500
1501
1502 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1132 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1503 Handle<JSObject> object, 1133 Handle<JSObject> object,
1504 Handle<JSObject> holder, 1134 Handle<JSObject> holder,
1505 Handle<Name> name, 1135 Handle<Name> name,
1506 Handle<ExecutableAccessorInfo> callback) { 1136 Handle<ExecutableAccessorInfo> callback) {
1507 Register holder_reg = HandlerFrontend( 1137 Register holder_reg = HandlerFrontend(
1508 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1138 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1509 1139
1510 __ PopReturnAddressTo(scratch1()); 1140 __ PopReturnAddressTo(scratch1());
1511 __ push(receiver()); 1141 __ push(receiver());
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 1374
1745 // Check for deleted property if property can actually be deleted. 1375 // Check for deleted property if property can actually be deleted.
1746 if (!is_dont_delete) { 1376 if (!is_dont_delete) {
1747 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 1377 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
1748 __ j(equal, &miss); 1378 __ j(equal, &miss);
1749 } else if (FLAG_debug_code) { 1379 } else if (FLAG_debug_code) {
1750 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 1380 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
1751 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 1381 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
1752 } 1382 }
1753 1383
1754 HandlerFrontendFooter(name, &miss);
1755
1756 Counters* counters = isolate()->counters(); 1384 Counters* counters = isolate()->counters();
1757 __ IncrementCounter(counters->named_load_global_stub(), 1); 1385 __ IncrementCounter(counters->named_load_global_stub(), 1);
1758 __ movp(rax, rbx); 1386 __ movp(rax, rbx);
1759 __ ret(0); 1387 __ ret(0);
1760 1388
1389 HandlerFrontendFooter(name, &miss);
1390
1761 // Return the generated code. 1391 // Return the generated code.
1762 return GetCode(kind(), Code::NORMAL, name); 1392 return GetCode(kind(), Code::NORMAL, name);
1763 } 1393 }
1764 1394
1765 1395
1766 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1396 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
1767 TypeHandleList* types, 1397 TypeHandleList* types,
1768 CodeHandleList* handlers, 1398 CodeHandleList* handlers,
1769 Handle<Name> name, 1399 Handle<Name> name,
1770 Code::StubType type, 1400 Code::StubType type,
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 // ----------------------------------- 1485 // -----------------------------------
1856 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1486 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
1857 } 1487 }
1858 1488
1859 1489
1860 #undef __ 1490 #undef __
1861 1491
1862 } } // namespace v8::internal 1492 } } // namespace v8::internal
1863 1493
1864 #endif // V8_TARGET_ARCH_X64 1494 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-x64.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698