| 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_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 | 183 |
| 184 // Possibly allocate a local context. | 184 // Possibly allocate a local context. |
| 185 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 185 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 186 if (heap_slots > 0) { | 186 if (heap_slots > 0) { |
| 187 Comment cmnt(masm_, "[ Allocate context"); | 187 Comment cmnt(masm_, "[ Allocate context"); |
| 188 bool need_write_barrier = true; | 188 bool need_write_barrier = true; |
| 189 // Argument to NewContext is the function, which is still in edi. | 189 // Argument to NewContext is the function, which is still in edi. |
| 190 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { | 190 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { |
| 191 __ push(edi); | 191 __ push(edi); |
| 192 __ Push(info->scope()->GetScopeInfo()); | 192 __ Push(info->scope()->GetScopeInfo()); |
| 193 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); | 193 __ CallRuntime(Runtime::kNewGlobalContext, 2); |
| 194 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 194 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 195 FastNewContextStub stub(isolate(), heap_slots); | 195 FastNewContextStub stub(isolate(), heap_slots); |
| 196 __ CallStub(&stub); | 196 __ CallStub(&stub); |
| 197 // Result of FastNewContextStub is always in new space. | 197 // Result of FastNewContextStub is always in new space. |
| 198 need_write_barrier = false; | 198 need_write_barrier = false; |
| 199 } else { | 199 } else { |
| 200 __ push(edi); | 200 __ push(edi); |
| 201 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); | 201 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 202 } | 202 } |
| 203 function_in_register = false; | 203 function_in_register = false; |
| 204 // Context is returned in eax. It replaces the context passed to us. | 204 // Context is returned in eax. It replaces the context passed to us. |
| 205 // It's saved in the stack and kept live in esi. | 205 // It's saved in the stack and kept live in esi. |
| 206 __ mov(esi, eax); | 206 __ mov(esi, eax); |
| 207 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); | 207 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); |
| 208 | 208 |
| 209 // Copy parameters into context if necessary. | 209 // Copy parameters into context if necessary. |
| 210 int num_parameters = info->scope()->num_parameters(); | 210 int num_parameters = info->scope()->num_parameters(); |
| 211 for (int i = 0; i < num_parameters; i++) { | 211 for (int i = 0; i < num_parameters; i++) { |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 __ push(Immediate(Smi::FromInt(attr))); | 794 __ push(Immediate(Smi::FromInt(attr))); |
| 795 // Push initial value, if any. | 795 // Push initial value, if any. |
| 796 // Note: For variables we must not push an initial value (such as | 796 // Note: For variables we must not push an initial value (such as |
| 797 // 'undefined') because we may have a (legal) redeclaration and we | 797 // 'undefined') because we may have a (legal) redeclaration and we |
| 798 // must not destroy the current value. | 798 // must not destroy the current value. |
| 799 if (hole_init) { | 799 if (hole_init) { |
| 800 __ push(Immediate(isolate()->factory()->the_hole_value())); | 800 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 801 } else { | 801 } else { |
| 802 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 802 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
| 803 } | 803 } |
| 804 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 804 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 805 break; | 805 break; |
| 806 } | 806 } |
| 807 } | 807 } |
| 808 } | 808 } |
| 809 | 809 |
| 810 | 810 |
| 811 void FullCodeGenerator::VisitFunctionDeclaration( | 811 void FullCodeGenerator::VisitFunctionDeclaration( |
| 812 FunctionDeclaration* declaration) { | 812 FunctionDeclaration* declaration) { |
| 813 VariableProxy* proxy = declaration->proxy(); | 813 VariableProxy* proxy = declaration->proxy(); |
| 814 Variable* variable = proxy->var(); | 814 Variable* variable = proxy->var(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 846 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 847 break; | 847 break; |
| 848 } | 848 } |
| 849 | 849 |
| 850 case Variable::LOOKUP: { | 850 case Variable::LOOKUP: { |
| 851 Comment cmnt(masm_, "[ FunctionDeclaration"); | 851 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 852 __ push(esi); | 852 __ push(esi); |
| 853 __ push(Immediate(variable->name())); | 853 __ push(Immediate(variable->name())); |
| 854 __ push(Immediate(Smi::FromInt(NONE))); | 854 __ push(Immediate(Smi::FromInt(NONE))); |
| 855 VisitForStackValue(declaration->fun()); | 855 VisitForStackValue(declaration->fun()); |
| 856 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 856 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 857 break; | 857 break; |
| 858 } | 858 } |
| 859 } | 859 } |
| 860 } | 860 } |
| 861 | 861 |
| 862 | 862 |
| 863 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 863 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 864 Variable* variable = declaration->proxy()->var(); | 864 Variable* variable = declaration->proxy()->var(); |
| 865 ASSERT(variable->location() == Variable::CONTEXT); | 865 ASSERT(variable->location() == Variable::CONTEXT); |
| 866 ASSERT(variable->interface()->IsFrozen()); | 866 ASSERT(variable->interface()->IsFrozen()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 915 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { | 915 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 916 // TODO(rossberg) | 916 // TODO(rossberg) |
| 917 } | 917 } |
| 918 | 918 |
| 919 | 919 |
| 920 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 920 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 921 // Call the runtime to declare the globals. | 921 // Call the runtime to declare the globals. |
| 922 __ push(esi); // The context is the first argument. | 922 __ push(esi); // The context is the first argument. |
| 923 __ Push(pairs); | 923 __ Push(pairs); |
| 924 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 924 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
| 925 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); | 925 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 926 // Return value is ignored. | 926 // Return value is ignored. |
| 927 } | 927 } |
| 928 | 928 |
| 929 | 929 |
| 930 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 930 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 931 // Call the runtime to declare the modules. | 931 // Call the runtime to declare the modules. |
| 932 __ Push(descriptions); | 932 __ Push(descriptions); |
| 933 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); | 933 __ CallRuntime(Runtime::kDeclareModules, 1); |
| 934 // Return value is ignored. | 934 // Return value is ignored. |
| 935 } | 935 } |
| 936 | 936 |
| 937 | 937 |
| 938 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 938 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 939 Comment cmnt(masm_, "[ SwitchStatement"); | 939 Comment cmnt(masm_, "[ SwitchStatement"); |
| 940 Breakable nested_statement(this, stmt); | 940 Breakable nested_statement(this, stmt); |
| 941 SetStatementPosition(stmt); | 941 SetStatementPosition(stmt); |
| 942 | 942 |
| 943 // Keep the switch value on the stack until a case matches. | 943 // Keep the switch value on the stack until a case matches. |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 info->strict_mode(), | 1265 info->strict_mode(), |
| 1266 info->is_generator()); | 1266 info->is_generator()); |
| 1267 __ mov(ebx, Immediate(info)); | 1267 __ mov(ebx, Immediate(info)); |
| 1268 __ CallStub(&stub); | 1268 __ CallStub(&stub); |
| 1269 } else { | 1269 } else { |
| 1270 __ push(esi); | 1270 __ push(esi); |
| 1271 __ push(Immediate(info)); | 1271 __ push(Immediate(info)); |
| 1272 __ push(Immediate(pretenure | 1272 __ push(Immediate(pretenure |
| 1273 ? isolate()->factory()->true_value() | 1273 ? isolate()->factory()->true_value() |
| 1274 : isolate()->factory()->false_value())); | 1274 : isolate()->factory()->false_value())); |
| 1275 __ CallRuntime(Runtime::kHiddenNewClosure, 3); | 1275 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1276 } | 1276 } |
| 1277 context()->Plug(eax); | 1277 context()->Plug(eax); |
| 1278 } | 1278 } |
| 1279 | 1279 |
| 1280 | 1280 |
| 1281 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1281 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1282 Comment cmnt(masm_, "[ VariableProxy"); | 1282 Comment cmnt(masm_, "[ VariableProxy"); |
| 1283 EmitVariableLoad(expr); | 1283 EmitVariableLoad(expr); |
| 1284 } | 1284 } |
| 1285 | 1285 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 Variable* local = var->local_if_not_shadowed(); | 1390 Variable* local = var->local_if_not_shadowed(); |
| 1391 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); | 1391 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); |
| 1392 if (local->mode() == LET || local->mode() == CONST || | 1392 if (local->mode() == LET || local->mode() == CONST || |
| 1393 local->mode() == CONST_LEGACY) { | 1393 local->mode() == CONST_LEGACY) { |
| 1394 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1394 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1395 __ j(not_equal, done); | 1395 __ j(not_equal, done); |
| 1396 if (local->mode() == CONST_LEGACY) { | 1396 if (local->mode() == CONST_LEGACY) { |
| 1397 __ mov(eax, isolate()->factory()->undefined_value()); | 1397 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1398 } else { // LET || CONST | 1398 } else { // LET || CONST |
| 1399 __ push(Immediate(var->name())); | 1399 __ push(Immediate(var->name())); |
| 1400 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1400 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1401 } | 1401 } |
| 1402 } | 1402 } |
| 1403 __ jmp(done); | 1403 __ jmp(done); |
| 1404 } | 1404 } |
| 1405 } | 1405 } |
| 1406 | 1406 |
| 1407 | 1407 |
| 1408 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1408 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
| 1409 // Record position before possible IC call. | 1409 // Record position before possible IC call. |
| 1410 SetSourcePosition(proxy->position()); | 1410 SetSourcePosition(proxy->position()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 if (!skip_init_check) { | 1467 if (!skip_init_check) { |
| 1468 // Let and const need a read barrier. | 1468 // Let and const need a read barrier. |
| 1469 Label done; | 1469 Label done; |
| 1470 GetVar(eax, var); | 1470 GetVar(eax, var); |
| 1471 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1471 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1472 __ j(not_equal, &done, Label::kNear); | 1472 __ j(not_equal, &done, Label::kNear); |
| 1473 if (var->mode() == LET || var->mode() == CONST) { | 1473 if (var->mode() == LET || var->mode() == CONST) { |
| 1474 // Throw a reference error when using an uninitialized let/const | 1474 // Throw a reference error when using an uninitialized let/const |
| 1475 // binding in harmony mode. | 1475 // binding in harmony mode. |
| 1476 __ push(Immediate(var->name())); | 1476 __ push(Immediate(var->name())); |
| 1477 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1477 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1478 } else { | 1478 } else { |
| 1479 // Uninitalized const bindings outside of harmony mode are unholed. | 1479 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1480 ASSERT(var->mode() == CONST_LEGACY); | 1480 ASSERT(var->mode() == CONST_LEGACY); |
| 1481 __ mov(eax, isolate()->factory()->undefined_value()); | 1481 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1482 } | 1482 } |
| 1483 __ bind(&done); | 1483 __ bind(&done); |
| 1484 context()->Plug(eax); | 1484 context()->Plug(eax); |
| 1485 break; | 1485 break; |
| 1486 } | 1486 } |
| 1487 } | 1487 } |
| 1488 context()->Plug(var); | 1488 context()->Plug(var); |
| 1489 break; | 1489 break; |
| 1490 } | 1490 } |
| 1491 | 1491 |
| 1492 case Variable::LOOKUP: { | 1492 case Variable::LOOKUP: { |
| 1493 Comment cmnt(masm_, "[ Lookup variable"); | 1493 Comment cmnt(masm_, "[ Lookup variable"); |
| 1494 Label done, slow; | 1494 Label done, slow; |
| 1495 // Generate code for loading from variables potentially shadowed | 1495 // Generate code for loading from variables potentially shadowed |
| 1496 // by eval-introduced variables. | 1496 // by eval-introduced variables. |
| 1497 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); | 1497 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1498 __ bind(&slow); | 1498 __ bind(&slow); |
| 1499 __ push(esi); // Context. | 1499 __ push(esi); // Context. |
| 1500 __ push(Immediate(var->name())); | 1500 __ push(Immediate(var->name())); |
| 1501 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 1501 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 1502 __ bind(&done); | 1502 __ bind(&done); |
| 1503 context()->Plug(eax); | 1503 context()->Plug(eax); |
| 1504 break; | 1504 break; |
| 1505 } | 1505 } |
| 1506 } | 1506 } |
| 1507 } | 1507 } |
| 1508 | 1508 |
| 1509 | 1509 |
| 1510 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1510 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1511 Comment cmnt(masm_, "[ RegExpLiteral"); | 1511 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1522 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 1522 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 1523 __ cmp(ebx, isolate()->factory()->undefined_value()); | 1523 __ cmp(ebx, isolate()->factory()->undefined_value()); |
| 1524 __ j(not_equal, &materialized, Label::kNear); | 1524 __ j(not_equal, &materialized, Label::kNear); |
| 1525 | 1525 |
| 1526 // Create regexp literal using runtime function | 1526 // Create regexp literal using runtime function |
| 1527 // Result will be in eax. | 1527 // Result will be in eax. |
| 1528 __ push(ecx); | 1528 __ push(ecx); |
| 1529 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1529 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 1530 __ push(Immediate(expr->pattern())); | 1530 __ push(Immediate(expr->pattern())); |
| 1531 __ push(Immediate(expr->flags())); | 1531 __ push(Immediate(expr->flags())); |
| 1532 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); | 1532 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 1533 __ mov(ebx, eax); | 1533 __ mov(ebx, eax); |
| 1534 | 1534 |
| 1535 __ bind(&materialized); | 1535 __ bind(&materialized); |
| 1536 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1536 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 1537 Label allocated, runtime_allocate; | 1537 Label allocated, runtime_allocate; |
| 1538 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); | 1538 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); |
| 1539 __ jmp(&allocated); | 1539 __ jmp(&allocated); |
| 1540 | 1540 |
| 1541 __ bind(&runtime_allocate); | 1541 __ bind(&runtime_allocate); |
| 1542 __ push(ebx); | 1542 __ push(ebx); |
| 1543 __ push(Immediate(Smi::FromInt(size))); | 1543 __ push(Immediate(Smi::FromInt(size))); |
| 1544 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 1544 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1545 __ pop(ebx); | 1545 __ pop(ebx); |
| 1546 | 1546 |
| 1547 __ bind(&allocated); | 1547 __ bind(&allocated); |
| 1548 // Copy the content into the newly allocated memory. | 1548 // Copy the content into the newly allocated memory. |
| 1549 // (Unroll copy loop once for better throughput). | 1549 // (Unroll copy loop once for better throughput). |
| 1550 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 1550 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
| 1551 __ mov(edx, FieldOperand(ebx, i)); | 1551 __ mov(edx, FieldOperand(ebx, i)); |
| 1552 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); | 1552 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); |
| 1553 __ mov(FieldOperand(eax, i), edx); | 1553 __ mov(FieldOperand(eax, i), edx); |
| 1554 __ mov(FieldOperand(eax, i + kPointerSize), ecx); | 1554 __ mov(FieldOperand(eax, i + kPointerSize), ecx); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1584 int properties_count = constant_properties->length() / 2; | 1584 int properties_count = constant_properties->length() / 2; |
| 1585 if (expr->may_store_doubles() || expr->depth() > 1 || | 1585 if (expr->may_store_doubles() || expr->depth() > 1 || |
| 1586 masm()->serializer_enabled() || | 1586 masm()->serializer_enabled() || |
| 1587 flags != ObjectLiteral::kFastElements || | 1587 flags != ObjectLiteral::kFastElements || |
| 1588 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1588 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 1589 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1589 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1590 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); | 1590 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 1591 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1591 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 1592 __ push(Immediate(constant_properties)); | 1592 __ push(Immediate(constant_properties)); |
| 1593 __ push(Immediate(Smi::FromInt(flags))); | 1593 __ push(Immediate(Smi::FromInt(flags))); |
| 1594 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); | 1594 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
| 1595 } else { | 1595 } else { |
| 1596 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1596 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1597 __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 1597 __ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 1598 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1598 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
| 1599 __ mov(ecx, Immediate(constant_properties)); | 1599 __ mov(ecx, Immediate(constant_properties)); |
| 1600 __ mov(edx, Immediate(Smi::FromInt(flags))); | 1600 __ mov(edx, Immediate(Smi::FromInt(flags))); |
| 1601 FastCloneShallowObjectStub stub(isolate(), properties_count); | 1601 FastCloneShallowObjectStub stub(isolate(), properties_count); |
| 1602 __ CallStub(&stub); | 1602 __ CallStub(&stub); |
| 1603 } | 1603 } |
| 1604 | 1604 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1721 // we can turn it off if we don't have anywhere else to transition to. | 1721 // we can turn it off if we don't have anywhere else to transition to. |
| 1722 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1722 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1723 } | 1723 } |
| 1724 | 1724 |
| 1725 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { | 1725 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { |
| 1726 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1726 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1727 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 1727 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
| 1728 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1728 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 1729 __ push(Immediate(constant_elements)); | 1729 __ push(Immediate(constant_elements)); |
| 1730 __ push(Immediate(Smi::FromInt(flags))); | 1730 __ push(Immediate(Smi::FromInt(flags))); |
| 1731 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); | 1731 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); |
| 1732 } else { | 1732 } else { |
| 1733 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1733 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1734 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 1734 __ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
| 1735 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1735 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
| 1736 __ mov(ecx, Immediate(constant_elements)); | 1736 __ mov(ecx, Immediate(constant_elements)); |
| 1737 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1737 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
| 1738 __ CallStub(&stub); | 1738 __ CallStub(&stub); |
| 1739 } | 1739 } |
| 1740 | 1740 |
| 1741 bool result_saved = false; // Is the result saved to the stack? | 1741 bool result_saved = false; // Is the result saved to the stack? |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1921 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1921 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
| 1922 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1922 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1923 Immediate(Smi::FromInt(continuation.pos()))); | 1923 Immediate(Smi::FromInt(continuation.pos()))); |
| 1924 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1924 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1925 __ mov(ecx, esi); | 1925 __ mov(ecx, esi); |
| 1926 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); | 1926 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
| 1927 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1927 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1928 __ cmp(esp, ebx); | 1928 __ cmp(esp, ebx); |
| 1929 __ j(equal, &post_runtime); | 1929 __ j(equal, &post_runtime); |
| 1930 __ push(eax); // generator object | 1930 __ push(eax); // generator object |
| 1931 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 1931 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 1932 __ mov(context_register(), | 1932 __ mov(context_register(), |
| 1933 Operand(ebp, StandardFrameConstants::kContextOffset)); | 1933 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1934 __ bind(&post_runtime); | 1934 __ bind(&post_runtime); |
| 1935 __ pop(result_register()); | 1935 __ pop(result_register()); |
| 1936 EmitReturnSequence(); | 1936 EmitReturnSequence(); |
| 1937 | 1937 |
| 1938 __ bind(&resume); | 1938 __ bind(&resume); |
| 1939 context()->Plug(result_register()); | 1939 context()->Plug(result_register()); |
| 1940 break; | 1940 break; |
| 1941 } | 1941 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1988 __ bind(&l_suspend); | 1988 __ bind(&l_suspend); |
| 1989 const int generator_object_depth = kPointerSize + handler_size; | 1989 const int generator_object_depth = kPointerSize + handler_size; |
| 1990 __ mov(eax, Operand(esp, generator_object_depth)); | 1990 __ mov(eax, Operand(esp, generator_object_depth)); |
| 1991 __ push(eax); // g | 1991 __ push(eax); // g |
| 1992 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 1992 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 1993 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1993 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1994 Immediate(Smi::FromInt(l_continuation.pos()))); | 1994 Immediate(Smi::FromInt(l_continuation.pos()))); |
| 1995 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1995 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1996 __ mov(ecx, esi); | 1996 __ mov(ecx, esi); |
| 1997 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); | 1997 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
| 1998 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 1998 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 1999 __ mov(context_register(), | 1999 __ mov(context_register(), |
| 2000 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2000 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2001 __ pop(eax); // result | 2001 __ pop(eax); // result |
| 2002 EmitReturnSequence(); | 2002 EmitReturnSequence(); |
| 2003 __ bind(&l_resume); // received in eax | 2003 __ bind(&l_resume); // received in eax |
| 2004 __ PopTryHandler(); | 2004 __ PopTryHandler(); |
| 2005 | 2005 |
| 2006 // receiver = iter; f = iter.next; arg = received; | 2006 // receiver = iter; f = iter.next; arg = received; |
| 2007 __ bind(&l_next); | 2007 __ bind(&l_next); |
| 2008 __ mov(ecx, isolate()->factory()->next_string()); // "next" | 2008 __ mov(ecx, isolate()->factory()->next_string()); // "next" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2042 break; | 2042 break; |
| 2043 } | 2043 } |
| 2044 } | 2044 } |
| 2045 } | 2045 } |
| 2046 | 2046 |
| 2047 | 2047 |
| 2048 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2048 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2049 Expression *value, | 2049 Expression *value, |
| 2050 JSGeneratorObject::ResumeMode resume_mode) { | 2050 JSGeneratorObject::ResumeMode resume_mode) { |
| 2051 // The value stays in eax, and is ultimately read by the resumed generator, as | 2051 // The value stays in eax, and is ultimately read by the resumed generator, as |
| 2052 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it | 2052 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
| 2053 // is read to throw the value when the resumed generator is already closed. | 2053 // is read to throw the value when the resumed generator is already closed. |
| 2054 // ebx will hold the generator object until the activation has been resumed. | 2054 // ebx will hold the generator object until the activation has been resumed. |
| 2055 VisitForStackValue(generator); | 2055 VisitForStackValue(generator); |
| 2056 VisitForAccumulatorValue(value); | 2056 VisitForAccumulatorValue(value); |
| 2057 __ pop(ebx); | 2057 __ pop(ebx); |
| 2058 | 2058 |
| 2059 // Check generator state. | 2059 // Check generator state. |
| 2060 Label wrong_state, closed_state, done; | 2060 Label wrong_state, closed_state, done; |
| 2061 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | 2061 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
| 2062 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | 2062 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2122 Label push_operand_holes, call_resume; | 2122 Label push_operand_holes, call_resume; |
| 2123 __ bind(&push_operand_holes); | 2123 __ bind(&push_operand_holes); |
| 2124 __ sub(edx, Immediate(1)); | 2124 __ sub(edx, Immediate(1)); |
| 2125 __ j(carry, &call_resume); | 2125 __ j(carry, &call_resume); |
| 2126 __ push(ecx); | 2126 __ push(ecx); |
| 2127 __ jmp(&push_operand_holes); | 2127 __ jmp(&push_operand_holes); |
| 2128 __ bind(&call_resume); | 2128 __ bind(&call_resume); |
| 2129 __ push(ebx); | 2129 __ push(ebx); |
| 2130 __ push(result_register()); | 2130 __ push(result_register()); |
| 2131 __ Push(Smi::FromInt(resume_mode)); | 2131 __ Push(Smi::FromInt(resume_mode)); |
| 2132 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); | 2132 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2133 // Not reached: the runtime call returns elsewhere. | 2133 // Not reached: the runtime call returns elsewhere. |
| 2134 __ Abort(kGeneratorFailedToResume); | 2134 __ Abort(kGeneratorFailedToResume); |
| 2135 | 2135 |
| 2136 // Reach here when generator is closed. | 2136 // Reach here when generator is closed. |
| 2137 __ bind(&closed_state); | 2137 __ bind(&closed_state); |
| 2138 if (resume_mode == JSGeneratorObject::NEXT) { | 2138 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2139 // Return completed iterator result when generator is closed. | 2139 // Return completed iterator result when generator is closed. |
| 2140 __ push(Immediate(isolate()->factory()->undefined_value())); | 2140 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2141 // Pop value from top-of-stack slot; box result into result register. | 2141 // Pop value from top-of-stack slot; box result into result register. |
| 2142 EmitCreateIteratorResult(true); | 2142 EmitCreateIteratorResult(true); |
| 2143 } else { | 2143 } else { |
| 2144 // Throw the provided value. | 2144 // Throw the provided value. |
| 2145 __ push(eax); | 2145 __ push(eax); |
| 2146 __ CallRuntime(Runtime::kHiddenThrow, 1); | 2146 __ CallRuntime(Runtime::kThrow, 1); |
| 2147 } | 2147 } |
| 2148 __ jmp(&done); | 2148 __ jmp(&done); |
| 2149 | 2149 |
| 2150 // Throw error if we attempt to operate on a running generator. | 2150 // Throw error if we attempt to operate on a running generator. |
| 2151 __ bind(&wrong_state); | 2151 __ bind(&wrong_state); |
| 2152 __ push(ebx); | 2152 __ push(ebx); |
| 2153 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); | 2153 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 2154 | 2154 |
| 2155 __ bind(&done); | 2155 __ bind(&done); |
| 2156 context()->Plug(result_register()); | 2156 context()->Plug(result_register()); |
| 2157 } | 2157 } |
| 2158 | 2158 |
| 2159 | 2159 |
| 2160 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2160 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2161 Label gc_required; | 2161 Label gc_required; |
| 2162 Label allocated; | 2162 Label allocated; |
| 2163 | 2163 |
| 2164 Handle<Map> map(isolate()->native_context()->iterator_result_map()); | 2164 Handle<Map> map(isolate()->native_context()->iterator_result_map()); |
| 2165 | 2165 |
| 2166 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); | 2166 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); |
| 2167 __ jmp(&allocated); | 2167 __ jmp(&allocated); |
| 2168 | 2168 |
| 2169 __ bind(&gc_required); | 2169 __ bind(&gc_required); |
| 2170 __ Push(Smi::FromInt(map->instance_size())); | 2170 __ Push(Smi::FromInt(map->instance_size())); |
| 2171 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 2171 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 2172 __ mov(context_register(), | 2172 __ mov(context_register(), |
| 2173 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2173 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2174 | 2174 |
| 2175 __ bind(&allocated); | 2175 __ bind(&allocated); |
| 2176 __ mov(ebx, map); | 2176 __ mov(ebx, map); |
| 2177 __ pop(ecx); | 2177 __ pop(ecx); |
| 2178 __ mov(edx, isolate()->factory()->ToBoolean(done)); | 2178 __ mov(edx, isolate()->factory()->ToBoolean(done)); |
| 2179 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2179 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); |
| 2180 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2180 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
| 2181 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2181 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2373 } | 2373 } |
| 2374 } | 2374 } |
| 2375 | 2375 |
| 2376 | 2376 |
| 2377 void FullCodeGenerator::EmitCallStoreContextSlot( | 2377 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2378 Handle<String> name, StrictMode strict_mode) { | 2378 Handle<String> name, StrictMode strict_mode) { |
| 2379 __ push(eax); // Value. | 2379 __ push(eax); // Value. |
| 2380 __ push(esi); // Context. | 2380 __ push(esi); // Context. |
| 2381 __ push(Immediate(name)); | 2381 __ push(Immediate(name)); |
| 2382 __ push(Immediate(Smi::FromInt(strict_mode))); | 2382 __ push(Immediate(Smi::FromInt(strict_mode))); |
| 2383 __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); | 2383 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2384 } | 2384 } |
| 2385 | 2385 |
| 2386 | 2386 |
| 2387 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2387 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2388 Token::Value op) { | 2388 Token::Value op) { |
| 2389 if (var->IsUnallocated()) { | 2389 if (var->IsUnallocated()) { |
| 2390 // Global var, const, or let. | 2390 // Global var, const, or let. |
| 2391 __ mov(ecx, var->name()); | 2391 __ mov(ecx, var->name()); |
| 2392 __ mov(edx, GlobalObjectOperand()); | 2392 __ mov(edx, GlobalObjectOperand()); |
| 2393 CallStoreIC(); | 2393 CallStoreIC(); |
| 2394 | 2394 |
| 2395 } else if (op == Token::INIT_CONST_LEGACY) { | 2395 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2396 // Const initializers need a write barrier. | 2396 // Const initializers need a write barrier. |
| 2397 ASSERT(!var->IsParameter()); // No const parameters. | 2397 ASSERT(!var->IsParameter()); // No const parameters. |
| 2398 if (var->IsLookupSlot()) { | 2398 if (var->IsLookupSlot()) { |
| 2399 __ push(eax); | 2399 __ push(eax); |
| 2400 __ push(esi); | 2400 __ push(esi); |
| 2401 __ push(Immediate(var->name())); | 2401 __ push(Immediate(var->name())); |
| 2402 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); | 2402 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2403 } else { | 2403 } else { |
| 2404 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2404 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2405 Label skip; | 2405 Label skip; |
| 2406 MemOperand location = VarOperand(var, ecx); | 2406 MemOperand location = VarOperand(var, ecx); |
| 2407 __ mov(edx, location); | 2407 __ mov(edx, location); |
| 2408 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2408 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2409 __ j(not_equal, &skip, Label::kNear); | 2409 __ j(not_equal, &skip, Label::kNear); |
| 2410 EmitStoreToStackLocalOrContextSlot(var, location); | 2410 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2411 __ bind(&skip); | 2411 __ bind(&skip); |
| 2412 } | 2412 } |
| 2413 | 2413 |
| 2414 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2414 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2415 // Non-initializing assignment to let variable needs a write barrier. | 2415 // Non-initializing assignment to let variable needs a write barrier. |
| 2416 if (var->IsLookupSlot()) { | 2416 if (var->IsLookupSlot()) { |
| 2417 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2417 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2418 } else { | 2418 } else { |
| 2419 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2419 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2420 Label assign; | 2420 Label assign; |
| 2421 MemOperand location = VarOperand(var, ecx); | 2421 MemOperand location = VarOperand(var, ecx); |
| 2422 __ mov(edx, location); | 2422 __ mov(edx, location); |
| 2423 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2423 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2424 __ j(not_equal, &assign, Label::kNear); | 2424 __ j(not_equal, &assign, Label::kNear); |
| 2425 __ push(Immediate(var->name())); | 2425 __ push(Immediate(var->name())); |
| 2426 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 2426 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2427 __ bind(&assign); | 2427 __ bind(&assign); |
| 2428 EmitStoreToStackLocalOrContextSlot(var, location); | 2428 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2429 } | 2429 } |
| 2430 | 2430 |
| 2431 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2431 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2432 // Assignment to var or initializing assignment to let/const | 2432 // Assignment to var or initializing assignment to let/const |
| 2433 // in harmony mode. | 2433 // in harmony mode. |
| 2434 if (var->IsLookupSlot()) { | 2434 if (var->IsLookupSlot()) { |
| 2435 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2435 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2436 } else { | 2436 } else { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2610 | 2610 |
| 2611 // Push the receiver of the enclosing function. | 2611 // Push the receiver of the enclosing function. |
| 2612 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); | 2612 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize)); |
| 2613 // Push the language mode. | 2613 // Push the language mode. |
| 2614 __ push(Immediate(Smi::FromInt(strict_mode()))); | 2614 __ push(Immediate(Smi::FromInt(strict_mode()))); |
| 2615 | 2615 |
| 2616 // Push the start position of the scope the calls resides in. | 2616 // Push the start position of the scope the calls resides in. |
| 2617 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | 2617 __ push(Immediate(Smi::FromInt(scope()->start_position()))); |
| 2618 | 2618 |
| 2619 // Do the runtime call. | 2619 // Do the runtime call. |
| 2620 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); | 2620 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2621 } | 2621 } |
| 2622 | 2622 |
| 2623 | 2623 |
| 2624 void FullCodeGenerator::VisitCall(Call* expr) { | 2624 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2625 #ifdef DEBUG | 2625 #ifdef DEBUG |
| 2626 // We want to verify that RecordJSReturnSite gets called on all paths | 2626 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2627 // through this function. Avoid early returns. | 2627 // through this function. Avoid early returns. |
| 2628 expr->return_is_recorded_ = false; | 2628 expr->return_is_recorded_ = false; |
| 2629 #endif | 2629 #endif |
| 2630 | 2630 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2677 { PreservePositionScope scope(masm()->positions_recorder()); | 2677 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2678 // Generate code for loading from variables potentially shadowed by | 2678 // Generate code for loading from variables potentially shadowed by |
| 2679 // eval-introduced variables. | 2679 // eval-introduced variables. |
| 2680 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2680 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2681 } | 2681 } |
| 2682 __ bind(&slow); | 2682 __ bind(&slow); |
| 2683 // Call the runtime to find the function to call (returned in eax) and | 2683 // Call the runtime to find the function to call (returned in eax) and |
| 2684 // the object holding it (returned in edx). | 2684 // the object holding it (returned in edx). |
| 2685 __ push(context_register()); | 2685 __ push(context_register()); |
| 2686 __ push(Immediate(proxy->name())); | 2686 __ push(Immediate(proxy->name())); |
| 2687 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 2687 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2688 __ push(eax); // Function. | 2688 __ push(eax); // Function. |
| 2689 __ push(edx); // Receiver. | 2689 __ push(edx); // Receiver. |
| 2690 | 2690 |
| 2691 // If fast case code has been generated, emit code to push the function | 2691 // If fast case code has been generated, emit code to push the function |
| 2692 // and receiver and have the slow path jump around this code. | 2692 // and receiver and have the slow path jump around this code. |
| 2693 if (done.is_linked()) { | 2693 if (done.is_linked()) { |
| 2694 Label call; | 2694 Label call; |
| 2695 __ jmp(&call, Label::kNear); | 2695 __ jmp(&call, Label::kNear); |
| 2696 __ bind(&done); | 2696 __ bind(&done); |
| 2697 // Push function. | 2697 // Push function. |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3316 } | 3316 } |
| 3317 __ bind(&runtime); | 3317 __ bind(&runtime); |
| 3318 __ PrepareCallCFunction(2, scratch); | 3318 __ PrepareCallCFunction(2, scratch); |
| 3319 __ mov(Operand(esp, 0), object); | 3319 __ mov(Operand(esp, 0), object); |
| 3320 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); | 3320 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); |
| 3321 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3321 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 3322 __ jmp(&done); | 3322 __ jmp(&done); |
| 3323 } | 3323 } |
| 3324 | 3324 |
| 3325 __ bind(¬_date_object); | 3325 __ bind(¬_date_object); |
| 3326 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); | 3326 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
| 3327 __ bind(&done); | 3327 __ bind(&done); |
| 3328 context()->Plug(result); | 3328 context()->Plug(result); |
| 3329 } | 3329 } |
| 3330 | 3330 |
| 3331 | 3331 |
| 3332 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3332 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3333 ZoneList<Expression*>* args = expr->arguments(); | 3333 ZoneList<Expression*>* args = expr->arguments(); |
| 3334 ASSERT_EQ(3, args->length()); | 3334 ASSERT_EQ(3, args->length()); |
| 3335 | 3335 |
| 3336 Register string = eax; | 3336 Register string = eax; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3398 } | 3398 } |
| 3399 | 3399 |
| 3400 | 3400 |
| 3401 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3401 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 3402 // Load the arguments on the stack and call the runtime function. | 3402 // Load the arguments on the stack and call the runtime function. |
| 3403 ZoneList<Expression*>* args = expr->arguments(); | 3403 ZoneList<Expression*>* args = expr->arguments(); |
| 3404 ASSERT(args->length() == 2); | 3404 ASSERT(args->length() == 2); |
| 3405 VisitForStackValue(args->at(0)); | 3405 VisitForStackValue(args->at(0)); |
| 3406 VisitForStackValue(args->at(1)); | 3406 VisitForStackValue(args->at(1)); |
| 3407 | 3407 |
| 3408 __ CallRuntime(Runtime::kHiddenMathPowSlow, 2); | 3408 __ CallRuntime(Runtime::kMathPowSlow, 2); |
| 3409 context()->Plug(eax); | 3409 context()->Plug(eax); |
| 3410 } | 3410 } |
| 3411 | 3411 |
| 3412 | 3412 |
| 3413 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3413 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
| 3414 ZoneList<Expression*>* args = expr->arguments(); | 3414 ZoneList<Expression*>* args = expr->arguments(); |
| 3415 ASSERT(args->length() == 2); | 3415 ASSERT(args->length() == 2); |
| 3416 | 3416 |
| 3417 VisitForStackValue(args->at(0)); // Load the object. | 3417 VisitForStackValue(args->at(0)); // Load the object. |
| 3418 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3418 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3673 __ cmp(key, FixedArrayElementOperand(cache, tmp)); | 3673 __ cmp(key, FixedArrayElementOperand(cache, tmp)); |
| 3674 __ j(not_equal, ¬_found); | 3674 __ j(not_equal, ¬_found); |
| 3675 | 3675 |
| 3676 __ mov(eax, FixedArrayElementOperand(cache, tmp, 1)); | 3676 __ mov(eax, FixedArrayElementOperand(cache, tmp, 1)); |
| 3677 __ jmp(&done); | 3677 __ jmp(&done); |
| 3678 | 3678 |
| 3679 __ bind(¬_found); | 3679 __ bind(¬_found); |
| 3680 // Call runtime to perform the lookup. | 3680 // Call runtime to perform the lookup. |
| 3681 __ push(cache); | 3681 __ push(cache); |
| 3682 __ push(key); | 3682 __ push(key); |
| 3683 __ CallRuntime(Runtime::kHiddenGetFromCache, 2); | 3683 __ CallRuntime(Runtime::kGetFromCache, 2); |
| 3684 | 3684 |
| 3685 __ bind(&done); | 3685 __ bind(&done); |
| 3686 context()->Plug(eax); | 3686 context()->Plug(eax); |
| 3687 } | 3687 } |
| 3688 | 3688 |
| 3689 | 3689 |
| 3690 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3690 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3691 ZoneList<Expression*>* args = expr->arguments(); | 3691 ZoneList<Expression*>* args = expr->arguments(); |
| 3692 ASSERT(args->length() == 1); | 3692 ASSERT(args->length() == 1); |
| 3693 | 3693 |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4082 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4082 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4083 // Result of deleting non-global variables is false. 'this' is | 4083 // Result of deleting non-global variables is false. 'this' is |
| 4084 // not really a variable, though we implement it as one. The | 4084 // not really a variable, though we implement it as one. The |
| 4085 // subexpression does not have side effects. | 4085 // subexpression does not have side effects. |
| 4086 context()->Plug(var->is_this()); | 4086 context()->Plug(var->is_this()); |
| 4087 } else { | 4087 } else { |
| 4088 // Non-global variable. Call the runtime to try to delete from the | 4088 // Non-global variable. Call the runtime to try to delete from the |
| 4089 // context where the variable was introduced. | 4089 // context where the variable was introduced. |
| 4090 __ push(context_register()); | 4090 __ push(context_register()); |
| 4091 __ push(Immediate(var->name())); | 4091 __ push(Immediate(var->name())); |
| 4092 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); | 4092 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 4093 context()->Plug(eax); | 4093 context()->Plug(eax); |
| 4094 } | 4094 } |
| 4095 } else { | 4095 } else { |
| 4096 // Result of deleting non-property, non-variable reference is true. | 4096 // Result of deleting non-property, non-variable reference is true. |
| 4097 // The subexpression may have side effects. | 4097 // The subexpression may have side effects. |
| 4098 VisitForEffect(expr->expression()); | 4098 VisitForEffect(expr->expression()); |
| 4099 context()->Plug(true); | 4099 context()->Plug(true); |
| 4100 } | 4100 } |
| 4101 break; | 4101 break; |
| 4102 } | 4102 } |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4375 Comment cmnt(masm_, "[ Lookup slot"); | 4375 Comment cmnt(masm_, "[ Lookup slot"); |
| 4376 Label done, slow; | 4376 Label done, slow; |
| 4377 | 4377 |
| 4378 // Generate code for loading from variables potentially shadowed | 4378 // Generate code for loading from variables potentially shadowed |
| 4379 // by eval-introduced variables. | 4379 // by eval-introduced variables. |
| 4380 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4380 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4381 | 4381 |
| 4382 __ bind(&slow); | 4382 __ bind(&slow); |
| 4383 __ push(esi); | 4383 __ push(esi); |
| 4384 __ push(Immediate(proxy->name())); | 4384 __ push(Immediate(proxy->name())); |
| 4385 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); | 4385 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 4386 PrepareForBailout(expr, TOS_REG); | 4386 PrepareForBailout(expr, TOS_REG); |
| 4387 __ bind(&done); | 4387 __ bind(&done); |
| 4388 | 4388 |
| 4389 context()->Plug(eax); | 4389 context()->Plug(eax); |
| 4390 } else { | 4390 } else { |
| 4391 // This expression cannot throw a reference error at the top level. | 4391 // This expression cannot throw a reference error at the top level. |
| 4392 VisitInDuplicateContext(expr); | 4392 VisitInDuplicateContext(expr); |
| 4393 } | 4393 } |
| 4394 } | 4394 } |
| 4395 | 4395 |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4792 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4792 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4793 Assembler::target_address_at(call_target_address, | 4793 Assembler::target_address_at(call_target_address, |
| 4794 unoptimized_code)); | 4794 unoptimized_code)); |
| 4795 return OSR_AFTER_STACK_CHECK; | 4795 return OSR_AFTER_STACK_CHECK; |
| 4796 } | 4796 } |
| 4797 | 4797 |
| 4798 | 4798 |
| 4799 } } // namespace v8::internal | 4799 } } // namespace v8::internal |
| 4800 | 4800 |
| 4801 #endif // V8_TARGET_ARCH_X87 | 4801 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |