| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 2297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 ContextualMode mode, | 2308 ContextualMode mode, |
| 2309 TypeFeedbackId ast_id) { | 2309 TypeFeedbackId ast_id) { |
| 2310 ic_total_count_++; | 2310 ic_total_count_++; |
| 2311 // All calls must have a predictable size in full-codegen code to ensure that | 2311 // All calls must have a predictable size in full-codegen code to ensure that |
| 2312 // the debugger can patch them correctly. | 2312 // the debugger can patch them correctly. |
| 2313 ASSERT((mode != CONTEXTUAL) || ast_id.IsNone()); | 2313 ASSERT((mode != CONTEXTUAL) || ast_id.IsNone()); |
| 2314 __ Call(code, RelocInfo::CODE_TARGET, ast_id); | 2314 __ Call(code, RelocInfo::CODE_TARGET, ast_id); |
| 2315 } | 2315 } |
| 2316 | 2316 |
| 2317 | 2317 |
| 2318 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2318 // Code common for calls using the IC. |
| 2319 Handle<Object> name, | 2319 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
| 2320 ContextualMode mode) { | |
| 2321 ASM_LOCATION("EmitCallWithIC"); | 2320 ASM_LOCATION("EmitCallWithIC"); |
| 2322 // Code common for calls using the IC. | 2321 |
| 2322 Expression* callee = expr->expression(); |
| 2323 ZoneList<Expression*>* args = expr->arguments(); | 2323 ZoneList<Expression*>* args = expr->arguments(); |
| 2324 int arg_count = args->length(); | 2324 int arg_count = args->length(); |
| 2325 { PreservePositionScope scope(masm()->positions_recorder()); | 2325 |
| 2326 for (int i = 0; i < arg_count; i++) { | 2326 CallFunctionFlags flags; |
| 2327 VisitForStackValue(args->at(i)); | 2327 // Get the target function. |
| 2328 if (callee->IsVariableProxy()) { |
| 2329 { StackValueContext context(this); |
| 2330 EmitVariableLoad(callee->AsVariableProxy()); |
| 2331 PrepareForBailout(callee, NO_REGISTERS); |
| 2328 } | 2332 } |
| 2329 __ Mov(x2, Operand(name)); | 2333 // Push undefined as receiver. This is patched in the method prologue if it |
| 2334 // is a classic mode method. |
| 2335 __ Push(isolate()->factory()->undefined_value()); |
| 2336 flags = NO_CALL_FUNCTION_FLAGS; |
| 2337 } else { |
| 2338 // Load the function from the receiver. |
| 2339 ASSERT(callee->IsProperty()); |
| 2340 __ Peek(x0, 0); |
| 2341 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2342 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2343 // Push the target function under the receiver. |
| 2344 __ Pop(x10); |
| 2345 __ Push(x0, x10); |
| 2346 flags = CALL_AS_METHOD; |
| 2330 } | 2347 } |
| 2331 // Record source position for debugger. | |
| 2332 SetSourcePosition(expr->position()); | |
| 2333 // Call the IC initialization code. | |
| 2334 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | |
| 2335 TypeFeedbackId ast_id = mode == CONTEXTUAL | |
| 2336 ? TypeFeedbackId::None() | |
| 2337 : expr->CallFeedbackId(); | |
| 2338 CallIC(ic, mode, ast_id); | |
| 2339 RecordJSReturnSite(expr); | |
| 2340 // Restore context register. | |
| 2341 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2342 context()->Plug(x0); | |
| 2343 } | |
| 2344 | 2348 |
| 2345 | 2349 // Load the arguments. |
| 2346 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | |
| 2347 Expression* key) { | |
| 2348 // Load the key. | |
| 2349 VisitForAccumulatorValue(key); | |
| 2350 // Load the key. | |
| 2351 | |
| 2352 // Swap the name of the function and the receiver on the stack to follow | |
| 2353 // the calling convention for call ICs. | |
| 2354 __ Pop(x1); | |
| 2355 __ Push(x0, x1); | |
| 2356 | |
| 2357 // Code common for calls using the IC. | |
| 2358 ZoneList<Expression*>* args = expr->arguments(); | |
| 2359 int arg_count = args->length(); | |
| 2360 { PreservePositionScope scope(masm()->positions_recorder()); | 2350 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2361 for (int i = 0; i < arg_count; i++) { | 2351 for (int i = 0; i < arg_count; i++) { |
| 2362 VisitForStackValue(args->at(i)); | 2352 VisitForStackValue(args->at(i)); |
| 2363 } | 2353 } |
| 2364 } | 2354 } |
| 2355 |
| 2365 // Record source position for debugger. | 2356 // Record source position for debugger. |
| 2366 SetSourcePosition(expr->position()); | 2357 SetSourcePosition(expr->position()); |
| 2367 // Call the IC initialization code. | 2358 CallFunctionStub stub(arg_count, flags); |
| 2368 Handle<Code> ic = | 2359 __ Peek(x1, (arg_count + 1) * kPointerSize); |
| 2369 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2360 __ CallStub(&stub); |
| 2370 __ Peek(x2, (arg_count + 1) * kXRegSizeInBytes); // Key. | 2361 |
| 2371 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); | 2362 RecordJSReturnSite(expr); |
| 2363 |
| 2364 // Restore context register. |
| 2365 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2366 |
| 2367 context()->DropAndPlug(1, x0); |
| 2368 } |
| 2369 |
| 2370 |
| 2371 // Code common for calls using the IC. |
| 2372 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2373 Expression* key) { |
| 2374 // Load the key. |
| 2375 VisitForAccumulatorValue(key); |
| 2376 |
| 2377 Expression* callee = expr->expression(); |
| 2378 ZoneList<Expression*>* args = expr->arguments(); |
| 2379 int arg_count = args->length(); |
| 2380 |
| 2381 // Load the function from the receiver. |
| 2382 ASSERT(callee->IsProperty()); |
| 2383 __ Peek(x1, 0); |
| 2384 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2385 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2386 |
| 2387 // Push the target function under the receiver. |
| 2388 __ Pop(x10); |
| 2389 __ Push(x0, x10); |
| 2390 |
| 2391 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2392 for (int i = 0; i < arg_count; i++) { |
| 2393 VisitForStackValue(args->at(i)); |
| 2394 } |
| 2395 } |
| 2396 |
| 2397 // Record source position for debugger. |
| 2398 SetSourcePosition(expr->position()); |
| 2399 CallFunctionStub stub(arg_count, CALL_AS_METHOD); |
| 2400 __ Peek(x1, (arg_count + 1) * kPointerSize); |
| 2401 __ CallStub(&stub); |
| 2402 |
| 2372 RecordJSReturnSite(expr); | 2403 RecordJSReturnSite(expr); |
| 2373 // Restore context register. | 2404 // Restore context register. |
| 2374 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2405 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2375 context()->DropAndPlug(1, x0); // Drop the key still on the stack. | 2406 |
| 2407 context()->DropAndPlug(1, x0); |
| 2376 } | 2408 } |
| 2377 | 2409 |
| 2378 | 2410 |
| 2379 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2411 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 2380 // Code common for calls using the call stub. | 2412 // Code common for calls using the call stub. |
| 2381 ZoneList<Expression*>* args = expr->arguments(); | 2413 ZoneList<Expression*>* args = expr->arguments(); |
| 2382 int arg_count = args->length(); | 2414 int arg_count = args->length(); |
| 2383 { PreservePositionScope scope(masm()->positions_recorder()); | 2415 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2384 for (int i = 0; i < arg_count; i++) { | 2416 for (int i = 0; i < arg_count; i++) { |
| 2385 VisitForStackValue(args->at(i)); | 2417 VisitForStackValue(args->at(i)); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2483 // Call the evaluated function. | 2515 // Call the evaluated function. |
| 2484 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); | 2516 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 2485 __ Peek(x1, (arg_count + 1) * kXRegSizeInBytes); | 2517 __ Peek(x1, (arg_count + 1) * kXRegSizeInBytes); |
| 2486 __ CallStub(&stub); | 2518 __ CallStub(&stub); |
| 2487 RecordJSReturnSite(expr); | 2519 RecordJSReturnSite(expr); |
| 2488 // Restore context register. | 2520 // Restore context register. |
| 2489 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2521 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2490 context()->DropAndPlug(1, x0); | 2522 context()->DropAndPlug(1, x0); |
| 2491 | 2523 |
| 2492 } else if (call_type == Call::GLOBAL_CALL) { | 2524 } else if (call_type == Call::GLOBAL_CALL) { |
| 2493 // Push global object as receiver for the call IC. | 2525 EmitCallWithIC(expr); |
| 2494 __ Ldr(x10, GlobalObjectMemOperand()); | |
| 2495 __ Push(x10); | |
| 2496 VariableProxy* proxy = callee->AsVariableProxy(); | |
| 2497 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); | |
| 2498 | 2526 |
| 2499 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2527 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
| 2500 // Call to a lookup slot (dynamically introduced variable). | 2528 // Call to a lookup slot (dynamically introduced variable). |
| 2501 VariableProxy* proxy = callee->AsVariableProxy(); | 2529 VariableProxy* proxy = callee->AsVariableProxy(); |
| 2502 Label slow, done; | 2530 Label slow, done; |
| 2503 | 2531 |
| 2504 { PreservePositionScope scope(masm()->positions_recorder()); | 2532 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2505 // Generate code for loading from variables potentially shadowed | 2533 // Generate code for loading from variables potentially shadowed |
| 2506 // by eval-introduced variables. | 2534 // by eval-introduced variables. |
| 2507 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2535 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2534 | 2562 |
| 2535 // The receiver is either the global receiver or an object found | 2563 // The receiver is either the global receiver or an object found |
| 2536 // by LoadContextSlot. | 2564 // by LoadContextSlot. |
| 2537 EmitCallWithStub(expr); | 2565 EmitCallWithStub(expr); |
| 2538 } else if (call_type == Call::PROPERTY_CALL) { | 2566 } else if (call_type == Call::PROPERTY_CALL) { |
| 2539 Property* property = callee->AsProperty(); | 2567 Property* property = callee->AsProperty(); |
| 2540 { PreservePositionScope scope(masm()->positions_recorder()); | 2568 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2541 VisitForStackValue(property->obj()); | 2569 VisitForStackValue(property->obj()); |
| 2542 } | 2570 } |
| 2543 if (property->key()->IsPropertyName()) { | 2571 if (property->key()->IsPropertyName()) { |
| 2544 EmitCallWithIC(expr, | 2572 EmitCallWithIC(expr); |
| 2545 property->key()->AsLiteral()->value(), | |
| 2546 NOT_CONTEXTUAL); | |
| 2547 } else { | 2573 } else { |
| 2548 EmitKeyedCallWithIC(expr, property->key()); | 2574 EmitKeyedCallWithIC(expr, property->key()); |
| 2549 } | 2575 } |
| 2550 | 2576 |
| 2551 } else { | 2577 } else { |
| 2552 ASSERT(call_type == Call::OTHER_CALL); | 2578 ASSERT(call_type == Call::OTHER_CALL); |
| 2553 // Call to an arbitrary expression not handled specially above. | 2579 // Call to an arbitrary expression not handled specially above. |
| 2554 { PreservePositionScope scope(masm()->positions_recorder()); | 2580 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2555 VisitForStackValue(callee); | 2581 VisitForStackValue(callee); |
| 2556 } | 2582 } |
| (...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3553 | 3579 |
| 3554 // Call runtime to perform the lookup. | 3580 // Call runtime to perform the lookup. |
| 3555 __ Push(cache, key); | 3581 __ Push(cache, key); |
| 3556 __ CallRuntime(Runtime::kGetFromCache, 2); | 3582 __ CallRuntime(Runtime::kGetFromCache, 2); |
| 3557 | 3583 |
| 3558 __ Bind(&done); | 3584 __ Bind(&done); |
| 3559 context()->Plug(x0); | 3585 context()->Plug(x0); |
| 3560 } | 3586 } |
| 3561 | 3587 |
| 3562 | 3588 |
| 3563 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { | |
| 3564 ASM_UNIMPLEMENTED("EmitIsRegExpEquivalent has not been tested"); | |
| 3565 | |
| 3566 ZoneList<Expression*>* args = expr->arguments(); | |
| 3567 ASSERT_EQ(2, args->length()); | |
| 3568 | |
| 3569 Register right = x2; | |
| 3570 Register left = x1; | |
| 3571 | |
| 3572 VisitForStackValue(args->at(0)); | |
| 3573 VisitForAccumulatorValue(args->at(1)); | |
| 3574 __ Pop(left); | |
| 3575 __ Mov(right, x0); | |
| 3576 | |
| 3577 // Speculatively set result to true. | |
| 3578 Register result = x0; | |
| 3579 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
| 3580 | |
| 3581 Label fail, ok; | |
| 3582 __ Cmp(left, right); | |
| 3583 __ B(eq, &ok); | |
| 3584 | |
| 3585 // Fail if either is a non-HeapObject. | |
| 3586 __ JumpIfEitherSmi(left, right, &fail); | |
| 3587 | |
| 3588 Register left_map = x10; | |
| 3589 __ Ldr(left_map, FieldMemOperand(left, HeapObject::kMapOffset)); | |
| 3590 __ Ldrb(x11, FieldMemOperand(left_map, Map::kInstanceTypeOffset)); | |
| 3591 __ Cmp(x11, JS_REGEXP_TYPE); | |
| 3592 __ B(ne, &fail); | |
| 3593 | |
| 3594 Register right_map = x11; | |
| 3595 __ Ldr(right_map, FieldMemOperand(right, HeapObject::kMapOffset)); | |
| 3596 __ Cmp(left_map, right_map); | |
| 3597 __ B(ne, &fail); | |
| 3598 | |
| 3599 __ Ldr(x10, FieldMemOperand(left, JSRegExp::kDataOffset)); | |
| 3600 __ Ldr(x11, FieldMemOperand(right, JSRegExp::kDataOffset)); | |
| 3601 __ Cmp(x10, x11); | |
| 3602 __ B(eq, &ok); | |
| 3603 | |
| 3604 __ Bind(&fail); | |
| 3605 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
| 3606 | |
| 3607 __ Bind(&ok); | |
| 3608 context()->Plug(result); | |
| 3609 } | |
| 3610 | |
| 3611 | |
| 3612 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3589 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3613 ZoneList<Expression*>* args = expr->arguments(); | 3590 ZoneList<Expression*>* args = expr->arguments(); |
| 3614 VisitForAccumulatorValue(args->at(0)); | 3591 VisitForAccumulatorValue(args->at(0)); |
| 3615 | 3592 |
| 3616 Label materialize_true, materialize_false; | 3593 Label materialize_true, materialize_false; |
| 3617 Label* if_true = NULL; | 3594 Label* if_true = NULL; |
| 3618 Label* if_false = NULL; | 3595 Label* if_false = NULL; |
| 3619 Label* fall_through = NULL; | 3596 Label* fall_through = NULL; |
| 3620 context()->PrepareTest(&materialize_true, &materialize_false, | 3597 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3621 &if_true, &if_false, &fall_through); | 3598 &if_true, &if_false, &fall_through); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3862 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 3839 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 3863 Handle<String> name = expr->name(); | 3840 Handle<String> name = expr->name(); |
| 3864 if (name->length() > 0 && name->Get(0) == '_') { | 3841 if (name->length() > 0 && name->Get(0) == '_') { |
| 3865 Comment cmnt(masm_, "[ InlineRuntimeCall"); | 3842 Comment cmnt(masm_, "[ InlineRuntimeCall"); |
| 3866 EmitInlineRuntimeCall(expr); | 3843 EmitInlineRuntimeCall(expr); |
| 3867 return; | 3844 return; |
| 3868 } | 3845 } |
| 3869 | 3846 |
| 3870 Comment cmnt(masm_, "[ CallRunTime"); | 3847 Comment cmnt(masm_, "[ CallRunTime"); |
| 3871 ZoneList<Expression*>* args = expr->arguments(); | 3848 ZoneList<Expression*>* args = expr->arguments(); |
| 3849 int arg_count = args->length(); |
| 3872 | 3850 |
| 3873 if (expr->is_jsruntime()) { | 3851 if (expr->is_jsruntime()) { |
| 3874 // Prepare for calling JS runtime function. | 3852 // Push the builtins object as the receiver. |
| 3875 __ Ldr(x10, GlobalObjectMemOperand()); | 3853 __ Ldr(x10, GlobalObjectMemOperand()); |
| 3876 __ Ldr(x11, FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); | 3854 __ Ldr(x0, FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); |
| 3877 __ Push(x11); | 3855 __ Push(x0); |
| 3878 } | |
| 3879 | 3856 |
| 3880 int arg_count = args->length(); | 3857 // Load the function from the receiver. |
| 3881 for (int i = 0; i < arg_count; i++) { | 3858 __ Mov(x2, Operand(name)); |
| 3882 VisitForStackValue(args->at(i)); | 3859 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
| 3883 } | |
| 3884 | 3860 |
| 3885 if (expr->is_jsruntime()) { | 3861 // Push the target function under the receiver. |
| 3886 // Call the JS runtime function. | 3862 __ Pop(x10); |
| 3887 __ Mov(x2, Operand(expr->name())); | 3863 __ Push(x0, x10); |
| 3888 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 3864 |
| 3889 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 3865 int arg_count = args->length(); |
| 3866 for (int i = 0; i < arg_count; i++) { |
| 3867 VisitForStackValue(args->at(i)); |
| 3868 } |
| 3869 |
| 3870 // Record source position of the IC call. |
| 3871 SetSourcePosition(expr->position()); |
| 3872 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 3873 __ Peek(x1, (arg_count + 1) * kPointerSize); |
| 3874 __ CallStub(&stub); |
| 3875 |
| 3890 // Restore context register. | 3876 // Restore context register. |
| 3891 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3877 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3878 |
| 3879 context()->DropAndPlug(1, x0); |
| 3892 } else { | 3880 } else { |
| 3881 // Push the arguments ("left-to-right"). |
| 3882 for (int i = 0; i < arg_count; i++) { |
| 3883 VisitForStackValue(args->at(i)); |
| 3884 } |
| 3885 |
| 3893 // Call the C runtime function. | 3886 // Call the C runtime function. |
| 3894 __ CallRuntime(expr->function(), arg_count); | 3887 __ CallRuntime(expr->function(), arg_count); |
| 3888 context()->Plug(x0); |
| 3895 } | 3889 } |
| 3896 | |
| 3897 context()->Plug(x0); | |
| 3898 } | 3890 } |
| 3899 | 3891 |
| 3900 | 3892 |
| 3901 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3893 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3902 switch (expr->op()) { | 3894 switch (expr->op()) { |
| 3903 case Token::DELETE: { | 3895 case Token::DELETE: { |
| 3904 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3896 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3905 Property* property = expr->expression()->AsProperty(); | 3897 Property* property = expr->expression()->AsProperty(); |
| 3906 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3898 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 3907 | 3899 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4258 Split(eq, if_true, if_false, fall_through); | 4250 Split(eq, if_true, if_false, fall_through); |
| 4259 } else if (check->Equals(isolate()->heap()->string_string())) { | 4251 } else if (check->Equals(isolate()->heap()->string_string())) { |
| 4260 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string"); | 4252 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string"); |
| 4261 __ JumpIfSmi(x0, if_false); | 4253 __ JumpIfSmi(x0, if_false); |
| 4262 // Check for undetectable objects => false. | 4254 // Check for undetectable objects => false. |
| 4263 __ JumpIfObjectType(x0, x0, x1, FIRST_NONSTRING_TYPE, if_false, ge); | 4255 __ JumpIfObjectType(x0, x0, x1, FIRST_NONSTRING_TYPE, if_false, ge); |
| 4264 __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); | 4256 __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); |
| 4265 __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_true, if_false, | 4257 __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_true, if_false, |
| 4266 fall_through); | 4258 fall_through); |
| 4267 } else if (check->Equals(isolate()->heap()->symbol_string())) { | 4259 } else if (check->Equals(isolate()->heap()->symbol_string())) { |
| 4260 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof symbol_string"); |
| 4268 __ JumpIfSmi(x0, if_false); | 4261 __ JumpIfSmi(x0, if_false); |
| 4269 __ CompareObjectType(x0, x0, x1, SYMBOL_TYPE); | 4262 __ CompareObjectType(x0, x0, x1, SYMBOL_TYPE); |
| 4270 Split(eq, if_true, if_false, fall_through); | 4263 Split(eq, if_true, if_false, fall_through); |
| 4271 } else if (check->Equals(isolate()->heap()->boolean_string())) { | 4264 } else if (check->Equals(isolate()->heap()->boolean_string())) { |
| 4272 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string"); | 4265 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string"); |
| 4273 __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true); | 4266 __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true); |
| 4274 __ CompareRoot(x0, Heap::kFalseValueRootIndex); | 4267 __ CompareRoot(x0, Heap::kFalseValueRootIndex); |
| 4275 Split(eq, if_true, if_false, fall_through); | 4268 Split(eq, if_true, if_false, fall_through); |
| 4276 } else if (FLAG_harmony_typeof && | 4269 } else if (FLAG_harmony_typeof && |
| 4277 check->Equals(isolate()->heap()->null_string())) { | 4270 check->Equals(isolate()->heap()->null_string())) { |
| 4271 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof null_string"); |
| 4278 __ CompareRoot(x0, Heap::kNullValueRootIndex); | 4272 __ CompareRoot(x0, Heap::kNullValueRootIndex); |
| 4279 Split(eq, if_true, if_false, fall_through); | 4273 Split(eq, if_true, if_false, fall_through); |
| 4280 } else if (check->Equals(isolate()->heap()->undefined_string())) { | 4274 } else if (check->Equals(isolate()->heap()->undefined_string())) { |
| 4281 ASM_LOCATION( | 4275 ASM_LOCATION( |
| 4282 "FullCodeGenerator::EmitLiteralCompareTypeof undefined_string"); | 4276 "FullCodeGenerator::EmitLiteralCompareTypeof undefined_string"); |
| 4283 __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, if_true); | 4277 __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, if_true); |
| 4284 __ JumpIfSmi(x0, if_false); | 4278 __ JumpIfSmi(x0, if_false); |
| 4285 // Check for undetectable objects => true. | 4279 // Check for undetectable objects => true. |
| 4286 __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); | 4280 __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); |
| 4287 __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); | 4281 __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4307 if_false, lt); | 4301 if_false, lt); |
| 4308 __ CompareInstanceType(map, x11, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4302 __ CompareInstanceType(map, x11, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4309 __ B(gt, if_false); | 4303 __ B(gt, if_false); |
| 4310 // Check for undetectable objects => false. | 4304 // Check for undetectable objects => false. |
| 4311 __ Ldrb(x10, FieldMemOperand(map, Map::kBitFieldOffset)); | 4305 __ Ldrb(x10, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 4312 | 4306 |
| 4313 __ TestAndSplit(x10, 1 << Map::kIsUndetectable, if_true, if_false, | 4307 __ TestAndSplit(x10, 1 << Map::kIsUndetectable, if_true, if_false, |
| 4314 fall_through); | 4308 fall_through); |
| 4315 | 4309 |
| 4316 } else { | 4310 } else { |
| 4311 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof other"); |
| 4317 if (if_false != fall_through) __ B(if_false); | 4312 if (if_false != fall_through) __ B(if_false); |
| 4318 } | 4313 } |
| 4319 context()->Plug(if_true, if_false); | 4314 context()->Plug(if_true, if_false); |
| 4320 } | 4315 } |
| 4321 | 4316 |
| 4322 | 4317 |
| 4323 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 4318 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 4324 Comment cmnt(masm_, "[ CompareOperation"); | 4319 Comment cmnt(masm_, "[ CompareOperation"); |
| 4325 SetSourcePosition(expr->position()); | 4320 SetSourcePosition(expr->position()); |
| 4326 | 4321 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4501 | 4496 |
| 4502 Label l_catch, l_try, l_suspend, l_continuation, l_resume; | 4497 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
| 4503 Label l_next, l_call, l_loop; | 4498 Label l_next, l_call, l_loop; |
| 4504 // Initial send value is undefined. | 4499 // Initial send value is undefined. |
| 4505 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 4500 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 4506 __ B(&l_next); | 4501 __ B(&l_next); |
| 4507 | 4502 |
| 4508 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 4503 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
| 4509 __ Bind(&l_catch); | 4504 __ Bind(&l_catch); |
| 4510 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 4505 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| 4511 __ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw" | 4506 __ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw" |
| 4512 __ Peek(x3, 1 * kPointerSize); // iter | 4507 __ Peek(x3, 1 * kPointerSize); // iter |
| 4513 __ Push(x3); // iter | 4508 __ Push(x2, x3, x0); // "throw", iter, except |
| 4514 __ Push(x0); // exception | |
| 4515 __ B(&l_call); | 4509 __ B(&l_call); |
| 4516 | 4510 |
| 4517 // try { received = %yield result } | 4511 // try { received = %yield result } |
| 4518 // Shuffle the received result above a try handler and yield it without | 4512 // Shuffle the received result above a try handler and yield it without |
| 4519 // re-boxing. | 4513 // re-boxing. |
| 4520 __ Bind(&l_try); | 4514 __ Bind(&l_try); |
| 4521 __ Pop(x0); // result | 4515 __ Pop(x0); // result |
| 4522 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 4516 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 4523 const int handler_size = StackHandlerConstants::kSize; | 4517 const int handler_size = StackHandlerConstants::kSize; |
| 4524 __ Push(x0); // result | 4518 __ Push(x0); // result |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4543 kLRHasBeenSaved, kDontSaveFPRegs); | 4537 kLRHasBeenSaved, kDontSaveFPRegs); |
| 4544 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 4538 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 4545 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4539 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4546 __ Pop(x0); // result | 4540 __ Pop(x0); // result |
| 4547 EmitReturnSequence(); | 4541 EmitReturnSequence(); |
| 4548 __ Bind(&l_resume); // received in x0 | 4542 __ Bind(&l_resume); // received in x0 |
| 4549 __ PopTryHandler(); | 4543 __ PopTryHandler(); |
| 4550 | 4544 |
| 4551 // receiver = iter; f = 'next'; arg = received; | 4545 // receiver = iter; f = 'next'; arg = received; |
| 4552 __ Bind(&l_next); | 4546 __ Bind(&l_next); |
| 4553 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" | 4547 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" |
| 4554 __ Peek(x3, 1 * kPointerSize); // iter | 4548 __ Peek(x3, 1 * kPointerSize); // iter |
| 4555 __ Push(x3); // iter | 4549 __ Push(x2, x3, x0); // "next", iter, received |
| 4556 __ Push(x0); // received | |
| 4557 | 4550 |
| 4558 // result = receiver[f](arg); | 4551 // result = receiver[f](arg); |
| 4559 __ Bind(&l_call); | 4552 __ Bind(&l_call); |
| 4560 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 4553 __ Peek(x1, 1 * kPointerSize); |
| 4561 CallIC(ic); | 4554 __ Peek(x0, 2 * kPointerSize); |
| 4555 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 4556 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); |
| 4557 __ Mov(x1, x0); |
| 4558 __ Poke(x1, 2 * kPointerSize); |
| 4559 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 4560 __ CallStub(&stub); |
| 4561 |
| 4562 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4562 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4563 __ Drop(1); // The function is still on the stack; drop it. |
| 4563 | 4564 |
| 4564 // if (!result.done) goto l_try; | 4565 // if (!result.done) goto l_try; |
| 4565 __ Bind(&l_loop); | 4566 __ Bind(&l_loop); |
| 4566 __ Push(x0); // save result | 4567 __ Push(x0); // save result |
| 4567 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done" | 4568 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done" |
| 4568 CallLoadIC(NOT_CONTEXTUAL); // result.done in x0 | 4569 CallLoadIC(NOT_CONTEXTUAL); // result.done in x0 |
| 4569 // The ToBooleanStub argument (result.done) is in x0. | 4570 // The ToBooleanStub argument (result.done) is in x0. |
| 4570 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 4571 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 4571 CallIC(bool_ic); | 4572 CallIC(bool_ic); |
| 4572 __ Cbz(x0, &l_try); | 4573 __ Cbz(x0, &l_try); |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5009 return previous_; | 5010 return previous_; |
| 5010 } | 5011 } |
| 5011 | 5012 |
| 5012 | 5013 |
| 5013 #undef __ | 5014 #undef __ |
| 5014 | 5015 |
| 5015 | 5016 |
| 5016 } } // namespace v8::internal | 5017 } } // namespace v8::internal |
| 5017 | 5018 |
| 5018 #endif // V8_TARGET_ARCH_A64 | 5019 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |