OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1344 context()->Plug(x0); | 1344 context()->Plug(x0); |
1345 } | 1345 } |
1346 | 1346 |
1347 | 1347 |
1348 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1348 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
1349 Comment cmnt(masm_, "[ VariableProxy"); | 1349 Comment cmnt(masm_, "[ VariableProxy"); |
1350 EmitVariableLoad(expr); | 1350 EmitVariableLoad(expr); |
1351 } | 1351 } |
1352 | 1352 |
1353 | 1353 |
1354 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1354 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, |
1355 TypeofState typeof_state, | 1355 TypeofState typeof_state, |
1356 Label* slow) { | 1356 Label* slow) { |
1357 Register current = cp; | 1357 Register current = cp; |
1358 Register next = x10; | 1358 Register next = x10; |
1359 Register temp = x11; | 1359 Register temp = x11; |
1360 | 1360 |
1361 Scope* s = scope(); | 1361 Scope* s = scope(); |
1362 while (s != NULL) { | 1362 while (s != NULL) { |
1363 if (s->num_heap_slots() > 0) { | 1363 if (s->num_heap_slots() > 0) { |
1364 if (s->calls_sloppy_eval()) { | 1364 if (s->calls_sloppy_eval()) { |
(...skipping 23 matching lines...) Expand all Loading... |
1388 // Check that extension is NULL. | 1388 // Check that extension is NULL. |
1389 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); | 1389 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); |
1390 __ Cbnz(temp, slow); | 1390 __ Cbnz(temp, slow); |
1391 // Load next context in chain. | 1391 // Load next context in chain. |
1392 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); | 1392 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); |
1393 __ B(&loop); | 1393 __ B(&loop); |
1394 __ Bind(&fast); | 1394 __ Bind(&fast); |
1395 } | 1395 } |
1396 | 1396 |
1397 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); | 1397 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); |
1398 __ Mov(LoadIC::NameRegister(), Operand(var->name())); | 1398 __ Mov(LoadIC::NameRegister(), Operand(proxy->var()->name())); |
| 1399 if (FLAG_vector_ics) { |
| 1400 __ Mov(LoadIC::SlotRegister(), |
| 1401 Smi::FromInt(proxy->VariableFeedbackSlot())); |
| 1402 } |
| 1403 |
1399 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL | 1404 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL |
1400 : CONTEXTUAL; | 1405 : CONTEXTUAL; |
1401 CallLoadIC(mode); | 1406 CallLoadIC(mode); |
1402 } | 1407 } |
1403 | 1408 |
1404 | 1409 |
1405 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1410 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1406 Label* slow) { | 1411 Label* slow) { |
1407 ASSERT(var->IsContextSlot()); | 1412 ASSERT(var->IsContextSlot()); |
1408 Register context = cp; | 1413 Register context = cp; |
(...skipping 16 matching lines...) Expand all Loading... |
1425 __ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | 1430 __ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); |
1426 __ Cbnz(temp, slow); | 1431 __ Cbnz(temp, slow); |
1427 | 1432 |
1428 // This function is used only for loads, not stores, so it's safe to | 1433 // This function is used only for loads, not stores, so it's safe to |
1429 // return an cp-based operand (the write barrier cannot be allowed to | 1434 // return an cp-based operand (the write barrier cannot be allowed to |
1430 // destroy the cp register). | 1435 // destroy the cp register). |
1431 return ContextMemOperand(context, var->index()); | 1436 return ContextMemOperand(context, var->index()); |
1432 } | 1437 } |
1433 | 1438 |
1434 | 1439 |
1435 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, | 1440 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, |
1436 TypeofState typeof_state, | 1441 TypeofState typeof_state, |
1437 Label* slow, | 1442 Label* slow, |
1438 Label* done) { | 1443 Label* done) { |
1439 // Generate fast-case code for variables that might be shadowed by | 1444 // Generate fast-case code for variables that might be shadowed by |
1440 // eval-introduced variables. Eval is used a lot without | 1445 // eval-introduced variables. Eval is used a lot without |
1441 // introducing variables. In those cases, we do not want to | 1446 // introducing variables. In those cases, we do not want to |
1442 // perform a runtime call for all variables in the scope | 1447 // perform a runtime call for all variables in the scope |
1443 // containing the eval. | 1448 // containing the eval. |
| 1449 Variable* var = proxy->var(); |
1444 if (var->mode() == DYNAMIC_GLOBAL) { | 1450 if (var->mode() == DYNAMIC_GLOBAL) { |
1445 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 1451 EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow); |
1446 __ B(done); | 1452 __ B(done); |
1447 } else if (var->mode() == DYNAMIC_LOCAL) { | 1453 } else if (var->mode() == DYNAMIC_LOCAL) { |
1448 Variable* local = var->local_if_not_shadowed(); | 1454 Variable* local = var->local_if_not_shadowed(); |
1449 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); | 1455 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); |
1450 if (local->mode() == LET || local->mode() == CONST || | 1456 if (local->mode() == LET || local->mode() == CONST || |
1451 local->mode() == CONST_LEGACY) { | 1457 local->mode() == CONST_LEGACY) { |
1452 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); | 1458 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); |
1453 if (local->mode() == CONST_LEGACY) { | 1459 if (local->mode() == CONST_LEGACY) { |
1454 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1460 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
1455 } else { // LET || CONST | 1461 } else { // LET || CONST |
(...skipping 12 matching lines...) Expand all Loading... |
1468 SetSourcePosition(proxy->position()); | 1474 SetSourcePosition(proxy->position()); |
1469 Variable* var = proxy->var(); | 1475 Variable* var = proxy->var(); |
1470 | 1476 |
1471 // Three cases: global variables, lookup variables, and all other types of | 1477 // Three cases: global variables, lookup variables, and all other types of |
1472 // variables. | 1478 // variables. |
1473 switch (var->location()) { | 1479 switch (var->location()) { |
1474 case Variable::UNALLOCATED: { | 1480 case Variable::UNALLOCATED: { |
1475 Comment cmnt(masm_, "Global variable"); | 1481 Comment cmnt(masm_, "Global variable"); |
1476 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); | 1482 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); |
1477 __ Mov(LoadIC::NameRegister(), Operand(var->name())); | 1483 __ Mov(LoadIC::NameRegister(), Operand(var->name())); |
| 1484 if (FLAG_vector_ics) { |
| 1485 __ Mov(LoadIC::SlotRegister(), |
| 1486 Smi::FromInt(proxy->VariableFeedbackSlot())); |
| 1487 } |
1478 CallLoadIC(CONTEXTUAL); | 1488 CallLoadIC(CONTEXTUAL); |
1479 context()->Plug(x0); | 1489 context()->Plug(x0); |
1480 break; | 1490 break; |
1481 } | 1491 } |
1482 | 1492 |
1483 case Variable::PARAMETER: | 1493 case Variable::PARAMETER: |
1484 case Variable::LOCAL: | 1494 case Variable::LOCAL: |
1485 case Variable::CONTEXT: { | 1495 case Variable::CONTEXT: { |
1486 Comment cmnt(masm_, var->IsContextSlot() | 1496 Comment cmnt(masm_, var->IsContextSlot() |
1487 ? "Context variable" | 1497 ? "Context variable" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1544 } | 1554 } |
1545 } | 1555 } |
1546 context()->Plug(var); | 1556 context()->Plug(var); |
1547 break; | 1557 break; |
1548 } | 1558 } |
1549 | 1559 |
1550 case Variable::LOOKUP: { | 1560 case Variable::LOOKUP: { |
1551 Label done, slow; | 1561 Label done, slow; |
1552 // Generate code for loading from variables potentially shadowed by | 1562 // Generate code for loading from variables potentially shadowed by |
1553 // eval-introduced variables. | 1563 // eval-introduced variables. |
1554 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); | 1564 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); |
1555 __ Bind(&slow); | 1565 __ Bind(&slow); |
1556 Comment cmnt(masm_, "Lookup variable"); | 1566 Comment cmnt(masm_, "Lookup variable"); |
1557 __ Mov(x1, Operand(var->name())); | 1567 __ Mov(x1, Operand(var->name())); |
1558 __ Push(cp, x1); // Context and name. | 1568 __ Push(cp, x1); // Context and name. |
1559 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1569 __ CallRuntime(Runtime::kLoadLookupSlot, 2); |
1560 __ Bind(&done); | 1570 __ Bind(&done); |
1561 context()->Plug(x0); | 1571 context()->Plug(x0); |
1562 break; | 1572 break; |
1563 } | 1573 } |
1564 } | 1574 } |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1943 EmitKeyedPropertyAssignment(expr); | 1953 EmitKeyedPropertyAssignment(expr); |
1944 break; | 1954 break; |
1945 } | 1955 } |
1946 } | 1956 } |
1947 | 1957 |
1948 | 1958 |
1949 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1959 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1950 SetSourcePosition(prop->position()); | 1960 SetSourcePosition(prop->position()); |
1951 Literal* key = prop->key()->AsLiteral(); | 1961 Literal* key = prop->key()->AsLiteral(); |
1952 __ Mov(LoadIC::NameRegister(), Operand(key->value())); | 1962 __ Mov(LoadIC::NameRegister(), Operand(key->value())); |
1953 // Call load IC. It has arguments receiver and property name x0 and x2. | 1963 if (FLAG_vector_ics) { |
1954 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 1964 __ Mov(LoadIC::SlotRegister(), |
| 1965 Smi::FromInt(prop->PropertyFeedbackSlot())); |
| 1966 CallLoadIC(NOT_CONTEXTUAL); |
| 1967 } else { |
| 1968 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 1969 } |
1955 } | 1970 } |
1956 | 1971 |
1957 | 1972 |
1958 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1973 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1959 SetSourcePosition(prop->position()); | 1974 SetSourcePosition(prop->position()); |
1960 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1975 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1961 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1976 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1962 CallIC(ic, prop->PropertyFeedbackId()); | 1977 if (FLAG_vector_ics) { |
| 1978 __ Mov(LoadIC::SlotRegister(), |
| 1979 Smi::FromInt(prop->PropertyFeedbackSlot())); |
| 1980 CallIC(ic); |
| 1981 } else { |
| 1982 CallIC(ic, prop->PropertyFeedbackId()); |
| 1983 } |
1963 } | 1984 } |
1964 | 1985 |
1965 | 1986 |
1966 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1987 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1967 Token::Value op, | 1988 Token::Value op, |
1968 OverwriteMode mode, | 1989 OverwriteMode mode, |
1969 Expression* left_expr, | 1990 Expression* left_expr, |
1970 Expression* right_expr) { | 1991 Expression* right_expr) { |
1971 Label done, both_smis, stub_call; | 1992 Label done, both_smis, stub_call; |
1972 | 1993 |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2445 EmitCallWithLoadIC(expr); | 2466 EmitCallWithLoadIC(expr); |
2446 | 2467 |
2447 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2468 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
2448 // Call to a lookup slot (dynamically introduced variable). | 2469 // Call to a lookup slot (dynamically introduced variable). |
2449 VariableProxy* proxy = callee->AsVariableProxy(); | 2470 VariableProxy* proxy = callee->AsVariableProxy(); |
2450 Label slow, done; | 2471 Label slow, done; |
2451 | 2472 |
2452 { PreservePositionScope scope(masm()->positions_recorder()); | 2473 { PreservePositionScope scope(masm()->positions_recorder()); |
2453 // Generate code for loading from variables potentially shadowed | 2474 // Generate code for loading from variables potentially shadowed |
2454 // by eval-introduced variables. | 2475 // by eval-introduced variables. |
2455 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2476 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); |
2456 } | 2477 } |
2457 | 2478 |
2458 __ Bind(&slow); | 2479 __ Bind(&slow); |
2459 // Call the runtime to find the function to call (returned in x0) | 2480 // Call the runtime to find the function to call (returned in x0) |
2460 // and the object holding it (returned in x1). | 2481 // and the object holding it (returned in x1). |
2461 __ Mov(x10, Operand(proxy->name())); | 2482 __ Mov(x10, Operand(proxy->name())); |
2462 __ Push(context_register(), x10); | 2483 __ Push(context_register(), x10); |
2463 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2484 __ CallRuntime(Runtime::kLoadLookupSlot, 2); |
2464 __ Push(x0, x1); // Receiver, function. | 2485 __ Push(x0, x1); // Receiver, function. |
2465 | 2486 |
(...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3738 if (expr->is_jsruntime()) { | 3759 if (expr->is_jsruntime()) { |
3739 // Push the builtins object as the receiver. | 3760 // Push the builtins object as the receiver. |
3740 __ Ldr(x10, GlobalObjectMemOperand()); | 3761 __ Ldr(x10, GlobalObjectMemOperand()); |
3741 __ Ldr(LoadIC::ReceiverRegister(), | 3762 __ Ldr(LoadIC::ReceiverRegister(), |
3742 FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); | 3763 FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); |
3743 __ Push(LoadIC::ReceiverRegister()); | 3764 __ Push(LoadIC::ReceiverRegister()); |
3744 | 3765 |
3745 // Load the function from the receiver. | 3766 // Load the function from the receiver. |
3746 Handle<String> name = expr->name(); | 3767 Handle<String> name = expr->name(); |
3747 __ Mov(LoadIC::NameRegister(), Operand(name)); | 3768 __ Mov(LoadIC::NameRegister(), Operand(name)); |
3748 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 3769 if (FLAG_vector_ics) { |
| 3770 __ Mov(LoadIC::SlotRegister(), |
| 3771 Smi::FromInt(expr->CallRuntimeFeedbackSlot())); |
| 3772 CallLoadIC(NOT_CONTEXTUAL); |
| 3773 } else { |
| 3774 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
| 3775 } |
3749 | 3776 |
3750 // Push the target function under the receiver. | 3777 // Push the target function under the receiver. |
3751 __ Pop(x10); | 3778 __ Pop(x10); |
3752 __ Push(x0, x10); | 3779 __ Push(x0, x10); |
3753 | 3780 |
3754 int arg_count = args->length(); | 3781 int arg_count = args->length(); |
3755 for (int i = 0; i < arg_count; i++) { | 3782 for (int i = 0; i < arg_count; i++) { |
3756 VisitForStackValue(args->at(i)); | 3783 VisitForStackValue(args->at(i)); |
3757 } | 3784 } |
3758 | 3785 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4073 | 4100 |
4074 | 4101 |
4075 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4102 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4076 ASSERT(!context()->IsEffect()); | 4103 ASSERT(!context()->IsEffect()); |
4077 ASSERT(!context()->IsTest()); | 4104 ASSERT(!context()->IsTest()); |
4078 VariableProxy* proxy = expr->AsVariableProxy(); | 4105 VariableProxy* proxy = expr->AsVariableProxy(); |
4079 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4106 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4080 Comment cmnt(masm_, "Global variable"); | 4107 Comment cmnt(masm_, "Global variable"); |
4081 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); | 4108 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); |
4082 __ Mov(LoadIC::NameRegister(), Operand(proxy->name())); | 4109 __ Mov(LoadIC::NameRegister(), Operand(proxy->name())); |
| 4110 if (FLAG_vector_ics) { |
| 4111 __ Mov(LoadIC::SlotRegister(), |
| 4112 Smi::FromInt(proxy->VariableFeedbackSlot())); |
| 4113 } |
4083 // Use a regular load, not a contextual load, to avoid a reference | 4114 // Use a regular load, not a contextual load, to avoid a reference |
4084 // error. | 4115 // error. |
4085 CallLoadIC(NOT_CONTEXTUAL); | 4116 CallLoadIC(NOT_CONTEXTUAL); |
4086 PrepareForBailout(expr, TOS_REG); | 4117 PrepareForBailout(expr, TOS_REG); |
4087 context()->Plug(x0); | 4118 context()->Plug(x0); |
4088 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4119 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
4089 Label done, slow; | 4120 Label done, slow; |
4090 | 4121 |
4091 // Generate code for loading from variables potentially shadowed | 4122 // Generate code for loading from variables potentially shadowed |
4092 // by eval-introduced variables. | 4123 // by eval-introduced variables. |
4093 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4124 EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); |
4094 | 4125 |
4095 __ Bind(&slow); | 4126 __ Bind(&slow); |
4096 __ Mov(x0, Operand(proxy->name())); | 4127 __ Mov(x0, Operand(proxy->name())); |
4097 __ Push(cp, x0); | 4128 __ Push(cp, x0); |
4098 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); | 4129 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); |
4099 PrepareForBailout(expr, TOS_REG); | 4130 PrepareForBailout(expr, TOS_REG); |
4100 __ Bind(&done); | 4131 __ Bind(&done); |
4101 | 4132 |
4102 context()->Plug(x0); | 4133 context()->Plug(x0); |
4103 } else { | 4134 } else { |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4425 __ Bind(&l_next); | 4456 __ Bind(&l_next); |
4426 | 4457 |
4427 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" | 4458 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" |
4428 __ Peek(x3, 1 * kPointerSize); // iter | 4459 __ Peek(x3, 1 * kPointerSize); // iter |
4429 __ Push(load_name, x3, x0); // "next", iter, received | 4460 __ Push(load_name, x3, x0); // "next", iter, received |
4430 | 4461 |
4431 // result = receiver[f](arg); | 4462 // result = receiver[f](arg); |
4432 __ Bind(&l_call); | 4463 __ Bind(&l_call); |
4433 __ Peek(load_receiver, 1 * kPointerSize); | 4464 __ Peek(load_receiver, 1 * kPointerSize); |
4434 __ Peek(load_name, 2 * kPointerSize); | 4465 __ Peek(load_name, 2 * kPointerSize); |
| 4466 if (FLAG_vector_ics) { |
| 4467 __ Mov(LoadIC::SlotRegister(), |
| 4468 Smi::FromInt(expr->KeyedLoadFeedbackSlot())); |
| 4469 } |
4435 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 4470 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
4436 CallIC(ic, TypeFeedbackId::None()); | 4471 CallIC(ic, TypeFeedbackId::None()); |
4437 __ Mov(x1, x0); | 4472 __ Mov(x1, x0); |
4438 __ Poke(x1, 2 * kPointerSize); | 4473 __ Poke(x1, 2 * kPointerSize); |
4439 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 4474 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); |
4440 __ CallStub(&stub); | 4475 __ CallStub(&stub); |
4441 | 4476 |
4442 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4477 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4443 __ Drop(1); // The function is still on the stack; drop it. | 4478 __ Drop(1); // The function is still on the stack; drop it. |
4444 | 4479 |
4445 // if (!result.done) goto l_try; | 4480 // if (!result.done) goto l_try; |
4446 __ Bind(&l_loop); | 4481 __ Bind(&l_loop); |
4447 __ Move(load_receiver, x0); | 4482 __ Move(load_receiver, x0); |
4448 | 4483 |
4449 __ Push(load_receiver); // save result | 4484 __ Push(load_receiver); // save result |
4450 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" | 4485 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" |
| 4486 if (FLAG_vector_ics) { |
| 4487 __ Mov(LoadIC::SlotRegister(), |
| 4488 Smi::FromInt(expr->DoneFeedbackSlot())); |
| 4489 } |
4451 CallLoadIC(NOT_CONTEXTUAL); // x0=result.done | 4490 CallLoadIC(NOT_CONTEXTUAL); // x0=result.done |
4452 // The ToBooleanStub argument (result.done) is in x0. | 4491 // The ToBooleanStub argument (result.done) is in x0. |
4453 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 4492 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
4454 CallIC(bool_ic); | 4493 CallIC(bool_ic); |
4455 __ Cbz(x0, &l_try); | 4494 __ Cbz(x0, &l_try); |
4456 | 4495 |
4457 // result.value | 4496 // result.value |
4458 __ Pop(load_receiver); // result | 4497 __ Pop(load_receiver); // result |
4459 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" | 4498 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" |
| 4499 if (FLAG_vector_ics) { |
| 4500 __ Mov(LoadIC::SlotRegister(), |
| 4501 Smi::FromInt(expr->ValueFeedbackSlot())); |
| 4502 } |
4460 CallLoadIC(NOT_CONTEXTUAL); // x0=result.value | 4503 CallLoadIC(NOT_CONTEXTUAL); // x0=result.value |
4461 context()->DropAndPlug(2, x0); // drop iter and g | 4504 context()->DropAndPlug(2, x0); // drop iter and g |
4462 break; | 4505 break; |
4463 } | 4506 } |
4464 } | 4507 } |
4465 } | 4508 } |
4466 | 4509 |
4467 | 4510 |
4468 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 4511 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
4469 Expression *value, | 4512 Expression *value, |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4879 return previous_; | 4922 return previous_; |
4880 } | 4923 } |
4881 | 4924 |
4882 | 4925 |
4883 #undef __ | 4926 #undef __ |
4884 | 4927 |
4885 | 4928 |
4886 } } // namespace v8::internal | 4929 } } // namespace v8::internal |
4887 | 4930 |
4888 #endif // V8_TARGET_ARCH_ARM64 | 4931 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |