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

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

Issue 155723005: A64: Synchronize with r19001. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: 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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 // Load the prototype from the initial map. 264 // Load the prototype from the initial map.
265 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 265 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
266 } 266 }
267 267
268 268
269 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 269 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
270 MacroAssembler* masm, 270 MacroAssembler* masm,
271 int index, 271 int index,
272 Register prototype, 272 Register prototype,
273 Label* miss) { 273 Label* miss) {
274 // Check we're still in the same context.
275 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)),
276 masm->isolate()->global_object());
277 __ j(not_equal, miss);
278 // Get the global function with the given index. 274 // Get the global function with the given index.
279 Handle<JSFunction> function( 275 Handle<JSFunction> function(
280 JSFunction::cast(masm->isolate()->native_context()->get(index))); 276 JSFunction::cast(masm->isolate()->native_context()->get(index)));
277 // Check we're still in the same context.
278 Register scratch = prototype;
279 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
280 __ mov(scratch, Operand(esi, offset));
281 __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
282 __ cmp(Operand(scratch, Context::SlotOffset(index)), function);
283 __ j(not_equal, miss);
284
281 // Load its initial map. The global functions all have initial maps. 285 // Load its initial map. The global functions all have initial maps.
282 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); 286 __ Set(prototype, Immediate(Handle<Map>(function->initial_map())));
283 // Load the prototype from the initial map. 287 // Load the prototype from the initial map.
284 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 288 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
285 } 289 }
286 290
287 291
288 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
289 Register receiver, 293 Register receiver,
290 Register scratch, 294 Register scratch,
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 // Put api_function_address in place. 459 // Put api_function_address in place.
456 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 460 Address function_address = v8::ToCData<Address>(api_call_info->callback());
457 __ mov(api_function_address, Immediate(function_address)); 461 __ mov(api_function_address, Immediate(function_address));
458 462
459 // Jump to stub. 463 // Jump to stub.
460 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); 464 CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
461 __ TailCallStub(&stub); 465 __ TailCallStub(&stub);
462 } 466 }
463 467
464 468
465 // Generates call to API function.
466 static void GenerateFastApiCall(MacroAssembler* masm,
467 const CallOptimization& optimization,
468 int argc,
469 Handle<Map> map_to_holder,
470 CallOptimization::HolderLookup holder_lookup) {
471 Counters* counters = masm->isolate()->counters();
472 __ IncrementCounter(counters->call_const_fast_api(), 1);
473
474 // Move holder to a register
475 Register holder_reg = ecx;
476 switch (holder_lookup) {
477 case CallOptimization::kHolderIsReceiver:
478 {
479 ASSERT(map_to_holder.is_null());
480 __ mov(holder_reg, Operand(esp, (argc + 1)* kPointerSize));
481 }
482 break;
483 case CallOptimization::kHolderIsPrototypeOfMap:
484 {
485 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
486 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
487 __ mov(holder_reg, holder);
488 } else {
489 __ mov(holder_reg, map_to_holder);
490 __ mov(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
491 }
492 }
493 break;
494 case CallOptimization::kHolderNotFound:
495 UNREACHABLE();
496 }
497 GenerateFastApiCallBody(masm,
498 optimization,
499 argc,
500 holder_reg,
501 false);
502 }
503
504
505 // Generate call to api function. 469 // Generate call to api function.
506 // This function uses push() to generate smaller, faster code than 470 // This function uses push() to generate smaller, faster code than
507 // the version above. It is an optimization that should will be removed 471 // the version above. It is an optimization that should will be removed
508 // when api call ICs are generated in hydrogen. 472 // when api call ICs are generated in hydrogen.
509 static void GenerateFastApiCall(MacroAssembler* masm, 473 static void GenerateFastApiCall(MacroAssembler* masm,
510 const CallOptimization& optimization, 474 const CallOptimization& optimization,
511 Register receiver, 475 Register receiver,
512 Register scratch1, 476 Register scratch1,
513 int argc, 477 int argc,
514 Register* values) { 478 Register* values) {
(...skipping 11 matching lines...) Expand all
526 __ push(scratch1); 490 __ push(scratch1);
527 // Stack now matches JSFunction abi. 491 // Stack now matches JSFunction abi.
528 GenerateFastApiCallBody(masm, 492 GenerateFastApiCallBody(masm,
529 optimization, 493 optimization,
530 argc, 494 argc,
531 receiver, 495 receiver,
532 true); 496 true);
533 } 497 }
534 498
535 499
536 class CallInterceptorCompiler BASE_EMBEDDED {
537 public:
538 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
539 const ParameterCount& arguments,
540 Register name)
541 : stub_compiler_(stub_compiler),
542 arguments_(arguments),
543 name_(name) {}
544
545 void Compile(MacroAssembler* masm,
546 Handle<JSObject> object,
547 Handle<JSObject> holder,
548 Handle<Name> name,
549 LookupResult* lookup,
550 Register receiver,
551 Register scratch1,
552 Register scratch2,
553 Register scratch3,
554 Label* miss) {
555 ASSERT(holder->HasNamedInterceptor());
556 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
557
558 // Check that the receiver isn't a smi.
559 __ JumpIfSmi(receiver, miss);
560
561 CallOptimization optimization(lookup);
562 if (optimization.is_constant_call()) {
563 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
564 holder, lookup, name, optimization, miss);
565 } else {
566 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
567 name, holder, miss);
568 }
569 }
570
571 private:
572 void CompileCacheable(MacroAssembler* masm,
573 Handle<JSObject> object,
574 Register receiver,
575 Register scratch1,
576 Register scratch2,
577 Register scratch3,
578 Handle<JSObject> interceptor_holder,
579 LookupResult* lookup,
580 Handle<Name> name,
581 const CallOptimization& optimization,
582 Label* miss_label) {
583 ASSERT(optimization.is_constant_call());
584 ASSERT(!lookup->holder()->IsGlobalObject());
585
586 Counters* counters = masm->isolate()->counters();
587 __ IncrementCounter(counters->call_const_interceptor(), 1);
588
589 // Check that the maps from receiver to interceptor's holder
590 // haven't changed and thus we can invoke interceptor.
591 Register holder =
592 stub_compiler_->CheckPrototypes(
593 IC::CurrentTypeOf(object, masm->isolate()), receiver,
594 interceptor_holder, scratch1, scratch2, scratch3,
595 name, miss_label);
596
597 // Invoke an interceptor and if it provides a value,
598 // branch to |regular_invoke|.
599 Label regular_invoke;
600 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
601 &regular_invoke);
602
603 // Interceptor returned nothing for this property. Try to use cached
604 // constant function.
605
606 // Check that the maps from interceptor's holder to constant function's
607 // holder haven't changed and thus we can use cached constant function.
608 if (*interceptor_holder != lookup->holder()) {
609 stub_compiler_->CheckPrototypes(
610 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
611 handle(lookup->holder()), scratch1, scratch2, scratch3,
612 name, miss_label);
613 }
614
615 Handle<Map> lookup_map;
616 CallOptimization::HolderLookup holder_lookup =
617 CallOptimization::kHolderNotFound;
618 if (optimization.is_simple_api_call() &&
619 !lookup->holder()->IsGlobalObject()) {
620 lookup_map = optimization.LookupHolderOfExpectedType(
621 object, object, interceptor_holder, &holder_lookup);
622 if (holder_lookup == CallOptimization::kHolderNotFound) {
623 lookup_map =
624 optimization.LookupHolderOfExpectedType(
625 object,
626 interceptor_holder,
627 Handle<JSObject>(lookup->holder()),
628 &holder_lookup);
629 }
630 }
631
632 // Invoke function.
633 if (holder_lookup != CallOptimization::kHolderNotFound) {
634 int argc = arguments_.immediate();
635 GenerateFastApiCall(masm,
636 optimization,
637 argc,
638 lookup_map,
639 holder_lookup);
640 } else {
641 Handle<JSFunction> fun = optimization.constant_function();
642 stub_compiler_->GenerateJumpFunction(object, fun);
643 }
644
645 // Invoke a regular function.
646 __ bind(&regular_invoke);
647 }
648
649 void CompileRegular(MacroAssembler* masm,
650 Handle<JSObject> object,
651 Register receiver,
652 Register scratch1,
653 Register scratch2,
654 Register scratch3,
655 Handle<Name> name,
656 Handle<JSObject> interceptor_holder,
657 Label* miss_label) {
658 Register holder =
659 stub_compiler_->CheckPrototypes(
660 IC::CurrentTypeOf(object, masm->isolate()), receiver,
661 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
662
663 FrameScope scope(masm, StackFrame::INTERNAL);
664 // Save the name_ register across the call.
665 __ push(name_);
666
667 CompileCallLoadPropertyWithInterceptor(
668 masm, receiver, holder, name_, interceptor_holder,
669 IC::kLoadPropertyWithInterceptorForCall);
670
671 // Restore the name_ register.
672 __ pop(name_);
673
674 // Leave the internal frame.
675 }
676
677 void LoadWithInterceptor(MacroAssembler* masm,
678 Register receiver,
679 Register holder,
680 Handle<JSObject> holder_obj,
681 Label* interceptor_succeeded) {
682 {
683 FrameScope scope(masm, StackFrame::INTERNAL);
684 __ push(receiver);
685 __ push(holder);
686 __ push(name_);
687
688 CompileCallLoadPropertyWithInterceptor(
689 masm, receiver, holder, name_, holder_obj,
690 IC::kLoadPropertyWithInterceptorOnly);
691
692 __ pop(name_);
693 __ pop(holder);
694 __ pop(receiver);
695 // Leave the internal frame.
696 }
697
698 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
699 __ j(not_equal, interceptor_succeeded);
700 }
701
702 CallStubCompiler* stub_compiler_;
703 const ParameterCount& arguments_;
704 Register name_;
705 };
706
707
708 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, 500 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
709 Label* label, 501 Label* label,
710 Handle<Name> name) { 502 Handle<Name> name) {
711 if (!label->is_unused()) { 503 if (!label->is_unused()) {
712 __ bind(label); 504 __ bind(label);
713 __ mov(this->name(), Immediate(name)); 505 __ mov(this->name(), Immediate(name));
714 } 506 }
715 } 507 }
716 508
717 509
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 // ReturnValue default value 1098 // ReturnValue default value
1307 __ push(Immediate(isolate()->factory()->undefined_value())); 1099 __ push(Immediate(isolate()->factory()->undefined_value()));
1308 __ push(Immediate(reinterpret_cast<int>(isolate()))); 1100 __ push(Immediate(reinterpret_cast<int>(isolate())));
1309 __ push(reg); // holder 1101 __ push(reg); // holder
1310 1102
1311 // Save a pointer to where we pushed the arguments. This will be 1103 // Save a pointer to where we pushed the arguments. This will be
1312 // passed as the const PropertyAccessorInfo& to the C++ callback. 1104 // passed as the const PropertyAccessorInfo& to the C++ callback.
1313 __ push(esp); 1105 __ push(esp);
1314 1106
1315 __ push(name()); // name 1107 __ push(name()); // name
1316 __ mov(ebx, esp); // esp points to reference to name (handler).
1317 1108
1318 __ push(scratch3()); // Restore return address. 1109 __ push(scratch3()); // Restore return address.
1319 1110
1320 // array for v8::Arguments::values_, handler for name and pointer 1111 // Abi for CallApiGetter
1321 // to the values (it considered as smi in GC).
1322 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 2;
1323 // Allocate space for opional callback address parameter in case
1324 // CPU profiler is active.
1325 const int kApiArgc = 2 + 1;
1326
1327 __ PrepareCallApiFunction(kApiArgc);
1328 __ mov(ApiParameterOperand(0), ebx); // name.
1329 __ add(ebx, Immediate(kPointerSize));
1330 __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
1331
1332 // Emitting a stub call may try to allocate (if the code is not
1333 // already generated). Do not allow the assembler to perform a
1334 // garbage collection but instead return the allocation failure
1335 // object.
1336
1337 Register getter_address = edx; 1112 Register getter_address = edx;
1338 Address function_address = v8::ToCData<Address>(callback->getter()); 1113 Address function_address = v8::ToCData<Address>(callback->getter());
1339 __ mov(getter_address, Immediate(function_address)); 1114 __ mov(getter_address, Immediate(function_address));
1340 1115
1341 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); 1116 CallApiGetterStub stub;
1342 1117 __ TailCallStub(&stub);
1343 __ CallApiFunctionAndReturn(getter_address,
1344 thunk_address,
1345 ApiParameterOperand(2),
1346 kStackSpace,
1347 Operand(ebp, 7 * kPointerSize),
1348 NULL);
1349 } 1118 }
1350 1119
1351 1120
1352 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { 1121 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
1353 // Return the constant value. 1122 // Return the constant value.
1354 __ LoadObject(eax, value); 1123 __ LoadObject(eax, value);
1355 __ ret(0); 1124 __ ret(0);
1356 } 1125 }
1357 1126
1358 1127
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1448 __ push(scratch2()); // restore old return address 1217 __ push(scratch2()); // restore old return address
1449 1218
1450 ExternalReference ref = 1219 ExternalReference ref =
1451 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1220 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1452 isolate()); 1221 isolate());
1453 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1222 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1454 } 1223 }
1455 } 1224 }
1456 1225
1457 1226
1458 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1459 if (kind_ == Code::KEYED_CALL_IC) {
1460 __ cmp(ecx, Immediate(name));
1461 __ j(not_equal, miss);
1462 }
1463 }
1464
1465
1466 void CallStubCompiler::GenerateFunctionCheck(Register function,
1467 Register scratch,
1468 Label* miss) {
1469 __ JumpIfSmi(function, miss);
1470 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
1471 __ j(not_equal, miss);
1472 }
1473
1474
1475 void CallStubCompiler::GenerateLoadFunctionFromCell(
1476 Handle<Cell> cell,
1477 Handle<JSFunction> function,
1478 Label* miss) {
1479 // Get the value from the cell.
1480 if (Serializer::enabled()) {
1481 __ mov(edi, Immediate(cell));
1482 __ mov(edi, FieldOperand(edi, Cell::kValueOffset));
1483 } else {
1484 __ mov(edi, Operand::ForCell(cell));
1485 }
1486
1487 // Check that the cell contains the same function.
1488 if (isolate()->heap()->InNewSpace(*function)) {
1489 // We can't embed a pointer to a function in new space so we have
1490 // to verify that the shared function info is unchanged. This has
1491 // the nice side effect that multiple closures based on the same
1492 // function can all use this call IC. Before we load through the
1493 // function, we have to verify that it still is a function.
1494 GenerateFunctionCheck(edi, ebx, miss);
1495
1496 // Check the shared function info. Make sure it hasn't changed.
1497 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
1498 Immediate(Handle<SharedFunctionInfo>(function->shared())));
1499 } else {
1500 __ cmp(edi, Immediate(function));
1501 }
1502 __ j(not_equal, miss);
1503 }
1504
1505
1506 void CallStubCompiler::GenerateMissBranch() {
1507 Handle<Code> code =
1508 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1509 kind_,
1510 extra_state());
1511 __ jmp(code, RelocInfo::CODE_TARGET);
1512 }
1513
1514
1515 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1516 Handle<JSObject> holder,
1517 PropertyIndex index,
1518 Handle<Name> name) {
1519 Label miss;
1520
1521 Register reg = HandlerFrontendHeader(
1522 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1523
1524 GenerateFastPropertyLoad(
1525 masm(), edi, reg, index.is_inobject(holder),
1526 index.translate(holder), Representation::Tagged());
1527 GenerateJumpFunction(object, edi, &miss);
1528
1529 HandlerFrontendFooter(&miss);
1530
1531 // Return the generated code.
1532 return GetCode(Code::FAST, name);
1533 }
1534
1535
1536 Handle<Code> CallStubCompiler::CompileFastApiCall(
1537 const CallOptimization& optimization,
1538 Handle<Object> object,
1539 Handle<JSObject> holder,
1540 Handle<Cell> cell,
1541 Handle<JSFunction> function,
1542 Handle<String> name) {
1543 ASSERT(optimization.is_simple_api_call());
1544 // Bail out if object is a global object as we don't want to
1545 // repatch it to global receiver.
1546 if (object->IsGlobalObject()) return Handle<Code>::null();
1547 if (!cell.is_null()) return Handle<Code>::null();
1548 if (!object->IsJSObject()) return Handle<Code>::null();
1549 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1550 CallOptimization::HolderLookup holder_lookup =
1551 CallOptimization::kHolderNotFound;
1552 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1553 receiver, receiver, holder, &holder_lookup);
1554 if (holder_lookup == CallOptimization::kHolderNotFound) {
1555 return Handle<Code>::null();
1556 }
1557
1558 Label miss;
1559 GenerateNameCheck(name, &miss);
1560
1561 // Get the receiver from the stack.
1562 const int argc = arguments().immediate();
1563 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1564
1565 // Check that the receiver isn't a smi.
1566 __ JumpIfSmi(edx, &miss);
1567
1568 Counters* counters = isolate()->counters();
1569 __ IncrementCounter(counters->call_const(), 1);
1570
1571 // Check that the maps haven't changed and find a Holder as a side effect.
1572 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
1573 ebx, eax, edi, name, &miss);
1574
1575 GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
1576
1577 HandlerFrontendFooter(&miss);
1578
1579 // Return the generated code.
1580 return GetCode(function);
1581 }
1582
1583
1584 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1227 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1585 Label success; 1228 Label success;
1586 // Check that the object is a boolean. 1229 // Check that the object is a boolean.
1587 __ cmp(object, factory()->true_value()); 1230 __ cmp(object, factory()->true_value());
1588 __ j(equal, &success); 1231 __ j(equal, &success);
1589 __ cmp(object, factory()->false_value()); 1232 __ cmp(object, factory()->false_value());
1590 __ j(not_equal, miss); 1233 __ j(not_equal, miss);
1591 __ bind(&success); 1234 __ bind(&success);
1592 } 1235 }
1593 1236
1594 1237
1595 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1596 if (object->IsGlobalObject()) {
1597 const int argc = arguments().immediate();
1598 const int receiver_offset = (argc + 1) * kPointerSize;
1599 __ mov(Operand(esp, receiver_offset),
1600 isolate()->factory()->undefined_value());
1601 }
1602 }
1603
1604
1605 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1606 Handle<JSObject> holder,
1607 Handle<Name> name,
1608 CheckType check,
1609 Label* miss) {
1610 GenerateNameCheck(name, miss);
1611
1612 Register reg = edx;
1613
1614 const int argc = arguments().immediate();
1615 const int receiver_offset = (argc + 1) * kPointerSize;
1616 __ mov(reg, Operand(esp, receiver_offset));
1617
1618 // Check that the receiver isn't a smi.
1619 if (check != NUMBER_CHECK) {
1620 __ JumpIfSmi(reg, miss);
1621 }
1622
1623 // Make sure that it's okay not to patch the on stack receiver
1624 // unless we're doing a receiver map check.
1625 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1626 switch (check) {
1627 case RECEIVER_MAP_CHECK:
1628 __ IncrementCounter(isolate()->counters()->call_const(), 1);
1629
1630 // Check that the maps haven't changed.
1631 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
1632 ebx, eax, edi, name, miss);
1633
1634 break;
1635
1636 case STRING_CHECK: {
1637 // Check that the object is a string.
1638 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax);
1639 __ j(above_equal, miss);
1640 // Check that the maps starting from the prototype haven't changed.
1641 GenerateDirectLoadGlobalFunctionPrototype(
1642 masm(), Context::STRING_FUNCTION_INDEX, eax, miss);
1643 break;
1644 }
1645 case SYMBOL_CHECK: {
1646 // Check that the object is a symbol.
1647 __ CmpObjectType(reg, SYMBOL_TYPE, eax);
1648 __ j(not_equal, miss);
1649 // Check that the maps starting from the prototype haven't changed.
1650 GenerateDirectLoadGlobalFunctionPrototype(
1651 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss);
1652 break;
1653 }
1654 case NUMBER_CHECK: {
1655 Label fast;
1656 // Check that the object is a smi or a heap number.
1657 __ JumpIfSmi(reg, &fast);
1658 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax);
1659 __ j(not_equal, miss);
1660 __ bind(&fast);
1661 // Check that the maps starting from the prototype haven't changed.
1662 GenerateDirectLoadGlobalFunctionPrototype(
1663 masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss);
1664 break;
1665 }
1666 case BOOLEAN_CHECK: {
1667 GenerateBooleanCheck(reg, miss);
1668 // Check that the maps starting from the prototype haven't changed.
1669 GenerateDirectLoadGlobalFunctionPrototype(
1670 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss);
1671 break;
1672 }
1673 }
1674
1675 if (check != RECEIVER_MAP_CHECK) {
1676 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
1677 reg = CheckPrototypes(
1678 IC::CurrentTypeOf(prototype, isolate()),
1679 eax, holder, ebx, edx, edi, name, miss);
1680 }
1681
1682 return reg;
1683 }
1684
1685
1686 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1687 Register function,
1688 Label* miss) {
1689 // Check that the function really is a function.
1690 GenerateFunctionCheck(function, ebx, miss);
1691
1692 if (!function.is(edi)) __ mov(edi, function);
1693 PatchImplicitReceiver(object);
1694
1695 // Invoke the function.
1696 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, NullCallWrapper());
1697 }
1698
1699
1700 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
1701 Handle<JSObject> holder,
1702 Handle<Name> name) {
1703 Label miss;
1704
1705 GenerateNameCheck(name, &miss);
1706
1707 // Get the number of arguments.
1708 const int argc = arguments().immediate();
1709
1710 LookupResult lookup(isolate());
1711 LookupPostInterceptor(holder, name, &lookup);
1712
1713 // Get the receiver from the stack.
1714 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1715
1716 CallInterceptorCompiler compiler(this, arguments(), ecx);
1717 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
1718 &miss);
1719
1720 // Restore receiver.
1721 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1722
1723 GenerateJumpFunction(object, eax, &miss);
1724
1725 HandlerFrontendFooter(&miss);
1726
1727 // Return the generated code.
1728 return GetCode(Code::FAST, name);
1729 }
1730
1731
1732 Handle<Code> CallStubCompiler::CompileCallGlobal(
1733 Handle<JSObject> object,
1734 Handle<GlobalObject> holder,
1735 Handle<PropertyCell> cell,
1736 Handle<JSFunction> function,
1737 Handle<Name> name) {
1738 if (HasCustomCallGenerator(function)) {
1739 Handle<Code> code = CompileCustomCall(
1740 object, holder, cell, function, Handle<String>::cast(name),
1741 Code::NORMAL);
1742 // A null handle means bail out to the regular compiler code below.
1743 if (!code.is_null()) return code;
1744 }
1745
1746 Label miss;
1747 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1748 // Potentially loads a closure that matches the shared function info of the
1749 // function, rather than function.
1750 GenerateLoadFunctionFromCell(cell, function, &miss);
1751 GenerateJumpFunction(object, edi, function);
1752
1753 HandlerFrontendFooter(&miss);
1754
1755 // Return the generated code.
1756 return GetCode(Code::NORMAL, name);
1757 }
1758
1759
1760 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1238 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1761 Handle<JSObject> object, 1239 Handle<JSObject> object,
1762 Handle<JSObject> holder, 1240 Handle<JSObject> holder,
1763 Handle<Name> name, 1241 Handle<Name> name,
1764 Handle<ExecutableAccessorInfo> callback) { 1242 Handle<ExecutableAccessorInfo> callback) {
1765 Register holder_reg = HandlerFrontend( 1243 Register holder_reg = HandlerFrontend(
1766 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1244 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1767 1245
1768 __ pop(scratch1()); // remove the return address 1246 __ pop(scratch1()); // remove the return address
1769 __ push(receiver()); 1247 __ push(receiver());
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1991 1469
1992 // Check for deleted property if property can actually be deleted. 1470 // Check for deleted property if property can actually be deleted.
1993 if (!is_dont_delete) { 1471 if (!is_dont_delete) {
1994 __ cmp(eax, factory()->the_hole_value()); 1472 __ cmp(eax, factory()->the_hole_value());
1995 __ j(equal, &miss); 1473 __ j(equal, &miss);
1996 } else if (FLAG_debug_code) { 1474 } else if (FLAG_debug_code) {
1997 __ cmp(eax, factory()->the_hole_value()); 1475 __ cmp(eax, factory()->the_hole_value());
1998 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 1476 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
1999 } 1477 }
2000 1478
2001 HandlerFrontendFooter(name, &miss);
2002
2003 Counters* counters = isolate()->counters(); 1479 Counters* counters = isolate()->counters();
2004 __ IncrementCounter(counters->named_load_global_stub(), 1); 1480 __ IncrementCounter(counters->named_load_global_stub(), 1);
2005 // The code above already loads the result into the return register. 1481 // The code above already loads the result into the return register.
2006 __ ret(0); 1482 __ ret(0);
2007 1483
1484 HandlerFrontendFooter(name, &miss);
1485
2008 // Return the generated code. 1486 // Return the generated code.
2009 return GetCode(kind(), Code::NORMAL, name); 1487 return GetCode(kind(), Code::NORMAL, name);
2010 } 1488 }
2011 1489
2012 1490
2013 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1491 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2014 TypeHandleList* types, 1492 TypeHandleList* types,
2015 CodeHandleList* handlers, 1493 CodeHandleList* handlers,
2016 Handle<Name> name, 1494 Handle<Name> name,
2017 Code::StubType type, 1495 Code::StubType type,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 // ----------------------------------- 1581 // -----------------------------------
2104 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1582 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2105 } 1583 }
2106 1584
2107 1585
2108 #undef __ 1586 #undef __
2109 1587
2110 } } // namespace v8::internal 1588 } } // namespace v8::internal
2111 1589
2112 #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