| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 182 |
| 183 // Possibly allocate a local context. | 183 // Possibly allocate a local context. |
| 184 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 184 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 185 if (heap_slots > 0) { | 185 if (heap_slots > 0) { |
| 186 Comment cmnt(masm_, "[ Allocate context"); | 186 Comment cmnt(masm_, "[ Allocate context"); |
| 187 bool need_write_barrier = true; | 187 bool need_write_barrier = true; |
| 188 // Argument to NewContext is the function, which is still in rdi. | 188 // Argument to NewContext is the function, which is still in rdi. |
| 189 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { | 189 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { |
| 190 __ Push(rdi); | 190 __ Push(rdi); |
| 191 __ Push(info->scope()->GetScopeInfo()); | 191 __ Push(info->scope()->GetScopeInfo()); |
| 192 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); | 192 __ CallRuntime(Runtime::kNewGlobalContext, 2); |
| 193 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 193 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 194 FastNewContextStub stub(isolate(), heap_slots); | 194 FastNewContextStub stub(isolate(), heap_slots); |
| 195 __ CallStub(&stub); | 195 __ CallStub(&stub); |
| 196 // Result of FastNewContextStub is always in new space. | 196 // Result of FastNewContextStub is always in new space. |
| 197 need_write_barrier = false; | 197 need_write_barrier = false; |
| 198 } else { | 198 } else { |
| 199 __ Push(rdi); | 199 __ Push(rdi); |
| 200 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); | 200 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 201 } | 201 } |
| 202 function_in_register = false; | 202 function_in_register = false; |
| 203 // Context is returned in rax. It replaces the context passed to us. | 203 // Context is returned in rax. It replaces the context passed to us. |
| 204 // It's saved in the stack and kept live in rsi. | 204 // It's saved in the stack and kept live in rsi. |
| 205 __ movp(rsi, rax); | 205 __ movp(rsi, rax); |
| 206 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); | 206 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); |
| 207 | 207 |
| 208 // Copy any necessary parameters into the context. | 208 // Copy any necessary parameters into the context. |
| 209 int num_parameters = info->scope()->num_parameters(); | 209 int num_parameters = info->scope()->num_parameters(); |
| 210 for (int i = 0; i < num_parameters; i++) { | 210 for (int i = 0; i < num_parameters; i++) { |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 __ Push(Smi::FromInt(attr)); | 817 __ Push(Smi::FromInt(attr)); |
| 818 // Push initial value, if any. | 818 // Push initial value, if any. |
| 819 // Note: For variables we must not push an initial value (such as | 819 // Note: For variables we must not push an initial value (such as |
| 820 // 'undefined') because we may have a (legal) redeclaration and we | 820 // 'undefined') because we may have a (legal) redeclaration and we |
| 821 // must not destroy the current value. | 821 // must not destroy the current value. |
| 822 if (hole_init) { | 822 if (hole_init) { |
| 823 __ PushRoot(Heap::kTheHoleValueRootIndex); | 823 __ PushRoot(Heap::kTheHoleValueRootIndex); |
| 824 } else { | 824 } else { |
| 825 __ Push(Smi::FromInt(0)); // Indicates no initial value. | 825 __ Push(Smi::FromInt(0)); // Indicates no initial value. |
| 826 } | 826 } |
| 827 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 827 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 828 break; | 828 break; |
| 829 } | 829 } |
| 830 } | 830 } |
| 831 } | 831 } |
| 832 | 832 |
| 833 | 833 |
| 834 void FullCodeGenerator::VisitFunctionDeclaration( | 834 void FullCodeGenerator::VisitFunctionDeclaration( |
| 835 FunctionDeclaration* declaration) { | 835 FunctionDeclaration* declaration) { |
| 836 VariableProxy* proxy = declaration->proxy(); | 836 VariableProxy* proxy = declaration->proxy(); |
| 837 Variable* variable = proxy->var(); | 837 Variable* variable = proxy->var(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 871 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 872 break; | 872 break; |
| 873 } | 873 } |
| 874 | 874 |
| 875 case Variable::LOOKUP: { | 875 case Variable::LOOKUP: { |
| 876 Comment cmnt(masm_, "[ FunctionDeclaration"); | 876 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 877 __ Push(rsi); | 877 __ Push(rsi); |
| 878 __ Push(variable->name()); | 878 __ Push(variable->name()); |
| 879 __ Push(Smi::FromInt(NONE)); | 879 __ Push(Smi::FromInt(NONE)); |
| 880 VisitForStackValue(declaration->fun()); | 880 VisitForStackValue(declaration->fun()); |
| 881 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 881 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 882 break; | 882 break; |
| 883 } | 883 } |
| 884 } | 884 } |
| 885 } | 885 } |
| 886 | 886 |
| 887 | 887 |
| 888 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 888 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 889 Variable* variable = declaration->proxy()->var(); | 889 Variable* variable = declaration->proxy()->var(); |
| 890 ASSERT(variable->location() == Variable::CONTEXT); | 890 ASSERT(variable->location() == Variable::CONTEXT); |
| 891 ASSERT(variable->interface()->IsFrozen()); | 891 ASSERT(variable->interface()->IsFrozen()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { | 941 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 942 // TODO(rossberg) | 942 // TODO(rossberg) |
| 943 } | 943 } |
| 944 | 944 |
| 945 | 945 |
| 946 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 946 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 947 // Call the runtime to declare the globals. | 947 // Call the runtime to declare the globals. |
| 948 __ Push(rsi); // The context is the first argument. | 948 __ Push(rsi); // The context is the first argument. |
| 949 __ Push(pairs); | 949 __ Push(pairs); |
| 950 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 950 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
| 951 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); | 951 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 952 // Return value is ignored. | 952 // Return value is ignored. |
| 953 } | 953 } |
| 954 | 954 |
| 955 | 955 |
| 956 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 956 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 957 // Call the runtime to declare the modules. | 957 // Call the runtime to declare the modules. |
| 958 __ Push(descriptions); | 958 __ Push(descriptions); |
| 959 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); | 959 __ CallRuntime(Runtime::kDeclareModules, 1); |
| 960 // Return value is ignored. | 960 // Return value is ignored. |
| 961 } | 961 } |
| 962 | 962 |
| 963 | 963 |
| 964 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 964 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 965 Comment cmnt(masm_, "[ SwitchStatement"); | 965 Comment cmnt(masm_, "[ SwitchStatement"); |
| 966 Breakable nested_statement(this, stmt); | 966 Breakable nested_statement(this, stmt); |
| 967 SetStatementPosition(stmt); | 967 SetStatementPosition(stmt); |
| 968 | 968 |
| 969 // Keep the switch value on the stack until a case matches. | 969 // Keep the switch value on the stack until a case matches. |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 info->strict_mode(), | 1302 info->strict_mode(), |
| 1303 info->is_generator()); | 1303 info->is_generator()); |
| 1304 __ Move(rbx, info); | 1304 __ Move(rbx, info); |
| 1305 __ CallStub(&stub); | 1305 __ CallStub(&stub); |
| 1306 } else { | 1306 } else { |
| 1307 __ Push(rsi); | 1307 __ Push(rsi); |
| 1308 __ Push(info); | 1308 __ Push(info); |
| 1309 __ Push(pretenure | 1309 __ Push(pretenure |
| 1310 ? isolate()->factory()->true_value() | 1310 ? isolate()->factory()->true_value() |
| 1311 : isolate()->factory()->false_value()); | 1311 : isolate()->factory()->false_value()); |
| 1312 __ CallRuntime(Runtime::kHiddenNewClosure, 3); | 1312 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1313 } | 1313 } |
| 1314 context()->Plug(rax); | 1314 context()->Plug(rax); |
| 1315 } | 1315 } |
| 1316 | 1316 |
| 1317 | 1317 |
| 1318 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1318 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1319 Comment cmnt(masm_, "[ VariableProxy"); | 1319 Comment cmnt(masm_, "[ VariableProxy"); |
| 1320 EmitVariableLoad(expr); | 1320 EmitVariableLoad(expr); |
| 1321 } | 1321 } |
| 1322 | 1322 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 Variable* local = var->local_if_not_shadowed(); | 1427 Variable* local = var->local_if_not_shadowed(); |
| 1428 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow)); | 1428 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow)); |
| 1429 if (local->mode() == LET || local->mode() == CONST || | 1429 if (local->mode() == LET || local->mode() == CONST || |
| 1430 local->mode() == CONST_LEGACY) { | 1430 local->mode() == CONST_LEGACY) { |
| 1431 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1431 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
| 1432 __ j(not_equal, done); | 1432 __ j(not_equal, done); |
| 1433 if (local->mode() == CONST_LEGACY) { | 1433 if (local->mode() == CONST_LEGACY) { |
| 1434 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1434 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1435 } else { // LET || CONST | 1435 } else { // LET || CONST |
| 1436 __ Push(var->name()); | 1436 __ Push(var->name()); |
| 1437 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1437 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1438 } | 1438 } |
| 1439 } | 1439 } |
| 1440 __ jmp(done); | 1440 __ jmp(done); |
| 1441 } | 1441 } |
| 1442 } | 1442 } |
| 1443 | 1443 |
| 1444 | 1444 |
| 1445 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1445 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
| 1446 // Record position before possible IC call. | 1446 // Record position before possible IC call. |
| 1447 SetSourcePosition(proxy->position()); | 1447 SetSourcePosition(proxy->position()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 if (!skip_init_check) { | 1504 if (!skip_init_check) { |
| 1505 // Let and const need a read barrier. | 1505 // Let and const need a read barrier. |
| 1506 Label done; | 1506 Label done; |
| 1507 GetVar(rax, var); | 1507 GetVar(rax, var); |
| 1508 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1508 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
| 1509 __ j(not_equal, &done, Label::kNear); | 1509 __ j(not_equal, &done, Label::kNear); |
| 1510 if (var->mode() == LET || var->mode() == CONST) { | 1510 if (var->mode() == LET || var->mode() == CONST) { |
| 1511 // Throw a reference error when using an uninitialized let/const | 1511 // Throw a reference error when using an uninitialized let/const |
| 1512 // binding in harmony mode. | 1512 // binding in harmony mode. |
| 1513 __ Push(var->name()); | 1513 __ Push(var->name()); |
| 1514 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1514 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1515 } else { | 1515 } else { |
| 1516 // Uninitalized const bindings outside of harmony mode are unholed. | 1516 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1517 ASSERT(var->mode() == CONST_LEGACY); | 1517 ASSERT(var->mode() == CONST_LEGACY); |
| 1518 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1518 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1519 } | 1519 } |
| 1520 __ bind(&done); | 1520 __ bind(&done); |
| 1521 context()->Plug(rax); | 1521 context()->Plug(rax); |
| 1522 break; | 1522 break; |
| 1523 } | 1523 } |
| 1524 } | 1524 } |
| 1525 context()->Plug(var); | 1525 context()->Plug(var); |
| 1526 break; | 1526 break; |
| 1527 } | 1527 } |
| 1528 | 1528 |
| 1529 case Variable::LOOKUP: { | 1529 case Variable::LOOKUP: { |
| 1530 Comment cmnt(masm_, "[ Lookup slot"); | 1530 Comment cmnt(masm_, "[ Lookup slot"); |
| 1531 Label done, slow; | 1531 Label done, slow; |
| 1532 // Generate code for loading from variables potentially shadowed | 1532 // Generate code for loading from variables potentially shadowed |
| 1533 // by eval-introduced variables. | 1533 // by eval-introduced variables. |
| 1534 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); | 1534 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1535 __ bind(&slow); | 1535 __ bind(&slow); |
| 1536 __ Push(rsi); // Context. | 1536 __ Push(rsi); // Context. |
| 1537 __ Push(var->name()); | 1537 __ Push(var->name()); |
| 1538 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 1538 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 1539 __ bind(&done); | 1539 __ bind(&done); |
| 1540 context()->Plug(rax); | 1540 context()->Plug(rax); |
| 1541 break; | 1541 break; |
| 1542 } | 1542 } |
| 1543 } | 1543 } |
| 1544 } | 1544 } |
| 1545 | 1545 |
| 1546 | 1546 |
| 1547 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1547 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1548 Comment cmnt(masm_, "[ RegExpLiteral"); | 1548 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1559 __ movp(rbx, FieldOperand(rcx, literal_offset)); | 1559 __ movp(rbx, FieldOperand(rcx, literal_offset)); |
| 1560 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 1560 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 1561 __ j(not_equal, &materialized, Label::kNear); | 1561 __ j(not_equal, &materialized, Label::kNear); |
| 1562 | 1562 |
| 1563 // Create regexp literal using runtime function | 1563 // Create regexp literal using runtime function |
| 1564 // Result will be in rax. | 1564 // Result will be in rax. |
| 1565 __ Push(rcx); | 1565 __ Push(rcx); |
| 1566 __ Push(Smi::FromInt(expr->literal_index())); | 1566 __ Push(Smi::FromInt(expr->literal_index())); |
| 1567 __ Push(expr->pattern()); | 1567 __ Push(expr->pattern()); |
| 1568 __ Push(expr->flags()); | 1568 __ Push(expr->flags()); |
| 1569 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); | 1569 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 1570 __ movp(rbx, rax); | 1570 __ movp(rbx, rax); |
| 1571 | 1571 |
| 1572 __ bind(&materialized); | 1572 __ bind(&materialized); |
| 1573 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1573 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 1574 Label allocated, runtime_allocate; | 1574 Label allocated, runtime_allocate; |
| 1575 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); | 1575 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); |
| 1576 __ jmp(&allocated); | 1576 __ jmp(&allocated); |
| 1577 | 1577 |
| 1578 __ bind(&runtime_allocate); | 1578 __ bind(&runtime_allocate); |
| 1579 __ Push(rbx); | 1579 __ Push(rbx); |
| 1580 __ Push(Smi::FromInt(size)); | 1580 __ Push(Smi::FromInt(size)); |
| 1581 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 1581 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1582 __ Pop(rbx); | 1582 __ Pop(rbx); |
| 1583 | 1583 |
| 1584 __ bind(&allocated); | 1584 __ bind(&allocated); |
| 1585 // Copy the content into the newly allocated memory. | 1585 // Copy the content into the newly allocated memory. |
| 1586 // (Unroll copy loop once for better throughput). | 1586 // (Unroll copy loop once for better throughput). |
| 1587 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 1587 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
| 1588 __ movp(rdx, FieldOperand(rbx, i)); | 1588 __ movp(rdx, FieldOperand(rbx, i)); |
| 1589 __ movp(rcx, FieldOperand(rbx, i + kPointerSize)); | 1589 __ movp(rcx, FieldOperand(rbx, i + kPointerSize)); |
| 1590 __ movp(FieldOperand(rax, i), rdx); | 1590 __ movp(FieldOperand(rax, i), rdx); |
| 1591 __ movp(FieldOperand(rax, i + kPointerSize), rcx); | 1591 __ movp(FieldOperand(rax, i + kPointerSize), rcx); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1620 : ObjectLiteral::kNoFlags; | 1620 : ObjectLiteral::kNoFlags; |
| 1621 int properties_count = constant_properties->length() / 2; | 1621 int properties_count = constant_properties->length() / 2; |
| 1622 if (expr->may_store_doubles() || expr->depth() > 1 || | 1622 if (expr->may_store_doubles() || expr->depth() > 1 || |
| 1623 masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || | 1623 masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || |
| 1624 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1624 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 1625 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1625 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1626 __ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 1626 __ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 1627 __ Push(Smi::FromInt(expr->literal_index())); | 1627 __ Push(Smi::FromInt(expr->literal_index())); |
| 1628 __ Push(constant_properties); | 1628 __ Push(constant_properties); |
| 1629 __ Push(Smi::FromInt(flags)); | 1629 __ Push(Smi::FromInt(flags)); |
| 1630 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); | 1630 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
| 1631 } else { | 1631 } else { |
| 1632 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1632 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1633 __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 1633 __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 1634 __ Move(rbx, Smi::FromInt(expr->literal_index())); | 1634 __ Move(rbx, Smi::FromInt(expr->literal_index())); |
| 1635 __ Move(rcx, constant_properties); | 1635 __ Move(rcx, constant_properties); |
| 1636 __ Move(rdx, Smi::FromInt(flags)); | 1636 __ Move(rdx, Smi::FromInt(flags)); |
| 1637 FastCloneShallowObjectStub stub(isolate(), properties_count); | 1637 FastCloneShallowObjectStub stub(isolate(), properties_count); |
| 1638 __ CallStub(&stub); | 1638 __ CallStub(&stub); |
| 1639 } | 1639 } |
| 1640 | 1640 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1757 // we can turn it off if we don't have anywhere else to transition to. | 1757 // we can turn it off if we don't have anywhere else to transition to. |
| 1758 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1758 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1759 } | 1759 } |
| 1760 | 1760 |
| 1761 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { | 1761 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { |
| 1762 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1762 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1763 __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); | 1763 __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); |
| 1764 __ Push(Smi::FromInt(expr->literal_index())); | 1764 __ Push(Smi::FromInt(expr->literal_index())); |
| 1765 __ Push(constant_elements); | 1765 __ Push(constant_elements); |
| 1766 __ Push(Smi::FromInt(flags)); | 1766 __ Push(Smi::FromInt(flags)); |
| 1767 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); | 1767 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); |
| 1768 } else { | 1768 } else { |
| 1769 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1769 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1770 __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset)); | 1770 __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset)); |
| 1771 __ Move(rbx, Smi::FromInt(expr->literal_index())); | 1771 __ Move(rbx, Smi::FromInt(expr->literal_index())); |
| 1772 __ Move(rcx, constant_elements); | 1772 __ Move(rcx, constant_elements); |
| 1773 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1773 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
| 1774 __ CallStub(&stub); | 1774 __ CallStub(&stub); |
| 1775 } | 1775 } |
| 1776 | 1776 |
| 1777 bool result_saved = false; // Is the result saved to the stack? | 1777 bool result_saved = false; // Is the result saved to the stack? |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1958 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), | 1958 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), |
| 1959 Smi::FromInt(continuation.pos())); | 1959 Smi::FromInt(continuation.pos())); |
| 1960 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); | 1960 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); |
| 1961 __ movp(rcx, rsi); | 1961 __ movp(rcx, rsi); |
| 1962 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, | 1962 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, |
| 1963 kDontSaveFPRegs); | 1963 kDontSaveFPRegs); |
| 1964 __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); | 1964 __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); |
| 1965 __ cmpp(rsp, rbx); | 1965 __ cmpp(rsp, rbx); |
| 1966 __ j(equal, &post_runtime); | 1966 __ j(equal, &post_runtime); |
| 1967 __ Push(rax); // generator object | 1967 __ Push(rax); // generator object |
| 1968 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 1968 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 1969 __ movp(context_register(), | 1969 __ movp(context_register(), |
| 1970 Operand(rbp, StandardFrameConstants::kContextOffset)); | 1970 Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1971 __ bind(&post_runtime); | 1971 __ bind(&post_runtime); |
| 1972 | 1972 |
| 1973 __ Pop(result_register()); | 1973 __ Pop(result_register()); |
| 1974 EmitReturnSequence(); | 1974 EmitReturnSequence(); |
| 1975 | 1975 |
| 1976 __ bind(&resume); | 1976 __ bind(&resume); |
| 1977 context()->Plug(result_register()); | 1977 context()->Plug(result_register()); |
| 1978 break; | 1978 break; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 const int generator_object_depth = kPointerSize + handler_size; | 2027 const int generator_object_depth = kPointerSize + handler_size; |
| 2028 __ movp(rax, Operand(rsp, generator_object_depth)); | 2028 __ movp(rax, Operand(rsp, generator_object_depth)); |
| 2029 __ Push(rax); // g | 2029 __ Push(rax); // g |
| 2030 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2030 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 2031 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), | 2031 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), |
| 2032 Smi::FromInt(l_continuation.pos())); | 2032 Smi::FromInt(l_continuation.pos())); |
| 2033 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); | 2033 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); |
| 2034 __ movp(rcx, rsi); | 2034 __ movp(rcx, rsi); |
| 2035 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, | 2035 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, |
| 2036 kDontSaveFPRegs); | 2036 kDontSaveFPRegs); |
| 2037 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 2037 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 2038 __ movp(context_register(), | 2038 __ movp(context_register(), |
| 2039 Operand(rbp, StandardFrameConstants::kContextOffset)); | 2039 Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2040 __ Pop(rax); // result | 2040 __ Pop(rax); // result |
| 2041 EmitReturnSequence(); | 2041 EmitReturnSequence(); |
| 2042 __ bind(&l_resume); // received in rax | 2042 __ bind(&l_resume); // received in rax |
| 2043 __ PopTryHandler(); | 2043 __ PopTryHandler(); |
| 2044 | 2044 |
| 2045 // receiver = iter; f = 'next'; arg = received; | 2045 // receiver = iter; f = 'next'; arg = received; |
| 2046 __ bind(&l_next); | 2046 __ bind(&l_next); |
| 2047 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" | 2047 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 break; | 2081 break; |
| 2082 } | 2082 } |
| 2083 } | 2083 } |
| 2084 } | 2084 } |
| 2085 | 2085 |
| 2086 | 2086 |
| 2087 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2087 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2088 Expression *value, | 2088 Expression *value, |
| 2089 JSGeneratorObject::ResumeMode resume_mode) { | 2089 JSGeneratorObject::ResumeMode resume_mode) { |
| 2090 // The value stays in rax, and is ultimately read by the resumed generator, as | 2090 // The value stays in rax, and is ultimately read by the resumed generator, as |
| 2091 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it | 2091 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
| 2092 // is read to throw the value when the resumed generator is already closed. | 2092 // is read to throw the value when the resumed generator is already closed. |
| 2093 // rbx will hold the generator object until the activation has been resumed. | 2093 // rbx will hold the generator object until the activation has been resumed. |
| 2094 VisitForStackValue(generator); | 2094 VisitForStackValue(generator); |
| 2095 VisitForAccumulatorValue(value); | 2095 VisitForAccumulatorValue(value); |
| 2096 __ Pop(rbx); | 2096 __ Pop(rbx); |
| 2097 | 2097 |
| 2098 // Check generator state. | 2098 // Check generator state. |
| 2099 Label wrong_state, closed_state, done; | 2099 Label wrong_state, closed_state, done; |
| 2100 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | 2100 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
| 2101 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | 2101 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2161 Label push_operand_holes, call_resume; | 2161 Label push_operand_holes, call_resume; |
| 2162 __ bind(&push_operand_holes); | 2162 __ bind(&push_operand_holes); |
| 2163 __ subp(rdx, Immediate(1)); | 2163 __ subp(rdx, Immediate(1)); |
| 2164 __ j(carry, &call_resume); | 2164 __ j(carry, &call_resume); |
| 2165 __ Push(rcx); | 2165 __ Push(rcx); |
| 2166 __ jmp(&push_operand_holes); | 2166 __ jmp(&push_operand_holes); |
| 2167 __ bind(&call_resume); | 2167 __ bind(&call_resume); |
| 2168 __ Push(rbx); | 2168 __ Push(rbx); |
| 2169 __ Push(result_register()); | 2169 __ Push(result_register()); |
| 2170 __ Push(Smi::FromInt(resume_mode)); | 2170 __ Push(Smi::FromInt(resume_mode)); |
| 2171 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); | 2171 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2172 // Not reached: the runtime call returns elsewhere. | 2172 // Not reached: the runtime call returns elsewhere. |
| 2173 __ Abort(kGeneratorFailedToResume); | 2173 __ Abort(kGeneratorFailedToResume); |
| 2174 | 2174 |
| 2175 // Reach here when generator is closed. | 2175 // Reach here when generator is closed. |
| 2176 __ bind(&closed_state); | 2176 __ bind(&closed_state); |
| 2177 if (resume_mode == JSGeneratorObject::NEXT) { | 2177 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2178 // Return completed iterator result when generator is closed. | 2178 // Return completed iterator result when generator is closed. |
| 2179 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2179 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 2180 // Pop value from top-of-stack slot; box result into result register. | 2180 // Pop value from top-of-stack slot; box result into result register. |
| 2181 EmitCreateIteratorResult(true); | 2181 EmitCreateIteratorResult(true); |
| 2182 } else { | 2182 } else { |
| 2183 // Throw the provided value. | 2183 // Throw the provided value. |
| 2184 __ Push(rax); | 2184 __ Push(rax); |
| 2185 __ CallRuntime(Runtime::kHiddenThrow, 1); | 2185 __ CallRuntime(Runtime::kThrow, 1); |
| 2186 } | 2186 } |
| 2187 __ jmp(&done); | 2187 __ jmp(&done); |
| 2188 | 2188 |
| 2189 // Throw error if we attempt to operate on a running generator. | 2189 // Throw error if we attempt to operate on a running generator. |
| 2190 __ bind(&wrong_state); | 2190 __ bind(&wrong_state); |
| 2191 __ Push(rbx); | 2191 __ Push(rbx); |
| 2192 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); | 2192 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 2193 | 2193 |
| 2194 __ bind(&done); | 2194 __ bind(&done); |
| 2195 context()->Plug(result_register()); | 2195 context()->Plug(result_register()); |
| 2196 } | 2196 } |
| 2197 | 2197 |
| 2198 | 2198 |
| 2199 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2199 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2200 Label gc_required; | 2200 Label gc_required; |
| 2201 Label allocated; | 2201 Label allocated; |
| 2202 | 2202 |
| 2203 Handle<Map> map(isolate()->native_context()->iterator_result_map()); | 2203 Handle<Map> map(isolate()->native_context()->iterator_result_map()); |
| 2204 | 2204 |
| 2205 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT); | 2205 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT); |
| 2206 __ jmp(&allocated); | 2206 __ jmp(&allocated); |
| 2207 | 2207 |
| 2208 __ bind(&gc_required); | 2208 __ bind(&gc_required); |
| 2209 __ Push(Smi::FromInt(map->instance_size())); | 2209 __ Push(Smi::FromInt(map->instance_size())); |
| 2210 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 2210 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 2211 __ movp(context_register(), | 2211 __ movp(context_register(), |
| 2212 Operand(rbp, StandardFrameConstants::kContextOffset)); | 2212 Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2213 | 2213 |
| 2214 __ bind(&allocated); | 2214 __ bind(&allocated); |
| 2215 __ Move(rbx, map); | 2215 __ Move(rbx, map); |
| 2216 __ Pop(rcx); | 2216 __ Pop(rcx); |
| 2217 __ Move(rdx, isolate()->factory()->ToBoolean(done)); | 2217 __ Move(rdx, isolate()->factory()->ToBoolean(done)); |
| 2218 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2218 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); |
| 2219 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); | 2219 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); |
| 2220 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), | 2220 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2379 } | 2379 } |
| 2380 } | 2380 } |
| 2381 | 2381 |
| 2382 | 2382 |
| 2383 void FullCodeGenerator::EmitCallStoreContextSlot( | 2383 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2384 Handle<String> name, StrictMode strict_mode) { | 2384 Handle<String> name, StrictMode strict_mode) { |
| 2385 __ Push(rax); // Value. | 2385 __ Push(rax); // Value. |
| 2386 __ Push(rsi); // Context. | 2386 __ Push(rsi); // Context. |
| 2387 __ Push(name); | 2387 __ Push(name); |
| 2388 __ Push(Smi::FromInt(strict_mode)); | 2388 __ Push(Smi::FromInt(strict_mode)); |
| 2389 __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); | 2389 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2390 } | 2390 } |
| 2391 | 2391 |
| 2392 | 2392 |
| 2393 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2393 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2394 Token::Value op) { | 2394 Token::Value op) { |
| 2395 if (var->IsUnallocated()) { | 2395 if (var->IsUnallocated()) { |
| 2396 // Global var, const, or let. | 2396 // Global var, const, or let. |
| 2397 __ Move(rcx, var->name()); | 2397 __ Move(rcx, var->name()); |
| 2398 __ movp(rdx, GlobalObjectOperand()); | 2398 __ movp(rdx, GlobalObjectOperand()); |
| 2399 CallStoreIC(); | 2399 CallStoreIC(); |
| 2400 | 2400 |
| 2401 } else if (op == Token::INIT_CONST_LEGACY) { | 2401 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2402 // Const initializers need a write barrier. | 2402 // Const initializers need a write barrier. |
| 2403 ASSERT(!var->IsParameter()); // No const parameters. | 2403 ASSERT(!var->IsParameter()); // No const parameters. |
| 2404 if (var->IsLookupSlot()) { | 2404 if (var->IsLookupSlot()) { |
| 2405 __ Push(rax); | 2405 __ Push(rax); |
| 2406 __ Push(rsi); | 2406 __ Push(rsi); |
| 2407 __ Push(var->name()); | 2407 __ Push(var->name()); |
| 2408 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); | 2408 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2409 } else { | 2409 } else { |
| 2410 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2410 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2411 Label skip; | 2411 Label skip; |
| 2412 MemOperand location = VarOperand(var, rcx); | 2412 MemOperand location = VarOperand(var, rcx); |
| 2413 __ movp(rdx, location); | 2413 __ movp(rdx, location); |
| 2414 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2414 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 2415 __ j(not_equal, &skip); | 2415 __ j(not_equal, &skip); |
| 2416 EmitStoreToStackLocalOrContextSlot(var, location); | 2416 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2417 __ bind(&skip); | 2417 __ bind(&skip); |
| 2418 } | 2418 } |
| 2419 | 2419 |
| 2420 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2420 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2421 // Non-initializing assignment to let variable needs a write barrier. | 2421 // Non-initializing assignment to let variable needs a write barrier. |
| 2422 if (var->IsLookupSlot()) { | 2422 if (var->IsLookupSlot()) { |
| 2423 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2423 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2424 } else { | 2424 } else { |
| 2425 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2425 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2426 Label assign; | 2426 Label assign; |
| 2427 MemOperand location = VarOperand(var, rcx); | 2427 MemOperand location = VarOperand(var, rcx); |
| 2428 __ movp(rdx, location); | 2428 __ movp(rdx, location); |
| 2429 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2429 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 2430 __ j(not_equal, &assign, Label::kNear); | 2430 __ j(not_equal, &assign, Label::kNear); |
| 2431 __ Push(var->name()); | 2431 __ Push(var->name()); |
| 2432 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 2432 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2433 __ bind(&assign); | 2433 __ bind(&assign); |
| 2434 EmitStoreToStackLocalOrContextSlot(var, location); | 2434 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2435 } | 2435 } |
| 2436 | 2436 |
| 2437 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2437 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2438 // Assignment to var or initializing assignment to let/const | 2438 // Assignment to var or initializing assignment to let/const |
| 2439 // in harmony mode. | 2439 // in harmony mode. |
| 2440 if (var->IsLookupSlot()) { | 2440 if (var->IsLookupSlot()) { |
| 2441 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2441 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2442 } else { | 2442 } else { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2609 StackArgumentsAccessor args(rbp, info_->scope()->num_parameters()); | 2609 StackArgumentsAccessor args(rbp, info_->scope()->num_parameters()); |
| 2610 __ Push(args.GetReceiverOperand()); | 2610 __ Push(args.GetReceiverOperand()); |
| 2611 | 2611 |
| 2612 // Push the language mode. | 2612 // Push the language mode. |
| 2613 __ Push(Smi::FromInt(strict_mode())); | 2613 __ Push(Smi::FromInt(strict_mode())); |
| 2614 | 2614 |
| 2615 // Push the start position of the scope the calls resides in. | 2615 // Push the start position of the scope the calls resides in. |
| 2616 __ Push(Smi::FromInt(scope()->start_position())); | 2616 __ Push(Smi::FromInt(scope()->start_position())); |
| 2617 | 2617 |
| 2618 // Do the runtime call. | 2618 // Do the runtime call. |
| 2619 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); | 2619 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2620 } | 2620 } |
| 2621 | 2621 |
| 2622 | 2622 |
| 2623 void FullCodeGenerator::VisitCall(Call* expr) { | 2623 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2624 #ifdef DEBUG | 2624 #ifdef DEBUG |
| 2625 // We want to verify that RecordJSReturnSite gets called on all paths | 2625 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2626 // through this function. Avoid early returns. | 2626 // through this function. Avoid early returns. |
| 2627 expr->return_is_recorded_ = false; | 2627 expr->return_is_recorded_ = false; |
| 2628 #endif | 2628 #endif |
| 2629 | 2629 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2676 { PreservePositionScope scope(masm()->positions_recorder()); | 2676 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2677 // Generate code for loading from variables potentially shadowed by | 2677 // Generate code for loading from variables potentially shadowed by |
| 2678 // eval-introduced variables. | 2678 // eval-introduced variables. |
| 2679 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2679 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2680 } | 2680 } |
| 2681 __ bind(&slow); | 2681 __ bind(&slow); |
| 2682 // Call the runtime to find the function to call (returned in rax) and | 2682 // Call the runtime to find the function to call (returned in rax) and |
| 2683 // the object holding it (returned in rdx). | 2683 // the object holding it (returned in rdx). |
| 2684 __ Push(context_register()); | 2684 __ Push(context_register()); |
| 2685 __ Push(proxy->name()); | 2685 __ Push(proxy->name()); |
| 2686 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 2686 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2687 __ Push(rax); // Function. | 2687 __ Push(rax); // Function. |
| 2688 __ Push(rdx); // Receiver. | 2688 __ Push(rdx); // Receiver. |
| 2689 | 2689 |
| 2690 // If fast case code has been generated, emit code to push the function | 2690 // If fast case code has been generated, emit code to push the function |
| 2691 // and receiver and have the slow path jump around this code. | 2691 // and receiver and have the slow path jump around this code. |
| 2692 if (done.is_linked()) { | 2692 if (done.is_linked()) { |
| 2693 Label call; | 2693 Label call; |
| 2694 __ jmp(&call, Label::kNear); | 2694 __ jmp(&call, Label::kNear); |
| 2695 __ bind(&done); | 2695 __ bind(&done); |
| 2696 // Push function. | 2696 // Push function. |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3308 __ bind(&runtime); | 3308 __ bind(&runtime); |
| 3309 __ PrepareCallCFunction(2); | 3309 __ PrepareCallCFunction(2); |
| 3310 __ movp(arg_reg_1, object); | 3310 __ movp(arg_reg_1, object); |
| 3311 __ Move(arg_reg_2, index, Assembler::RelocInfoNone()); | 3311 __ Move(arg_reg_2, index, Assembler::RelocInfoNone()); |
| 3312 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3312 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 3313 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3313 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3314 __ jmp(&done); | 3314 __ jmp(&done); |
| 3315 } | 3315 } |
| 3316 | 3316 |
| 3317 __ bind(¬_date_object); | 3317 __ bind(¬_date_object); |
| 3318 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); | 3318 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
| 3319 __ bind(&done); | 3319 __ bind(&done); |
| 3320 context()->Plug(rax); | 3320 context()->Plug(rax); |
| 3321 } | 3321 } |
| 3322 | 3322 |
| 3323 | 3323 |
| 3324 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3324 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3325 ZoneList<Expression*>* args = expr->arguments(); | 3325 ZoneList<Expression*>* args = expr->arguments(); |
| 3326 ASSERT_EQ(3, args->length()); | 3326 ASSERT_EQ(3, args->length()); |
| 3327 | 3327 |
| 3328 Register string = rax; | 3328 Register string = rax; |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3668 __ movp(rax, FieldOperand(cache, | 3668 __ movp(rax, FieldOperand(cache, |
| 3669 index.reg, | 3669 index.reg, |
| 3670 index.scale, | 3670 index.scale, |
| 3671 FixedArray::kHeaderSize + kPointerSize)); | 3671 FixedArray::kHeaderSize + kPointerSize)); |
| 3672 __ jmp(&done, Label::kNear); | 3672 __ jmp(&done, Label::kNear); |
| 3673 | 3673 |
| 3674 __ bind(¬_found); | 3674 __ bind(¬_found); |
| 3675 // Call runtime to perform the lookup. | 3675 // Call runtime to perform the lookup. |
| 3676 __ Push(cache); | 3676 __ Push(cache); |
| 3677 __ Push(key); | 3677 __ Push(key); |
| 3678 __ CallRuntime(Runtime::kHiddenGetFromCache, 2); | 3678 __ CallRuntime(Runtime::kGetFromCache, 2); |
| 3679 | 3679 |
| 3680 __ bind(&done); | 3680 __ bind(&done); |
| 3681 context()->Plug(rax); | 3681 context()->Plug(rax); |
| 3682 } | 3682 } |
| 3683 | 3683 |
| 3684 | 3684 |
| 3685 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3685 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3686 ZoneList<Expression*>* args = expr->arguments(); | 3686 ZoneList<Expression*>* args = expr->arguments(); |
| 3687 ASSERT(args->length() == 1); | 3687 ASSERT(args->length() == 1); |
| 3688 | 3688 |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4097 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4097 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4098 // Result of deleting non-global variables is false. 'this' is | 4098 // Result of deleting non-global variables is false. 'this' is |
| 4099 // not really a variable, though we implement it as one. The | 4099 // not really a variable, though we implement it as one. The |
| 4100 // subexpression does not have side effects. | 4100 // subexpression does not have side effects. |
| 4101 context()->Plug(var->is_this()); | 4101 context()->Plug(var->is_this()); |
| 4102 } else { | 4102 } else { |
| 4103 // Non-global variable. Call the runtime to try to delete from the | 4103 // Non-global variable. Call the runtime to try to delete from the |
| 4104 // context where the variable was introduced. | 4104 // context where the variable was introduced. |
| 4105 __ Push(context_register()); | 4105 __ Push(context_register()); |
| 4106 __ Push(var->name()); | 4106 __ Push(var->name()); |
| 4107 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); | 4107 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 4108 context()->Plug(rax); | 4108 context()->Plug(rax); |
| 4109 } | 4109 } |
| 4110 } else { | 4110 } else { |
| 4111 // Result of deleting non-property, non-variable reference is true. | 4111 // Result of deleting non-property, non-variable reference is true. |
| 4112 // The subexpression may have side effects. | 4112 // The subexpression may have side effects. |
| 4113 VisitForEffect(expr->expression()); | 4113 VisitForEffect(expr->expression()); |
| 4114 context()->Plug(true); | 4114 context()->Plug(true); |
| 4115 } | 4115 } |
| 4116 break; | 4116 break; |
| 4117 } | 4117 } |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4384 Comment cmnt(masm_, "[ Lookup slot"); | 4384 Comment cmnt(masm_, "[ Lookup slot"); |
| 4385 Label done, slow; | 4385 Label done, slow; |
| 4386 | 4386 |
| 4387 // Generate code for loading from variables potentially shadowed | 4387 // Generate code for loading from variables potentially shadowed |
| 4388 // by eval-introduced variables. | 4388 // by eval-introduced variables. |
| 4389 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4389 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4390 | 4390 |
| 4391 __ bind(&slow); | 4391 __ bind(&slow); |
| 4392 __ Push(rsi); | 4392 __ Push(rsi); |
| 4393 __ Push(proxy->name()); | 4393 __ Push(proxy->name()); |
| 4394 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); | 4394 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 4395 PrepareForBailout(expr, TOS_REG); | 4395 PrepareForBailout(expr, TOS_REG); |
| 4396 __ bind(&done); | 4396 __ bind(&done); |
| 4397 | 4397 |
| 4398 context()->Plug(rax); | 4398 context()->Plug(rax); |
| 4399 } else { | 4399 } else { |
| 4400 // This expression cannot throw a reference error at the top level. | 4400 // This expression cannot throw a reference error at the top level. |
| 4401 VisitInDuplicateContext(expr); | 4401 VisitInDuplicateContext(expr); |
| 4402 } | 4402 } |
| 4403 } | 4403 } |
| 4404 | 4404 |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4804 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4804 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4805 Assembler::target_address_at(call_target_address, | 4805 Assembler::target_address_at(call_target_address, |
| 4806 unoptimized_code)); | 4806 unoptimized_code)); |
| 4807 return OSR_AFTER_STACK_CHECK; | 4807 return OSR_AFTER_STACK_CHECK; |
| 4808 } | 4808 } |
| 4809 | 4809 |
| 4810 | 4810 |
| 4811 } } // namespace v8::internal | 4811 } } // namespace v8::internal |
| 4812 | 4812 |
| 4813 #endif // V8_TARGET_ARCH_X64 | 4813 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |