Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 // the frame (that is done below). | 112 // the frame (that is done below). |
| 113 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 113 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
| 114 | 114 |
| 115 info->set_prologue_offset(masm_->pc_offset()); | 115 info->set_prologue_offset(masm_->pc_offset()); |
| 116 __ Prologue(info->GeneratePreagedPrologue()); | 116 __ Prologue(info->GeneratePreagedPrologue()); |
| 117 | 117 |
| 118 { Comment cmnt(masm_, "[ Allocate locals"); | 118 { Comment cmnt(masm_, "[ Allocate locals"); |
| 119 int locals_count = info->scope()->num_stack_slots(); | 119 int locals_count = info->scope()->num_stack_slots(); |
| 120 // Generators allocate locals, if any, in context slots. | 120 // Generators allocate locals, if any, in context slots. |
| 121 DCHECK(!IsGeneratorFunction(literal()->kind()) || locals_count == 0); | 121 DCHECK(!IsGeneratorFunction(literal()->kind()) || locals_count == 0); |
| 122 OperandStackDepthIncrement(locals_count); | |
| 122 if (locals_count == 1) { | 123 if (locals_count == 1) { |
| 123 __ push(Immediate(isolate()->factory()->undefined_value())); | 124 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 124 } else if (locals_count > 1) { | 125 } else if (locals_count > 1) { |
| 125 if (locals_count >= 128) { | 126 if (locals_count >= 128) { |
| 126 Label ok; | 127 Label ok; |
| 127 __ mov(ecx, esp); | 128 __ mov(ecx, esp); |
| 128 __ sub(ecx, Immediate(locals_count * kPointerSize)); | 129 __ sub(ecx, Immediate(locals_count * kPointerSize)); |
| 129 ExternalReference stack_limit = | 130 ExternalReference stack_limit = |
| 130 ExternalReference::address_of_real_stack_limit(isolate()); | 131 ExternalReference::address_of_real_stack_limit(isolate()); |
| 131 __ cmp(ecx, Operand::StaticVariable(stack_limit)); | 132 __ cmp(ecx, Operand::StaticVariable(stack_limit)); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 __ leave(); | 422 __ leave(); |
| 422 | 423 |
| 423 int arg_count = info_->scope()->num_parameters() + 1; | 424 int arg_count = info_->scope()->num_parameters() + 1; |
| 424 int arguments_bytes = arg_count * kPointerSize; | 425 int arguments_bytes = arg_count * kPointerSize; |
| 425 __ Ret(arguments_bytes, ecx); | 426 __ Ret(arguments_bytes, ecx); |
| 426 } | 427 } |
| 427 } | 428 } |
| 428 | 429 |
| 429 | 430 |
| 430 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 431 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
| 432 codegen()->OperandStackDepthIncrement(1); | |
| 431 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 433 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 432 MemOperand operand = codegen()->VarOperand(var, result_register()); | 434 MemOperand operand = codegen()->VarOperand(var, result_register()); |
| 433 // Memory operands can be pushed directly. | 435 // Memory operands can be pushed directly. |
| 434 __ push(operand); | 436 __ push(operand); |
| 435 } | 437 } |
| 436 | 438 |
| 437 | 439 |
| 438 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 440 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
| 439 UNREACHABLE(); // Not used on IA32. | 441 UNREACHABLE(); // Not used on IA32. |
| 440 } | 442 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 465 Handle<Object> lit) const { | 467 Handle<Object> lit) const { |
| 466 if (lit->IsSmi()) { | 468 if (lit->IsSmi()) { |
| 467 __ SafeMove(result_register(), Immediate(lit)); | 469 __ SafeMove(result_register(), Immediate(lit)); |
| 468 } else { | 470 } else { |
| 469 __ Move(result_register(), Immediate(lit)); | 471 __ Move(result_register(), Immediate(lit)); |
| 470 } | 472 } |
| 471 } | 473 } |
| 472 | 474 |
| 473 | 475 |
| 474 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { | 476 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
| 477 codegen()->OperandStackDepthIncrement(1); | |
| 475 if (lit->IsSmi()) { | 478 if (lit->IsSmi()) { |
| 476 __ SafePush(Immediate(lit)); | 479 __ SafePush(Immediate(lit)); |
| 477 } else { | 480 } else { |
| 478 __ push(Immediate(lit)); | 481 __ push(Immediate(lit)); |
| 479 } | 482 } |
| 480 } | 483 } |
| 481 | 484 |
| 482 | 485 |
| 483 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 486 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
| 484 codegen()->PrepareForBailoutBeforeSplit(condition(), | 487 codegen()->PrepareForBailoutBeforeSplit(condition(), |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 505 } else { | 508 } else { |
| 506 // For simplicity we always test the accumulator register. | 509 // For simplicity we always test the accumulator register. |
| 507 __ mov(result_register(), lit); | 510 __ mov(result_register(), lit); |
| 508 codegen()->DoTest(this); | 511 codegen()->DoTest(this); |
| 509 } | 512 } |
| 510 } | 513 } |
| 511 | 514 |
| 512 | 515 |
| 513 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 516 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| 514 Register reg) const { | 517 Register reg) const { |
| 518 codegen()->OperandStackDepthDecrement(count); | |
| 515 DCHECK(count > 0); | 519 DCHECK(count > 0); |
| 516 __ Drop(count); | 520 __ Drop(count); |
| 517 } | 521 } |
| 518 | 522 |
| 519 | 523 |
| 520 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 524 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| 521 int count, | 525 int count, |
| 522 Register reg) const { | 526 Register reg) const { |
| 527 codegen()->OperandStackDepthDecrement(count); | |
| 523 DCHECK(count > 0); | 528 DCHECK(count > 0); |
| 524 __ Drop(count); | 529 __ Drop(count); |
| 525 __ Move(result_register(), reg); | 530 __ Move(result_register(), reg); |
| 526 } | 531 } |
| 527 | 532 |
| 528 | 533 |
| 529 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 534 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
| 530 Register reg) const { | 535 Register reg) const { |
| 536 codegen()->OperandStackDepthDecrement(count - 1); | |
| 531 DCHECK(count > 0); | 537 DCHECK(count > 0); |
| 532 if (count > 1) __ Drop(count - 1); | 538 if (count > 1) __ Drop(count - 1); |
| 533 __ mov(Operand(esp, 0), reg); | 539 __ mov(Operand(esp, 0), reg); |
| 534 } | 540 } |
| 535 | 541 |
| 536 | 542 |
| 537 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 543 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| 538 Register reg) const { | 544 Register reg) const { |
| 545 codegen()->OperandStackDepthDecrement(count); | |
| 539 DCHECK(count > 0); | 546 DCHECK(count > 0); |
| 540 // For simplicity we always test the accumulator register. | 547 // For simplicity we always test the accumulator register. |
| 541 __ Drop(count); | 548 __ Drop(count); |
| 542 __ Move(result_register(), reg); | 549 __ Move(result_register(), reg); |
| 543 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 550 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 544 codegen()->DoTest(this); | 551 codegen()->DoTest(this); |
| 545 } | 552 } |
| 546 | 553 |
| 547 | 554 |
| 548 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 555 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 561 __ jmp(&done, Label::kNear); | 568 __ jmp(&done, Label::kNear); |
| 562 __ bind(materialize_false); | 569 __ bind(materialize_false); |
| 563 __ mov(result_register(), isolate()->factory()->false_value()); | 570 __ mov(result_register(), isolate()->factory()->false_value()); |
| 564 __ bind(&done); | 571 __ bind(&done); |
| 565 } | 572 } |
| 566 | 573 |
| 567 | 574 |
| 568 void FullCodeGenerator::StackValueContext::Plug( | 575 void FullCodeGenerator::StackValueContext::Plug( |
| 569 Label* materialize_true, | 576 Label* materialize_true, |
| 570 Label* materialize_false) const { | 577 Label* materialize_false) const { |
| 578 codegen()->OperandStackDepthIncrement(1); | |
| 571 Label done; | 579 Label done; |
| 572 __ bind(materialize_true); | 580 __ bind(materialize_true); |
| 573 __ push(Immediate(isolate()->factory()->true_value())); | 581 __ push(Immediate(isolate()->factory()->true_value())); |
| 574 __ jmp(&done, Label::kNear); | 582 __ jmp(&done, Label::kNear); |
| 575 __ bind(materialize_false); | 583 __ bind(materialize_false); |
| 576 __ push(Immediate(isolate()->factory()->false_value())); | 584 __ push(Immediate(isolate()->factory()->false_value())); |
| 577 __ bind(&done); | 585 __ bind(&done); |
| 578 } | 586 } |
| 579 | 587 |
| 580 | 588 |
| 581 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 589 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 582 Label* materialize_false) const { | 590 Label* materialize_false) const { |
| 583 DCHECK(materialize_true == true_label_); | 591 DCHECK(materialize_true == true_label_); |
| 584 DCHECK(materialize_false == false_label_); | 592 DCHECK(materialize_false == false_label_); |
| 585 } | 593 } |
| 586 | 594 |
| 587 | 595 |
| 588 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 596 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
| 589 Handle<Object> value = flag | 597 Handle<Object> value = flag |
| 590 ? isolate()->factory()->true_value() | 598 ? isolate()->factory()->true_value() |
| 591 : isolate()->factory()->false_value(); | 599 : isolate()->factory()->false_value(); |
| 592 __ mov(result_register(), value); | 600 __ mov(result_register(), value); |
| 593 } | 601 } |
| 594 | 602 |
| 595 | 603 |
| 596 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 604 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
| 605 codegen()->OperandStackDepthIncrement(1); | |
| 597 Handle<Object> value = flag | 606 Handle<Object> value = flag |
| 598 ? isolate()->factory()->true_value() | 607 ? isolate()->factory()->true_value() |
| 599 : isolate()->factory()->false_value(); | 608 : isolate()->factory()->false_value(); |
| 600 __ push(Immediate(value)); | 609 __ push(Immediate(value)); |
| 601 } | 610 } |
| 602 | 611 |
| 603 | 612 |
| 604 void FullCodeGenerator::TestContext::Plug(bool flag) const { | 613 void FullCodeGenerator::TestContext::Plug(bool flag) const { |
| 605 codegen()->PrepareForBailoutBeforeSplit(condition(), | 614 codegen()->PrepareForBailoutBeforeSplit(condition(), |
| 606 true, | 615 true, |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 824 ecx, | 833 ecx, |
| 825 kDontSaveFPRegs, | 834 kDontSaveFPRegs, |
| 826 EMIT_REMEMBERED_SET, | 835 EMIT_REMEMBERED_SET, |
| 827 OMIT_SMI_CHECK); | 836 OMIT_SMI_CHECK); |
| 828 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 837 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 829 break; | 838 break; |
| 830 } | 839 } |
| 831 | 840 |
| 832 case VariableLocation::LOOKUP: { | 841 case VariableLocation::LOOKUP: { |
| 833 Comment cmnt(masm_, "[ FunctionDeclaration"); | 842 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 834 __ push(Immediate(variable->name())); | 843 PushOperand(variable->name()); |
| 835 VisitForStackValue(declaration->fun()); | 844 VisitForStackValue(declaration->fun()); |
| 836 __ push( | 845 PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
| 837 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); | 846 CallRuntimeWithOperands(Runtime::kDeclareLookupSlot); |
| 838 __ CallRuntime(Runtime::kDeclareLookupSlot); | |
| 839 break; | 847 break; |
| 840 } | 848 } |
| 841 } | 849 } |
| 842 } | 850 } |
| 843 | 851 |
| 844 | 852 |
| 845 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 853 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 846 // Call the runtime to declare the globals. | 854 // Call the runtime to declare the globals. |
| 847 __ Push(pairs); | 855 __ Push(pairs); |
| 848 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 856 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 924 | 932 |
| 925 __ test(eax, eax); | 933 __ test(eax, eax); |
| 926 __ j(not_equal, &next_test); | 934 __ j(not_equal, &next_test); |
| 927 __ Drop(1); // Switch value is no longer needed. | 935 __ Drop(1); // Switch value is no longer needed. |
| 928 __ jmp(clause->body_target()); | 936 __ jmp(clause->body_target()); |
| 929 } | 937 } |
| 930 | 938 |
| 931 // Discard the test value and jump to the default if present, otherwise to | 939 // Discard the test value and jump to the default if present, otherwise to |
| 932 // the end of the statement. | 940 // the end of the statement. |
| 933 __ bind(&next_test); | 941 __ bind(&next_test); |
| 934 __ Drop(1); // Switch value is no longer needed. | 942 DropOperands(1); // Switch value is no longer needed. |
| 935 if (default_clause == NULL) { | 943 if (default_clause == NULL) { |
| 936 __ jmp(nested_statement.break_label()); | 944 __ jmp(nested_statement.break_label()); |
| 937 } else { | 945 } else { |
| 938 __ jmp(default_clause->body_target()); | 946 __ jmp(default_clause->body_target()); |
| 939 } | 947 } |
| 940 | 948 |
| 941 // Compile all the case bodies. | 949 // Compile all the case bodies. |
| 942 for (int i = 0; i < clauses->length(); i++) { | 950 for (int i = 0; i < clauses->length(); i++) { |
| 943 Comment cmnt(masm_, "[ Case body"); | 951 Comment cmnt(masm_, "[ Case body"); |
| 944 CaseClause* clause = clauses->at(i); | 952 CaseClause* clause = clauses->at(i); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 958 | 966 |
| 959 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); | 967 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); |
| 960 | 968 |
| 961 Label loop, exit; | 969 Label loop, exit; |
| 962 ForIn loop_statement(this, stmt); | 970 ForIn loop_statement(this, stmt); |
| 963 increment_loop_depth(); | 971 increment_loop_depth(); |
| 964 | 972 |
| 965 // Get the object to enumerate over. | 973 // Get the object to enumerate over. |
| 966 SetExpressionAsStatementPosition(stmt->enumerable()); | 974 SetExpressionAsStatementPosition(stmt->enumerable()); |
| 967 VisitForAccumulatorValue(stmt->enumerable()); | 975 VisitForAccumulatorValue(stmt->enumerable()); |
| 976 OperandStackDepthIncrement(ForIn::kElementCount); | |
| 968 | 977 |
| 969 // If the object is null or undefined, skip over the loop, otherwise convert | 978 // If the object is null or undefined, skip over the loop, otherwise convert |
| 970 // it to a JS receiver. See ECMA-262 version 5, section 12.6.4. | 979 // it to a JS receiver. See ECMA-262 version 5, section 12.6.4. |
| 971 Label convert, done_convert; | 980 Label convert, done_convert; |
| 972 __ JumpIfSmi(eax, &convert, Label::kNear); | 981 __ JumpIfSmi(eax, &convert, Label::kNear); |
| 973 __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx); | 982 __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx); |
| 974 __ j(above_equal, &done_convert, Label::kNear); | 983 __ j(above_equal, &done_convert, Label::kNear); |
| 975 __ cmp(eax, isolate()->factory()->undefined_value()); | 984 __ cmp(eax, isolate()->factory()->undefined_value()); |
| 976 __ j(equal, &exit); | 985 __ j(equal, &exit); |
| 977 __ cmp(eax, isolate()->factory()->null_value()); | 986 __ cmp(eax, isolate()->factory()->null_value()); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1106 // index (smi) stored on top of the stack. | 1115 // index (smi) stored on top of the stack. |
| 1107 __ bind(loop_statement.continue_label()); | 1116 __ bind(loop_statement.continue_label()); |
| 1108 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); | 1117 __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); |
| 1109 | 1118 |
| 1110 EmitBackEdgeBookkeeping(stmt, &loop); | 1119 EmitBackEdgeBookkeeping(stmt, &loop); |
| 1111 __ jmp(&loop); | 1120 __ jmp(&loop); |
| 1112 | 1121 |
| 1113 // Remove the pointers stored on the stack. | 1122 // Remove the pointers stored on the stack. |
| 1114 __ bind(loop_statement.break_label()); | 1123 __ bind(loop_statement.break_label()); |
| 1115 __ add(esp, Immediate(5 * kPointerSize)); | 1124 __ add(esp, Immediate(5 * kPointerSize)); |
| 1125 OperandStackDepthDecrement(ForIn::kElementCount); | |
| 1116 | 1126 |
| 1117 // Exit and decrement the loop depth. | 1127 // Exit and decrement the loop depth. |
| 1118 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1128 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1119 __ bind(&exit); | 1129 __ bind(&exit); |
| 1120 decrement_loop_depth(); | 1130 decrement_loop_depth(); |
| 1121 } | 1131 } |
| 1122 | 1132 |
| 1123 | 1133 |
| 1124 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1134 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1125 bool pretenure) { | 1135 bool pretenure) { |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1377 __ Move(edx, Immediate(Smi::FromInt(expr->flags()))); | 1387 __ Move(edx, Immediate(Smi::FromInt(expr->flags()))); |
| 1378 FastCloneRegExpStub stub(isolate()); | 1388 FastCloneRegExpStub stub(isolate()); |
| 1379 __ CallStub(&stub); | 1389 __ CallStub(&stub); |
| 1380 context()->Plug(eax); | 1390 context()->Plug(eax); |
| 1381 } | 1391 } |
| 1382 | 1392 |
| 1383 | 1393 |
| 1384 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 1394 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
| 1385 Expression* expression = (property == NULL) ? NULL : property->value(); | 1395 Expression* expression = (property == NULL) ? NULL : property->value(); |
| 1386 if (expression == NULL) { | 1396 if (expression == NULL) { |
| 1387 __ push(Immediate(isolate()->factory()->null_value())); | 1397 PushOperand(isolate()->factory()->null_value()); |
| 1388 } else { | 1398 } else { |
| 1389 VisitForStackValue(expression); | 1399 VisitForStackValue(expression); |
| 1390 if (NeedsHomeObject(expression)) { | 1400 if (NeedsHomeObject(expression)) { |
| 1391 DCHECK(property->kind() == ObjectLiteral::Property::GETTER || | 1401 DCHECK(property->kind() == ObjectLiteral::Property::GETTER || |
| 1392 property->kind() == ObjectLiteral::Property::SETTER); | 1402 property->kind() == ObjectLiteral::Property::SETTER); |
| 1393 int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3; | 1403 int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3; |
| 1394 EmitSetHomeObject(expression, offset, property->GetSlot()); | 1404 EmitSetHomeObject(expression, offset, property->GetSlot()); |
| 1395 } | 1405 } |
| 1396 } | 1406 } |
| 1397 } | 1407 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1427 AccessorTable accessor_table(zone()); | 1437 AccessorTable accessor_table(zone()); |
| 1428 int property_index = 0; | 1438 int property_index = 0; |
| 1429 for (; property_index < expr->properties()->length(); property_index++) { | 1439 for (; property_index < expr->properties()->length(); property_index++) { |
| 1430 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1440 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1431 if (property->is_computed_name()) break; | 1441 if (property->is_computed_name()) break; |
| 1432 if (property->IsCompileTimeValue()) continue; | 1442 if (property->IsCompileTimeValue()) continue; |
| 1433 | 1443 |
| 1434 Literal* key = property->key()->AsLiteral(); | 1444 Literal* key = property->key()->AsLiteral(); |
| 1435 Expression* value = property->value(); | 1445 Expression* value = property->value(); |
| 1436 if (!result_saved) { | 1446 if (!result_saved) { |
| 1437 __ push(eax); // Save result on the stack | 1447 PushOperand(eax); // Save result on the stack |
| 1438 result_saved = true; | 1448 result_saved = true; |
| 1439 } | 1449 } |
| 1440 switch (property->kind()) { | 1450 switch (property->kind()) { |
| 1441 case ObjectLiteral::Property::CONSTANT: | 1451 case ObjectLiteral::Property::CONSTANT: |
| 1442 UNREACHABLE(); | 1452 UNREACHABLE(); |
| 1443 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1453 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1444 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); | 1454 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1445 // Fall through. | 1455 // Fall through. |
| 1446 case ObjectLiteral::Property::COMPUTED: | 1456 case ObjectLiteral::Property::COMPUTED: |
| 1447 // It is safe to use [[Put]] here because the boilerplate already | 1457 // It is safe to use [[Put]] here because the boilerplate already |
| 1448 // contains computed properties with an uninitialized value. | 1458 // contains computed properties with an uninitialized value. |
| 1449 if (key->value()->IsInternalizedString()) { | 1459 if (key->value()->IsInternalizedString()) { |
| 1450 if (property->emit_store()) { | 1460 if (property->emit_store()) { |
| 1451 VisitForAccumulatorValue(value); | 1461 VisitForAccumulatorValue(value); |
| 1452 DCHECK(StoreDescriptor::ValueRegister().is(eax)); | 1462 DCHECK(StoreDescriptor::ValueRegister().is(eax)); |
| 1453 __ mov(StoreDescriptor::NameRegister(), Immediate(key->value())); | 1463 __ mov(StoreDescriptor::NameRegister(), Immediate(key->value())); |
| 1454 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1464 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 1455 EmitLoadStoreICSlot(property->GetSlot(0)); | 1465 EmitLoadStoreICSlot(property->GetSlot(0)); |
| 1456 CallStoreIC(); | 1466 CallStoreIC(); |
| 1457 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1467 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1458 if (NeedsHomeObject(value)) { | 1468 if (NeedsHomeObject(value)) { |
| 1459 EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); | 1469 EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); |
| 1460 } | 1470 } |
| 1461 } else { | 1471 } else { |
| 1462 VisitForEffect(value); | 1472 VisitForEffect(value); |
| 1463 } | 1473 } |
| 1464 break; | 1474 break; |
| 1465 } | 1475 } |
| 1466 __ push(Operand(esp, 0)); // Duplicate receiver. | 1476 PushOperand(Operand(esp, 0)); // Duplicate receiver. |
| 1467 VisitForStackValue(key); | 1477 VisitForStackValue(key); |
| 1468 VisitForStackValue(value); | 1478 VisitForStackValue(value); |
| 1469 if (property->emit_store()) { | 1479 if (property->emit_store()) { |
| 1470 if (NeedsHomeObject(value)) { | 1480 if (NeedsHomeObject(value)) { |
| 1471 EmitSetHomeObject(value, 2, property->GetSlot()); | 1481 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1472 } | 1482 } |
| 1473 __ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode | 1483 PushOperand(Smi::FromInt(SLOPPY)); // Language mode |
| 1474 __ CallRuntime(Runtime::kSetProperty); | 1484 CallRuntimeWithOperands(Runtime::kSetProperty); |
| 1475 } else { | 1485 } else { |
| 1476 __ Drop(3); | 1486 DropOperands(3); |
| 1477 } | 1487 } |
| 1478 break; | 1488 break; |
| 1479 case ObjectLiteral::Property::PROTOTYPE: | 1489 case ObjectLiteral::Property::PROTOTYPE: |
| 1480 __ push(Operand(esp, 0)); // Duplicate receiver. | 1490 PushOperand(Operand(esp, 0)); // Duplicate receiver. |
| 1481 VisitForStackValue(value); | 1491 VisitForStackValue(value); |
| 1482 DCHECK(property->emit_store()); | 1492 DCHECK(property->emit_store()); |
| 1483 __ CallRuntime(Runtime::kInternalSetPrototype); | 1493 CallRuntimeWithOperands(Runtime::kInternalSetPrototype); |
| 1484 PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), | 1494 PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), |
| 1485 NO_REGISTERS); | 1495 NO_REGISTERS); |
| 1486 break; | 1496 break; |
| 1487 case ObjectLiteral::Property::GETTER: | 1497 case ObjectLiteral::Property::GETTER: |
| 1488 if (property->emit_store()) { | 1498 if (property->emit_store()) { |
| 1489 accessor_table.lookup(key)->second->getter = property; | 1499 accessor_table.lookup(key)->second->getter = property; |
| 1490 } | 1500 } |
| 1491 break; | 1501 break; |
| 1492 case ObjectLiteral::Property::SETTER: | 1502 case ObjectLiteral::Property::SETTER: |
| 1493 if (property->emit_store()) { | 1503 if (property->emit_store()) { |
| 1494 accessor_table.lookup(key)->second->setter = property; | 1504 accessor_table.lookup(key)->second->setter = property; |
| 1495 } | 1505 } |
| 1496 break; | 1506 break; |
| 1497 } | 1507 } |
| 1498 } | 1508 } |
| 1499 | 1509 |
| 1500 // Emit code to define accessors, using only a single call to the runtime for | 1510 // Emit code to define accessors, using only a single call to the runtime for |
| 1501 // each pair of corresponding getters and setters. | 1511 // each pair of corresponding getters and setters. |
| 1502 for (AccessorTable::Iterator it = accessor_table.begin(); | 1512 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1503 it != accessor_table.end(); | 1513 it != accessor_table.end(); |
| 1504 ++it) { | 1514 ++it) { |
| 1505 __ push(Operand(esp, 0)); // Duplicate receiver. | 1515 PushOperand(Operand(esp, 0)); // Duplicate receiver. |
| 1506 VisitForStackValue(it->first); | 1516 VisitForStackValue(it->first); |
| 1507 | 1517 |
| 1508 EmitAccessor(it->second->getter); | 1518 EmitAccessor(it->second->getter); |
| 1509 EmitAccessor(it->second->setter); | 1519 EmitAccessor(it->second->setter); |
| 1510 | 1520 |
| 1511 __ push(Immediate(Smi::FromInt(NONE))); | 1521 PushOperand(Smi::FromInt(NONE)); |
| 1512 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); | 1522 CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked); |
| 1513 } | 1523 } |
| 1514 | 1524 |
| 1515 // Object literals have two parts. The "static" part on the left contains no | 1525 // Object literals have two parts. The "static" part on the left contains no |
| 1516 // computed property names, and so we can compute its map ahead of time; see | 1526 // computed property names, and so we can compute its map ahead of time; see |
| 1517 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1527 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
| 1518 // starts with the first computed property name, and continues with all | 1528 // starts with the first computed property name, and continues with all |
| 1519 // properties to its right. All the code from above initializes the static | 1529 // properties to its right. All the code from above initializes the static |
| 1520 // component of the object literal, and arranges for the map of the result to | 1530 // component of the object literal, and arranges for the map of the result to |
| 1521 // reflect the static order in which the keys appear. For the dynamic | 1531 // reflect the static order in which the keys appear. For the dynamic |
| 1522 // properties, we compile them into a series of "SetOwnProperty" runtime | 1532 // properties, we compile them into a series of "SetOwnProperty" runtime |
| 1523 // calls. This will preserve insertion order. | 1533 // calls. This will preserve insertion order. |
| 1524 for (; property_index < expr->properties()->length(); property_index++) { | 1534 for (; property_index < expr->properties()->length(); property_index++) { |
| 1525 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1535 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1526 | 1536 |
| 1527 Expression* value = property->value(); | 1537 Expression* value = property->value(); |
| 1528 if (!result_saved) { | 1538 if (!result_saved) { |
| 1529 __ push(eax); // Save result on the stack | 1539 PushOperand(eax); // Save result on the stack |
| 1530 result_saved = true; | 1540 result_saved = true; |
| 1531 } | 1541 } |
| 1532 | 1542 |
| 1533 __ push(Operand(esp, 0)); // Duplicate receiver. | 1543 PushOperand(Operand(esp, 0)); // Duplicate receiver. |
| 1534 | 1544 |
| 1535 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1545 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1536 DCHECK(!property->is_computed_name()); | 1546 DCHECK(!property->is_computed_name()); |
| 1537 VisitForStackValue(value); | 1547 VisitForStackValue(value); |
| 1538 DCHECK(property->emit_store()); | 1548 DCHECK(property->emit_store()); |
| 1539 __ CallRuntime(Runtime::kInternalSetPrototype); | 1549 CallRuntimeWithOperands(Runtime::kInternalSetPrototype); |
| 1540 PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), | 1550 PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), |
| 1541 NO_REGISTERS); | 1551 NO_REGISTERS); |
| 1542 } else { | 1552 } else { |
| 1543 EmitPropertyKey(property, expr->GetIdForPropertyName(property_index)); | 1553 EmitPropertyKey(property, expr->GetIdForPropertyName(property_index)); |
| 1544 VisitForStackValue(value); | 1554 VisitForStackValue(value); |
| 1545 if (NeedsHomeObject(value)) { | 1555 if (NeedsHomeObject(value)) { |
| 1546 EmitSetHomeObject(value, 2, property->GetSlot()); | 1556 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 1547 } | 1557 } |
| 1548 | 1558 |
| 1549 switch (property->kind()) { | 1559 switch (property->kind()) { |
| 1550 case ObjectLiteral::Property::CONSTANT: | 1560 case ObjectLiteral::Property::CONSTANT: |
| 1551 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1561 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1552 case ObjectLiteral::Property::COMPUTED: | 1562 case ObjectLiteral::Property::COMPUTED: |
| 1553 if (property->emit_store()) { | 1563 if (property->emit_store()) { |
| 1554 __ Push(Smi::FromInt(NONE)); | 1564 PushOperand(Smi::FromInt(NONE)); |
| 1555 __ Push(Smi::FromInt(property->NeedsSetFunctionName())); | 1565 PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); |
| 1556 __ CallRuntime(Runtime::kDefineDataPropertyInLiteral); | 1566 CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); |
| 1557 } else { | 1567 } else { |
| 1558 __ Drop(3); | 1568 DropOperands(3); |
| 1559 } | 1569 } |
| 1560 break; | 1570 break; |
| 1561 | 1571 |
| 1562 case ObjectLiteral::Property::PROTOTYPE: | 1572 case ObjectLiteral::Property::PROTOTYPE: |
| 1563 UNREACHABLE(); | 1573 UNREACHABLE(); |
| 1564 break; | 1574 break; |
| 1565 | 1575 |
| 1566 case ObjectLiteral::Property::GETTER: | 1576 case ObjectLiteral::Property::GETTER: |
| 1567 __ Push(Smi::FromInt(NONE)); | 1577 PushOperand(Smi::FromInt(NONE)); |
| 1568 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); | 1578 CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); |
| 1569 break; | 1579 break; |
| 1570 | 1580 |
| 1571 case ObjectLiteral::Property::SETTER: | 1581 case ObjectLiteral::Property::SETTER: |
| 1572 __ Push(Smi::FromInt(NONE)); | 1582 PushOperand(Smi::FromInt(NONE)); |
| 1573 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); | 1583 CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); |
| 1574 break; | 1584 break; |
| 1575 } | 1585 } |
| 1576 } | 1586 } |
| 1577 } | 1587 } |
| 1578 | 1588 |
| 1579 if (expr->has_function()) { | 1589 if (expr->has_function()) { |
| 1580 DCHECK(result_saved); | 1590 DCHECK(result_saved); |
| 1581 __ push(Operand(esp, 0)); | 1591 __ push(Operand(esp, 0)); |
| 1582 __ CallRuntime(Runtime::kToFastProperties); | 1592 __ CallRuntime(Runtime::kToFastProperties); |
| 1583 } | 1593 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1628 int array_index = 0; | 1638 int array_index = 0; |
| 1629 for (; array_index < length; array_index++) { | 1639 for (; array_index < length; array_index++) { |
| 1630 Expression* subexpr = subexprs->at(array_index); | 1640 Expression* subexpr = subexprs->at(array_index); |
| 1631 DCHECK(!subexpr->IsSpread()); | 1641 DCHECK(!subexpr->IsSpread()); |
| 1632 | 1642 |
| 1633 // If the subexpression is a literal or a simple materialized literal it | 1643 // If the subexpression is a literal or a simple materialized literal it |
| 1634 // is already set in the cloned array. | 1644 // is already set in the cloned array. |
| 1635 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 1645 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 1636 | 1646 |
| 1637 if (!result_saved) { | 1647 if (!result_saved) { |
| 1638 __ push(eax); // array literal. | 1648 PushOperand(eax); // array literal. |
| 1639 result_saved = true; | 1649 result_saved = true; |
| 1640 } | 1650 } |
| 1641 VisitForAccumulatorValue(subexpr); | 1651 VisitForAccumulatorValue(subexpr); |
| 1642 | 1652 |
| 1643 __ mov(StoreDescriptor::NameRegister(), | 1653 __ mov(StoreDescriptor::NameRegister(), |
| 1644 Immediate(Smi::FromInt(array_index))); | 1654 Immediate(Smi::FromInt(array_index))); |
| 1645 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1655 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 1646 EmitLoadStoreICSlot(expr->LiteralFeedbackSlot()); | 1656 EmitLoadStoreICSlot(expr->LiteralFeedbackSlot()); |
| 1647 Handle<Code> ic = | 1657 Handle<Code> ic = |
| 1648 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 1658 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 1649 CallIC(ic); | 1659 CallIC(ic); |
| 1650 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1660 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
| 1651 } | 1661 } |
| 1652 | 1662 |
| 1653 // In case the array literal contains spread expressions it has two parts. The | 1663 // In case the array literal contains spread expressions it has two parts. The |
| 1654 // first part is the "static" array which has a literal index is handled | 1664 // first part is the "static" array which has a literal index is handled |
| 1655 // above. The second part is the part after the first spread expression | 1665 // above. The second part is the part after the first spread expression |
| 1656 // (inclusive) and these elements gets appended to the array. Note that the | 1666 // (inclusive) and these elements gets appended to the array. Note that the |
| 1657 // number elements an iterable produces is unknown ahead of time. | 1667 // number elements an iterable produces is unknown ahead of time. |
| 1658 if (array_index < length && result_saved) { | 1668 if (array_index < length && result_saved) { |
| 1659 __ Pop(eax); | 1669 PopOperand(eax); |
| 1660 result_saved = false; | 1670 result_saved = false; |
| 1661 } | 1671 } |
| 1662 for (; array_index < length; array_index++) { | 1672 for (; array_index < length; array_index++) { |
| 1663 Expression* subexpr = subexprs->at(array_index); | 1673 Expression* subexpr = subexprs->at(array_index); |
| 1664 | 1674 |
| 1665 __ Push(eax); | 1675 PushOperand(eax); |
| 1666 DCHECK(!subexpr->IsSpread()); | 1676 DCHECK(!subexpr->IsSpread()); |
| 1667 VisitForStackValue(subexpr); | 1677 VisitForStackValue(subexpr); |
| 1668 __ CallRuntime(Runtime::kAppendElement); | 1678 CallRuntimeWithOperands(Runtime::kAppendElement); |
| 1669 | 1679 |
| 1670 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1680 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
| 1671 } | 1681 } |
| 1672 | 1682 |
| 1673 if (result_saved) { | 1683 if (result_saved) { |
| 1674 context()->PlugTOS(); | 1684 context()->PlugTOS(); |
| 1675 } else { | 1685 } else { |
| 1676 context()->Plug(eax); | 1686 context()->Plug(eax); |
| 1677 } | 1687 } |
| 1678 } | 1688 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1690 // Evaluate LHS expression. | 1700 // Evaluate LHS expression. |
| 1691 switch (assign_type) { | 1701 switch (assign_type) { |
| 1692 case VARIABLE: | 1702 case VARIABLE: |
| 1693 // Nothing to do here. | 1703 // Nothing to do here. |
| 1694 break; | 1704 break; |
| 1695 case NAMED_SUPER_PROPERTY: | 1705 case NAMED_SUPER_PROPERTY: |
| 1696 VisitForStackValue( | 1706 VisitForStackValue( |
| 1697 property->obj()->AsSuperPropertyReference()->this_var()); | 1707 property->obj()->AsSuperPropertyReference()->this_var()); |
| 1698 VisitForAccumulatorValue( | 1708 VisitForAccumulatorValue( |
| 1699 property->obj()->AsSuperPropertyReference()->home_object()); | 1709 property->obj()->AsSuperPropertyReference()->home_object()); |
| 1700 __ push(result_register()); | 1710 PushOperand(result_register()); |
| 1701 if (expr->is_compound()) { | 1711 if (expr->is_compound()) { |
| 1702 __ push(MemOperand(esp, kPointerSize)); | 1712 PushOperand(MemOperand(esp, kPointerSize)); |
| 1703 __ push(result_register()); | 1713 PushOperand(result_register()); |
| 1704 } | 1714 } |
| 1705 break; | 1715 break; |
| 1706 case NAMED_PROPERTY: | 1716 case NAMED_PROPERTY: |
| 1707 if (expr->is_compound()) { | 1717 if (expr->is_compound()) { |
| 1708 // We need the receiver both on the stack and in the register. | 1718 // We need the receiver both on the stack and in the register. |
| 1709 VisitForStackValue(property->obj()); | 1719 VisitForStackValue(property->obj()); |
| 1710 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1720 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 1711 } else { | 1721 } else { |
| 1712 VisitForStackValue(property->obj()); | 1722 VisitForStackValue(property->obj()); |
| 1713 } | 1723 } |
| 1714 break; | 1724 break; |
| 1715 case KEYED_SUPER_PROPERTY: | 1725 case KEYED_SUPER_PROPERTY: |
| 1716 VisitForStackValue( | 1726 VisitForStackValue( |
| 1717 property->obj()->AsSuperPropertyReference()->this_var()); | 1727 property->obj()->AsSuperPropertyReference()->this_var()); |
| 1718 VisitForStackValue( | 1728 VisitForStackValue( |
| 1719 property->obj()->AsSuperPropertyReference()->home_object()); | 1729 property->obj()->AsSuperPropertyReference()->home_object()); |
| 1720 VisitForAccumulatorValue(property->key()); | 1730 VisitForAccumulatorValue(property->key()); |
| 1721 __ Push(result_register()); | 1731 PushOperand(result_register()); |
| 1722 if (expr->is_compound()) { | 1732 if (expr->is_compound()) { |
| 1723 __ push(MemOperand(esp, 2 * kPointerSize)); | 1733 PushOperand(MemOperand(esp, 2 * kPointerSize)); |
| 1724 __ push(MemOperand(esp, 2 * kPointerSize)); | 1734 PushOperand(MemOperand(esp, 2 * kPointerSize)); |
| 1725 __ push(result_register()); | 1735 PushOperand(result_register()); |
| 1726 } | 1736 } |
| 1727 break; | 1737 break; |
| 1728 case KEYED_PROPERTY: { | 1738 case KEYED_PROPERTY: { |
| 1729 if (expr->is_compound()) { | 1739 if (expr->is_compound()) { |
| 1730 VisitForStackValue(property->obj()); | 1740 VisitForStackValue(property->obj()); |
| 1731 VisitForStackValue(property->key()); | 1741 VisitForStackValue(property->key()); |
| 1732 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize)); | 1742 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize)); |
| 1733 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); | 1743 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); |
| 1734 } else { | 1744 } else { |
| 1735 VisitForStackValue(property->obj()); | 1745 VisitForStackValue(property->obj()); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1762 PrepareForBailoutForId(property->LoadId(), TOS_REG); | 1772 PrepareForBailoutForId(property->LoadId(), TOS_REG); |
| 1763 break; | 1773 break; |
| 1764 case KEYED_PROPERTY: | 1774 case KEYED_PROPERTY: |
| 1765 EmitKeyedPropertyLoad(property); | 1775 EmitKeyedPropertyLoad(property); |
| 1766 PrepareForBailoutForId(property->LoadId(), TOS_REG); | 1776 PrepareForBailoutForId(property->LoadId(), TOS_REG); |
| 1767 break; | 1777 break; |
| 1768 } | 1778 } |
| 1769 } | 1779 } |
| 1770 | 1780 |
| 1771 Token::Value op = expr->binary_op(); | 1781 Token::Value op = expr->binary_op(); |
| 1772 __ push(eax); // Left operand goes on the stack. | 1782 PushOperand(eax); // Left operand goes on the stack. |
| 1773 VisitForAccumulatorValue(expr->value()); | 1783 VisitForAccumulatorValue(expr->value()); |
| 1774 | 1784 |
| 1775 if (ShouldInlineSmiCase(op)) { | 1785 if (ShouldInlineSmiCase(op)) { |
| 1776 EmitInlineSmiBinaryOp(expr->binary_operation(), | 1786 EmitInlineSmiBinaryOp(expr->binary_operation(), |
| 1777 op, | 1787 op, |
| 1778 expr->target(), | 1788 expr->target(), |
| 1779 expr->value()); | 1789 expr->value()); |
| 1780 } else { | 1790 } else { |
| 1781 EmitBinaryOp(expr->binary_operation(), op); | 1791 EmitBinaryOp(expr->binary_operation(), op); |
| 1782 } | 1792 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1855 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 1865 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, |
| 1856 kDontSaveFPRegs); | 1866 kDontSaveFPRegs); |
| 1857 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1867 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1858 __ cmp(esp, ebx); | 1868 __ cmp(esp, ebx); |
| 1859 __ j(equal, &post_runtime); | 1869 __ j(equal, &post_runtime); |
| 1860 __ push(eax); // generator object | 1870 __ push(eax); // generator object |
| 1861 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1871 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 1862 __ mov(context_register(), | 1872 __ mov(context_register(), |
| 1863 Operand(ebp, StandardFrameConstants::kContextOffset)); | 1873 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1864 __ bind(&post_runtime); | 1874 __ bind(&post_runtime); |
| 1865 __ pop(result_register()); | 1875 PopOperand(result_register()); |
| 1866 EmitReturnSequence(); | 1876 EmitReturnSequence(); |
| 1867 | 1877 |
| 1868 __ bind(&resume); | 1878 __ bind(&resume); |
| 1869 context()->Plug(result_register()); | 1879 context()->Plug(result_register()); |
| 1870 break; | 1880 break; |
| 1871 } | 1881 } |
| 1872 | 1882 |
| 1873 case Yield::kFinal: { | 1883 case Yield::kFinal: { |
| 1874 // Pop value from top-of-stack slot, box result into result register. | 1884 // Pop value from top-of-stack slot, box result into result register. |
| 1885 OperandStackDepthDecrement(1); | |
| 1875 EmitCreateIteratorResult(true); | 1886 EmitCreateIteratorResult(true); |
| 1876 EmitUnwindAndReturn(); | 1887 EmitUnwindAndReturn(); |
| 1877 break; | 1888 break; |
| 1878 } | 1889 } |
| 1879 | 1890 |
| 1880 case Yield::kDelegating: | 1891 case Yield::kDelegating: |
| 1881 UNREACHABLE(); | 1892 UNREACHABLE(); |
| 1882 } | 1893 } |
| 1883 } | 1894 } |
| 1884 | 1895 |
| 1885 | 1896 |
| 1886 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 1897 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 1887 Expression *value, | 1898 Expression *value, |
| 1888 JSGeneratorObject::ResumeMode resume_mode) { | 1899 JSGeneratorObject::ResumeMode resume_mode) { |
| 1889 // The value stays in eax, and is ultimately read by the resumed generator, as | 1900 // The value stays in eax, and is ultimately read by the resumed generator, as |
| 1890 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 1901 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
| 1891 // is read to throw the value when the resumed generator is already closed. | 1902 // is read to throw the value when the resumed generator is already closed. |
| 1892 // ebx will hold the generator object until the activation has been resumed. | 1903 // ebx will hold the generator object until the activation has been resumed. |
| 1893 VisitForStackValue(generator); | 1904 VisitForStackValue(generator); |
| 1894 VisitForAccumulatorValue(value); | 1905 VisitForAccumulatorValue(value); |
| 1895 __ pop(ebx); | 1906 PopOperand(ebx); |
| 1896 | 1907 |
| 1897 // Store input value into generator object. | 1908 // Store input value into generator object. |
| 1898 __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), result_register()); | 1909 __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), result_register()); |
| 1899 __ mov(ecx, result_register()); | 1910 __ mov(ecx, result_register()); |
| 1900 __ RecordWriteField(ebx, JSGeneratorObject::kInputOffset, ecx, edx, | 1911 __ RecordWriteField(ebx, JSGeneratorObject::kInputOffset, ecx, edx, |
| 1901 kDontSaveFPRegs); | 1912 kDontSaveFPRegs); |
| 1902 | 1913 |
| 1903 // Load suspended function and context. | 1914 // Load suspended function and context. |
| 1904 __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset)); | 1915 __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset)); |
| 1905 __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); | 1916 __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1967 __ push(result_register()); | 1978 __ push(result_register()); |
| 1968 __ Push(Smi::FromInt(resume_mode)); | 1979 __ Push(Smi::FromInt(resume_mode)); |
| 1969 __ CallRuntime(Runtime::kResumeJSGeneratorObject); | 1980 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
| 1970 // Not reached: the runtime call returns elsewhere. | 1981 // Not reached: the runtime call returns elsewhere. |
| 1971 __ Abort(kGeneratorFailedToResume); | 1982 __ Abort(kGeneratorFailedToResume); |
| 1972 | 1983 |
| 1973 __ bind(&done); | 1984 __ bind(&done); |
| 1974 context()->Plug(result_register()); | 1985 context()->Plug(result_register()); |
| 1975 } | 1986 } |
| 1976 | 1987 |
| 1988 void FullCodeGenerator::EmitOperandStackDepthCheck() { | |
| 1989 if (generate_debug_code_) { | |
| 1990 Vector<char> buf = Vector<char>::New(50); | |
| 1991 SNPrintF(buf, " > depth=%d", operand_stack_depth_); | |
| 1992 Comment cmnt(masm(), buf.start()); | |
| 1993 int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + | |
| 1994 operand_stack_depth_ * kPointerSize; | |
| 1995 __ mov(eax, ebp); | |
| 1996 __ sub(eax, esp); | |
| 1997 __ cmp(eax, Immediate(expected_diff)); | |
| 1998 __ Assert(equal, kUnexpectedStackDepth); | |
|
Jarin
2016/02/19 06:52:04
Hmm, just wondering: is it ok to clobber eax here?
Michael Starzinger
2016/02/19 09:24:04
Acknowledged. As discussed offline: We are current
| |
| 1999 } | |
| 2000 } | |
| 1977 | 2001 |
| 1978 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2002 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 1979 Label allocate, done_allocate; | 2003 Label allocate, done_allocate; |
| 1980 | 2004 |
| 1981 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); | 2005 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); |
| 1982 __ jmp(&done_allocate, Label::kNear); | 2006 __ jmp(&done_allocate, Label::kNear); |
| 1983 | 2007 |
| 1984 __ bind(&allocate); | 2008 __ bind(&allocate); |
| 1985 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2009 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
| 1986 __ CallRuntime(Runtime::kAllocateInNewSpace); | 2010 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2013 } | 2037 } |
| 2014 | 2038 |
| 2015 | 2039 |
| 2016 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2040 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
| 2017 // Stack: receiver, home_object. | 2041 // Stack: receiver, home_object. |
| 2018 SetExpressionPosition(prop); | 2042 SetExpressionPosition(prop); |
| 2019 Literal* key = prop->key()->AsLiteral(); | 2043 Literal* key = prop->key()->AsLiteral(); |
| 2020 DCHECK(!key->value()->IsSmi()); | 2044 DCHECK(!key->value()->IsSmi()); |
| 2021 DCHECK(prop->IsSuperAccess()); | 2045 DCHECK(prop->IsSuperAccess()); |
| 2022 | 2046 |
| 2023 __ push(Immediate(key->value())); | 2047 PushOperand(key->value()); |
| 2024 __ CallRuntime(Runtime::kLoadFromSuper); | 2048 CallRuntimeWithOperands(Runtime::kLoadFromSuper); |
| 2025 } | 2049 } |
| 2026 | 2050 |
| 2027 | 2051 |
| 2028 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2052 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2029 SetExpressionPosition(prop); | 2053 SetExpressionPosition(prop); |
| 2030 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); | 2054 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); |
| 2031 __ mov(LoadDescriptor::SlotRegister(), | 2055 __ mov(LoadDescriptor::SlotRegister(), |
| 2032 Immediate(SmiFromSlot(prop->PropertyFeedbackSlot()))); | 2056 Immediate(SmiFromSlot(prop->PropertyFeedbackSlot()))); |
| 2033 CallIC(ic); | 2057 CallIC(ic); |
| 2034 } | 2058 } |
| 2035 | 2059 |
| 2036 | 2060 |
| 2037 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2061 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| 2038 // Stack: receiver, home_object, key. | 2062 // Stack: receiver, home_object, key. |
| 2039 SetExpressionPosition(prop); | 2063 SetExpressionPosition(prop); |
| 2040 __ CallRuntime(Runtime::kLoadKeyedFromSuper); | 2064 CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); |
| 2041 } | 2065 } |
| 2042 | 2066 |
| 2043 | 2067 |
| 2044 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2068 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2045 Token::Value op, | 2069 Token::Value op, |
| 2046 Expression* left, | 2070 Expression* left, |
| 2047 Expression* right) { | 2071 Expression* right) { |
| 2048 // Do combined smi check of the operands. Left operand is on the | 2072 // Do combined smi check of the operands. Left operand is on the |
| 2049 // stack. Right operand is in eax. | 2073 // stack. Right operand is in eax. |
| 2050 Label smi_case, done, stub_call; | 2074 Label smi_case, done, stub_call; |
| 2051 __ pop(edx); | 2075 PopOperand(edx); |
| 2052 __ mov(ecx, eax); | 2076 __ mov(ecx, eax); |
| 2053 __ or_(eax, edx); | 2077 __ or_(eax, edx); |
| 2054 JumpPatchSite patch_site(masm_); | 2078 JumpPatchSite patch_site(masm_); |
| 2055 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 2079 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
| 2056 | 2080 |
| 2057 __ bind(&stub_call); | 2081 __ bind(&stub_call); |
| 2058 __ mov(eax, ecx); | 2082 __ mov(eax, ecx); |
| 2059 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); | 2083 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
| 2060 CallIC(code, expr->BinaryOperationFeedbackId()); | 2084 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2061 patch_site.EmitPatchInfo(); | 2085 patch_site.EmitPatchInfo(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2134 context()->Plug(eax); | 2158 context()->Plug(eax); |
| 2135 } | 2159 } |
| 2136 | 2160 |
| 2137 | 2161 |
| 2138 void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { | 2162 void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
| 2139 for (int i = 0; i < lit->properties()->length(); i++) { | 2163 for (int i = 0; i < lit->properties()->length(); i++) { |
| 2140 ObjectLiteral::Property* property = lit->properties()->at(i); | 2164 ObjectLiteral::Property* property = lit->properties()->at(i); |
| 2141 Expression* value = property->value(); | 2165 Expression* value = property->value(); |
| 2142 | 2166 |
| 2143 if (property->is_static()) { | 2167 if (property->is_static()) { |
| 2144 __ push(Operand(esp, kPointerSize)); // constructor | 2168 PushOperand(Operand(esp, kPointerSize)); // constructor |
| 2145 } else { | 2169 } else { |
| 2146 __ push(Operand(esp, 0)); // prototype | 2170 PushOperand(Operand(esp, 0)); // prototype |
| 2147 } | 2171 } |
| 2148 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2172 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
| 2149 | 2173 |
| 2150 // The static prototype property is read only. We handle the non computed | 2174 // The static prototype property is read only. We handle the non computed |
| 2151 // property name case in the parser. Since this is the only case where we | 2175 // property name case in the parser. Since this is the only case where we |
| 2152 // need to check for an own read only property we special case this so we do | 2176 // need to check for an own read only property we special case this so we do |
| 2153 // not need to do this for every property. | 2177 // not need to do this for every property. |
| 2154 if (property->is_static() && property->is_computed_name()) { | 2178 if (property->is_static() && property->is_computed_name()) { |
| 2155 __ CallRuntime(Runtime::kThrowIfStaticPrototype); | 2179 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
| 2156 __ push(eax); | 2180 __ push(eax); |
| 2157 } | 2181 } |
| 2158 | 2182 |
| 2159 VisitForStackValue(value); | 2183 VisitForStackValue(value); |
| 2160 if (NeedsHomeObject(value)) { | 2184 if (NeedsHomeObject(value)) { |
| 2161 EmitSetHomeObject(value, 2, property->GetSlot()); | 2185 EmitSetHomeObject(value, 2, property->GetSlot()); |
| 2162 } | 2186 } |
| 2163 | 2187 |
| 2164 switch (property->kind()) { | 2188 switch (property->kind()) { |
| 2165 case ObjectLiteral::Property::CONSTANT: | 2189 case ObjectLiteral::Property::CONSTANT: |
| 2166 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2190 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2167 case ObjectLiteral::Property::PROTOTYPE: | 2191 case ObjectLiteral::Property::PROTOTYPE: |
| 2168 UNREACHABLE(); | 2192 UNREACHABLE(); |
| 2169 case ObjectLiteral::Property::COMPUTED: | 2193 case ObjectLiteral::Property::COMPUTED: |
| 2170 __ Push(Smi::FromInt(DONT_ENUM)); | 2194 PushOperand(Smi::FromInt(DONT_ENUM)); |
| 2171 __ Push(Smi::FromInt(property->NeedsSetFunctionName())); | 2195 PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); |
| 2172 __ CallRuntime(Runtime::kDefineDataPropertyInLiteral); | 2196 CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); |
| 2173 break; | 2197 break; |
| 2174 | 2198 |
| 2175 case ObjectLiteral::Property::GETTER: | 2199 case ObjectLiteral::Property::GETTER: |
| 2176 __ Push(Smi::FromInt(DONT_ENUM)); | 2200 PushOperand(Smi::FromInt(DONT_ENUM)); |
| 2177 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); | 2201 CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); |
| 2178 break; | 2202 break; |
| 2179 | 2203 |
| 2180 case ObjectLiteral::Property::SETTER: | 2204 case ObjectLiteral::Property::SETTER: |
| 2181 __ Push(Smi::FromInt(DONT_ENUM)); | 2205 PushOperand(Smi::FromInt(DONT_ENUM)); |
| 2182 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); | 2206 CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); |
| 2183 break; | 2207 break; |
| 2184 } | 2208 } |
| 2185 } | 2209 } |
| 2186 } | 2210 } |
| 2187 | 2211 |
| 2188 | 2212 |
| 2189 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2213 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
| 2190 __ pop(edx); | 2214 PopOperand(edx); |
| 2191 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); | 2215 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
| 2192 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2216 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2193 CallIC(code, expr->BinaryOperationFeedbackId()); | 2217 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2194 patch_site.EmitPatchInfo(); | 2218 patch_site.EmitPatchInfo(); |
| 2195 context()->Plug(eax); | 2219 context()->Plug(eax); |
| 2196 } | 2220 } |
| 2197 | 2221 |
| 2198 | 2222 |
| 2199 void FullCodeGenerator::EmitAssignment(Expression* expr, | 2223 void FullCodeGenerator::EmitAssignment(Expression* expr, |
| 2200 FeedbackVectorSlot slot) { | 2224 FeedbackVectorSlot slot) { |
| 2201 DCHECK(expr->IsValidReferenceExpressionOrThis()); | 2225 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
| 2202 | 2226 |
| 2203 Property* prop = expr->AsProperty(); | 2227 Property* prop = expr->AsProperty(); |
| 2204 LhsKind assign_type = Property::GetAssignType(prop); | 2228 LhsKind assign_type = Property::GetAssignType(prop); |
| 2205 | 2229 |
| 2206 switch (assign_type) { | 2230 switch (assign_type) { |
| 2207 case VARIABLE: { | 2231 case VARIABLE: { |
| 2208 Variable* var = expr->AsVariableProxy()->var(); | 2232 Variable* var = expr->AsVariableProxy()->var(); |
| 2209 EffectContext context(this); | 2233 EffectContext context(this); |
| 2210 EmitVariableAssignment(var, Token::ASSIGN, slot); | 2234 EmitVariableAssignment(var, Token::ASSIGN, slot); |
| 2211 break; | 2235 break; |
| 2212 } | 2236 } |
| 2213 case NAMED_PROPERTY: { | 2237 case NAMED_PROPERTY: { |
| 2214 __ push(eax); // Preserve value. | 2238 PushOperand(eax); // Preserve value. |
| 2215 VisitForAccumulatorValue(prop->obj()); | 2239 VisitForAccumulatorValue(prop->obj()); |
| 2216 __ Move(StoreDescriptor::ReceiverRegister(), eax); | 2240 __ Move(StoreDescriptor::ReceiverRegister(), eax); |
| 2217 __ pop(StoreDescriptor::ValueRegister()); // Restore value. | 2241 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
| 2218 __ mov(StoreDescriptor::NameRegister(), | 2242 __ mov(StoreDescriptor::NameRegister(), |
| 2219 prop->key()->AsLiteral()->value()); | 2243 prop->key()->AsLiteral()->value()); |
| 2220 EmitLoadStoreICSlot(slot); | 2244 EmitLoadStoreICSlot(slot); |
| 2221 CallStoreIC(); | 2245 CallStoreIC(); |
| 2222 break; | 2246 break; |
| 2223 } | 2247 } |
| 2224 case NAMED_SUPER_PROPERTY: { | 2248 case NAMED_SUPER_PROPERTY: { |
| 2225 __ push(eax); | 2249 PushOperand(eax); |
| 2226 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); | 2250 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
| 2227 VisitForAccumulatorValue( | 2251 VisitForAccumulatorValue( |
| 2228 prop->obj()->AsSuperPropertyReference()->home_object()); | 2252 prop->obj()->AsSuperPropertyReference()->home_object()); |
| 2229 // stack: value, this; eax: home_object | 2253 // stack: value, this; eax: home_object |
| 2230 Register scratch = ecx; | 2254 Register scratch = ecx; |
| 2231 Register scratch2 = edx; | 2255 Register scratch2 = edx; |
| 2232 __ mov(scratch, result_register()); // home_object | 2256 __ mov(scratch, result_register()); // home_object |
| 2233 __ mov(eax, MemOperand(esp, kPointerSize)); // value | 2257 __ mov(eax, MemOperand(esp, kPointerSize)); // value |
| 2234 __ mov(scratch2, MemOperand(esp, 0)); // this | 2258 __ mov(scratch2, MemOperand(esp, 0)); // this |
| 2235 __ mov(MemOperand(esp, kPointerSize), scratch2); // this | 2259 __ mov(MemOperand(esp, kPointerSize), scratch2); // this |
| 2236 __ mov(MemOperand(esp, 0), scratch); // home_object | 2260 __ mov(MemOperand(esp, 0), scratch); // home_object |
| 2237 // stack: this, home_object. eax: value | 2261 // stack: this, home_object. eax: value |
| 2238 EmitNamedSuperPropertyStore(prop); | 2262 EmitNamedSuperPropertyStore(prop); |
| 2239 break; | 2263 break; |
| 2240 } | 2264 } |
| 2241 case KEYED_SUPER_PROPERTY: { | 2265 case KEYED_SUPER_PROPERTY: { |
| 2242 __ push(eax); | 2266 PushOperand(eax); |
| 2243 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); | 2267 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
| 2244 VisitForStackValue( | 2268 VisitForStackValue( |
| 2245 prop->obj()->AsSuperPropertyReference()->home_object()); | 2269 prop->obj()->AsSuperPropertyReference()->home_object()); |
| 2246 VisitForAccumulatorValue(prop->key()); | 2270 VisitForAccumulatorValue(prop->key()); |
| 2247 Register scratch = ecx; | 2271 Register scratch = ecx; |
| 2248 Register scratch2 = edx; | 2272 Register scratch2 = edx; |
| 2249 __ mov(scratch2, MemOperand(esp, 2 * kPointerSize)); // value | 2273 __ mov(scratch2, MemOperand(esp, 2 * kPointerSize)); // value |
| 2250 // stack: value, this, home_object; eax: key, edx: value | 2274 // stack: value, this, home_object; eax: key, edx: value |
| 2251 __ mov(scratch, MemOperand(esp, kPointerSize)); // this | 2275 __ mov(scratch, MemOperand(esp, kPointerSize)); // this |
| 2252 __ mov(MemOperand(esp, 2 * kPointerSize), scratch); | 2276 __ mov(MemOperand(esp, 2 * kPointerSize), scratch); |
| 2253 __ mov(scratch, MemOperand(esp, 0)); // home_object | 2277 __ mov(scratch, MemOperand(esp, 0)); // home_object |
| 2254 __ mov(MemOperand(esp, kPointerSize), scratch); | 2278 __ mov(MemOperand(esp, kPointerSize), scratch); |
| 2255 __ mov(MemOperand(esp, 0), eax); | 2279 __ mov(MemOperand(esp, 0), eax); |
| 2256 __ mov(eax, scratch2); | 2280 __ mov(eax, scratch2); |
| 2257 // stack: this, home_object, key; eax: value. | 2281 // stack: this, home_object, key; eax: value. |
| 2258 EmitKeyedSuperPropertyStore(prop); | 2282 EmitKeyedSuperPropertyStore(prop); |
| 2259 break; | 2283 break; |
| 2260 } | 2284 } |
| 2261 case KEYED_PROPERTY: { | 2285 case KEYED_PROPERTY: { |
| 2262 __ push(eax); // Preserve value. | 2286 PushOperand(eax); // Preserve value. |
| 2263 VisitForStackValue(prop->obj()); | 2287 VisitForStackValue(prop->obj()); |
| 2264 VisitForAccumulatorValue(prop->key()); | 2288 VisitForAccumulatorValue(prop->key()); |
| 2265 __ Move(StoreDescriptor::NameRegister(), eax); | 2289 __ Move(StoreDescriptor::NameRegister(), eax); |
| 2266 __ pop(StoreDescriptor::ReceiverRegister()); // Receiver. | 2290 PopOperand(StoreDescriptor::ReceiverRegister()); // Receiver. |
| 2267 __ pop(StoreDescriptor::ValueRegister()); // Restore value. | 2291 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
| 2268 EmitLoadStoreICSlot(slot); | 2292 EmitLoadStoreICSlot(slot); |
| 2269 Handle<Code> ic = | 2293 Handle<Code> ic = |
| 2270 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 2294 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 2271 CallIC(ic); | 2295 CallIC(ic); |
| 2272 break; | 2296 break; |
| 2273 } | 2297 } |
| 2274 } | 2298 } |
| 2275 context()->Plug(eax); | 2299 context()->Plug(eax); |
| 2276 } | 2300 } |
| 2277 | 2301 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2394 | 2418 |
| 2395 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2419 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2396 // Assignment to a property, using a named store IC. | 2420 // Assignment to a property, using a named store IC. |
| 2397 // eax : value | 2421 // eax : value |
| 2398 // esp[0] : receiver | 2422 // esp[0] : receiver |
| 2399 Property* prop = expr->target()->AsProperty(); | 2423 Property* prop = expr->target()->AsProperty(); |
| 2400 DCHECK(prop != NULL); | 2424 DCHECK(prop != NULL); |
| 2401 DCHECK(prop->key()->IsLiteral()); | 2425 DCHECK(prop->key()->IsLiteral()); |
| 2402 | 2426 |
| 2403 __ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value()); | 2427 __ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value()); |
| 2404 __ pop(StoreDescriptor::ReceiverRegister()); | 2428 PopOperand(StoreDescriptor::ReceiverRegister()); |
| 2405 EmitLoadStoreICSlot(expr->AssignmentSlot()); | 2429 EmitLoadStoreICSlot(expr->AssignmentSlot()); |
| 2406 CallStoreIC(); | 2430 CallStoreIC(); |
| 2407 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2431 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2408 context()->Plug(eax); | 2432 context()->Plug(eax); |
| 2409 } | 2433 } |
| 2410 | 2434 |
| 2411 | 2435 |
| 2412 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { | 2436 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { |
| 2413 // Assignment to named property of super. | 2437 // Assignment to named property of super. |
| 2414 // eax : value | 2438 // eax : value |
| 2415 // stack : receiver ('this'), home_object | 2439 // stack : receiver ('this'), home_object |
| 2416 DCHECK(prop != NULL); | 2440 DCHECK(prop != NULL); |
| 2417 Literal* key = prop->key()->AsLiteral(); | 2441 Literal* key = prop->key()->AsLiteral(); |
| 2418 DCHECK(key != NULL); | 2442 DCHECK(key != NULL); |
| 2419 | 2443 |
| 2420 __ push(Immediate(key->value())); | 2444 PushOperand(key->value()); |
| 2421 __ push(eax); | 2445 PushOperand(eax); |
| 2422 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2446 CallRuntimeWithOperands(is_strict(language_mode()) |
| 2423 : Runtime::kStoreToSuper_Sloppy)); | 2447 ? Runtime::kStoreToSuper_Strict |
| 2448 : Runtime::kStoreToSuper_Sloppy); | |
| 2424 } | 2449 } |
| 2425 | 2450 |
| 2426 | 2451 |
| 2427 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2452 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
| 2428 // Assignment to named property of super. | 2453 // Assignment to named property of super. |
| 2429 // eax : value | 2454 // eax : value |
| 2430 // stack : receiver ('this'), home_object, key | 2455 // stack : receiver ('this'), home_object, key |
| 2431 | 2456 |
| 2432 __ push(eax); | 2457 PushOperand(eax); |
| 2433 __ CallRuntime((is_strict(language_mode()) | 2458 CallRuntimeWithOperands(is_strict(language_mode()) |
| 2434 ? Runtime::kStoreKeyedToSuper_Strict | 2459 ? Runtime::kStoreKeyedToSuper_Strict |
| 2435 : Runtime::kStoreKeyedToSuper_Sloppy)); | 2460 : Runtime::kStoreKeyedToSuper_Sloppy); |
| 2436 } | 2461 } |
| 2437 | 2462 |
| 2438 | 2463 |
| 2439 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2464 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2440 // Assignment to a property, using a keyed store IC. | 2465 // Assignment to a property, using a keyed store IC. |
| 2441 // eax : value | 2466 // eax : value |
| 2442 // esp[0] : key | 2467 // esp[0] : key |
| 2443 // esp[kPointerSize] : receiver | 2468 // esp[kPointerSize] : receiver |
| 2444 | 2469 |
| 2445 __ pop(StoreDescriptor::NameRegister()); // Key. | 2470 PopOperand(StoreDescriptor::NameRegister()); // Key. |
| 2446 __ pop(StoreDescriptor::ReceiverRegister()); | 2471 PopOperand(StoreDescriptor::ReceiverRegister()); |
| 2447 DCHECK(StoreDescriptor::ValueRegister().is(eax)); | 2472 DCHECK(StoreDescriptor::ValueRegister().is(eax)); |
| 2448 Handle<Code> ic = | 2473 Handle<Code> ic = |
| 2449 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 2474 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 2450 EmitLoadStoreICSlot(expr->AssignmentSlot()); | 2475 EmitLoadStoreICSlot(expr->AssignmentSlot()); |
| 2451 CallIC(ic); | 2476 CallIC(ic); |
| 2452 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2477 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2453 context()->Plug(eax); | 2478 context()->Plug(eax); |
| 2454 } | 2479 } |
| 2455 | 2480 |
| 2456 | 2481 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2468 } else { | 2493 } else { |
| 2469 VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var()); | 2494 VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var()); |
| 2470 VisitForStackValue( | 2495 VisitForStackValue( |
| 2471 expr->obj()->AsSuperPropertyReference()->home_object()); | 2496 expr->obj()->AsSuperPropertyReference()->home_object()); |
| 2472 EmitNamedSuperPropertyLoad(expr); | 2497 EmitNamedSuperPropertyLoad(expr); |
| 2473 } | 2498 } |
| 2474 } else { | 2499 } else { |
| 2475 if (!expr->IsSuperAccess()) { | 2500 if (!expr->IsSuperAccess()) { |
| 2476 VisitForStackValue(expr->obj()); | 2501 VisitForStackValue(expr->obj()); |
| 2477 VisitForAccumulatorValue(expr->key()); | 2502 VisitForAccumulatorValue(expr->key()); |
| 2478 __ pop(LoadDescriptor::ReceiverRegister()); // Object. | 2503 PopOperand(LoadDescriptor::ReceiverRegister()); // Object. |
| 2479 __ Move(LoadDescriptor::NameRegister(), result_register()); // Key. | 2504 __ Move(LoadDescriptor::NameRegister(), result_register()); // Key. |
| 2480 EmitKeyedPropertyLoad(expr); | 2505 EmitKeyedPropertyLoad(expr); |
| 2481 } else { | 2506 } else { |
| 2482 VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var()); | 2507 VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var()); |
| 2483 VisitForStackValue( | 2508 VisitForStackValue( |
| 2484 expr->obj()->AsSuperPropertyReference()->home_object()); | 2509 expr->obj()->AsSuperPropertyReference()->home_object()); |
| 2485 VisitForStackValue(expr->key()); | 2510 VisitForStackValue(expr->key()); |
| 2486 EmitKeyedSuperPropertyLoad(expr); | 2511 EmitKeyedSuperPropertyLoad(expr); |
| 2487 } | 2512 } |
| 2488 } | 2513 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2504 | 2529 |
| 2505 // Get the target function. | 2530 // Get the target function. |
| 2506 ConvertReceiverMode convert_mode; | 2531 ConvertReceiverMode convert_mode; |
| 2507 if (callee->IsVariableProxy()) { | 2532 if (callee->IsVariableProxy()) { |
| 2508 { StackValueContext context(this); | 2533 { StackValueContext context(this); |
| 2509 EmitVariableLoad(callee->AsVariableProxy()); | 2534 EmitVariableLoad(callee->AsVariableProxy()); |
| 2510 PrepareForBailout(callee, NO_REGISTERS); | 2535 PrepareForBailout(callee, NO_REGISTERS); |
| 2511 } | 2536 } |
| 2512 // Push undefined as receiver. This is patched in the method prologue if it | 2537 // Push undefined as receiver. This is patched in the method prologue if it |
| 2513 // is a sloppy mode method. | 2538 // is a sloppy mode method. |
| 2514 __ push(Immediate(isolate()->factory()->undefined_value())); | 2539 PushOperand(isolate()->factory()->undefined_value()); |
| 2515 convert_mode = ConvertReceiverMode::kNullOrUndefined; | 2540 convert_mode = ConvertReceiverMode::kNullOrUndefined; |
| 2516 } else { | 2541 } else { |
| 2517 // Load the function from the receiver. | 2542 // Load the function from the receiver. |
| 2518 DCHECK(callee->IsProperty()); | 2543 DCHECK(callee->IsProperty()); |
| 2519 DCHECK(!callee->AsProperty()->IsSuperAccess()); | 2544 DCHECK(!callee->AsProperty()->IsSuperAccess()); |
| 2520 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 2545 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 2521 EmitNamedPropertyLoad(callee->AsProperty()); | 2546 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2522 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2547 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2523 // Push the target function under the receiver. | 2548 // Push the target function under the receiver. |
| 2524 __ push(Operand(esp, 0)); | 2549 PushOperand(Operand(esp, 0)); |
| 2525 __ mov(Operand(esp, kPointerSize), eax); | 2550 __ mov(Operand(esp, kPointerSize), eax); |
| 2526 convert_mode = ConvertReceiverMode::kNotNullOrUndefined; | 2551 convert_mode = ConvertReceiverMode::kNotNullOrUndefined; |
| 2527 } | 2552 } |
| 2528 | 2553 |
| 2529 EmitCall(expr, convert_mode); | 2554 EmitCall(expr, convert_mode); |
| 2530 } | 2555 } |
| 2531 | 2556 |
| 2532 | 2557 |
| 2533 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { | 2558 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
| 2534 SetExpressionPosition(expr); | 2559 SetExpressionPosition(expr); |
| 2535 Expression* callee = expr->expression(); | 2560 Expression* callee = expr->expression(); |
| 2536 DCHECK(callee->IsProperty()); | 2561 DCHECK(callee->IsProperty()); |
| 2537 Property* prop = callee->AsProperty(); | 2562 Property* prop = callee->AsProperty(); |
| 2538 DCHECK(prop->IsSuperAccess()); | 2563 DCHECK(prop->IsSuperAccess()); |
| 2539 | 2564 |
| 2540 Literal* key = prop->key()->AsLiteral(); | 2565 Literal* key = prop->key()->AsLiteral(); |
| 2541 DCHECK(!key->value()->IsSmi()); | 2566 DCHECK(!key->value()->IsSmi()); |
| 2542 // Load the function from the receiver. | 2567 // Load the function from the receiver. |
| 2543 SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); | 2568 SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); |
| 2544 VisitForStackValue(super_ref->home_object()); | 2569 VisitForStackValue(super_ref->home_object()); |
| 2545 VisitForAccumulatorValue(super_ref->this_var()); | 2570 VisitForAccumulatorValue(super_ref->this_var()); |
| 2546 __ push(eax); | 2571 PushOperand(eax); |
| 2547 __ push(eax); | 2572 PushOperand(eax); |
| 2548 __ push(Operand(esp, kPointerSize * 2)); | 2573 PushOperand(Operand(esp, kPointerSize * 2)); |
| 2549 __ push(Immediate(key->value())); | 2574 PushOperand(key->value()); |
| 2550 // Stack here: | 2575 // Stack here: |
| 2551 // - home_object | 2576 // - home_object |
| 2552 // - this (receiver) | 2577 // - this (receiver) |
| 2553 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2578 // - this (receiver) <-- LoadFromSuper will pop here and below. |
| 2554 // - home_object | 2579 // - home_object |
| 2555 // - key | 2580 // - key |
| 2556 __ CallRuntime(Runtime::kLoadFromSuper); | 2581 CallRuntimeWithOperands(Runtime::kLoadFromSuper); |
| 2557 | 2582 |
| 2558 // Replace home_object with target function. | 2583 // Replace home_object with target function. |
| 2559 __ mov(Operand(esp, kPointerSize), eax); | 2584 __ mov(Operand(esp, kPointerSize), eax); |
| 2560 | 2585 |
| 2561 // Stack here: | 2586 // Stack here: |
| 2562 // - target function | 2587 // - target function |
| 2563 // - this (receiver) | 2588 // - this (receiver) |
| 2564 EmitCall(expr); | 2589 EmitCall(expr); |
| 2565 } | 2590 } |
| 2566 | 2591 |
| 2567 | 2592 |
| 2568 // Code common for calls using the IC. | 2593 // Code common for calls using the IC. |
| 2569 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2594 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
| 2570 Expression* key) { | 2595 Expression* key) { |
| 2571 // Load the key. | 2596 // Load the key. |
| 2572 VisitForAccumulatorValue(key); | 2597 VisitForAccumulatorValue(key); |
| 2573 | 2598 |
| 2574 Expression* callee = expr->expression(); | 2599 Expression* callee = expr->expression(); |
| 2575 | 2600 |
| 2576 // Load the function from the receiver. | 2601 // Load the function from the receiver. |
| 2577 DCHECK(callee->IsProperty()); | 2602 DCHECK(callee->IsProperty()); |
| 2578 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 2603 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 2579 __ mov(LoadDescriptor::NameRegister(), eax); | 2604 __ mov(LoadDescriptor::NameRegister(), eax); |
| 2580 EmitKeyedPropertyLoad(callee->AsProperty()); | 2605 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2581 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2606 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2582 | 2607 |
| 2583 // Push the target function under the receiver. | 2608 // Push the target function under the receiver. |
| 2584 __ push(Operand(esp, 0)); | 2609 PushOperand(Operand(esp, 0)); |
| 2585 __ mov(Operand(esp, kPointerSize), eax); | 2610 __ mov(Operand(esp, kPointerSize), eax); |
| 2586 | 2611 |
| 2587 EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); | 2612 EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); |
| 2588 } | 2613 } |
| 2589 | 2614 |
| 2590 | 2615 |
| 2591 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { | 2616 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { |
| 2592 Expression* callee = expr->expression(); | 2617 Expression* callee = expr->expression(); |
| 2593 DCHECK(callee->IsProperty()); | 2618 DCHECK(callee->IsProperty()); |
| 2594 Property* prop = callee->AsProperty(); | 2619 Property* prop = callee->AsProperty(); |
| 2595 DCHECK(prop->IsSuperAccess()); | 2620 DCHECK(prop->IsSuperAccess()); |
| 2596 | 2621 |
| 2597 SetExpressionPosition(prop); | 2622 SetExpressionPosition(prop); |
| 2598 // Load the function from the receiver. | 2623 // Load the function from the receiver. |
| 2599 SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); | 2624 SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); |
| 2600 VisitForStackValue(super_ref->home_object()); | 2625 VisitForStackValue(super_ref->home_object()); |
| 2601 VisitForAccumulatorValue(super_ref->this_var()); | 2626 VisitForAccumulatorValue(super_ref->this_var()); |
| 2602 __ push(eax); | 2627 PushOperand(eax); |
| 2603 __ push(eax); | 2628 PushOperand(eax); |
| 2604 __ push(Operand(esp, kPointerSize * 2)); | 2629 PushOperand(Operand(esp, kPointerSize * 2)); |
| 2605 VisitForStackValue(prop->key()); | 2630 VisitForStackValue(prop->key()); |
| 2606 // Stack here: | 2631 // Stack here: |
| 2607 // - home_object | 2632 // - home_object |
| 2608 // - this (receiver) | 2633 // - this (receiver) |
| 2609 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2634 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
| 2610 // - home_object | 2635 // - home_object |
| 2611 // - key | 2636 // - key |
| 2612 __ CallRuntime(Runtime::kLoadKeyedFromSuper); | 2637 CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); |
| 2613 | 2638 |
| 2614 // Replace home_object with target function. | 2639 // Replace home_object with target function. |
| 2615 __ mov(Operand(esp, kPointerSize), eax); | 2640 __ mov(Operand(esp, kPointerSize), eax); |
| 2616 | 2641 |
| 2617 // Stack here: | 2642 // Stack here: |
| 2618 // - target function | 2643 // - target function |
| 2619 // - this (receiver) | 2644 // - this (receiver) |
| 2620 EmitCall(expr); | 2645 EmitCall(expr); |
| 2621 } | 2646 } |
| 2622 | 2647 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2640 EmitProfilingCounterHandlingForReturnSequence(true); | 2665 EmitProfilingCounterHandlingForReturnSequence(true); |
| 2641 } | 2666 } |
| 2642 Handle<Code> ic = | 2667 Handle<Code> ic = |
| 2643 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) | 2668 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) |
| 2644 .code(); | 2669 .code(); |
| 2645 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); | 2670 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); |
| 2646 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2671 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2647 // Don't assign a type feedback id to the IC, since type feedback is provided | 2672 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2648 // by the vector above. | 2673 // by the vector above. |
| 2649 CallIC(ic); | 2674 CallIC(ic); |
| 2675 OperandStackDepthDecrement(arg_count + 1); | |
| 2650 | 2676 |
| 2651 RecordJSReturnSite(expr); | 2677 RecordJSReturnSite(expr); |
| 2652 | 2678 |
| 2653 // Restore context register. | 2679 // Restore context register. |
| 2654 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2680 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2655 | 2681 |
| 2656 context()->DropAndPlug(1, eax); | 2682 context()->DropAndPlug(1, eax); |
| 2657 } | 2683 } |
| 2658 | 2684 |
| 2659 | 2685 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2687 SetExpressionPosition(callee); | 2713 SetExpressionPosition(callee); |
| 2688 // Generate code for loading from variables potentially shadowed by | 2714 // Generate code for loading from variables potentially shadowed by |
| 2689 // eval-introduced variables. | 2715 // eval-introduced variables. |
| 2690 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2716 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
| 2691 | 2717 |
| 2692 __ bind(&slow); | 2718 __ bind(&slow); |
| 2693 // Call the runtime to find the function to call (returned in eax) and | 2719 // Call the runtime to find the function to call (returned in eax) and |
| 2694 // the object holding it (returned in edx). | 2720 // the object holding it (returned in edx). |
| 2695 __ Push(callee->name()); | 2721 __ Push(callee->name()); |
| 2696 __ CallRuntime(Runtime::kLoadLookupSlotForCall); | 2722 __ CallRuntime(Runtime::kLoadLookupSlotForCall); |
| 2697 __ Push(eax); // Function. | 2723 PushOperand(eax); // Function. |
| 2698 __ Push(edx); // Receiver. | 2724 PushOperand(edx); // Receiver. |
| 2699 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2725 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
| 2700 | 2726 |
| 2701 // If fast case code has been generated, emit code to push the function | 2727 // If fast case code has been generated, emit code to push the function |
| 2702 // and receiver and have the slow path jump around this code. | 2728 // and receiver and have the slow path jump around this code. |
| 2703 if (done.is_linked()) { | 2729 if (done.is_linked()) { |
| 2704 Label call; | 2730 Label call; |
| 2705 __ jmp(&call, Label::kNear); | 2731 __ jmp(&call, Label::kNear); |
| 2706 __ bind(&done); | 2732 __ bind(&done); |
| 2707 // Push function. | 2733 // Push function. |
| 2708 __ push(eax); | 2734 __ push(eax); |
| 2709 // The receiver is implicitly the global receiver. Indicate this by | 2735 // The receiver is implicitly the global receiver. Indicate this by |
| 2710 // passing the hole to the call function stub. | 2736 // passing the hole to the call function stub. |
| 2711 __ push(Immediate(isolate()->factory()->undefined_value())); | 2737 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2712 __ bind(&call); | 2738 __ bind(&call); |
| 2713 } | 2739 } |
| 2714 } else { | 2740 } else { |
| 2715 VisitForStackValue(callee); | 2741 VisitForStackValue(callee); |
| 2716 // refEnv.WithBaseObject() | 2742 // refEnv.WithBaseObject() |
| 2717 __ push(Immediate(isolate()->factory()->undefined_value())); | 2743 PushOperand(isolate()->factory()->undefined_value()); |
| 2718 } | 2744 } |
| 2719 } | 2745 } |
| 2720 | 2746 |
| 2721 | 2747 |
| 2722 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { | 2748 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { |
| 2723 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval | 2749 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval |
| 2724 // to resolve the function we need to call. Then we call the resolved | 2750 // to resolve the function we need to call. Then we call the resolved |
| 2725 // function using the given arguments. | 2751 // function using the given arguments. |
| 2726 ZoneList<Expression*>* args = expr->arguments(); | 2752 ZoneList<Expression*>* args = expr->arguments(); |
| 2727 int arg_count = args->length(); | 2753 int arg_count = args->length(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2740 | 2766 |
| 2741 // Touch up the stack with the resolved function. | 2767 // Touch up the stack with the resolved function. |
| 2742 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | 2768 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); |
| 2743 | 2769 |
| 2744 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); | 2770 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); |
| 2745 | 2771 |
| 2746 SetCallPosition(expr); | 2772 SetCallPosition(expr); |
| 2747 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2773 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2748 __ Set(eax, arg_count); | 2774 __ Set(eax, arg_count); |
| 2749 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 2775 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 2776 OperandStackDepthDecrement(arg_count + 1); | |
| 2750 RecordJSReturnSite(expr); | 2777 RecordJSReturnSite(expr); |
| 2751 // Restore context register. | 2778 // Restore context register. |
| 2752 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2779 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2753 context()->DropAndPlug(1, eax); | 2780 context()->DropAndPlug(1, eax); |
| 2754 } | 2781 } |
| 2755 | 2782 |
| 2756 | 2783 |
| 2757 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2784 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2758 Comment cmnt(masm_, "[ CallNew"); | 2785 Comment cmnt(masm_, "[ CallNew"); |
| 2759 // According to ECMA-262, section 11.2.2, page 44, the function | 2786 // According to ECMA-262, section 11.2.2, page 44, the function |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2780 // Load function and argument count into edi and eax. | 2807 // Load function and argument count into edi and eax. |
| 2781 __ Move(eax, Immediate(arg_count)); | 2808 __ Move(eax, Immediate(arg_count)); |
| 2782 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2809 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2783 | 2810 |
| 2784 // Record call targets in unoptimized code. | 2811 // Record call targets in unoptimized code. |
| 2785 __ EmitLoadTypeFeedbackVector(ebx); | 2812 __ EmitLoadTypeFeedbackVector(ebx); |
| 2786 __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot()))); | 2813 __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot()))); |
| 2787 | 2814 |
| 2788 CallConstructStub stub(isolate()); | 2815 CallConstructStub stub(isolate()); |
| 2789 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); | 2816 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 2817 OperandStackDepthDecrement(arg_count + 1); | |
| 2790 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2818 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 2791 // Restore context register. | 2819 // Restore context register. |
| 2792 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2820 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2793 context()->Plug(eax); | 2821 context()->Plug(eax); |
| 2794 } | 2822 } |
| 2795 | 2823 |
| 2796 | 2824 |
| 2797 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { | 2825 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
| 2798 SuperCallReference* super_call_ref = | 2826 SuperCallReference* super_call_ref = |
| 2799 expr->expression()->AsSuperCallReference(); | 2827 expr->expression()->AsSuperCallReference(); |
| 2800 DCHECK_NOT_NULL(super_call_ref); | 2828 DCHECK_NOT_NULL(super_call_ref); |
| 2801 | 2829 |
| 2802 // Push the super constructor target on the stack (may be null, | 2830 // Push the super constructor target on the stack (may be null, |
| 2803 // but the Construct builtin can deal with that properly). | 2831 // but the Construct builtin can deal with that properly). |
| 2804 VisitForAccumulatorValue(super_call_ref->this_function_var()); | 2832 VisitForAccumulatorValue(super_call_ref->this_function_var()); |
| 2805 __ AssertFunction(result_register()); | 2833 __ AssertFunction(result_register()); |
| 2806 __ mov(result_register(), | 2834 __ mov(result_register(), |
| 2807 FieldOperand(result_register(), HeapObject::kMapOffset)); | 2835 FieldOperand(result_register(), HeapObject::kMapOffset)); |
| 2808 __ Push(FieldOperand(result_register(), Map::kPrototypeOffset)); | 2836 PushOperand(FieldOperand(result_register(), Map::kPrototypeOffset)); |
| 2809 | 2837 |
| 2810 // Push the arguments ("left-to-right") on the stack. | 2838 // Push the arguments ("left-to-right") on the stack. |
| 2811 ZoneList<Expression*>* args = expr->arguments(); | 2839 ZoneList<Expression*>* args = expr->arguments(); |
| 2812 int arg_count = args->length(); | 2840 int arg_count = args->length(); |
| 2813 for (int i = 0; i < arg_count; i++) { | 2841 for (int i = 0; i < arg_count; i++) { |
| 2814 VisitForStackValue(args->at(i)); | 2842 VisitForStackValue(args->at(i)); |
| 2815 } | 2843 } |
| 2816 | 2844 |
| 2817 // Call the construct call builtin that handles allocation and | 2845 // Call the construct call builtin that handles allocation and |
| 2818 // constructor invocation. | 2846 // constructor invocation. |
| 2819 SetConstructCallPosition(expr); | 2847 SetConstructCallPosition(expr); |
| 2820 | 2848 |
| 2821 // Load new target into edx. | 2849 // Load new target into edx. |
| 2822 VisitForAccumulatorValue(super_call_ref->new_target_var()); | 2850 VisitForAccumulatorValue(super_call_ref->new_target_var()); |
| 2823 __ mov(edx, result_register()); | 2851 __ mov(edx, result_register()); |
| 2824 | 2852 |
| 2825 // Load function and argument count into edi and eax. | 2853 // Load function and argument count into edi and eax. |
| 2826 __ Move(eax, Immediate(arg_count)); | 2854 __ Move(eax, Immediate(arg_count)); |
| 2827 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2855 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2828 | 2856 |
| 2829 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2857 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2858 OperandStackDepthDecrement(arg_count + 1); | |
| 2830 | 2859 |
| 2831 RecordJSReturnSite(expr); | 2860 RecordJSReturnSite(expr); |
| 2832 | 2861 |
| 2833 // Restore context register. | 2862 // Restore context register. |
| 2834 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2863 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2835 context()->Plug(eax); | 2864 context()->Plug(eax); |
| 2836 } | 2865 } |
| 2837 | 2866 |
| 2838 | 2867 |
| 2839 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2868 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3040 DCHECK_EQ(3, args->length()); | 3069 DCHECK_EQ(3, args->length()); |
| 3041 | 3070 |
| 3042 Register string = eax; | 3071 Register string = eax; |
| 3043 Register index = ebx; | 3072 Register index = ebx; |
| 3044 Register value = ecx; | 3073 Register value = ecx; |
| 3045 | 3074 |
| 3046 VisitForStackValue(args->at(0)); // index | 3075 VisitForStackValue(args->at(0)); // index |
| 3047 VisitForStackValue(args->at(1)); // value | 3076 VisitForStackValue(args->at(1)); // value |
| 3048 VisitForAccumulatorValue(args->at(2)); // string | 3077 VisitForAccumulatorValue(args->at(2)); // string |
| 3049 | 3078 |
| 3050 __ pop(value); | 3079 PopOperand(value); |
| 3051 __ pop(index); | 3080 PopOperand(index); |
| 3052 | 3081 |
| 3053 if (FLAG_debug_code) { | 3082 if (FLAG_debug_code) { |
| 3054 __ test(value, Immediate(kSmiTagMask)); | 3083 __ test(value, Immediate(kSmiTagMask)); |
| 3055 __ Check(zero, kNonSmiValue); | 3084 __ Check(zero, kNonSmiValue); |
| 3056 __ test(index, Immediate(kSmiTagMask)); | 3085 __ test(index, Immediate(kSmiTagMask)); |
| 3057 __ Check(zero, kNonSmiValue); | 3086 __ Check(zero, kNonSmiValue); |
| 3058 } | 3087 } |
| 3059 | 3088 |
| 3060 __ SmiUntag(value); | 3089 __ SmiUntag(value); |
| 3061 __ SmiUntag(index); | 3090 __ SmiUntag(index); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 3075 ZoneList<Expression*>* args = expr->arguments(); | 3104 ZoneList<Expression*>* args = expr->arguments(); |
| 3076 DCHECK_EQ(3, args->length()); | 3105 DCHECK_EQ(3, args->length()); |
| 3077 | 3106 |
| 3078 Register string = eax; | 3107 Register string = eax; |
| 3079 Register index = ebx; | 3108 Register index = ebx; |
| 3080 Register value = ecx; | 3109 Register value = ecx; |
| 3081 | 3110 |
| 3082 VisitForStackValue(args->at(0)); // index | 3111 VisitForStackValue(args->at(0)); // index |
| 3083 VisitForStackValue(args->at(1)); // value | 3112 VisitForStackValue(args->at(1)); // value |
| 3084 VisitForAccumulatorValue(args->at(2)); // string | 3113 VisitForAccumulatorValue(args->at(2)); // string |
| 3085 __ pop(value); | 3114 PopOperand(value); |
| 3086 __ pop(index); | 3115 PopOperand(index); |
| 3087 | 3116 |
| 3088 if (FLAG_debug_code) { | 3117 if (FLAG_debug_code) { |
| 3089 __ test(value, Immediate(kSmiTagMask)); | 3118 __ test(value, Immediate(kSmiTagMask)); |
| 3090 __ Check(zero, kNonSmiValue); | 3119 __ Check(zero, kNonSmiValue); |
| 3091 __ test(index, Immediate(kSmiTagMask)); | 3120 __ test(index, Immediate(kSmiTagMask)); |
| 3092 __ Check(zero, kNonSmiValue); | 3121 __ Check(zero, kNonSmiValue); |
| 3093 __ SmiUntag(index); | 3122 __ SmiUntag(index); |
| 3094 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 3123 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 3095 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); | 3124 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); |
| 3096 __ SmiTag(index); | 3125 __ SmiTag(index); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3144 ZoneList<Expression*>* args = expr->arguments(); | 3173 ZoneList<Expression*>* args = expr->arguments(); |
| 3145 DCHECK(args->length() == 2); | 3174 DCHECK(args->length() == 2); |
| 3146 | 3175 |
| 3147 VisitForStackValue(args->at(0)); | 3176 VisitForStackValue(args->at(0)); |
| 3148 VisitForAccumulatorValue(args->at(1)); | 3177 VisitForAccumulatorValue(args->at(1)); |
| 3149 | 3178 |
| 3150 Register object = ebx; | 3179 Register object = ebx; |
| 3151 Register index = eax; | 3180 Register index = eax; |
| 3152 Register result = edx; | 3181 Register result = edx; |
| 3153 | 3182 |
| 3154 __ pop(object); | 3183 PopOperand(object); |
| 3155 | 3184 |
| 3156 Label need_conversion; | 3185 Label need_conversion; |
| 3157 Label index_out_of_range; | 3186 Label index_out_of_range; |
| 3158 Label done; | 3187 Label done; |
| 3159 StringCharCodeAtGenerator generator(object, | 3188 StringCharCodeAtGenerator generator(object, |
| 3160 index, | 3189 index, |
| 3161 result, | 3190 result, |
| 3162 &need_conversion, | 3191 &need_conversion, |
| 3163 &need_conversion, | 3192 &need_conversion, |
| 3164 &index_out_of_range, | 3193 &index_out_of_range, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 3191 DCHECK(args->length() == 2); | 3220 DCHECK(args->length() == 2); |
| 3192 | 3221 |
| 3193 VisitForStackValue(args->at(0)); | 3222 VisitForStackValue(args->at(0)); |
| 3194 VisitForAccumulatorValue(args->at(1)); | 3223 VisitForAccumulatorValue(args->at(1)); |
| 3195 | 3224 |
| 3196 Register object = ebx; | 3225 Register object = ebx; |
| 3197 Register index = eax; | 3226 Register index = eax; |
| 3198 Register scratch = edx; | 3227 Register scratch = edx; |
| 3199 Register result = eax; | 3228 Register result = eax; |
| 3200 | 3229 |
| 3201 __ pop(object); | 3230 PopOperand(object); |
| 3202 | 3231 |
| 3203 Label need_conversion; | 3232 Label need_conversion; |
| 3204 Label index_out_of_range; | 3233 Label index_out_of_range; |
| 3205 Label done; | 3234 Label done; |
| 3206 StringCharAtGenerator generator(object, | 3235 StringCharAtGenerator generator(object, |
| 3207 index, | 3236 index, |
| 3208 scratch, | 3237 scratch, |
| 3209 result, | 3238 result, |
| 3210 &need_conversion, | 3239 &need_conversion, |
| 3211 &need_conversion, | 3240 &need_conversion, |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 3241 for (Expression* const arg : *args) { | 3270 for (Expression* const arg : *args) { |
| 3242 VisitForStackValue(arg); | 3271 VisitForStackValue(arg); |
| 3243 } | 3272 } |
| 3244 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 3273 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
| 3245 // Move target to edi. | 3274 // Move target to edi. |
| 3246 int const argc = args->length() - 2; | 3275 int const argc = args->length() - 2; |
| 3247 __ mov(edi, Operand(esp, (argc + 1) * kPointerSize)); | 3276 __ mov(edi, Operand(esp, (argc + 1) * kPointerSize)); |
| 3248 // Call the target. | 3277 // Call the target. |
| 3249 __ mov(eax, Immediate(argc)); | 3278 __ mov(eax, Immediate(argc)); |
| 3250 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 3279 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 3280 OperandStackDepthDecrement(argc + 1); | |
| 3251 // Restore context register. | 3281 // Restore context register. |
| 3252 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3282 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3253 // Discard the function left on TOS. | 3283 // Discard the function left on TOS. |
| 3254 context()->DropAndPlug(1, eax); | 3284 context()->DropAndPlug(1, eax); |
| 3255 } | 3285 } |
| 3256 | 3286 |
| 3257 | 3287 |
| 3258 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3288 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3259 ZoneList<Expression*>* args = expr->arguments(); | 3289 ZoneList<Expression*>* args = expr->arguments(); |
| 3260 DCHECK(args->length() == 1); | 3290 DCHECK(args->length() == 1); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3327 | 3357 |
| 3328 Register scratch = ebx; | 3358 Register scratch = ebx; |
| 3329 | 3359 |
| 3330 Register array_length = edi; | 3360 Register array_length = edi; |
| 3331 Register result_pos = no_reg; // Will be edi. | 3361 Register result_pos = no_reg; // Will be edi. |
| 3332 | 3362 |
| 3333 // Separator operand is already pushed. | 3363 // Separator operand is already pushed. |
| 3334 Operand separator_operand = Operand(esp, 2 * kPointerSize); | 3364 Operand separator_operand = Operand(esp, 2 * kPointerSize); |
| 3335 Operand result_operand = Operand(esp, 1 * kPointerSize); | 3365 Operand result_operand = Operand(esp, 1 * kPointerSize); |
| 3336 Operand array_length_operand = Operand(esp, 0); | 3366 Operand array_length_operand = Operand(esp, 0); |
| 3367 OperandStackDepthIncrement(2); | |
| 3337 __ sub(esp, Immediate(2 * kPointerSize)); | 3368 __ sub(esp, Immediate(2 * kPointerSize)); |
| 3338 __ cld(); | 3369 __ cld(); |
| 3339 // Check that the array is a JSArray | 3370 // Check that the array is a JSArray |
| 3340 __ JumpIfSmi(array, &bailout); | 3371 __ JumpIfSmi(array, &bailout); |
| 3341 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); | 3372 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); |
| 3342 __ j(not_equal, &bailout); | 3373 __ j(not_equal, &bailout); |
| 3343 | 3374 |
| 3344 // Check that the array has fast elements. | 3375 // Check that the array has fast elements. |
| 3345 __ CheckFastElements(scratch, &bailout); | 3376 __ CheckFastElements(scratch, &bailout); |
| 3346 | 3377 |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3559 __ cmp(index, array_length_operand); | 3590 __ cmp(index, array_length_operand); |
| 3560 __ j(less, &loop_3); // End while (index < length). | 3591 __ j(less, &loop_3); // End while (index < length). |
| 3561 __ jmp(&done); | 3592 __ jmp(&done); |
| 3562 | 3593 |
| 3563 | 3594 |
| 3564 __ bind(&bailout); | 3595 __ bind(&bailout); |
| 3565 __ mov(result_operand, isolate()->factory()->undefined_value()); | 3596 __ mov(result_operand, isolate()->factory()->undefined_value()); |
| 3566 __ bind(&done); | 3597 __ bind(&done); |
| 3567 __ mov(eax, result_operand); | 3598 __ mov(eax, result_operand); |
| 3568 // Drop temp values from the stack, and restore context register. | 3599 // Drop temp values from the stack, and restore context register. |
| 3600 OperandStackDepthDecrement(3); | |
| 3569 __ add(esp, Immediate(3 * kPointerSize)); | 3601 __ add(esp, Immediate(3 * kPointerSize)); |
| 3570 | 3602 |
| 3571 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3603 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3572 context()->Plug(eax); | 3604 context()->Plug(eax); |
| 3573 } | 3605 } |
| 3574 | 3606 |
| 3575 | 3607 |
| 3576 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 3608 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
| 3577 DCHECK(expr->arguments()->length() == 0); | 3609 DCHECK(expr->arguments()->length() == 0); |
| 3578 ExternalReference debug_is_active = | 3610 ExternalReference debug_is_active = |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 3598 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 3630 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 3599 isolate()->factory()->empty_fixed_array()); | 3631 isolate()->factory()->empty_fixed_array()); |
| 3600 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 3632 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 3601 isolate()->factory()->empty_fixed_array()); | 3633 isolate()->factory()->empty_fixed_array()); |
| 3602 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); | 3634 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); |
| 3603 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 3635 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
| 3604 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 3636 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 3605 __ jmp(&done, Label::kNear); | 3637 __ jmp(&done, Label::kNear); |
| 3606 | 3638 |
| 3607 __ bind(&runtime); | 3639 __ bind(&runtime); |
| 3608 __ CallRuntime(Runtime::kCreateIterResultObject); | 3640 CallRuntimeWithOperands(Runtime::kCreateIterResultObject); |
| 3609 | 3641 |
| 3610 __ bind(&done); | 3642 __ bind(&done); |
| 3611 context()->Plug(eax); | 3643 context()->Plug(eax); |
| 3612 } | 3644 } |
| 3613 | 3645 |
| 3614 | 3646 |
| 3615 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 3647 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 3616 // Push undefined as receiver. | 3648 // Push undefined as receiver. |
| 3617 __ push(Immediate(isolate()->factory()->undefined_value())); | 3649 PushOperand(isolate()->factory()->undefined_value()); |
| 3618 | 3650 |
| 3619 __ LoadGlobalFunction(expr->context_index(), eax); | 3651 __ LoadGlobalFunction(expr->context_index(), eax); |
| 3620 } | 3652 } |
| 3621 | 3653 |
| 3622 | 3654 |
| 3623 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 3655 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| 3624 ZoneList<Expression*>* args = expr->arguments(); | 3656 ZoneList<Expression*>* args = expr->arguments(); |
| 3625 int arg_count = args->length(); | 3657 int arg_count = args->length(); |
| 3626 | 3658 |
| 3627 SetCallPosition(expr); | 3659 SetCallPosition(expr); |
| 3628 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 3660 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 3629 __ Set(eax, arg_count); | 3661 __ Set(eax, arg_count); |
| 3630 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), | 3662 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
| 3631 RelocInfo::CODE_TARGET); | 3663 RelocInfo::CODE_TARGET); |
| 3664 OperandStackDepthDecrement(arg_count + 1); | |
| 3632 } | 3665 } |
| 3633 | 3666 |
| 3634 | 3667 |
| 3635 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 3668 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 3636 ZoneList<Expression*>* args = expr->arguments(); | 3669 ZoneList<Expression*>* args = expr->arguments(); |
| 3637 int arg_count = args->length(); | 3670 int arg_count = args->length(); |
| 3638 | 3671 |
| 3639 if (expr->is_jsruntime()) { | 3672 if (expr->is_jsruntime()) { |
| 3640 Comment cmnt(masm_, "[ CallRuntime"); | 3673 Comment cmnt(masm_, "[ CallRuntime"); |
| 3641 EmitLoadJSRuntimeFunction(expr); | 3674 EmitLoadJSRuntimeFunction(expr); |
| 3642 | 3675 |
| 3643 // Push the target function under the receiver. | 3676 // Push the target function under the receiver. |
| 3644 __ push(Operand(esp, 0)); | 3677 PushOperand(Operand(esp, 0)); |
| 3645 __ mov(Operand(esp, kPointerSize), eax); | 3678 __ mov(Operand(esp, kPointerSize), eax); |
| 3646 | 3679 |
| 3647 // Push the arguments ("left-to-right"). | 3680 // Push the arguments ("left-to-right"). |
| 3648 for (int i = 0; i < arg_count; i++) { | 3681 for (int i = 0; i < arg_count; i++) { |
| 3649 VisitForStackValue(args->at(i)); | 3682 VisitForStackValue(args->at(i)); |
| 3650 } | 3683 } |
| 3651 | 3684 |
| 3652 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 3685 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
| 3653 EmitCallJSRuntimeFunction(expr); | 3686 EmitCallJSRuntimeFunction(expr); |
| 3654 | 3687 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 3669 default: { | 3702 default: { |
| 3670 Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic"); | 3703 Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic"); |
| 3671 // Push the arguments ("left-to-right"). | 3704 // Push the arguments ("left-to-right"). |
| 3672 for (int i = 0; i < arg_count; i++) { | 3705 for (int i = 0; i < arg_count; i++) { |
| 3673 VisitForStackValue(args->at(i)); | 3706 VisitForStackValue(args->at(i)); |
| 3674 } | 3707 } |
| 3675 | 3708 |
| 3676 // Call the C runtime function. | 3709 // Call the C runtime function. |
| 3677 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 3710 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
| 3678 __ CallRuntime(expr->function(), arg_count); | 3711 __ CallRuntime(expr->function(), arg_count); |
| 3712 OperandStackDepthDecrement(arg_count); | |
| 3679 context()->Plug(eax); | 3713 context()->Plug(eax); |
| 3680 } | 3714 } |
| 3681 } | 3715 } |
| 3682 } | 3716 } |
| 3683 } | 3717 } |
| 3684 | 3718 |
| 3685 | 3719 |
| 3686 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3720 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3687 switch (expr->op()) { | 3721 switch (expr->op()) { |
| 3688 case Token::DELETE: { | 3722 case Token::DELETE: { |
| 3689 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3723 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3690 Property* property = expr->expression()->AsProperty(); | 3724 Property* property = expr->expression()->AsProperty(); |
| 3691 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3725 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 3692 | 3726 |
| 3693 if (property != NULL) { | 3727 if (property != NULL) { |
| 3694 VisitForStackValue(property->obj()); | 3728 VisitForStackValue(property->obj()); |
| 3695 VisitForStackValue(property->key()); | 3729 VisitForStackValue(property->key()); |
| 3696 __ CallRuntime(is_strict(language_mode()) | 3730 CallRuntimeWithOperands(is_strict(language_mode()) |
| 3697 ? Runtime::kDeleteProperty_Strict | 3731 ? Runtime::kDeleteProperty_Strict |
| 3698 : Runtime::kDeleteProperty_Sloppy); | 3732 : Runtime::kDeleteProperty_Sloppy); |
| 3699 context()->Plug(eax); | 3733 context()->Plug(eax); |
| 3700 } else if (proxy != NULL) { | 3734 } else if (proxy != NULL) { |
| 3701 Variable* var = proxy->var(); | 3735 Variable* var = proxy->var(); |
| 3702 // Delete of an unqualified identifier is disallowed in strict mode but | 3736 // Delete of an unqualified identifier is disallowed in strict mode but |
| 3703 // "delete this" is allowed. | 3737 // "delete this" is allowed. |
| 3704 bool is_this = var->HasThisName(isolate()); | 3738 bool is_this = var->HasThisName(isolate()); |
| 3705 DCHECK(is_sloppy(language_mode()) || is_this); | 3739 DCHECK(is_sloppy(language_mode()) || is_this); |
| 3706 if (var->IsUnallocatedOrGlobalSlot()) { | 3740 if (var->IsUnallocatedOrGlobalSlot()) { |
| 3707 __ mov(eax, NativeContextOperand()); | 3741 __ mov(eax, NativeContextOperand()); |
| 3708 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); | 3742 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3756 // for control and plugging the control flow into the context, | 3790 // for control and plugging the control flow into the context, |
| 3757 // because we need to prepare a pair of extra administrative AST ids | 3791 // because we need to prepare a pair of extra administrative AST ids |
| 3758 // for the optimizing compiler. | 3792 // for the optimizing compiler. |
| 3759 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); | 3793 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); |
| 3760 Label materialize_true, materialize_false, done; | 3794 Label materialize_true, materialize_false, done; |
| 3761 VisitForControl(expr->expression(), | 3795 VisitForControl(expr->expression(), |
| 3762 &materialize_false, | 3796 &materialize_false, |
| 3763 &materialize_true, | 3797 &materialize_true, |
| 3764 &materialize_true); | 3798 &materialize_true); |
| 3765 __ bind(&materialize_true); | 3799 __ bind(&materialize_true); |
| 3800 if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1); | |
| 3766 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); | 3801 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
| 3767 if (context()->IsAccumulatorValue()) { | 3802 if (context()->IsAccumulatorValue()) { |
| 3768 __ mov(eax, isolate()->factory()->true_value()); | 3803 __ mov(eax, isolate()->factory()->true_value()); |
| 3769 } else { | 3804 } else { |
| 3770 __ Push(isolate()->factory()->true_value()); | 3805 __ Push(isolate()->factory()->true_value()); |
| 3771 } | 3806 } |
| 3772 __ jmp(&done, Label::kNear); | 3807 __ jmp(&done, Label::kNear); |
| 3773 __ bind(&materialize_false); | 3808 __ bind(&materialize_false); |
| 3774 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); | 3809 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); |
| 3775 if (context()->IsAccumulatorValue()) { | 3810 if (context()->IsAccumulatorValue()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3810 LhsKind assign_type = Property::GetAssignType(prop); | 3845 LhsKind assign_type = Property::GetAssignType(prop); |
| 3811 | 3846 |
| 3812 // Evaluate expression and get value. | 3847 // Evaluate expression and get value. |
| 3813 if (assign_type == VARIABLE) { | 3848 if (assign_type == VARIABLE) { |
| 3814 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); | 3849 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
| 3815 AccumulatorValueContext context(this); | 3850 AccumulatorValueContext context(this); |
| 3816 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 3851 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
| 3817 } else { | 3852 } else { |
| 3818 // Reserve space for result of postfix operation. | 3853 // Reserve space for result of postfix operation. |
| 3819 if (expr->is_postfix() && !context()->IsEffect()) { | 3854 if (expr->is_postfix() && !context()->IsEffect()) { |
| 3820 __ push(Immediate(Smi::FromInt(0))); | 3855 PushOperand(Smi::FromInt(0)); |
| 3821 } | 3856 } |
| 3822 switch (assign_type) { | 3857 switch (assign_type) { |
| 3823 case NAMED_PROPERTY: { | 3858 case NAMED_PROPERTY: { |
| 3824 // Put the object both on the stack and in the register. | 3859 // Put the object both on the stack and in the register. |
| 3825 VisitForStackValue(prop->obj()); | 3860 VisitForStackValue(prop->obj()); |
| 3826 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 3861 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 3827 EmitNamedPropertyLoad(prop); | 3862 EmitNamedPropertyLoad(prop); |
| 3828 break; | 3863 break; |
| 3829 } | 3864 } |
| 3830 | 3865 |
| 3831 case NAMED_SUPER_PROPERTY: { | 3866 case NAMED_SUPER_PROPERTY: { |
| 3832 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); | 3867 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
| 3833 VisitForAccumulatorValue( | 3868 VisitForAccumulatorValue( |
| 3834 prop->obj()->AsSuperPropertyReference()->home_object()); | 3869 prop->obj()->AsSuperPropertyReference()->home_object()); |
| 3835 __ push(result_register()); | 3870 PushOperand(result_register()); |
| 3836 __ push(MemOperand(esp, kPointerSize)); | 3871 PushOperand(MemOperand(esp, kPointerSize)); |
| 3837 __ push(result_register()); | 3872 PushOperand(result_register()); |
| 3838 EmitNamedSuperPropertyLoad(prop); | 3873 EmitNamedSuperPropertyLoad(prop); |
| 3839 break; | 3874 break; |
| 3840 } | 3875 } |
| 3841 | 3876 |
| 3842 case KEYED_SUPER_PROPERTY: { | 3877 case KEYED_SUPER_PROPERTY: { |
| 3843 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); | 3878 VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
| 3844 VisitForStackValue( | 3879 VisitForStackValue( |
| 3845 prop->obj()->AsSuperPropertyReference()->home_object()); | 3880 prop->obj()->AsSuperPropertyReference()->home_object()); |
| 3846 VisitForAccumulatorValue(prop->key()); | 3881 VisitForAccumulatorValue(prop->key()); |
| 3847 __ push(result_register()); | 3882 PushOperand(result_register()); |
| 3848 __ push(MemOperand(esp, 2 * kPointerSize)); | 3883 PushOperand(MemOperand(esp, 2 * kPointerSize)); |
| 3849 __ push(MemOperand(esp, 2 * kPointerSize)); | 3884 PushOperand(MemOperand(esp, 2 * kPointerSize)); |
| 3850 __ push(result_register()); | 3885 PushOperand(result_register()); |
| 3851 EmitKeyedSuperPropertyLoad(prop); | 3886 EmitKeyedSuperPropertyLoad(prop); |
| 3852 break; | 3887 break; |
| 3853 } | 3888 } |
| 3854 | 3889 |
| 3855 case KEYED_PROPERTY: { | 3890 case KEYED_PROPERTY: { |
| 3856 VisitForStackValue(prop->obj()); | 3891 VisitForStackValue(prop->obj()); |
| 3857 VisitForStackValue(prop->key()); | 3892 VisitForStackValue(prop->key()); |
| 3858 __ mov(LoadDescriptor::ReceiverRegister(), | 3893 __ mov(LoadDescriptor::ReceiverRegister(), |
| 3859 Operand(esp, kPointerSize)); // Object. | 3894 Operand(esp, kPointerSize)); // Object. |
| 3860 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key. | 3895 __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3930 } | 3965 } |
| 3931 | 3966 |
| 3932 // Save result for postfix expressions. | 3967 // Save result for postfix expressions. |
| 3933 if (expr->is_postfix()) { | 3968 if (expr->is_postfix()) { |
| 3934 if (!context()->IsEffect()) { | 3969 if (!context()->IsEffect()) { |
| 3935 // Save the result on the stack. If we have a named or keyed property | 3970 // Save the result on the stack. If we have a named or keyed property |
| 3936 // we store the result under the receiver that is currently on top | 3971 // we store the result under the receiver that is currently on top |
| 3937 // of the stack. | 3972 // of the stack. |
| 3938 switch (assign_type) { | 3973 switch (assign_type) { |
| 3939 case VARIABLE: | 3974 case VARIABLE: |
| 3940 __ push(eax); | 3975 PushOperand(eax); |
| 3941 break; | 3976 break; |
| 3942 case NAMED_PROPERTY: | 3977 case NAMED_PROPERTY: |
| 3943 __ mov(Operand(esp, kPointerSize), eax); | 3978 __ mov(Operand(esp, kPointerSize), eax); |
| 3944 break; | 3979 break; |
| 3945 case NAMED_SUPER_PROPERTY: | 3980 case NAMED_SUPER_PROPERTY: |
| 3946 __ mov(Operand(esp, 2 * kPointerSize), eax); | 3981 __ mov(Operand(esp, 2 * kPointerSize), eax); |
| 3947 break; | 3982 break; |
| 3948 case KEYED_PROPERTY: | 3983 case KEYED_PROPERTY: |
| 3949 __ mov(Operand(esp, 2 * kPointerSize), eax); | 3984 __ mov(Operand(esp, 2 * kPointerSize), eax); |
| 3950 break; | 3985 break; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3990 // Perform the assignment as if via '='. | 4025 // Perform the assignment as if via '='. |
| 3991 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4026 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3992 Token::ASSIGN, expr->CountSlot()); | 4027 Token::ASSIGN, expr->CountSlot()); |
| 3993 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4028 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3994 context()->Plug(eax); | 4029 context()->Plug(eax); |
| 3995 } | 4030 } |
| 3996 break; | 4031 break; |
| 3997 case NAMED_PROPERTY: { | 4032 case NAMED_PROPERTY: { |
| 3998 __ mov(StoreDescriptor::NameRegister(), | 4033 __ mov(StoreDescriptor::NameRegister(), |
| 3999 prop->key()->AsLiteral()->value()); | 4034 prop->key()->AsLiteral()->value()); |
| 4000 __ pop(StoreDescriptor::ReceiverRegister()); | 4035 PopOperand(StoreDescriptor::ReceiverRegister()); |
| 4001 EmitLoadStoreICSlot(expr->CountSlot()); | 4036 EmitLoadStoreICSlot(expr->CountSlot()); |
| 4002 CallStoreIC(); | 4037 CallStoreIC(); |
| 4003 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4038 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4004 if (expr->is_postfix()) { | 4039 if (expr->is_postfix()) { |
| 4005 if (!context()->IsEffect()) { | 4040 if (!context()->IsEffect()) { |
| 4006 context()->PlugTOS(); | 4041 context()->PlugTOS(); |
| 4007 } | 4042 } |
| 4008 } else { | 4043 } else { |
| 4009 context()->Plug(eax); | 4044 context()->Plug(eax); |
| 4010 } | 4045 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 4026 if (expr->is_postfix()) { | 4061 if (expr->is_postfix()) { |
| 4027 if (!context()->IsEffect()) { | 4062 if (!context()->IsEffect()) { |
| 4028 context()->PlugTOS(); | 4063 context()->PlugTOS(); |
| 4029 } | 4064 } |
| 4030 } else { | 4065 } else { |
| 4031 context()->Plug(eax); | 4066 context()->Plug(eax); |
| 4032 } | 4067 } |
| 4033 break; | 4068 break; |
| 4034 } | 4069 } |
| 4035 case KEYED_PROPERTY: { | 4070 case KEYED_PROPERTY: { |
| 4036 __ pop(StoreDescriptor::NameRegister()); | 4071 PopOperand(StoreDescriptor::NameRegister()); |
| 4037 __ pop(StoreDescriptor::ReceiverRegister()); | 4072 PopOperand(StoreDescriptor::ReceiverRegister()); |
| 4038 Handle<Code> ic = | 4073 Handle<Code> ic = |
| 4039 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 4074 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 4040 EmitLoadStoreICSlot(expr->CountSlot()); | 4075 EmitLoadStoreICSlot(expr->CountSlot()); |
| 4041 CallIC(ic); | 4076 CallIC(ic); |
| 4042 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4077 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4043 if (expr->is_postfix()) { | 4078 if (expr->is_postfix()) { |
| 4044 // Result is on the stack | 4079 // Result is on the stack |
| 4045 if (!context()->IsEffect()) { | 4080 if (!context()->IsEffect()) { |
| 4046 context()->PlugTOS(); | 4081 context()->PlugTOS(); |
| 4047 } | 4082 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4148 Label* if_false = NULL; | 4183 Label* if_false = NULL; |
| 4149 Label* fall_through = NULL; | 4184 Label* fall_through = NULL; |
| 4150 context()->PrepareTest(&materialize_true, &materialize_false, | 4185 context()->PrepareTest(&materialize_true, &materialize_false, |
| 4151 &if_true, &if_false, &fall_through); | 4186 &if_true, &if_false, &fall_through); |
| 4152 | 4187 |
| 4153 Token::Value op = expr->op(); | 4188 Token::Value op = expr->op(); |
| 4154 VisitForStackValue(expr->left()); | 4189 VisitForStackValue(expr->left()); |
| 4155 switch (op) { | 4190 switch (op) { |
| 4156 case Token::IN: | 4191 case Token::IN: |
| 4157 VisitForStackValue(expr->right()); | 4192 VisitForStackValue(expr->right()); |
| 4158 __ CallRuntime(Runtime::kHasProperty); | 4193 CallRuntimeWithOperands(Runtime::kHasProperty); |
| 4159 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4194 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 4160 __ cmp(eax, isolate()->factory()->true_value()); | 4195 __ cmp(eax, isolate()->factory()->true_value()); |
| 4161 Split(equal, if_true, if_false, fall_through); | 4196 Split(equal, if_true, if_false, fall_through); |
| 4162 break; | 4197 break; |
| 4163 | 4198 |
| 4164 case Token::INSTANCEOF: { | 4199 case Token::INSTANCEOF: { |
| 4165 VisitForAccumulatorValue(expr->right()); | 4200 VisitForAccumulatorValue(expr->right()); |
| 4166 __ Pop(edx); | 4201 PopOperand(edx); |
| 4167 InstanceOfStub stub(isolate()); | 4202 InstanceOfStub stub(isolate()); |
| 4168 __ CallStub(&stub); | 4203 __ CallStub(&stub); |
| 4169 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4204 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 4170 __ cmp(eax, isolate()->factory()->true_value()); | 4205 __ cmp(eax, isolate()->factory()->true_value()); |
| 4171 Split(equal, if_true, if_false, fall_through); | 4206 Split(equal, if_true, if_false, fall_through); |
| 4172 break; | 4207 break; |
| 4173 } | 4208 } |
| 4174 | 4209 |
| 4175 default: { | 4210 default: { |
| 4176 VisitForAccumulatorValue(expr->right()); | 4211 VisitForAccumulatorValue(expr->right()); |
| 4177 Condition cc = CompareIC::ComputeCondition(op); | 4212 Condition cc = CompareIC::ComputeCondition(op); |
| 4178 __ pop(edx); | 4213 PopOperand(edx); |
| 4179 | 4214 |
| 4180 bool inline_smi_code = ShouldInlineSmiCase(op); | 4215 bool inline_smi_code = ShouldInlineSmiCase(op); |
| 4181 JumpPatchSite patch_site(masm_); | 4216 JumpPatchSite patch_site(masm_); |
| 4182 if (inline_smi_code) { | 4217 if (inline_smi_code) { |
| 4183 Label slow_case; | 4218 Label slow_case; |
| 4184 __ mov(ecx, edx); | 4219 __ mov(ecx, edx); |
| 4185 __ or_(ecx, eax); | 4220 __ or_(ecx, eax); |
| 4186 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4221 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
| 4187 __ cmp(edx, eax); | 4222 __ cmp(edx, eax); |
| 4188 Split(cc, if_true, if_false, NULL); | 4223 Split(cc, if_true, if_false, NULL); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4262 | 4297 |
| 4263 | 4298 |
| 4264 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4299 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
| 4265 Scope* closure_scope = scope()->ClosureScope(); | 4300 Scope* closure_scope = scope()->ClosureScope(); |
| 4266 if (closure_scope->is_script_scope() || | 4301 if (closure_scope->is_script_scope() || |
| 4267 closure_scope->is_module_scope()) { | 4302 closure_scope->is_module_scope()) { |
| 4268 // Contexts nested in the native context have a canonical empty function | 4303 // Contexts nested in the native context have a canonical empty function |
| 4269 // as their closure, not the anonymous closure containing the global | 4304 // as their closure, not the anonymous closure containing the global |
| 4270 // code. | 4305 // code. |
| 4271 __ mov(eax, NativeContextOperand()); | 4306 __ mov(eax, NativeContextOperand()); |
| 4272 __ push(ContextOperand(eax, Context::CLOSURE_INDEX)); | 4307 PushOperand(ContextOperand(eax, Context::CLOSURE_INDEX)); |
| 4273 } else if (closure_scope->is_eval_scope()) { | 4308 } else if (closure_scope->is_eval_scope()) { |
| 4274 // Contexts nested inside eval code have the same closure as the context | 4309 // Contexts nested inside eval code have the same closure as the context |
| 4275 // calling eval, not the anonymous closure containing the eval code. | 4310 // calling eval, not the anonymous closure containing the eval code. |
| 4276 // Fetch it from the context. | 4311 // Fetch it from the context. |
| 4277 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); | 4312 PushOperand(ContextOperand(esi, Context::CLOSURE_INDEX)); |
| 4278 } else { | 4313 } else { |
| 4279 DCHECK(closure_scope->is_function_scope()); | 4314 DCHECK(closure_scope->is_function_scope()); |
| 4280 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4315 PushOperand(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4281 } | 4316 } |
| 4282 } | 4317 } |
| 4283 | 4318 |
| 4284 | 4319 |
| 4285 // ---------------------------------------------------------------------------- | 4320 // ---------------------------------------------------------------------------- |
| 4286 // Non-local control flow support. | 4321 // Non-local control flow support. |
| 4287 | 4322 |
| 4288 void FullCodeGenerator::EnterFinallyBlock() { | 4323 void FullCodeGenerator::EnterFinallyBlock() { |
| 4289 // Store pending message while executing finally block. | 4324 // Store pending message while executing finally block. |
| 4290 ExternalReference pending_message_obj = | 4325 ExternalReference pending_message_obj = |
| 4291 ExternalReference::address_of_pending_message_obj(isolate()); | 4326 ExternalReference::address_of_pending_message_obj(isolate()); |
| 4292 __ mov(edx, Operand::StaticVariable(pending_message_obj)); | 4327 __ mov(edx, Operand::StaticVariable(pending_message_obj)); |
| 4293 __ push(edx); | 4328 PushOperand(edx); |
| 4294 | 4329 |
| 4295 ClearPendingMessage(); | 4330 ClearPendingMessage(); |
| 4296 } | 4331 } |
| 4297 | 4332 |
| 4298 | 4333 |
| 4299 void FullCodeGenerator::ExitFinallyBlock() { | 4334 void FullCodeGenerator::ExitFinallyBlock() { |
| 4300 DCHECK(!result_register().is(edx)); | 4335 DCHECK(!result_register().is(edx)); |
| 4301 // Restore pending message from stack. | 4336 // Restore pending message from stack. |
| 4302 __ pop(edx); | 4337 PopOperand(edx); |
| 4303 ExternalReference pending_message_obj = | 4338 ExternalReference pending_message_obj = |
| 4304 ExternalReference::address_of_pending_message_obj(isolate()); | 4339 ExternalReference::address_of_pending_message_obj(isolate()); |
| 4305 __ mov(Operand::StaticVariable(pending_message_obj), edx); | 4340 __ mov(Operand::StaticVariable(pending_message_obj), edx); |
| 4306 } | 4341 } |
| 4307 | 4342 |
| 4308 | 4343 |
| 4309 void FullCodeGenerator::ClearPendingMessage() { | 4344 void FullCodeGenerator::ClearPendingMessage() { |
| 4310 DCHECK(!result_register().is(edx)); | 4345 DCHECK(!result_register().is(edx)); |
| 4311 ExternalReference pending_message_obj = | 4346 ExternalReference pending_message_obj = |
| 4312 ExternalReference::address_of_pending_message_obj(isolate()); | 4347 ExternalReference::address_of_pending_message_obj(isolate()); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4425 Assembler::target_address_at(call_target_address, | 4460 Assembler::target_address_at(call_target_address, |
| 4426 unoptimized_code)); | 4461 unoptimized_code)); |
| 4427 return OSR_AFTER_STACK_CHECK; | 4462 return OSR_AFTER_STACK_CHECK; |
| 4428 } | 4463 } |
| 4429 | 4464 |
| 4430 | 4465 |
| 4431 } // namespace internal | 4466 } // namespace internal |
| 4432 } // namespace v8 | 4467 } // namespace v8 |
| 4433 | 4468 |
| 4434 #endif // V8_TARGET_ARCH_IA32 | 4469 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |