| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 bool function_in_register = true; | 218 bool function_in_register = true; |
| 219 | 219 |
| 220 // Possibly allocate a local context. | 220 // Possibly allocate a local context. |
| 221 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 221 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 222 if (heap_slots > 0) { | 222 if (heap_slots > 0) { |
| 223 Comment cmnt(masm_, "[ Allocate context"); | 223 Comment cmnt(masm_, "[ Allocate context"); |
| 224 // Argument to NewContext is the function, which is still in edi. | 224 // Argument to NewContext is the function, which is still in edi. |
| 225 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { | 225 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { |
| 226 __ push(edi); | 226 __ push(edi); |
| 227 __ Push(info->scope()->GetScopeInfo()); | 227 __ Push(info->scope()->GetScopeInfo()); |
| 228 __ CallRuntime(Runtime::kNewGlobalContext, 2); | 228 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); |
| 229 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 229 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 230 FastNewContextStub stub(heap_slots); | 230 FastNewContextStub stub(heap_slots); |
| 231 __ CallStub(&stub); | 231 __ CallStub(&stub); |
| 232 } else { | 232 } else { |
| 233 __ push(edi); | 233 __ push(edi); |
| 234 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 234 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); |
| 235 } | 235 } |
| 236 function_in_register = false; | 236 function_in_register = false; |
| 237 // Context is returned in eax. It replaces the context passed to us. | 237 // Context is returned in eax. It replaces the context passed to us. |
| 238 // It's saved in the stack and kept live in esi. | 238 // It's saved in the stack and kept live in esi. |
| 239 __ mov(esi, eax); | 239 __ mov(esi, eax); |
| 240 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); | 240 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); |
| 241 | 241 |
| 242 // Copy parameters into context if necessary. | 242 // Copy parameters into context if necessary. |
| 243 int num_parameters = info->scope()->num_parameters(); | 243 int num_parameters = info->scope()->num_parameters(); |
| 244 for (int i = 0; i < num_parameters; i++) { | 244 for (int i = 0; i < num_parameters; i++) { |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 __ push(Immediate(Smi::FromInt(attr))); | 817 __ push(Immediate(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 __ push(Immediate(isolate()->factory()->the_hole_value())); | 823 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 824 } else { | 824 } else { |
| 825 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 825 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
| 826 } | 826 } |
| 827 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 827 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 870 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 871 break; | 871 break; |
| 872 } | 872 } |
| 873 | 873 |
| 874 case Variable::LOOKUP: { | 874 case Variable::LOOKUP: { |
| 875 Comment cmnt(masm_, "[ FunctionDeclaration"); | 875 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 876 __ push(esi); | 876 __ push(esi); |
| 877 __ push(Immediate(variable->name())); | 877 __ push(Immediate(variable->name())); |
| 878 __ push(Immediate(Smi::FromInt(NONE))); | 878 __ push(Immediate(Smi::FromInt(NONE))); |
| 879 VisitForStackValue(declaration->fun()); | 879 VisitForStackValue(declaration->fun()); |
| 880 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 880 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); |
| 881 break; | 881 break; |
| 882 } | 882 } |
| 883 } | 883 } |
| 884 } | 884 } |
| 885 | 885 |
| 886 | 886 |
| 887 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 887 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 888 Variable* variable = declaration->proxy()->var(); | 888 Variable* variable = declaration->proxy()->var(); |
| 889 ASSERT(variable->location() == Variable::CONTEXT); | 889 ASSERT(variable->location() == Variable::CONTEXT); |
| 890 ASSERT(variable->interface()->IsFrozen()); | 890 ASSERT(variable->interface()->IsFrozen()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { | 940 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 941 // TODO(rossberg) | 941 // TODO(rossberg) |
| 942 } | 942 } |
| 943 | 943 |
| 944 | 944 |
| 945 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 945 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 946 // Call the runtime to declare the globals. | 946 // Call the runtime to declare the globals. |
| 947 __ push(esi); // The context is the first argument. | 947 __ push(esi); // The context is the first argument. |
| 948 __ Push(pairs); | 948 __ Push(pairs); |
| 949 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 949 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
| 950 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 950 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); |
| 951 // Return value is ignored. | 951 // Return value is ignored. |
| 952 } | 952 } |
| 953 | 953 |
| 954 | 954 |
| 955 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 955 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 956 // Call the runtime to declare the modules. | 956 // Call the runtime to declare the modules. |
| 957 __ Push(descriptions); | 957 __ Push(descriptions); |
| 958 __ CallRuntime(Runtime::kDeclareModules, 1); | 958 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); |
| 959 // Return value is ignored. | 959 // Return value is ignored. |
| 960 } | 960 } |
| 961 | 961 |
| 962 | 962 |
| 963 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 963 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 964 Comment cmnt(masm_, "[ SwitchStatement"); | 964 Comment cmnt(masm_, "[ SwitchStatement"); |
| 965 Breakable nested_statement(this, stmt); | 965 Breakable nested_statement(this, stmt); |
| 966 SetStatementPosition(stmt); | 966 SetStatementPosition(stmt); |
| 967 | 967 |
| 968 // Keep the switch value on the stack until a case matches. | 968 // Keep the switch value on the stack until a case matches. |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 info->num_literals() == 0) { | 1300 info->num_literals() == 0) { |
| 1301 FastNewClosureStub stub(info->strict_mode(), info->is_generator()); | 1301 FastNewClosureStub stub(info->strict_mode(), info->is_generator()); |
| 1302 __ mov(ebx, Immediate(info)); | 1302 __ mov(ebx, Immediate(info)); |
| 1303 __ CallStub(&stub); | 1303 __ CallStub(&stub); |
| 1304 } else { | 1304 } else { |
| 1305 __ push(esi); | 1305 __ push(esi); |
| 1306 __ push(Immediate(info)); | 1306 __ push(Immediate(info)); |
| 1307 __ push(Immediate(pretenure | 1307 __ push(Immediate(pretenure |
| 1308 ? isolate()->factory()->true_value() | 1308 ? isolate()->factory()->true_value() |
| 1309 : isolate()->factory()->false_value())); | 1309 : isolate()->factory()->false_value())); |
| 1310 __ CallRuntime(Runtime::kNewClosure, 3); | 1310 __ CallRuntime(Runtime::kHiddenNewClosure, 3); |
| 1311 } | 1311 } |
| 1312 context()->Plug(eax); | 1312 context()->Plug(eax); |
| 1313 } | 1313 } |
| 1314 | 1314 |
| 1315 | 1315 |
| 1316 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1316 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1317 Comment cmnt(masm_, "[ VariableProxy"); | 1317 Comment cmnt(masm_, "[ VariableProxy"); |
| 1318 EmitVariableLoad(expr); | 1318 EmitVariableLoad(expr); |
| 1319 } | 1319 } |
| 1320 | 1320 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 Variable* local = var->local_if_not_shadowed(); | 1425 Variable* local = var->local_if_not_shadowed(); |
| 1426 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); | 1426 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); |
| 1427 if (local->mode() == LET || local->mode() == CONST || | 1427 if (local->mode() == LET || local->mode() == CONST || |
| 1428 local->mode() == CONST_LEGACY) { | 1428 local->mode() == CONST_LEGACY) { |
| 1429 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1429 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1430 __ j(not_equal, done); | 1430 __ j(not_equal, done); |
| 1431 if (local->mode() == CONST_LEGACY) { | 1431 if (local->mode() == CONST_LEGACY) { |
| 1432 __ mov(eax, isolate()->factory()->undefined_value()); | 1432 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1433 } else { // LET || CONST | 1433 } else { // LET || CONST |
| 1434 __ push(Immediate(var->name())); | 1434 __ push(Immediate(var->name())); |
| 1435 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1435 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); |
| 1436 } | 1436 } |
| 1437 } | 1437 } |
| 1438 __ jmp(done); | 1438 __ jmp(done); |
| 1439 } | 1439 } |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 | 1442 |
| 1443 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1443 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
| 1444 // Record position before possible IC call. | 1444 // Record position before possible IC call. |
| 1445 SetSourcePosition(proxy->position()); | 1445 SetSourcePosition(proxy->position()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 if (!skip_init_check) { | 1502 if (!skip_init_check) { |
| 1503 // Let and const need a read barrier. | 1503 // Let and const need a read barrier. |
| 1504 Label done; | 1504 Label done; |
| 1505 GetVar(eax, var); | 1505 GetVar(eax, var); |
| 1506 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1506 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1507 __ j(not_equal, &done, Label::kNear); | 1507 __ j(not_equal, &done, Label::kNear); |
| 1508 if (var->mode() == LET || var->mode() == CONST) { | 1508 if (var->mode() == LET || var->mode() == CONST) { |
| 1509 // Throw a reference error when using an uninitialized let/const | 1509 // Throw a reference error when using an uninitialized let/const |
| 1510 // binding in harmony mode. | 1510 // binding in harmony mode. |
| 1511 __ push(Immediate(var->name())); | 1511 __ push(Immediate(var->name())); |
| 1512 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1512 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); |
| 1513 } else { | 1513 } else { |
| 1514 // Uninitalized const bindings outside of harmony mode are unholed. | 1514 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1515 ASSERT(var->mode() == CONST_LEGACY); | 1515 ASSERT(var->mode() == CONST_LEGACY); |
| 1516 __ mov(eax, isolate()->factory()->undefined_value()); | 1516 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1517 } | 1517 } |
| 1518 __ bind(&done); | 1518 __ bind(&done); |
| 1519 context()->Plug(eax); | 1519 context()->Plug(eax); |
| 1520 break; | 1520 break; |
| 1521 } | 1521 } |
| 1522 } | 1522 } |
| 1523 context()->Plug(var); | 1523 context()->Plug(var); |
| 1524 break; | 1524 break; |
| 1525 } | 1525 } |
| 1526 | 1526 |
| 1527 case Variable::LOOKUP: { | 1527 case Variable::LOOKUP: { |
| 1528 Comment cmnt(masm_, "[ Lookup variable"); | 1528 Comment cmnt(masm_, "[ Lookup variable"); |
| 1529 Label done, slow; | 1529 Label done, slow; |
| 1530 // Generate code for loading from variables potentially shadowed | 1530 // Generate code for loading from variables potentially shadowed |
| 1531 // by eval-introduced variables. | 1531 // by eval-introduced variables. |
| 1532 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); | 1532 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1533 __ bind(&slow); | 1533 __ bind(&slow); |
| 1534 __ push(esi); // Context. | 1534 __ push(esi); // Context. |
| 1535 __ push(Immediate(var->name())); | 1535 __ push(Immediate(var->name())); |
| 1536 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1536 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); |
| 1537 __ bind(&done); | 1537 __ bind(&done); |
| 1538 context()->Plug(eax); | 1538 context()->Plug(eax); |
| 1539 break; | 1539 break; |
| 1540 } | 1540 } |
| 1541 } | 1541 } |
| 1542 } | 1542 } |
| 1543 | 1543 |
| 1544 | 1544 |
| 1545 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1545 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1546 Comment cmnt(masm_, "[ RegExpLiteral"); | 1546 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1557 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 1557 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 1558 __ cmp(ebx, isolate()->factory()->undefined_value()); | 1558 __ cmp(ebx, isolate()->factory()->undefined_value()); |
| 1559 __ j(not_equal, &materialized, Label::kNear); | 1559 __ j(not_equal, &materialized, Label::kNear); |
| 1560 | 1560 |
| 1561 // Create regexp literal using runtime function | 1561 // Create regexp literal using runtime function |
| 1562 // Result will be in eax. | 1562 // Result will be in eax. |
| 1563 __ push(ecx); | 1563 __ push(ecx); |
| 1564 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1564 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 1565 __ push(Immediate(expr->pattern())); | 1565 __ push(Immediate(expr->pattern())); |
| 1566 __ push(Immediate(expr->flags())); | 1566 __ push(Immediate(expr->flags())); |
| 1567 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 1567 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); |
| 1568 __ mov(ebx, eax); | 1568 __ mov(ebx, eax); |
| 1569 | 1569 |
| 1570 __ bind(&materialized); | 1570 __ bind(&materialized); |
| 1571 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1571 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 1572 Label allocated, runtime_allocate; | 1572 Label allocated, runtime_allocate; |
| 1573 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); | 1573 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); |
| 1574 __ jmp(&allocated); | 1574 __ jmp(&allocated); |
| 1575 | 1575 |
| 1576 __ bind(&runtime_allocate); | 1576 __ bind(&runtime_allocate); |
| 1577 __ push(ebx); | 1577 __ push(ebx); |
| 1578 __ push(Immediate(Smi::FromInt(size))); | 1578 __ push(Immediate(Smi::FromInt(size))); |
| 1579 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 1579 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); |
| 1580 __ pop(ebx); | 1580 __ pop(ebx); |
| 1581 | 1581 |
| 1582 __ bind(&allocated); | 1582 __ bind(&allocated); |
| 1583 // Copy the content into the newly allocated memory. | 1583 // Copy the content into the newly allocated memory. |
| 1584 // (Unroll copy loop once for better throughput). | 1584 // (Unroll copy loop once for better throughput). |
| 1585 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 1585 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
| 1586 __ mov(edx, FieldOperand(ebx, i)); | 1586 __ mov(edx, FieldOperand(ebx, i)); |
| 1587 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); | 1587 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); |
| 1588 __ mov(FieldOperand(eax, i), edx); | 1588 __ mov(FieldOperand(eax, i), edx); |
| 1589 __ mov(FieldOperand(eax, i + kPointerSize), ecx); | 1589 __ mov(FieldOperand(eax, i + kPointerSize), ecx); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1618 : ObjectLiteral::kNoFlags; | 1618 : ObjectLiteral::kNoFlags; |
| 1619 int properties_count = constant_properties->length() / 2; | 1619 int properties_count = constant_properties->length() / 2; |
| 1620 if (expr->may_store_doubles() || expr->depth() > 1 || Serializer::enabled() || | 1620 if (expr->may_store_doubles() || expr->depth() > 1 || Serializer::enabled() || |
| 1621 flags != ObjectLiteral::kFastElements || | 1621 flags != ObjectLiteral::kFastElements || |
| 1622 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1622 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 1623 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1623 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1624 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); | 1624 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 1625 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1625 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 1626 __ push(Immediate(constant_properties)); | 1626 __ push(Immediate(constant_properties)); |
| 1627 __ push(Immediate(Smi::FromInt(flags))); | 1627 __ push(Immediate(Smi::FromInt(flags))); |
| 1628 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1628 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); |
| 1629 } else { | 1629 } else { |
| 1630 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1630 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1631 __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 1631 __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 1632 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1632 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
| 1633 __ mov(ecx, Immediate(constant_properties)); | 1633 __ mov(ecx, Immediate(constant_properties)); |
| 1634 __ mov(edx, Immediate(Smi::FromInt(flags))); | 1634 __ mov(edx, Immediate(Smi::FromInt(flags))); |
| 1635 FastCloneShallowObjectStub stub(properties_count); | 1635 FastCloneShallowObjectStub stub(properties_count); |
| 1636 __ CallStub(&stub); | 1636 __ CallStub(&stub); |
| 1637 } | 1637 } |
| 1638 | 1638 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1771 allocation_site_mode, | 1771 allocation_site_mode, |
| 1772 length); | 1772 length); |
| 1773 __ CallStub(&stub); | 1773 __ CallStub(&stub); |
| 1774 } else if (expr->depth() > 1 || Serializer::enabled() || | 1774 } else if (expr->depth() > 1 || Serializer::enabled() || |
| 1775 length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 1775 length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1776 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1776 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1777 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 1777 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
| 1778 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1778 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 1779 __ push(Immediate(constant_elements)); | 1779 __ push(Immediate(constant_elements)); |
| 1780 __ push(Immediate(Smi::FromInt(flags))); | 1780 __ push(Immediate(Smi::FromInt(flags))); |
| 1781 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1781 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); |
| 1782 } else { | 1782 } else { |
| 1783 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || | 1783 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || |
| 1784 FLAG_smi_only_arrays); | 1784 FLAG_smi_only_arrays); |
| 1785 FastCloneShallowArrayStub::Mode mode = | 1785 FastCloneShallowArrayStub::Mode mode = |
| 1786 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; | 1786 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; |
| 1787 | 1787 |
| 1788 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot | 1788 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot |
| 1789 // change, so it's possible to specialize the stub in advance. | 1789 // change, so it's possible to specialize the stub in advance. |
| 1790 if (has_constant_fast_elements) { | 1790 if (has_constant_fast_elements) { |
| 1791 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; | 1791 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1984 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1984 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1985 Immediate(Smi::FromInt(continuation.pos()))); | 1985 Immediate(Smi::FromInt(continuation.pos()))); |
| 1986 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1986 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1987 __ mov(ecx, esi); | 1987 __ mov(ecx, esi); |
| 1988 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 1988 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, |
| 1989 kDontSaveFPRegs); | 1989 kDontSaveFPRegs); |
| 1990 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1990 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1991 __ cmp(esp, ebx); | 1991 __ cmp(esp, ebx); |
| 1992 __ j(equal, &post_runtime); | 1992 __ j(equal, &post_runtime); |
| 1993 __ push(eax); // generator object | 1993 __ push(eax); // generator object |
| 1994 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1994 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 1995 __ mov(context_register(), | 1995 __ mov(context_register(), |
| 1996 Operand(ebp, StandardFrameConstants::kContextOffset)); | 1996 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1997 __ bind(&post_runtime); | 1997 __ bind(&post_runtime); |
| 1998 __ pop(result_register()); | 1998 __ pop(result_register()); |
| 1999 EmitReturnSequence(); | 1999 EmitReturnSequence(); |
| 2000 | 2000 |
| 2001 __ bind(&resume); | 2001 __ bind(&resume); |
| 2002 context()->Plug(result_register()); | 2002 context()->Plug(result_register()); |
| 2003 break; | 2003 break; |
| 2004 } | 2004 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2052 const int generator_object_depth = kPointerSize + handler_size; | 2052 const int generator_object_depth = kPointerSize + handler_size; |
| 2053 __ mov(eax, Operand(esp, generator_object_depth)); | 2053 __ mov(eax, Operand(esp, generator_object_depth)); |
| 2054 __ push(eax); // g | 2054 __ push(eax); // g |
| 2055 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2055 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 2056 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 2056 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 2057 Immediate(Smi::FromInt(l_continuation.pos()))); | 2057 Immediate(Smi::FromInt(l_continuation.pos()))); |
| 2058 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 2058 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 2059 __ mov(ecx, esi); | 2059 __ mov(ecx, esi); |
| 2060 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 2060 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, |
| 2061 kDontSaveFPRegs); | 2061 kDontSaveFPRegs); |
| 2062 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2062 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 2063 __ mov(context_register(), | 2063 __ mov(context_register(), |
| 2064 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2064 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2065 __ pop(eax); // result | 2065 __ pop(eax); // result |
| 2066 EmitReturnSequence(); | 2066 EmitReturnSequence(); |
| 2067 __ bind(&l_resume); // received in eax | 2067 __ bind(&l_resume); // received in eax |
| 2068 __ PopTryHandler(); | 2068 __ PopTryHandler(); |
| 2069 | 2069 |
| 2070 // receiver = iter; f = iter.next; arg = received; | 2070 // receiver = iter; f = iter.next; arg = received; |
| 2071 __ bind(&l_next); | 2071 __ bind(&l_next); |
| 2072 __ mov(ecx, isolate()->factory()->next_string()); // "next" | 2072 __ mov(ecx, isolate()->factory()->next_string()); // "next" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2106 break; | 2106 break; |
| 2107 } | 2107 } |
| 2108 } | 2108 } |
| 2109 } | 2109 } |
| 2110 | 2110 |
| 2111 | 2111 |
| 2112 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2112 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2113 Expression *value, | 2113 Expression *value, |
| 2114 JSGeneratorObject::ResumeMode resume_mode) { | 2114 JSGeneratorObject::ResumeMode resume_mode) { |
| 2115 // The value stays in eax, and is ultimately read by the resumed generator, as | 2115 // The value stays in eax, and is ultimately read by the resumed generator, as |
| 2116 // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 2116 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it |
| 2117 // is read to throw the value when the resumed generator is already closed. | 2117 // is read to throw the value when the resumed generator is already closed. |
| 2118 // ebx will hold the generator object until the activation has been resumed. | 2118 // ebx will hold the generator object until the activation has been resumed. |
| 2119 VisitForStackValue(generator); | 2119 VisitForStackValue(generator); |
| 2120 VisitForAccumulatorValue(value); | 2120 VisitForAccumulatorValue(value); |
| 2121 __ pop(ebx); | 2121 __ pop(ebx); |
| 2122 | 2122 |
| 2123 // Check generator state. | 2123 // Check generator state. |
| 2124 Label wrong_state, closed_state, done; | 2124 Label wrong_state, closed_state, done; |
| 2125 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | 2125 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
| 2126 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | 2126 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 Label push_operand_holes, call_resume; | 2186 Label push_operand_holes, call_resume; |
| 2187 __ bind(&push_operand_holes); | 2187 __ bind(&push_operand_holes); |
| 2188 __ sub(edx, Immediate(1)); | 2188 __ sub(edx, Immediate(1)); |
| 2189 __ j(carry, &call_resume); | 2189 __ j(carry, &call_resume); |
| 2190 __ push(ecx); | 2190 __ push(ecx); |
| 2191 __ jmp(&push_operand_holes); | 2191 __ jmp(&push_operand_holes); |
| 2192 __ bind(&call_resume); | 2192 __ bind(&call_resume); |
| 2193 __ push(ebx); | 2193 __ push(ebx); |
| 2194 __ push(result_register()); | 2194 __ push(result_register()); |
| 2195 __ Push(Smi::FromInt(resume_mode)); | 2195 __ Push(Smi::FromInt(resume_mode)); |
| 2196 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2196 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); |
| 2197 // Not reached: the runtime call returns elsewhere. | 2197 // Not reached: the runtime call returns elsewhere. |
| 2198 __ Abort(kGeneratorFailedToResume); | 2198 __ Abort(kGeneratorFailedToResume); |
| 2199 | 2199 |
| 2200 // Reach here when generator is closed. | 2200 // Reach here when generator is closed. |
| 2201 __ bind(&closed_state); | 2201 __ bind(&closed_state); |
| 2202 if (resume_mode == JSGeneratorObject::NEXT) { | 2202 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2203 // Return completed iterator result when generator is closed. | 2203 // Return completed iterator result when generator is closed. |
| 2204 __ push(Immediate(isolate()->factory()->undefined_value())); | 2204 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2205 // Pop value from top-of-stack slot; box result into result register. | 2205 // Pop value from top-of-stack slot; box result into result register. |
| 2206 EmitCreateIteratorResult(true); | 2206 EmitCreateIteratorResult(true); |
| 2207 } else { | 2207 } else { |
| 2208 // Throw the provided value. | 2208 // Throw the provided value. |
| 2209 __ push(eax); | 2209 __ push(eax); |
| 2210 __ CallRuntime(Runtime::kThrow, 1); | 2210 __ CallRuntime(Runtime::kHiddenThrow, 1); |
| 2211 } | 2211 } |
| 2212 __ jmp(&done); | 2212 __ jmp(&done); |
| 2213 | 2213 |
| 2214 // Throw error if we attempt to operate on a running generator. | 2214 // Throw error if we attempt to operate on a running generator. |
| 2215 __ bind(&wrong_state); | 2215 __ bind(&wrong_state); |
| 2216 __ push(ebx); | 2216 __ push(ebx); |
| 2217 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2217 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); |
| 2218 | 2218 |
| 2219 __ bind(&done); | 2219 __ bind(&done); |
| 2220 context()->Plug(result_register()); | 2220 context()->Plug(result_register()); |
| 2221 } | 2221 } |
| 2222 | 2222 |
| 2223 | 2223 |
| 2224 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2224 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2225 Label gc_required; | 2225 Label gc_required; |
| 2226 Label allocated; | 2226 Label allocated; |
| 2227 | 2227 |
| 2228 Handle<Map> map(isolate()->native_context()->generator_result_map()); | 2228 Handle<Map> map(isolate()->native_context()->generator_result_map()); |
| 2229 | 2229 |
| 2230 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); | 2230 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); |
| 2231 __ jmp(&allocated); | 2231 __ jmp(&allocated); |
| 2232 | 2232 |
| 2233 __ bind(&gc_required); | 2233 __ bind(&gc_required); |
| 2234 __ Push(Smi::FromInt(map->instance_size())); | 2234 __ Push(Smi::FromInt(map->instance_size())); |
| 2235 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2235 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); |
| 2236 __ mov(context_register(), | 2236 __ mov(context_register(), |
| 2237 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2237 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2238 | 2238 |
| 2239 __ bind(&allocated); | 2239 __ bind(&allocated); |
| 2240 __ mov(ebx, map); | 2240 __ mov(ebx, map); |
| 2241 __ pop(ecx); | 2241 __ pop(ecx); |
| 2242 __ mov(edx, isolate()->factory()->ToBoolean(done)); | 2242 __ mov(edx, isolate()->factory()->ToBoolean(done)); |
| 2243 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2243 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); |
| 2244 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2244 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
| 2245 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2245 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 } | 2437 } |
| 2438 } | 2438 } |
| 2439 | 2439 |
| 2440 | 2440 |
| 2441 void FullCodeGenerator::EmitCallStoreContextSlot( | 2441 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2442 Handle<String> name, StrictMode strict_mode) { | 2442 Handle<String> name, StrictMode strict_mode) { |
| 2443 __ push(eax); // Value. | 2443 __ push(eax); // Value. |
| 2444 __ push(esi); // Context. | 2444 __ push(esi); // Context. |
| 2445 __ push(Immediate(name)); | 2445 __ push(Immediate(name)); |
| 2446 __ push(Immediate(Smi::FromInt(strict_mode))); | 2446 __ push(Immediate(Smi::FromInt(strict_mode))); |
| 2447 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 2447 __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); |
| 2448 } | 2448 } |
| 2449 | 2449 |
| 2450 | 2450 |
| 2451 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2451 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2452 Token::Value op) { | 2452 Token::Value op) { |
| 2453 if (var->IsUnallocated()) { | 2453 if (var->IsUnallocated()) { |
| 2454 // Global var, const, or let. | 2454 // Global var, const, or let. |
| 2455 __ mov(ecx, var->name()); | 2455 __ mov(ecx, var->name()); |
| 2456 __ mov(edx, GlobalObjectOperand()); | 2456 __ mov(edx, GlobalObjectOperand()); |
| 2457 CallStoreIC(); | 2457 CallStoreIC(); |
| 2458 | 2458 |
| 2459 } else if (op == Token::INIT_CONST_LEGACY) { | 2459 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2460 // Const initializers need a write barrier. | 2460 // Const initializers need a write barrier. |
| 2461 ASSERT(!var->IsParameter()); // No const parameters. | 2461 ASSERT(!var->IsParameter()); // No const parameters. |
| 2462 if (var->IsLookupSlot()) { | 2462 if (var->IsLookupSlot()) { |
| 2463 __ push(eax); | 2463 __ push(eax); |
| 2464 __ push(esi); | 2464 __ push(esi); |
| 2465 __ push(Immediate(var->name())); | 2465 __ push(Immediate(var->name())); |
| 2466 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2466 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); |
| 2467 } else { | 2467 } else { |
| 2468 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2468 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2469 Label skip; | 2469 Label skip; |
| 2470 MemOperand location = VarOperand(var, ecx); | 2470 MemOperand location = VarOperand(var, ecx); |
| 2471 __ mov(edx, location); | 2471 __ mov(edx, location); |
| 2472 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2472 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2473 __ j(not_equal, &skip, Label::kNear); | 2473 __ j(not_equal, &skip, Label::kNear); |
| 2474 EmitStoreToStackLocalOrContextSlot(var, location); | 2474 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2475 __ bind(&skip); | 2475 __ bind(&skip); |
| 2476 } | 2476 } |
| 2477 | 2477 |
| 2478 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2478 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2479 // Non-initializing assignment to let variable needs a write barrier. | 2479 // Non-initializing assignment to let variable needs a write barrier. |
| 2480 if (var->IsLookupSlot()) { | 2480 if (var->IsLookupSlot()) { |
| 2481 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2481 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2482 } else { | 2482 } else { |
| 2483 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2483 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2484 Label assign; | 2484 Label assign; |
| 2485 MemOperand location = VarOperand(var, ecx); | 2485 MemOperand location = VarOperand(var, ecx); |
| 2486 __ mov(edx, location); | 2486 __ mov(edx, location); |
| 2487 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2487 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2488 __ j(not_equal, &assign, Label::kNear); | 2488 __ j(not_equal, &assign, Label::kNear); |
| 2489 __ push(Immediate(var->name())); | 2489 __ push(Immediate(var->name())); |
| 2490 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2490 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); |
| 2491 __ bind(&assign); | 2491 __ bind(&assign); |
| 2492 EmitStoreToStackLocalOrContextSlot(var, location); | 2492 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2493 } | 2493 } |
| 2494 | 2494 |
| 2495 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2495 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2496 // Assignment to var or initializing assignment to let/const | 2496 // Assignment to var or initializing assignment to let/const |
| 2497 // in harmony mode. | 2497 // in harmony mode. |
| 2498 if (var->IsLookupSlot()) { | 2498 if (var->IsLookupSlot()) { |
| 2499 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2499 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2500 } else { | 2500 } else { |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2715 | 2715 |
| 2716 // Push the receiver of the enclosing function. | 2716 // Push the receiver of the enclosing function. |
| 2717 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); | 2717 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); |
| 2718 // Push the language mode. | 2718 // Push the language mode. |
| 2719 __ push(Immediate(Smi::FromInt(strict_mode()))); | 2719 __ push(Immediate(Smi::FromInt(strict_mode()))); |
| 2720 | 2720 |
| 2721 // Push the start position of the scope the calls resides in. | 2721 // Push the start position of the scope the calls resides in. |
| 2722 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | 2722 __ push(Immediate(Smi::FromInt(scope()->start_position()))); |
| 2723 | 2723 |
| 2724 // Do the runtime call. | 2724 // Do the runtime call. |
| 2725 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2725 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); |
| 2726 } | 2726 } |
| 2727 | 2727 |
| 2728 | 2728 |
| 2729 void FullCodeGenerator::VisitCall(Call* expr) { | 2729 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2730 #ifdef DEBUG | 2730 #ifdef DEBUG |
| 2731 // We want to verify that RecordJSReturnSite gets called on all paths | 2731 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2732 // through this function. Avoid early returns. | 2732 // through this function. Avoid early returns. |
| 2733 expr->return_is_recorded_ = false; | 2733 expr->return_is_recorded_ = false; |
| 2734 #endif | 2734 #endif |
| 2735 | 2735 |
| 2736 Comment cmnt(masm_, "[ Call"); | 2736 Comment cmnt(masm_, "[ Call"); |
| 2737 Expression* callee = expr->expression(); | 2737 Expression* callee = expr->expression(); |
| 2738 Call::CallType call_type = expr->GetCallType(isolate()); | 2738 Call::CallType call_type = expr->GetCallType(isolate()); |
| 2739 | 2739 |
| 2740 if (call_type == Call::POSSIBLY_EVAL_CALL) { | 2740 if (call_type == Call::POSSIBLY_EVAL_CALL) { |
| 2741 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2741 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval |
| 2742 // resolve the function we need to call and the receiver of the call. | 2742 // to resolve the function we need to call and the receiver of the call. |
| 2743 // Then we call the resolved function using the given arguments. | 2743 // Then we call the resolved function using the given arguments. |
| 2744 ZoneList<Expression*>* args = expr->arguments(); | 2744 ZoneList<Expression*>* args = expr->arguments(); |
| 2745 int arg_count = args->length(); | 2745 int arg_count = args->length(); |
| 2746 { PreservePositionScope pos_scope(masm()->positions_recorder()); | 2746 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
| 2747 VisitForStackValue(callee); | 2747 VisitForStackValue(callee); |
| 2748 // Reserved receiver slot. | 2748 // Reserved receiver slot. |
| 2749 __ push(Immediate(isolate()->factory()->undefined_value())); | 2749 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2750 // Push the arguments. | 2750 // Push the arguments. |
| 2751 for (int i = 0; i < arg_count; i++) { | 2751 for (int i = 0; i < arg_count; i++) { |
| 2752 VisitForStackValue(args->at(i)); | 2752 VisitForStackValue(args->at(i)); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2782 { PreservePositionScope scope(masm()->positions_recorder()); | 2782 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2783 // Generate code for loading from variables potentially shadowed by | 2783 // Generate code for loading from variables potentially shadowed by |
| 2784 // eval-introduced variables. | 2784 // eval-introduced variables. |
| 2785 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2785 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2786 } | 2786 } |
| 2787 __ bind(&slow); | 2787 __ bind(&slow); |
| 2788 // Call the runtime to find the function to call (returned in eax) and | 2788 // Call the runtime to find the function to call (returned in eax) and |
| 2789 // the object holding it (returned in edx). | 2789 // the object holding it (returned in edx). |
| 2790 __ push(context_register()); | 2790 __ push(context_register()); |
| 2791 __ push(Immediate(proxy->name())); | 2791 __ push(Immediate(proxy->name())); |
| 2792 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2792 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); |
| 2793 __ push(eax); // Function. | 2793 __ push(eax); // Function. |
| 2794 __ push(edx); // Receiver. | 2794 __ push(edx); // Receiver. |
| 2795 | 2795 |
| 2796 // If fast case code has been generated, emit code to push the function | 2796 // If fast case code has been generated, emit code to push the function |
| 2797 // and receiver and have the slow path jump around this code. | 2797 // and receiver and have the slow path jump around this code. |
| 2798 if (done.is_linked()) { | 2798 if (done.is_linked()) { |
| 2799 Label call; | 2799 Label call; |
| 2800 __ jmp(&call, Label::kNear); | 2800 __ jmp(&call, Label::kNear); |
| 2801 __ bind(&done); | 2801 __ bind(&done); |
| 2802 // Push function. | 2802 // Push function. |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3446 } | 3446 } |
| 3447 __ bind(&runtime); | 3447 __ bind(&runtime); |
| 3448 __ PrepareCallCFunction(2, scratch); | 3448 __ PrepareCallCFunction(2, scratch); |
| 3449 __ mov(Operand(esp, 0), object); | 3449 __ mov(Operand(esp, 0), object); |
| 3450 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); | 3450 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); |
| 3451 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3451 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 3452 __ jmp(&done); | 3452 __ jmp(&done); |
| 3453 } | 3453 } |
| 3454 | 3454 |
| 3455 __ bind(¬_date_object); | 3455 __ bind(¬_date_object); |
| 3456 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3456 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); |
| 3457 __ bind(&done); | 3457 __ bind(&done); |
| 3458 context()->Plug(result); | 3458 context()->Plug(result); |
| 3459 } | 3459 } |
| 3460 | 3460 |
| 3461 | 3461 |
| 3462 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3462 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3463 ZoneList<Expression*>* args = expr->arguments(); | 3463 ZoneList<Expression*>* args = expr->arguments(); |
| 3464 ASSERT_EQ(3, args->length()); | 3464 ASSERT_EQ(3, args->length()); |
| 3465 | 3465 |
| 3466 Register string = eax; | 3466 Register string = eax; |
| (...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4227 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4227 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4228 // Result of deleting non-global variables is false. 'this' is | 4228 // Result of deleting non-global variables is false. 'this' is |
| 4229 // not really a variable, though we implement it as one. The | 4229 // not really a variable, though we implement it as one. The |
| 4230 // subexpression does not have side effects. | 4230 // subexpression does not have side effects. |
| 4231 context()->Plug(var->is_this()); | 4231 context()->Plug(var->is_this()); |
| 4232 } else { | 4232 } else { |
| 4233 // Non-global variable. Call the runtime to try to delete from the | 4233 // Non-global variable. Call the runtime to try to delete from the |
| 4234 // context where the variable was introduced. | 4234 // context where the variable was introduced. |
| 4235 __ push(context_register()); | 4235 __ push(context_register()); |
| 4236 __ push(Immediate(var->name())); | 4236 __ push(Immediate(var->name())); |
| 4237 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 4237 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); |
| 4238 context()->Plug(eax); | 4238 context()->Plug(eax); |
| 4239 } | 4239 } |
| 4240 } else { | 4240 } else { |
| 4241 // Result of deleting non-property, non-variable reference is true. | 4241 // Result of deleting non-property, non-variable reference is true. |
| 4242 // The subexpression may have side effects. | 4242 // The subexpression may have side effects. |
| 4243 VisitForEffect(expr->expression()); | 4243 VisitForEffect(expr->expression()); |
| 4244 context()->Plug(true); | 4244 context()->Plug(true); |
| 4245 } | 4245 } |
| 4246 break; | 4246 break; |
| 4247 } | 4247 } |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4520 Comment cmnt(masm_, "[ Lookup slot"); | 4520 Comment cmnt(masm_, "[ Lookup slot"); |
| 4521 Label done, slow; | 4521 Label done, slow; |
| 4522 | 4522 |
| 4523 // Generate code for loading from variables potentially shadowed | 4523 // Generate code for loading from variables potentially shadowed |
| 4524 // by eval-introduced variables. | 4524 // by eval-introduced variables. |
| 4525 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4525 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4526 | 4526 |
| 4527 __ bind(&slow); | 4527 __ bind(&slow); |
| 4528 __ push(esi); | 4528 __ push(esi); |
| 4529 __ push(Immediate(proxy->name())); | 4529 __ push(Immediate(proxy->name())); |
| 4530 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 4530 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); |
| 4531 PrepareForBailout(expr, TOS_REG); | 4531 PrepareForBailout(expr, TOS_REG); |
| 4532 __ bind(&done); | 4532 __ bind(&done); |
| 4533 | 4533 |
| 4534 context()->Plug(eax); | 4534 context()->Plug(eax); |
| 4535 } else { | 4535 } else { |
| 4536 // This expression cannot throw a reference error at the top level. | 4536 // This expression cannot throw a reference error at the top level. |
| 4537 VisitInDuplicateContext(expr); | 4537 VisitInDuplicateContext(expr); |
| 4538 } | 4538 } |
| 4539 } | 4539 } |
| 4540 | 4540 |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4936 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4936 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4937 Assembler::target_address_at(call_target_address, | 4937 Assembler::target_address_at(call_target_address, |
| 4938 unoptimized_code)); | 4938 unoptimized_code)); |
| 4939 return OSR_AFTER_STACK_CHECK; | 4939 return OSR_AFTER_STACK_CHECK; |
| 4940 } | 4940 } |
| 4941 | 4941 |
| 4942 | 4942 |
| 4943 } } // namespace v8::internal | 4943 } } // namespace v8::internal |
| 4944 | 4944 |
| 4945 #endif // V8_TARGET_ARCH_IA32 | 4945 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |