| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 kDontSaveFPRegs, | 710 kDontSaveFPRegs, |
| 711 EMIT_REMEMBERED_SET, | 711 EMIT_REMEMBERED_SET, |
| 712 OMIT_SMI_CHECK); | 712 OMIT_SMI_CHECK); |
| 713 } | 713 } |
| 714 break; | 714 break; |
| 715 | 715 |
| 716 case Slot::LOOKUP: { | 716 case Slot::LOOKUP: { |
| 717 __ push(rsi); | 717 __ push(rsi); |
| 718 __ Push(variable->name()); | 718 __ Push(variable->name()); |
| 719 // Declaration nodes are always introduced in one of two modes. | 719 // Declaration nodes are always introduced in one of two modes. |
| 720 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 720 ASSERT(mode == Variable::VAR || |
| 721 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 721 mode == Variable::CONST || |
| 722 mode == Variable::LET); |
| 723 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE; |
| 722 __ Push(Smi::FromInt(attr)); | 724 __ Push(Smi::FromInt(attr)); |
| 723 // Push initial value, if any. | 725 // Push initial value, if any. |
| 724 // Note: For variables we must not push an initial value (such as | 726 // Note: For variables we must not push an initial value (such as |
| 725 // 'undefined') because we may have a (legal) redeclaration and we | 727 // 'undefined') because we may have a (legal) redeclaration and we |
| 726 // must not destroy the current value. | 728 // must not destroy the current value. |
| 727 if (mode == Variable::CONST) { | 729 if (mode == Variable::CONST) { |
| 728 __ PushRoot(Heap::kTheHoleValueRootIndex); | 730 __ PushRoot(Heap::kTheHoleValueRootIndex); |
| 729 } else if (function != NULL) { | 731 } else if (function != NULL) { |
| 730 VisitForStackValue(function); | 732 VisitForStackValue(function); |
| 731 } else { | 733 } else { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 __ j(not_equal, &next_test); | 840 __ j(not_equal, &next_test); |
| 839 __ Drop(1); // Switch value is no longer needed. | 841 __ Drop(1); // Switch value is no longer needed. |
| 840 __ jmp(clause->body_target()); | 842 __ jmp(clause->body_target()); |
| 841 } | 843 } |
| 842 | 844 |
| 843 // Discard the test value and jump to the default if present, otherwise to | 845 // Discard the test value and jump to the default if present, otherwise to |
| 844 // the end of the statement. | 846 // the end of the statement. |
| 845 __ bind(&next_test); | 847 __ bind(&next_test); |
| 846 __ Drop(1); // Switch value is no longer needed. | 848 __ Drop(1); // Switch value is no longer needed. |
| 847 if (default_clause == NULL) { | 849 if (default_clause == NULL) { |
| 848 __ jmp(nested_statement.break_target()); | 850 __ jmp(nested_statement.break_label()); |
| 849 } else { | 851 } else { |
| 850 __ jmp(default_clause->body_target()); | 852 __ jmp(default_clause->body_target()); |
| 851 } | 853 } |
| 852 | 854 |
| 853 // Compile all the case bodies. | 855 // Compile all the case bodies. |
| 854 for (int i = 0; i < clauses->length(); i++) { | 856 for (int i = 0; i < clauses->length(); i++) { |
| 855 Comment cmnt(masm_, "[ Case body"); | 857 Comment cmnt(masm_, "[ Case body"); |
| 856 CaseClause* clause = clauses->at(i); | 858 CaseClause* clause = clauses->at(i); |
| 857 __ bind(clause->body_target()); | 859 __ bind(clause->body_target()); |
| 858 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); | 860 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); |
| 859 VisitStatements(clause->statements()); | 861 VisitStatements(clause->statements()); |
| 860 } | 862 } |
| 861 | 863 |
| 862 __ bind(nested_statement.break_target()); | 864 __ bind(nested_statement.break_label()); |
| 863 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 865 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 864 } | 866 } |
| 865 | 867 |
| 866 | 868 |
| 867 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 869 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 868 Comment cmnt(masm_, "[ ForInStatement"); | 870 Comment cmnt(masm_, "[ ForInStatement"); |
| 869 SetStatementPosition(stmt); | 871 SetStatementPosition(stmt); |
| 870 | 872 |
| 871 Label loop, exit; | 873 Label loop, exit; |
| 872 ForIn loop_statement(this, stmt); | 874 ForIn loop_statement(this, stmt); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 __ Push(Smi::FromInt(0)); // Map (0) - force slow check. | 980 __ Push(Smi::FromInt(0)); // Map (0) - force slow check. |
| 979 __ push(rax); | 981 __ push(rax); |
| 980 __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); | 982 __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); |
| 981 __ push(rax); // Fixed array length (as smi). | 983 __ push(rax); // Fixed array length (as smi). |
| 982 __ Push(Smi::FromInt(0)); // Initial index. | 984 __ Push(Smi::FromInt(0)); // Initial index. |
| 983 | 985 |
| 984 // Generate code for doing the condition check. | 986 // Generate code for doing the condition check. |
| 985 __ bind(&loop); | 987 __ bind(&loop); |
| 986 __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. | 988 __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. |
| 987 __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. | 989 __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. |
| 988 __ j(above_equal, loop_statement.break_target()); | 990 __ j(above_equal, loop_statement.break_label()); |
| 989 | 991 |
| 990 // Get the current entry of the array into register rbx. | 992 // Get the current entry of the array into register rbx. |
| 991 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); | 993 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); |
| 992 SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); | 994 SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); |
| 993 __ movq(rbx, FieldOperand(rbx, | 995 __ movq(rbx, FieldOperand(rbx, |
| 994 index.reg, | 996 index.reg, |
| 995 index.scale, | 997 index.scale, |
| 996 FixedArray::kHeaderSize)); | 998 FixedArray::kHeaderSize)); |
| 997 | 999 |
| 998 // Get the expected map from the stack or a zero map in the | 1000 // Get the expected map from the stack or a zero map in the |
| 999 // permanent slow case into register rdx. | 1001 // permanent slow case into register rdx. |
| 1000 __ movq(rdx, Operand(rsp, 3 * kPointerSize)); | 1002 __ movq(rdx, Operand(rsp, 3 * kPointerSize)); |
| 1001 | 1003 |
| 1002 // Check if the expected map still matches that of the enumerable. | 1004 // Check if the expected map still matches that of the enumerable. |
| 1003 // If not, we have to filter the key. | 1005 // If not, we have to filter the key. |
| 1004 Label update_each; | 1006 Label update_each; |
| 1005 __ movq(rcx, Operand(rsp, 4 * kPointerSize)); | 1007 __ movq(rcx, Operand(rsp, 4 * kPointerSize)); |
| 1006 __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); | 1008 __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); |
| 1007 __ j(equal, &update_each, Label::kNear); | 1009 __ j(equal, &update_each, Label::kNear); |
| 1008 | 1010 |
| 1009 // Convert the entry to a string or null if it isn't a property | 1011 // Convert the entry to a string or null if it isn't a property |
| 1010 // anymore. If the property has been removed while iterating, we | 1012 // anymore. If the property has been removed while iterating, we |
| 1011 // just skip it. | 1013 // just skip it. |
| 1012 __ push(rcx); // Enumerable. | 1014 __ push(rcx); // Enumerable. |
| 1013 __ push(rbx); // Current entry. | 1015 __ push(rbx); // Current entry. |
| 1014 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1016 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 1015 __ Cmp(rax, Smi::FromInt(0)); | 1017 __ Cmp(rax, Smi::FromInt(0)); |
| 1016 __ j(equal, loop_statement.continue_target()); | 1018 __ j(equal, loop_statement.continue_label()); |
| 1017 __ movq(rbx, rax); | 1019 __ movq(rbx, rax); |
| 1018 | 1020 |
| 1019 // Update the 'each' property or variable from the possibly filtered | 1021 // Update the 'each' property or variable from the possibly filtered |
| 1020 // entry in register rbx. | 1022 // entry in register rbx. |
| 1021 __ bind(&update_each); | 1023 __ bind(&update_each); |
| 1022 __ movq(result_register(), rbx); | 1024 __ movq(result_register(), rbx); |
| 1023 // Perform the assignment as if via '='. | 1025 // Perform the assignment as if via '='. |
| 1024 { EffectContext context(this); | 1026 { EffectContext context(this); |
| 1025 EmitAssignment(stmt->each(), stmt->AssignmentId()); | 1027 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 1026 } | 1028 } |
| 1027 | 1029 |
| 1028 // Generate code for the body of the loop. | 1030 // Generate code for the body of the loop. |
| 1029 Visit(stmt->body()); | 1031 Visit(stmt->body()); |
| 1030 | 1032 |
| 1031 // Generate code for going to the next element by incrementing the | 1033 // Generate code for going to the next element by incrementing the |
| 1032 // index (smi) stored on top of the stack. | 1034 // index (smi) stored on top of the stack. |
| 1033 __ bind(loop_statement.continue_target()); | 1035 __ bind(loop_statement.continue_label()); |
| 1034 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); | 1036 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); |
| 1035 | 1037 |
| 1036 EmitStackCheck(stmt); | 1038 EmitStackCheck(stmt); |
| 1037 __ jmp(&loop); | 1039 __ jmp(&loop); |
| 1038 | 1040 |
| 1039 // Remove the pointers stored on the stack. | 1041 // Remove the pointers stored on the stack. |
| 1040 __ bind(loop_statement.break_target()); | 1042 __ bind(loop_statement.break_label()); |
| 1041 __ addq(rsp, Immediate(5 * kPointerSize)); | 1043 __ addq(rsp, Immediate(5 * kPointerSize)); |
| 1042 | 1044 |
| 1043 // Exit and decrement the loop depth. | 1045 // Exit and decrement the loop depth. |
| 1044 __ bind(&exit); | 1046 __ bind(&exit); |
| 1045 decrement_loop_depth(); | 1047 decrement_loop_depth(); |
| 1046 } | 1048 } |
| 1047 | 1049 |
| 1048 | 1050 |
| 1049 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1051 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1050 bool pretenure) { | 1052 bool pretenure) { |
| (...skipping 2932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3983 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); | 3985 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); |
| 3984 __ j(above_equal, if_false); | 3986 __ j(above_equal, if_false); |
| 3985 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 3987 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
| 3986 Immediate(1 << Map::kIsUndetectable)); | 3988 Immediate(1 << Map::kIsUndetectable)); |
| 3987 Split(zero, if_true, if_false, fall_through); | 3989 Split(zero, if_true, if_false, fall_through); |
| 3988 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { | 3990 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { |
| 3989 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 3991 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
| 3990 __ j(equal, if_true); | 3992 __ j(equal, if_true); |
| 3991 __ CompareRoot(rax, Heap::kFalseValueRootIndex); | 3993 __ CompareRoot(rax, Heap::kFalseValueRootIndex); |
| 3992 Split(equal, if_true, if_false, fall_through); | 3994 Split(equal, if_true, if_false, fall_through); |
| 3995 } else if (FLAG_harmony_typeof && |
| 3996 check->Equals(isolate()->heap()->null_symbol())) { |
| 3997 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
| 3998 Split(equal, if_true, if_false, fall_through); |
| 3993 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { | 3999 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { |
| 3994 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 4000 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 3995 __ j(equal, if_true); | 4001 __ j(equal, if_true); |
| 3996 __ JumpIfSmi(rax, if_false); | 4002 __ JumpIfSmi(rax, if_false); |
| 3997 // Check for undetectable objects => true. | 4003 // Check for undetectable objects => true. |
| 3998 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 4004 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 3999 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4005 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
| 4000 Immediate(1 << Map::kIsUndetectable)); | 4006 Immediate(1 << Map::kIsUndetectable)); |
| 4001 Split(not_zero, if_true, if_false, fall_through); | 4007 Split(not_zero, if_true, if_false, fall_through); |
| 4002 } else if (check->Equals(isolate()->heap()->function_symbol())) { | 4008 } else if (check->Equals(isolate()->heap()->function_symbol())) { |
| 4003 __ JumpIfSmi(rax, if_false); | 4009 __ JumpIfSmi(rax, if_false); |
| 4004 STATIC_ASSERT(LAST_CALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE); | 4010 STATIC_ASSERT(LAST_CALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 4005 __ CmpObjectType(rax, FIRST_CALLABLE_SPEC_OBJECT_TYPE, rdx); | 4011 __ CmpObjectType(rax, FIRST_CALLABLE_SPEC_OBJECT_TYPE, rdx); |
| 4006 Split(above_equal, if_true, if_false, fall_through); | 4012 Split(above_equal, if_true, if_false, fall_through); |
| 4007 } else if (check->Equals(isolate()->heap()->object_symbol())) { | 4013 } else if (check->Equals(isolate()->heap()->object_symbol())) { |
| 4008 __ JumpIfSmi(rax, if_false); | 4014 __ JumpIfSmi(rax, if_false); |
| 4009 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 4015 if (!FLAG_harmony_typeof) { |
| 4010 __ j(equal, if_true); | 4016 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
| 4017 __ j(equal, if_true); |
| 4018 } |
| 4011 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); | 4019 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); |
| 4012 __ j(below, if_false); | 4020 __ j(below, if_false); |
| 4013 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4021 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4014 __ j(above, if_false); | 4022 __ j(above, if_false); |
| 4015 // Check for undetectable objects => false. | 4023 // Check for undetectable objects => false. |
| 4016 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4024 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
| 4017 Immediate(1 << Map::kIsUndetectable)); | 4025 Immediate(1 << Map::kIsUndetectable)); |
| 4018 Split(zero, if_true, if_false, fall_through); | 4026 Split(zero, if_true, if_false, fall_through); |
| 4019 } else { | 4027 } else { |
| 4020 if (if_false != fall_through) __ jmp(if_false); | 4028 if (if_false != fall_through) __ jmp(if_false); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4248 __ jmp(rdx); | 4256 __ jmp(rdx); |
| 4249 } | 4257 } |
| 4250 | 4258 |
| 4251 | 4259 |
| 4252 #undef __ | 4260 #undef __ |
| 4253 | 4261 |
| 4254 | 4262 |
| 4255 } } // namespace v8::internal | 4263 } } // namespace v8::internal |
| 4256 | 4264 |
| 4257 #endif // V8_TARGET_ARCH_X64 | 4265 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |