| 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 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 __ JumpIfRoot(temp, Heap::kNativeContextMapRootIndex, &fast); | 1386 __ JumpIfRoot(temp, Heap::kNativeContextMapRootIndex, &fast); |
| 1387 // Check that extension is NULL. | 1387 // Check that extension is NULL. |
| 1388 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); | 1388 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); |
| 1389 __ Cbnz(temp, slow); | 1389 __ Cbnz(temp, slow); |
| 1390 // Load next context in chain. | 1390 // Load next context in chain. |
| 1391 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); | 1391 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); |
| 1392 __ B(&loop); | 1392 __ B(&loop); |
| 1393 __ Bind(&fast); | 1393 __ Bind(&fast); |
| 1394 } | 1394 } |
| 1395 | 1395 |
| 1396 __ Ldr(x0, GlobalObjectMemOperand()); | 1396 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); |
| 1397 __ Mov(x2, Operand(var->name())); | 1397 __ Mov(LoadIC::NameRegister(), Operand(var->name())); |
| 1398 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL | 1398 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL |
| 1399 : CONTEXTUAL; | 1399 : CONTEXTUAL; |
| 1400 CallLoadIC(mode); | 1400 CallLoadIC(mode); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 | 1403 |
| 1404 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1404 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1405 Label* slow) { | 1405 Label* slow) { |
| 1406 ASSERT(var->IsContextSlot()); | 1406 ASSERT(var->IsContextSlot()); |
| 1407 Register context = cp; | 1407 Register context = cp; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1465 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
| 1466 // Record position before possible IC call. | 1466 // Record position before possible IC call. |
| 1467 SetSourcePosition(proxy->position()); | 1467 SetSourcePosition(proxy->position()); |
| 1468 Variable* var = proxy->var(); | 1468 Variable* var = proxy->var(); |
| 1469 | 1469 |
| 1470 // Three cases: global variables, lookup variables, and all other types of | 1470 // Three cases: global variables, lookup variables, and all other types of |
| 1471 // variables. | 1471 // variables. |
| 1472 switch (var->location()) { | 1472 switch (var->location()) { |
| 1473 case Variable::UNALLOCATED: { | 1473 case Variable::UNALLOCATED: { |
| 1474 Comment cmnt(masm_, "Global variable"); | 1474 Comment cmnt(masm_, "Global variable"); |
| 1475 // Use inline caching. Variable name is passed in x2 and the global | 1475 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); |
| 1476 // object (receiver) in x0. | 1476 __ Mov(LoadIC::NameRegister(), Operand(var->name())); |
| 1477 __ Ldr(x0, GlobalObjectMemOperand()); | |
| 1478 __ Mov(x2, Operand(var->name())); | |
| 1479 CallLoadIC(CONTEXTUAL); | 1477 CallLoadIC(CONTEXTUAL); |
| 1480 context()->Plug(x0); | 1478 context()->Plug(x0); |
| 1481 break; | 1479 break; |
| 1482 } | 1480 } |
| 1483 | 1481 |
| 1484 case Variable::PARAMETER: | 1482 case Variable::PARAMETER: |
| 1485 case Variable::LOCAL: | 1483 case Variable::LOCAL: |
| 1486 case Variable::CONTEXT: { | 1484 case Variable::CONTEXT: { |
| 1487 Comment cmnt(masm_, var->IsContextSlot() | 1485 Comment cmnt(masm_, var->IsContextSlot() |
| 1488 ? "Context variable" | 1486 ? "Context variable" |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1942 case KEYED_PROPERTY: | 1940 case KEYED_PROPERTY: |
| 1943 EmitKeyedPropertyAssignment(expr); | 1941 EmitKeyedPropertyAssignment(expr); |
| 1944 break; | 1942 break; |
| 1945 } | 1943 } |
| 1946 } | 1944 } |
| 1947 | 1945 |
| 1948 | 1946 |
| 1949 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1947 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1950 SetSourcePosition(prop->position()); | 1948 SetSourcePosition(prop->position()); |
| 1951 Literal* key = prop->key()->AsLiteral(); | 1949 Literal* key = prop->key()->AsLiteral(); |
| 1952 __ Mov(x2, Operand(key->value())); | 1950 __ Mov(LoadIC::NameRegister(), Operand(key->value())); |
| 1953 // Call load IC. It has arguments receiver and property name x0 and x2. | 1951 // Call load IC. It has arguments receiver and property name x0 and x2. |
| 1954 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 1952 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 1955 } | 1953 } |
| 1956 | 1954 |
| 1957 | 1955 |
| 1958 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1956 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1959 SetSourcePosition(prop->position()); | 1957 SetSourcePosition(prop->position()); |
| 1960 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1958 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 1961 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1959 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 1962 CallIC(ic, prop->PropertyFeedbackId()); | 1960 CallIC(ic, prop->PropertyFeedbackId()); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2255 context()->Plug(x0); | 2253 context()->Plug(x0); |
| 2256 } | 2254 } |
| 2257 | 2255 |
| 2258 | 2256 |
| 2259 void FullCodeGenerator::VisitProperty(Property* expr) { | 2257 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2260 Comment cmnt(masm_, "[ Property"); | 2258 Comment cmnt(masm_, "[ Property"); |
| 2261 Expression* key = expr->key(); | 2259 Expression* key = expr->key(); |
| 2262 | 2260 |
| 2263 if (key->IsPropertyName()) { | 2261 if (key->IsPropertyName()) { |
| 2264 VisitForAccumulatorValue(expr->obj()); | 2262 VisitForAccumulatorValue(expr->obj()); |
| 2263 ASSERT(x0.is(LoadIC::ReceiverRegister())); |
| 2265 EmitNamedPropertyLoad(expr); | 2264 EmitNamedPropertyLoad(expr); |
| 2266 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2265 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2267 context()->Plug(x0); | 2266 context()->Plug(x0); |
| 2268 } else { | 2267 } else { |
| 2269 VisitForStackValue(expr->obj()); | 2268 VisitForStackValue(expr->obj()); |
| 2270 VisitForAccumulatorValue(expr->key()); | 2269 VisitForAccumulatorValue(expr->key()); |
| 2271 __ Pop(x1); | 2270 ASSERT(x0.is(KeyedLoadIC::NameRegister())); |
| 2271 __ Pop(KeyedLoadIC::ReceiverRegister()); |
| 2272 EmitKeyedPropertyLoad(expr); | 2272 EmitKeyedPropertyLoad(expr); |
| 2273 context()->Plug(x0); | 2273 context()->Plug(x0); |
| 2274 } | 2274 } |
| 2275 } | 2275 } |
| 2276 | 2276 |
| 2277 | 2277 |
| 2278 void FullCodeGenerator::CallIC(Handle<Code> code, | 2278 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2279 TypeFeedbackId ast_id) { | 2279 TypeFeedbackId ast_id) { |
| 2280 ic_total_count_++; | 2280 ic_total_count_++; |
| 2281 // All calls must have a predictable size in full-codegen code to ensure that | 2281 // All calls must have a predictable size in full-codegen code to ensure that |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2297 { StackValueContext context(this); | 2297 { StackValueContext context(this); |
| 2298 EmitVariableLoad(callee->AsVariableProxy()); | 2298 EmitVariableLoad(callee->AsVariableProxy()); |
| 2299 PrepareForBailout(callee, NO_REGISTERS); | 2299 PrepareForBailout(callee, NO_REGISTERS); |
| 2300 } | 2300 } |
| 2301 // Push undefined as receiver. This is patched in the method prologue if it | 2301 // Push undefined as receiver. This is patched in the method prologue if it |
| 2302 // is a sloppy mode method. | 2302 // is a sloppy mode method. |
| 2303 __ Push(isolate()->factory()->undefined_value()); | 2303 __ Push(isolate()->factory()->undefined_value()); |
| 2304 } else { | 2304 } else { |
| 2305 // Load the function from the receiver. | 2305 // Load the function from the receiver. |
| 2306 ASSERT(callee->IsProperty()); | 2306 ASSERT(callee->IsProperty()); |
| 2307 __ Peek(x0, 0); | 2307 __ Peek(LoadIC::ReceiverRegister(), 0); |
| 2308 EmitNamedPropertyLoad(callee->AsProperty()); | 2308 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2309 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2309 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2310 // Push the target function under the receiver. | 2310 // Push the target function under the receiver. |
| 2311 __ Pop(x10); | 2311 __ Pop(x10); |
| 2312 __ Push(x0, x10); | 2312 __ Push(x0, x10); |
| 2313 } | 2313 } |
| 2314 | 2314 |
| 2315 EmitCall(expr, call_type); | 2315 EmitCall(expr, call_type); |
| 2316 } | 2316 } |
| 2317 | 2317 |
| 2318 | 2318 |
| 2319 // Code common for calls using the IC. | 2319 // Code common for calls using the IC. |
| 2320 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2320 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
| 2321 Expression* key) { | 2321 Expression* key) { |
| 2322 // Load the key. | 2322 // Load the key. |
| 2323 VisitForAccumulatorValue(key); | 2323 VisitForAccumulatorValue(key); |
| 2324 ASSERT(x0.is(KeyedLoadIC::NameRegister())); |
| 2324 | 2325 |
| 2325 Expression* callee = expr->expression(); | 2326 Expression* callee = expr->expression(); |
| 2326 | 2327 |
| 2327 // Load the function from the receiver. | 2328 // Load the function from the receiver. |
| 2328 ASSERT(callee->IsProperty()); | 2329 ASSERT(callee->IsProperty()); |
| 2329 __ Peek(x1, 0); | 2330 __ Peek(KeyedLoadIC::ReceiverRegister(), 0); |
| 2330 EmitKeyedPropertyLoad(callee->AsProperty()); | 2331 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2331 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2332 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2332 | 2333 |
| 2333 // Push the target function under the receiver. | 2334 // Push the target function under the receiver. |
| 2334 __ Pop(x10); | 2335 __ Pop(x10); |
| 2335 __ Push(x0, x10); | 2336 __ Push(x0, x10); |
| 2336 | 2337 |
| 2337 EmitCall(expr, CallIC::METHOD); | 2338 EmitCall(expr, CallIC::METHOD); |
| 2338 } | 2339 } |
| 2339 | 2340 |
| (...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3739 return; | 3740 return; |
| 3740 } | 3741 } |
| 3741 | 3742 |
| 3742 Comment cmnt(masm_, "[ CallRunTime"); | 3743 Comment cmnt(masm_, "[ CallRunTime"); |
| 3743 ZoneList<Expression*>* args = expr->arguments(); | 3744 ZoneList<Expression*>* args = expr->arguments(); |
| 3744 int arg_count = args->length(); | 3745 int arg_count = args->length(); |
| 3745 | 3746 |
| 3746 if (expr->is_jsruntime()) { | 3747 if (expr->is_jsruntime()) { |
| 3747 // Push the builtins object as the receiver. | 3748 // Push the builtins object as the receiver. |
| 3748 __ Ldr(x10, GlobalObjectMemOperand()); | 3749 __ Ldr(x10, GlobalObjectMemOperand()); |
| 3749 __ Ldr(x0, FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); | 3750 __ Ldr(LoadIC::ReceiverRegister(), |
| 3750 __ Push(x0); | 3751 FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); |
| 3752 __ Push(LoadIC::ReceiverRegister()); |
| 3751 | 3753 |
| 3752 // Load the function from the receiver. | 3754 // Load the function from the receiver. |
| 3753 Handle<String> name = expr->name(); | 3755 Handle<String> name = expr->name(); |
| 3754 __ Mov(x2, Operand(name)); | 3756 __ Mov(LoadIC::NameRegister(), Operand(name)); |
| 3755 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 3757 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
| 3756 | 3758 |
| 3757 // Push the target function under the receiver. | 3759 // Push the target function under the receiver. |
| 3758 __ Pop(x10); | 3760 __ Pop(x10); |
| 3759 __ Push(x0, x10); | 3761 __ Push(x0, x10); |
| 3760 | 3762 |
| 3761 int arg_count = args->length(); | 3763 int arg_count = args->length(); |
| 3762 for (int i = 0; i < arg_count; i++) { | 3764 for (int i = 0; i < arg_count; i++) { |
| 3763 VisitForStackValue(args->at(i)); | 3765 VisitForStackValue(args->at(i)); |
| 3764 } | 3766 } |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3920 AccumulatorValueContext context(this); | 3922 AccumulatorValueContext context(this); |
| 3921 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 3923 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
| 3922 } else { | 3924 } else { |
| 3923 // Reserve space for result of postfix operation. | 3925 // Reserve space for result of postfix operation. |
| 3924 if (expr->is_postfix() && !context()->IsEffect()) { | 3926 if (expr->is_postfix() && !context()->IsEffect()) { |
| 3925 __ Push(xzr); | 3927 __ Push(xzr); |
| 3926 } | 3928 } |
| 3927 if (assign_type == NAMED_PROPERTY) { | 3929 if (assign_type == NAMED_PROPERTY) { |
| 3928 // Put the object both on the stack and in the accumulator. | 3930 // Put the object both on the stack and in the accumulator. |
| 3929 VisitForAccumulatorValue(prop->obj()); | 3931 VisitForAccumulatorValue(prop->obj()); |
| 3930 __ Push(x0); | 3932 ASSERT(x0.is(LoadIC::ReceiverRegister())); |
| 3933 __ Push(LoadIC::ReceiverRegister()); |
| 3931 EmitNamedPropertyLoad(prop); | 3934 EmitNamedPropertyLoad(prop); |
| 3932 } else { | 3935 } else { |
| 3933 // KEYED_PROPERTY | 3936 // KEYED_PROPERTY |
| 3934 VisitForStackValue(prop->obj()); | 3937 VisitForStackValue(prop->obj()); |
| 3935 VisitForAccumulatorValue(prop->key()); | 3938 VisitForAccumulatorValue(prop->key()); |
| 3936 __ Peek(x1, 0); | 3939 ASSERT(x0.is(KeyedLoadIC::NameRegister())); |
| 3937 __ Push(x0); | 3940 __ Peek(KeyedLoadIC::ReceiverRegister(), 0); |
| 3941 __ Push(KeyedLoadIC::NameRegister()); |
| 3938 EmitKeyedPropertyLoad(prop); | 3942 EmitKeyedPropertyLoad(prop); |
| 3939 } | 3943 } |
| 3940 } | 3944 } |
| 3941 | 3945 |
| 3942 // We need a second deoptimization point after loading the value | 3946 // We need a second deoptimization point after loading the value |
| 3943 // in case evaluating the property load my have a side effect. | 3947 // in case evaluating the property load my have a side effect. |
| 3944 if (assign_type == VARIABLE) { | 3948 if (assign_type == VARIABLE) { |
| 3945 PrepareForBailout(expr->expression(), TOS_REG); | 3949 PrepareForBailout(expr->expression(), TOS_REG); |
| 3946 } else { | 3950 } else { |
| 3947 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 3951 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4077 } | 4081 } |
| 4078 } | 4082 } |
| 4079 | 4083 |
| 4080 | 4084 |
| 4081 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4085 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4082 ASSERT(!context()->IsEffect()); | 4086 ASSERT(!context()->IsEffect()); |
| 4083 ASSERT(!context()->IsTest()); | 4087 ASSERT(!context()->IsTest()); |
| 4084 VariableProxy* proxy = expr->AsVariableProxy(); | 4088 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4085 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4089 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4086 Comment cmnt(masm_, "Global variable"); | 4090 Comment cmnt(masm_, "Global variable"); |
| 4087 __ Ldr(x0, GlobalObjectMemOperand()); | 4091 __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand()); |
| 4088 __ Mov(x2, Operand(proxy->name())); | 4092 __ Mov(LoadIC::NameRegister(), Operand(proxy->name())); |
| 4089 // Use a regular load, not a contextual load, to avoid a reference | 4093 // Use a regular load, not a contextual load, to avoid a reference |
| 4090 // error. | 4094 // error. |
| 4091 CallLoadIC(NOT_CONTEXTUAL); | 4095 CallLoadIC(NOT_CONTEXTUAL); |
| 4092 PrepareForBailout(expr, TOS_REG); | 4096 PrepareForBailout(expr, TOS_REG); |
| 4093 context()->Plug(x0); | 4097 context()->Plug(x0); |
| 4094 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4098 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4095 Label done, slow; | 4099 Label done, slow; |
| 4096 | 4100 |
| 4097 // Generate code for loading from variables potentially shadowed | 4101 // Generate code for loading from variables potentially shadowed |
| 4098 // by eval-introduced variables. | 4102 // by eval-introduced variables. |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4426 kLRHasBeenSaved, kDontSaveFPRegs); | 4430 kLRHasBeenSaved, kDontSaveFPRegs); |
| 4427 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 4431 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 4428 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4432 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4429 __ Pop(x0); // result | 4433 __ Pop(x0); // result |
| 4430 EmitReturnSequence(); | 4434 EmitReturnSequence(); |
| 4431 __ Bind(&l_resume); // received in x0 | 4435 __ Bind(&l_resume); // received in x0 |
| 4432 __ PopTryHandler(); | 4436 __ PopTryHandler(); |
| 4433 | 4437 |
| 4434 // receiver = iter; f = 'next'; arg = received; | 4438 // receiver = iter; f = 'next'; arg = received; |
| 4435 __ Bind(&l_next); | 4439 __ Bind(&l_next); |
| 4440 Register keyedload_receiver = KeyedLoadIC::ReceiverRegister(); |
| 4441 Register keyedload_name = KeyedLoadIC::NameRegister(); |
| 4442 ASSERT(keyedload_receiver.is(x1)); |
| 4443 ASSERT(keyedload_name.is(x0)); |
| 4444 |
| 4436 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" | 4445 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" |
| 4437 __ Peek(x3, 1 * kPointerSize); // iter | 4446 __ Peek(x3, 1 * kPointerSize); // iter |
| 4438 __ Push(x2, x3, x0); // "next", iter, received | 4447 __ Push(x2, x3, x0); // "next", iter, received |
| 4439 | 4448 |
| 4440 // result = receiver[f](arg); | 4449 // result = receiver[f](arg); |
| 4441 __ Bind(&l_call); | 4450 __ Bind(&l_call); |
| 4442 __ Peek(x1, 1 * kPointerSize); | 4451 __ Peek(keyedload_receiver, 1 * kPointerSize); |
| 4443 __ Peek(x0, 2 * kPointerSize); | 4452 __ Peek(keyedload_name, 2 * kPointerSize); |
| 4444 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 4453 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 4445 CallIC(ic, TypeFeedbackId::None()); | 4454 CallIC(ic, TypeFeedbackId::None()); |
| 4446 __ Mov(x1, x0); | 4455 __ Mov(x1, x0); |
| 4447 __ Poke(x1, 2 * kPointerSize); | 4456 __ Poke(x1, 2 * kPointerSize); |
| 4448 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 4457 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); |
| 4449 __ CallStub(&stub); | 4458 __ CallStub(&stub); |
| 4450 | 4459 |
| 4451 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4460 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4452 __ Drop(1); // The function is still on the stack; drop it. | 4461 __ Drop(1); // The function is still on the stack; drop it. |
| 4453 | 4462 |
| 4454 // if (!result.done) goto l_try; | 4463 // if (!result.done) goto l_try; |
| 4455 __ Bind(&l_loop); | 4464 __ Bind(&l_loop); |
| 4456 __ Push(x0); // save result | 4465 Register load_receiver = LoadIC::ReceiverRegister(); |
| 4457 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done" | 4466 Register load_name = LoadIC::NameRegister(); |
| 4458 CallLoadIC(NOT_CONTEXTUAL); // result.done in x0 | 4467 ASSERT(load_receiver.is(x0)); |
| 4468 ASSERT(load_name.is(x2)); |
| 4469 __ Push(load_receiver); // save result |
| 4470 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" |
| 4471 CallLoadIC(NOT_CONTEXTUAL); // x0=result.done |
| 4459 // The ToBooleanStub argument (result.done) is in x0. | 4472 // The ToBooleanStub argument (result.done) is in x0. |
| 4460 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 4473 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 4461 CallIC(bool_ic); | 4474 CallIC(bool_ic); |
| 4462 __ Cbz(x0, &l_try); | 4475 __ Cbz(x0, &l_try); |
| 4463 | 4476 |
| 4464 // result.value | 4477 // result.value |
| 4465 __ Pop(x0); // result | 4478 __ Pop(load_receiver); // result |
| 4466 __ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value" | 4479 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" |
| 4467 CallLoadIC(NOT_CONTEXTUAL); // result.value in x0 | 4480 CallLoadIC(NOT_CONTEXTUAL); // x0=result.value |
| 4468 context()->DropAndPlug(2, x0); // drop iter and g | 4481 context()->DropAndPlug(2, x0); // drop iter and g |
| 4469 break; | 4482 break; |
| 4470 } | 4483 } |
| 4471 } | 4484 } |
| 4472 } | 4485 } |
| 4473 | 4486 |
| 4474 | 4487 |
| 4475 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 4488 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 4476 Expression *value, | 4489 Expression *value, |
| 4477 JSGeneratorObject::ResumeMode resume_mode) { | 4490 JSGeneratorObject::ResumeMode resume_mode) { |
| 4478 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); | 4491 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4886 return previous_; | 4899 return previous_; |
| 4887 } | 4900 } |
| 4888 | 4901 |
| 4889 | 4902 |
| 4890 #undef __ | 4903 #undef __ |
| 4891 | 4904 |
| 4892 | 4905 |
| 4893 } } // namespace v8::internal | 4906 } } // namespace v8::internal |
| 4894 | 4907 |
| 4895 #endif // V8_TARGET_ARCH_ARM64 | 4908 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |