| 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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 247     Comment cmnt(masm_, "[ Declarations"); | 247     Comment cmnt(masm_, "[ Declarations"); | 
| 248     scope()->VisitIllegalRedeclaration(this); | 248     scope()->VisitIllegalRedeclaration(this); | 
| 249 | 249 | 
| 250   } else { | 250   } else { | 
| 251     PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); | 251     PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); | 
| 252     { Comment cmnt(masm_, "[ Declarations"); | 252     { Comment cmnt(masm_, "[ Declarations"); | 
| 253       // For named function expressions, declare the function name as a | 253       // For named function expressions, declare the function name as a | 
| 254       // constant. | 254       // constant. | 
| 255       if (scope()->is_function_scope() && scope()->function() != NULL) { | 255       if (scope()->is_function_scope() && scope()->function() != NULL) { | 
| 256         int ignored = 0; | 256         int ignored = 0; | 
| 257         EmitDeclaration(scope()->function(), CONST, NULL, &ignored); | 257         VariableProxy* proxy = scope()->function(); | 
|  | 258         ASSERT(proxy->var()->mode() == CONST || | 
|  | 259                proxy->var()->mode() == CONST_HARMONY); | 
|  | 260         EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored); | 
| 258       } | 261       } | 
| 259       VisitDeclarations(scope()->declarations()); | 262       VisitDeclarations(scope()->declarations()); | 
| 260     } | 263     } | 
| 261 | 264 | 
| 262     { Comment cmnt(masm_, "[ Stack check"); | 265     { Comment cmnt(masm_, "[ Stack check"); | 
| 263       PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); | 266       PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); | 
| 264       Label ok; | 267       Label ok; | 
| 265       __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 268       __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 
| 266       __ j(above_equal, &ok, Label::kNear); | 269       __ j(above_equal, &ok, Label::kNear); | 
| 267       StackCheckStub stub; | 270       StackCheckStub stub; | 
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 677 | 680 | 
| 678 | 681 | 
| 679 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 682 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 
| 680                                         VariableMode mode, | 683                                         VariableMode mode, | 
| 681                                         FunctionLiteral* function, | 684                                         FunctionLiteral* function, | 
| 682                                         int* global_count) { | 685                                         int* global_count) { | 
| 683   // If it was not possible to allocate the variable at compile time, we | 686   // If it was not possible to allocate the variable at compile time, we | 
| 684   // need to "declare" it at runtime to make sure it actually exists in the | 687   // need to "declare" it at runtime to make sure it actually exists in the | 
| 685   // local context. | 688   // local context. | 
| 686   Variable* variable = proxy->var(); | 689   Variable* variable = proxy->var(); | 
|  | 690   bool binding_needs_init = | 
|  | 691       mode == CONST || mode == CONST_HARMONY || mode == LET; | 
| 687   switch (variable->location()) { | 692   switch (variable->location()) { | 
| 688     case Variable::UNALLOCATED: | 693     case Variable::UNALLOCATED: | 
| 689       ++(*global_count); | 694       ++(*global_count); | 
| 690       break; | 695       break; | 
| 691 | 696 | 
| 692     case Variable::PARAMETER: | 697     case Variable::PARAMETER: | 
| 693     case Variable::LOCAL: | 698     case Variable::LOCAL: | 
| 694       if (function != NULL) { | 699       if (function != NULL) { | 
| 695         Comment cmnt(masm_, "[ Declaration"); | 700         Comment cmnt(masm_, "[ Declaration"); | 
| 696         VisitForAccumulatorValue(function); | 701         VisitForAccumulatorValue(function); | 
| 697         __ movq(StackOperand(variable), result_register()); | 702         __ movq(StackOperand(variable), result_register()); | 
| 698       } else if (mode == CONST || mode == LET) { | 703       } else if (binding_needs_init) { | 
| 699         Comment cmnt(masm_, "[ Declaration"); | 704         Comment cmnt(masm_, "[ Declaration"); | 
| 700         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 705         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 
| 701         __ movq(StackOperand(variable), kScratchRegister); | 706         __ movq(StackOperand(variable), kScratchRegister); | 
| 702       } | 707       } | 
| 703       break; | 708       break; | 
| 704 | 709 | 
| 705     case Variable::CONTEXT: | 710     case Variable::CONTEXT: | 
| 706       // The variable in the decl always resides in the current function | 711       // The variable in the decl always resides in the current function | 
| 707       // context. | 712       // context. | 
| 708       ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 713       ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 721         int offset = Context::SlotOffset(variable->index()); | 726         int offset = Context::SlotOffset(variable->index()); | 
| 722         // We know that we have written a function, which is not a smi. | 727         // We know that we have written a function, which is not a smi. | 
| 723         __ RecordWriteContextSlot(rsi, | 728         __ RecordWriteContextSlot(rsi, | 
| 724                                   offset, | 729                                   offset, | 
| 725                                   result_register(), | 730                                   result_register(), | 
| 726                                   rcx, | 731                                   rcx, | 
| 727                                   kDontSaveFPRegs, | 732                                   kDontSaveFPRegs, | 
| 728                                   EMIT_REMEMBERED_SET, | 733                                   EMIT_REMEMBERED_SET, | 
| 729                                   OMIT_SMI_CHECK); | 734                                   OMIT_SMI_CHECK); | 
| 730         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 735         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
| 731       } else if (mode == CONST || mode == LET) { | 736       } else if (binding_needs_init) { | 
| 732         Comment cmnt(masm_, "[ Declaration"); | 737         Comment cmnt(masm_, "[ Declaration"); | 
| 733         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 738         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 
| 734         __ movq(ContextOperand(rsi, variable->index()), kScratchRegister); | 739         __ movq(ContextOperand(rsi, variable->index()), kScratchRegister); | 
| 735         // No write barrier since the hole value is in old space. | 740         // No write barrier since the hole value is in old space. | 
| 736         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 741         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
| 737       } | 742       } | 
| 738       break; | 743       break; | 
| 739 | 744 | 
| 740     case Variable::LOOKUP: { | 745     case Variable::LOOKUP: { | 
| 741       Comment cmnt(masm_, "[ Declaration"); | 746       Comment cmnt(masm_, "[ Declaration"); | 
| 742       __ push(rsi); | 747       __ push(rsi); | 
| 743       __ Push(variable->name()); | 748       __ Push(variable->name()); | 
| 744       // Declaration nodes are always introduced in one of three modes. | 749       // Declaration nodes are always introduced in one of four modes. | 
| 745       ASSERT(mode == VAR || mode == CONST || mode == LET); | 750       ASSERT(mode == VAR || | 
| 746       PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE; | 751              mode == CONST || | 
|  | 752              mode == CONST_HARMONY || | 
|  | 753              mode == LET); | 
|  | 754       PropertyAttributes attr = | 
|  | 755           (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE; | 
| 747       __ Push(Smi::FromInt(attr)); | 756       __ Push(Smi::FromInt(attr)); | 
| 748       // Push initial value, if any. | 757       // Push initial value, if any. | 
| 749       // Note: For variables we must not push an initial value (such as | 758       // Note: For variables we must not push an initial value (such as | 
| 750       // 'undefined') because we may have a (legal) redeclaration and we | 759       // 'undefined') because we may have a (legal) redeclaration and we | 
| 751       // must not destroy the current value. | 760       // must not destroy the current value. | 
| 752       if (function != NULL) { | 761       if (function != NULL) { | 
| 753         VisitForStackValue(function); | 762         VisitForStackValue(function); | 
| 754       } else if (mode == CONST || mode == LET) { | 763       } else if (binding_needs_init) { | 
| 755         __ PushRoot(Heap::kTheHoleValueRootIndex); | 764         __ PushRoot(Heap::kTheHoleValueRootIndex); | 
| 756       } else { | 765       } else { | 
| 757         __ Push(Smi::FromInt(0));  // Indicates no initial value. | 766         __ Push(Smi::FromInt(0));  // Indicates no initial value. | 
| 758       } | 767       } | 
| 759       __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 768       __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 
| 760       break; | 769       break; | 
| 761     } | 770     } | 
| 762   } | 771   } | 
| 763 } | 772 } | 
| 764 | 773 | 
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 883   Label convert, done_convert; | 892   Label convert, done_convert; | 
| 884   __ JumpIfSmi(rax, &convert); | 893   __ JumpIfSmi(rax, &convert); | 
| 885   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 894   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 
| 886   __ j(above_equal, &done_convert); | 895   __ j(above_equal, &done_convert); | 
| 887   __ bind(&convert); | 896   __ bind(&convert); | 
| 888   __ push(rax); | 897   __ push(rax); | 
| 889   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 898   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 
| 890   __ bind(&done_convert); | 899   __ bind(&done_convert); | 
| 891   __ push(rax); | 900   __ push(rax); | 
| 892 | 901 | 
|  | 902   // Check for proxies. | 
|  | 903   Label call_runtime; | 
|  | 904   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 
|  | 905   __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); | 
|  | 906   __ j(below_equal, &call_runtime); | 
|  | 907 | 
| 893   // Check cache validity in generated code. This is a fast case for | 908   // Check cache validity in generated code. This is a fast case for | 
| 894   // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 909   // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 
| 895   // guarantee cache validity, call the runtime system to check cache | 910   // guarantee cache validity, call the runtime system to check cache | 
| 896   // validity or get the property names in a fixed array. | 911   // validity or get the property names in a fixed array. | 
| 897   Label next, call_runtime; | 912   Label next; | 
| 898   Register empty_fixed_array_value = r8; | 913   Register empty_fixed_array_value = r8; | 
| 899   __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 914   __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 
| 900   Register empty_descriptor_array_value = r9; | 915   Register empty_descriptor_array_value = r9; | 
| 901   __ LoadRoot(empty_descriptor_array_value, | 916   __ LoadRoot(empty_descriptor_array_value, | 
| 902               Heap::kEmptyDescriptorArrayRootIndex); | 917               Heap::kEmptyDescriptorArrayRootIndex); | 
| 903   __ movq(rcx, rax); | 918   __ movq(rcx, rax); | 
| 904   __ bind(&next); | 919   __ bind(&next); | 
| 905 | 920 | 
| 906   // Check that there are no elements.  Register rcx contains the | 921   // Check that there are no elements.  Register rcx contains the | 
| 907   // current JS object we've reached through the prototype chain. | 922   // current JS object we've reached through the prototype chain. | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 963 | 978 | 
| 964   // Setup the four remaining stack slots. | 979   // Setup the four remaining stack slots. | 
| 965   __ push(rax);  // Map. | 980   __ push(rax);  // Map. | 
| 966   __ push(rdx);  // Enumeration cache. | 981   __ push(rdx);  // Enumeration cache. | 
| 967   __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); | 982   __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); | 
| 968   __ push(rax);  // Enumeration cache length (as smi). | 983   __ push(rax);  // Enumeration cache length (as smi). | 
| 969   __ Push(Smi::FromInt(0));  // Initial index. | 984   __ Push(Smi::FromInt(0));  // Initial index. | 
| 970   __ jmp(&loop); | 985   __ jmp(&loop); | 
| 971 | 986 | 
| 972   // We got a fixed array in register rax. Iterate through that. | 987   // We got a fixed array in register rax. Iterate through that. | 
|  | 988   Label non_proxy; | 
| 973   __ bind(&fixed_array); | 989   __ bind(&fixed_array); | 
| 974   __ Push(Smi::FromInt(0));  // Map (0) - force slow check. | 990   __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check | 
| 975   __ push(rax); | 991   __ movq(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object | 
|  | 992   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 
|  | 993   __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); | 
|  | 994   __ j(above, &non_proxy); | 
|  | 995   __ Move(rbx, Smi::FromInt(0));  // Zero indicates proxy | 
|  | 996   __ bind(&non_proxy); | 
|  | 997   __ push(rbx);  // Smi | 
|  | 998   __ push(rax);  // Array | 
| 976   __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); | 999   __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); | 
| 977   __ push(rax);  // Fixed array length (as smi). | 1000   __ push(rax);  // Fixed array length (as smi). | 
| 978   __ Push(Smi::FromInt(0));  // Initial index. | 1001   __ Push(Smi::FromInt(0));  // Initial index. | 
| 979 | 1002 | 
| 980   // Generate code for doing the condition check. | 1003   // Generate code for doing the condition check. | 
| 981   __ bind(&loop); | 1004   __ bind(&loop); | 
| 982   __ movq(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index. | 1005   __ movq(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index. | 
| 983   __ cmpq(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length. | 1006   __ cmpq(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length. | 
| 984   __ j(above_equal, loop_statement.break_label()); | 1007   __ j(above_equal, loop_statement.break_label()); | 
| 985 | 1008 | 
| 986   // Get the current entry of the array into register rbx. | 1009   // Get the current entry of the array into register rbx. | 
| 987   __ movq(rbx, Operand(rsp, 2 * kPointerSize)); | 1010   __ movq(rbx, Operand(rsp, 2 * kPointerSize)); | 
| 988   SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); | 1011   SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); | 
| 989   __ movq(rbx, FieldOperand(rbx, | 1012   __ movq(rbx, FieldOperand(rbx, | 
| 990                             index.reg, | 1013                             index.reg, | 
| 991                             index.scale, | 1014                             index.scale, | 
| 992                             FixedArray::kHeaderSize)); | 1015                             FixedArray::kHeaderSize)); | 
| 993 | 1016 | 
| 994   // Get the expected map from the stack or a zero map in the | 1017   // Get the expected map from the stack or a smi in the | 
| 995   // permanent slow case into register rdx. | 1018   // permanent slow case into register rdx. | 
| 996   __ movq(rdx, Operand(rsp, 3 * kPointerSize)); | 1019   __ movq(rdx, Operand(rsp, 3 * kPointerSize)); | 
| 997 | 1020 | 
| 998   // Check if the expected map still matches that of the enumerable. | 1021   // Check if the expected map still matches that of the enumerable. | 
| 999   // If not, we have to filter the key. | 1022   // If not, we may have to filter the key. | 
| 1000   Label update_each; | 1023   Label update_each; | 
| 1001   __ movq(rcx, Operand(rsp, 4 * kPointerSize)); | 1024   __ movq(rcx, Operand(rsp, 4 * kPointerSize)); | 
| 1002   __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); | 1025   __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); | 
| 1003   __ j(equal, &update_each, Label::kNear); | 1026   __ j(equal, &update_each, Label::kNear); | 
| 1004 | 1027 | 
|  | 1028   // For proxies, no filtering is done. | 
|  | 1029   // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. | 
|  | 1030   __ Cmp(rdx, Smi::FromInt(0)); | 
|  | 1031   __ j(equal, &update_each, Label::kNear); | 
|  | 1032 | 
| 1005   // Convert the entry to a string or null if it isn't a property | 1033   // Convert the entry to a string or null if it isn't a property | 
| 1006   // anymore. If the property has been removed while iterating, we | 1034   // anymore. If the property has been removed while iterating, we | 
| 1007   // just skip it. | 1035   // just skip it. | 
| 1008   __ push(rcx);  // Enumerable. | 1036   __ push(rcx);  // Enumerable. | 
| 1009   __ push(rbx);  // Current entry. | 1037   __ push(rbx);  // Current entry. | 
| 1010   __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1038   __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 
| 1011   __ Cmp(rax, Smi::FromInt(0)); | 1039   __ Cmp(rax, Smi::FromInt(0)); | 
| 1012   __ j(equal, loop_statement.continue_label()); | 1040   __ j(equal, loop_statement.continue_label()); | 
| 1013   __ movq(rbx, rax); | 1041   __ movq(rbx, rax); | 
| 1014 | 1042 | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1048   // space for nested functions that don't need literals cloning. If | 1076   // space for nested functions that don't need literals cloning. If | 
| 1049   // we're running with the --always-opt or the --prepare-always-opt | 1077   // we're running with the --always-opt or the --prepare-always-opt | 
| 1050   // flag, we need to use the runtime function so that the new function | 1078   // flag, we need to use the runtime function so that the new function | 
| 1051   // we are creating here gets a chance to have its code optimized and | 1079   // we are creating here gets a chance to have its code optimized and | 
| 1052   // doesn't just get a copy of the existing unoptimized code. | 1080   // doesn't just get a copy of the existing unoptimized code. | 
| 1053   if (!FLAG_always_opt && | 1081   if (!FLAG_always_opt && | 
| 1054       !FLAG_prepare_always_opt && | 1082       !FLAG_prepare_always_opt && | 
| 1055       !pretenure && | 1083       !pretenure && | 
| 1056       scope()->is_function_scope() && | 1084       scope()->is_function_scope() && | 
| 1057       info->num_literals() == 0) { | 1085       info->num_literals() == 0) { | 
| 1058     FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode); | 1086     FastNewClosureStub stub(info->strict_mode_flag()); | 
| 1059     __ Push(info); | 1087     __ Push(info); | 
| 1060     __ CallStub(&stub); | 1088     __ CallStub(&stub); | 
| 1061   } else { | 1089   } else { | 
| 1062     __ push(rsi); | 1090     __ push(rsi); | 
| 1063     __ Push(info); | 1091     __ Push(info); | 
| 1064     __ Push(pretenure | 1092     __ Push(pretenure | 
| 1065             ? isolate()->factory()->true_value() | 1093             ? isolate()->factory()->true_value() | 
| 1066             : isolate()->factory()->false_value()); | 1094             : isolate()->factory()->false_value()); | 
| 1067     __ CallRuntime(Runtime::kNewClosure, 3); | 1095     __ CallRuntime(Runtime::kNewClosure, 3); | 
| 1068   } | 1096   } | 
| 1069   context()->Plug(rax); | 1097   context()->Plug(rax); | 
| 1070 } | 1098 } | 
| 1071 | 1099 | 
| 1072 | 1100 | 
| 1073 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1101 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 
| 1074   Comment cmnt(masm_, "[ VariableProxy"); | 1102   Comment cmnt(masm_, "[ VariableProxy"); | 
| 1075   EmitVariableLoad(expr); | 1103   EmitVariableLoad(expr); | 
| 1076 } | 1104 } | 
| 1077 | 1105 | 
| 1078 | 1106 | 
| 1079 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1107 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 
| 1080                                                       TypeofState typeof_state, | 1108                                                       TypeofState typeof_state, | 
| 1081                                                       Label* slow) { | 1109                                                       Label* slow) { | 
| 1082   Register context = rsi; | 1110   Register context = rsi; | 
| 1083   Register temp = rdx; | 1111   Register temp = rdx; | 
| 1084 | 1112 | 
| 1085   Scope* s = scope(); | 1113   Scope* s = scope(); | 
| 1086   while (s != NULL) { | 1114   while (s != NULL) { | 
| 1087     if (s->num_heap_slots() > 0) { | 1115     if (s->num_heap_slots() > 0) { | 
| 1088       if (s->calls_eval()) { | 1116       if (s->calls_non_strict_eval()) { | 
| 1089         // Check that extension is NULL. | 1117         // Check that extension is NULL. | 
| 1090         __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | 1118         __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | 
| 1091                 Immediate(0)); | 1119                 Immediate(0)); | 
| 1092         __ j(not_equal, slow); | 1120         __ j(not_equal, slow); | 
| 1093       } | 1121       } | 
| 1094       // Load next context in chain. | 1122       // Load next context in chain. | 
| 1095       __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1123       __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 
| 1096       // Walk the rest of the chain without clobbering rsi. | 1124       // Walk the rest of the chain without clobbering rsi. | 
| 1097       context = temp; | 1125       context = temp; | 
| 1098     } | 1126     } | 
| 1099     // If no outer scope calls eval, we do not need to check more | 1127     // If no outer scope calls eval, we do not need to check more | 
| 1100     // context extensions.  If we have reached an eval scope, we check | 1128     // context extensions.  If we have reached an eval scope, we check | 
| 1101     // all extensions from this point. | 1129     // all extensions from this point. | 
| 1102     if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; | 1130     if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; | 
| 1103     s = s->outer_scope(); | 1131     s = s->outer_scope(); | 
| 1104   } | 1132   } | 
| 1105 | 1133 | 
| 1106   if (s != NULL && s->is_eval_scope()) { | 1134   if (s != NULL && s->is_eval_scope()) { | 
| 1107     // Loop up the context chain.  There is no frame effect so it is | 1135     // Loop up the context chain.  There is no frame effect so it is | 
| 1108     // safe to use raw labels here. | 1136     // safe to use raw labels here. | 
| 1109     Label next, fast; | 1137     Label next, fast; | 
| 1110     if (!context.is(temp)) { | 1138     if (!context.is(temp)) { | 
| 1111       __ movq(temp, context); | 1139       __ movq(temp, context); | 
| 1112     } | 1140     } | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 1138 | 1166 | 
| 1139 | 1167 | 
| 1140 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1168 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 
| 1141                                                                 Label* slow) { | 1169                                                                 Label* slow) { | 
| 1142   ASSERT(var->IsContextSlot()); | 1170   ASSERT(var->IsContextSlot()); | 
| 1143   Register context = rsi; | 1171   Register context = rsi; | 
| 1144   Register temp = rbx; | 1172   Register temp = rbx; | 
| 1145 | 1173 | 
| 1146   for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1174   for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 
| 1147     if (s->num_heap_slots() > 0) { | 1175     if (s->num_heap_slots() > 0) { | 
| 1148       if (s->calls_eval()) { | 1176       if (s->calls_non_strict_eval()) { | 
| 1149         // Check that extension is NULL. | 1177         // Check that extension is NULL. | 
| 1150         __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | 1178         __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | 
| 1151                 Immediate(0)); | 1179                 Immediate(0)); | 
| 1152         __ j(not_equal, slow); | 1180         __ j(not_equal, slow); | 
| 1153       } | 1181       } | 
| 1154       __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1182       __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 
| 1155       // Walk the rest of the chain without clobbering rsi. | 1183       // Walk the rest of the chain without clobbering rsi. | 
| 1156       context = temp; | 1184       context = temp; | 
| 1157     } | 1185     } | 
| 1158   } | 1186   } | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 1175   // eval-introduced variables.  Eval is used a lot without | 1203   // eval-introduced variables.  Eval is used a lot without | 
| 1176   // introducing variables.  In those cases, we do not want to | 1204   // introducing variables.  In those cases, we do not want to | 
| 1177   // perform a runtime call for all variables in the scope | 1205   // perform a runtime call for all variables in the scope | 
| 1178   // containing the eval. | 1206   // containing the eval. | 
| 1179   if (var->mode() == DYNAMIC_GLOBAL) { | 1207   if (var->mode() == DYNAMIC_GLOBAL) { | 
| 1180     EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 1208     EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 
| 1181     __ jmp(done); | 1209     __ jmp(done); | 
| 1182   } else if (var->mode() == DYNAMIC_LOCAL) { | 1210   } else if (var->mode() == DYNAMIC_LOCAL) { | 
| 1183     Variable* local = var->local_if_not_shadowed(); | 1211     Variable* local = var->local_if_not_shadowed(); | 
| 1184     __ movq(rax, ContextSlotOperandCheckExtensions(local, slow)); | 1212     __ movq(rax, ContextSlotOperandCheckExtensions(local, slow)); | 
| 1185     if (local->mode() == CONST || local->mode() == LET) { | 1213     if (local->mode() == CONST || | 
|  | 1214         local->mode() == CONST_HARMONY || | 
|  | 1215         local->mode() == LET) { | 
| 1186       __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1216       __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 
| 1187       __ j(not_equal, done); | 1217       __ j(not_equal, done); | 
| 1188       if (local->mode() == CONST) { | 1218       if (local->mode() == CONST) { | 
| 1189         __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1219         __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 
| 1190       } else {  // LET | 1220       } else {  // LET || CONST_HARMONY | 
| 1191         __ Push(var->name()); | 1221         __ Push(var->name()); | 
| 1192         __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1222         __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 1193       } | 1223       } | 
| 1194     } | 1224     } | 
| 1195     __ jmp(done); | 1225     __ jmp(done); | 
| 1196   } | 1226   } | 
| 1197 } | 1227 } | 
| 1198 | 1228 | 
| 1199 | 1229 | 
| 1200 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1230 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 1214       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1244       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 
| 1215       __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1245       __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 
| 1216       context()->Plug(rax); | 1246       context()->Plug(rax); | 
| 1217       break; | 1247       break; | 
| 1218     } | 1248     } | 
| 1219 | 1249 | 
| 1220     case Variable::PARAMETER: | 1250     case Variable::PARAMETER: | 
| 1221     case Variable::LOCAL: | 1251     case Variable::LOCAL: | 
| 1222     case Variable::CONTEXT: { | 1252     case Variable::CONTEXT: { | 
| 1223       Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); | 1253       Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); | 
| 1224       if (var->mode() != LET && var->mode() != CONST) { | 1254       if (!var->binding_needs_init()) { | 
| 1225         context()->Plug(var); | 1255         context()->Plug(var); | 
| 1226       } else { | 1256       } else { | 
| 1227         // Let and const need a read barrier. | 1257         // Let and const need a read barrier. | 
| 1228         Label done; | 1258         Label done; | 
| 1229         GetVar(rax, var); | 1259         GetVar(rax, var); | 
| 1230         __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1260         __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 
| 1231         __ j(not_equal, &done, Label::kNear); | 1261         __ j(not_equal, &done, Label::kNear); | 
| 1232         if (var->mode() == LET) { | 1262         if (var->mode() == LET || var->mode() == CONST_HARMONY) { | 
|  | 1263           // Throw a reference error when using an uninitialized let/const | 
|  | 1264           // binding in harmony mode. | 
| 1233           __ Push(var->name()); | 1265           __ Push(var->name()); | 
| 1234           __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1266           __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 1235         } else {  // CONST | 1267         } else { | 
|  | 1268           // Uninitalized const bindings outside of harmony mode are unholed. | 
|  | 1269           ASSERT(var->mode() == CONST); | 
| 1236           __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1270           __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 
| 1237         } | 1271         } | 
| 1238         __ bind(&done); | 1272         __ bind(&done); | 
| 1239         context()->Plug(rax); | 1273         context()->Plug(rax); | 
| 1240       } | 1274       } | 
| 1241       break; | 1275       break; | 
| 1242     } | 1276     } | 
| 1243 | 1277 | 
| 1244     case Variable::LOOKUP: { | 1278     case Variable::LOOKUP: { | 
| 1245       Label done, slow; | 1279       Label done, slow; | 
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1410     context()->Plug(rax); | 1444     context()->Plug(rax); | 
| 1411   } | 1445   } | 
| 1412 } | 1446 } | 
| 1413 | 1447 | 
| 1414 | 1448 | 
| 1415 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1449 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 
| 1416   Comment cmnt(masm_, "[ ArrayLiteral"); | 1450   Comment cmnt(masm_, "[ ArrayLiteral"); | 
| 1417 | 1451 | 
| 1418   ZoneList<Expression*>* subexprs = expr->values(); | 1452   ZoneList<Expression*>* subexprs = expr->values(); | 
| 1419   int length = subexprs->length(); | 1453   int length = subexprs->length(); | 
|  | 1454   Handle<FixedArray> constant_elements = expr->constant_elements(); | 
|  | 1455   ASSERT_EQ(2, constant_elements->length()); | 
|  | 1456   ElementsKind constant_elements_kind = | 
|  | 1457       static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 
|  | 1458   Handle<FixedArrayBase> constant_elements_values( | 
|  | 1459       FixedArrayBase::cast(constant_elements->get(1))); | 
| 1420 | 1460 | 
| 1421   __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1461   __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 
| 1422   __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); | 1462   __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); | 
| 1423   __ Push(Smi::FromInt(expr->literal_index())); | 1463   __ Push(Smi::FromInt(expr->literal_index())); | 
| 1424   __ Push(expr->constant_elements()); | 1464   __ Push(constant_elements); | 
| 1425   if (expr->constant_elements()->map() == | 1465   if (constant_elements_values->map() == | 
| 1426       isolate()->heap()->fixed_cow_array_map()) { | 1466       isolate()->heap()->fixed_cow_array_map()) { | 
| 1427     FastCloneShallowArrayStub stub( | 1467     FastCloneShallowArrayStub stub( | 
| 1428         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); | 1468         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); | 
| 1429     __ CallStub(&stub); | 1469     __ CallStub(&stub); | 
| 1430     __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); | 1470     __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); | 
| 1431   } else if (expr->depth() > 1) { | 1471   } else if (expr->depth() > 1) { | 
| 1432     __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1472     __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 
| 1433   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 1473   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 
| 1434     __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 1474     __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 
| 1435   } else { | 1475   } else { | 
| 1436     FastCloneShallowArrayStub stub( | 1476     ASSERT(constant_elements_kind == FAST_ELEMENTS || | 
| 1437         FastCloneShallowArrayStub::CLONE_ELEMENTS, length); | 1477            constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || | 
|  | 1478            FLAG_smi_only_arrays); | 
|  | 1479     FastCloneShallowArrayStub::Mode mode = | 
|  | 1480         constant_elements_kind == FAST_DOUBLE_ELEMENTS | 
|  | 1481         ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS | 
|  | 1482         : FastCloneShallowArrayStub::CLONE_ELEMENTS; | 
|  | 1483     FastCloneShallowArrayStub stub(mode, length); | 
| 1438     __ CallStub(&stub); | 1484     __ CallStub(&stub); | 
| 1439   } | 1485   } | 
| 1440 | 1486 | 
| 1441   bool result_saved = false;  // Is the result saved to the stack? | 1487   bool result_saved = false;  // Is the result saved to the stack? | 
| 1442 | 1488 | 
| 1443   // Emit code to evaluate all the non-constant subexpressions and to store | 1489   // Emit code to evaluate all the non-constant subexpressions and to store | 
| 1444   // them into the newly cloned array. | 1490   // them into the newly cloned array. | 
| 1445   for (int i = 0; i < length; i++) { | 1491   for (int i = 0; i < length; i++) { | 
| 1446     Expression* subexpr = subexprs->at(i); | 1492     Expression* subexpr = subexprs->at(i); | 
| 1447     // If the subexpression is a literal or a simple materialized literal it | 1493     // If the subexpression is a literal or a simple materialized literal it | 
| 1448     // is already set in the cloned array. | 1494     // is already set in the cloned array. | 
| 1449     if (subexpr->AsLiteral() != NULL || | 1495     if (subexpr->AsLiteral() != NULL || | 
| 1450         CompileTimeValue::IsCompileTimeValue(subexpr)) { | 1496         CompileTimeValue::IsCompileTimeValue(subexpr)) { | 
| 1451       continue; | 1497       continue; | 
| 1452     } | 1498     } | 
| 1453 | 1499 | 
| 1454     if (!result_saved) { | 1500     if (!result_saved) { | 
| 1455       __ push(rax); | 1501       __ push(rax); | 
| 1456       result_saved = true; | 1502       result_saved = true; | 
| 1457     } | 1503     } | 
| 1458     VisitForAccumulatorValue(subexpr); | 1504     VisitForAccumulatorValue(subexpr); | 
| 1459 | 1505 | 
| 1460     // Store the subexpression value in the array's elements. | 1506     // Store the subexpression value in the array's elements. | 
| 1461     __ movq(r8, Operand(rsp, 0));  // Copy of array literal. | 1507     __ movq(r8, Operand(rsp, 0));  // Copy of array literal. | 
|  | 1508     __ movq(rdi, FieldOperand(r8, JSObject::kMapOffset)); | 
| 1462     __ movq(rbx, FieldOperand(r8, JSObject::kElementsOffset)); | 1509     __ movq(rbx, FieldOperand(r8, JSObject::kElementsOffset)); | 
| 1463     int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1510     int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 
|  | 1511 | 
|  | 1512     Label element_done; | 
|  | 1513     Label double_elements; | 
|  | 1514     Label smi_element; | 
|  | 1515     Label slow_elements; | 
|  | 1516     Label fast_elements; | 
|  | 1517     __ CheckFastElements(rdi, &double_elements); | 
|  | 1518 | 
|  | 1519     // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS | 
|  | 1520     __ JumpIfSmi(result_register(), &smi_element); | 
|  | 1521     __ CheckFastSmiOnlyElements(rdi, &fast_elements); | 
|  | 1522 | 
|  | 1523     // Store into the array literal requires a elements transition. Call into | 
|  | 1524     // the runtime. | 
|  | 1525     __ bind(&slow_elements); | 
|  | 1526     __ push(r8);  // Copy of array literal. | 
|  | 1527     __ Push(Smi::FromInt(i)); | 
|  | 1528     __ push(result_register()); | 
|  | 1529     __ Push(Smi::FromInt(NONE));  // PropertyAttributes | 
|  | 1530     __ Push(Smi::FromInt(strict_mode_flag()));  // Strict mode. | 
|  | 1531     __ CallRuntime(Runtime::kSetProperty, 5); | 
|  | 1532     __ jmp(&element_done); | 
|  | 1533 | 
|  | 1534     // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. | 
|  | 1535     __ bind(&double_elements); | 
|  | 1536     __ movq(rcx, Immediate(i)); | 
|  | 1537     __ StoreNumberToDoubleElements(result_register(), | 
|  | 1538                                    rbx, | 
|  | 1539                                    rcx, | 
|  | 1540                                    xmm0, | 
|  | 1541                                    &slow_elements); | 
|  | 1542     __ jmp(&element_done); | 
|  | 1543 | 
|  | 1544     // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. | 
|  | 1545     __ bind(&fast_elements); | 
| 1464     __ movq(FieldOperand(rbx, offset), result_register()); | 1546     __ movq(FieldOperand(rbx, offset), result_register()); | 
| 1465 |  | 
| 1466     Label no_map_change; |  | 
| 1467     __ JumpIfSmi(result_register(), &no_map_change); |  | 
| 1468     // Update the write barrier for the array store. | 1547     // Update the write barrier for the array store. | 
| 1469     __ RecordWriteField(rbx, offset, result_register(), rcx, | 1548     __ RecordWriteField(rbx, offset, result_register(), rcx, | 
| 1470                         kDontSaveFPRegs, | 1549                         kDontSaveFPRegs, | 
| 1471                         EMIT_REMEMBERED_SET, | 1550                         EMIT_REMEMBERED_SET, | 
| 1472                         OMIT_SMI_CHECK); | 1551                         OMIT_SMI_CHECK); | 
| 1473     __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); | 1552     __ jmp(&element_done); | 
| 1474     __ CheckFastSmiOnlyElements(rdi, &no_map_change, Label::kNear); | 1553 | 
| 1475     __ push(r8); | 1554     // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or | 
| 1476     __ CallRuntime(Runtime::kNonSmiElementStored, 1); | 1555     // FAST_ELEMENTS, and value is Smi. | 
| 1477     __ bind(&no_map_change); | 1556     __ bind(&smi_element); | 
|  | 1557     __ movq(FieldOperand(rbx, offset), result_register()); | 
|  | 1558     // Fall through | 
|  | 1559 | 
|  | 1560     __ bind(&element_done); | 
| 1478 | 1561 | 
| 1479     PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1562     PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 
| 1480   } | 1563   } | 
| 1481 | 1564 | 
| 1482   if (result_saved) { | 1565   if (result_saved) { | 
| 1483     context()->PlugTOS(); | 1566     context()->PlugTOS(); | 
| 1484   } else { | 1567   } else { | 
| 1485     context()->Plug(rax); | 1568     context()->Plug(rax); | 
| 1486   } | 1569   } | 
| 1487 } | 1570 } | 
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1798       __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1881       __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 1799       __ bind(&assign); | 1882       __ bind(&assign); | 
| 1800       __ movq(location, rax); | 1883       __ movq(location, rax); | 
| 1801       if (var->IsContextSlot()) { | 1884       if (var->IsContextSlot()) { | 
| 1802         __ movq(rdx, rax); | 1885         __ movq(rdx, rax); | 
| 1803         __ RecordWriteContextSlot( | 1886         __ RecordWriteContextSlot( | 
| 1804             rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); | 1887             rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); | 
| 1805       } | 1888       } | 
| 1806     } | 1889     } | 
| 1807 | 1890 | 
| 1808   } else if (var->mode() != CONST) { | 1891   } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { | 
| 1809     // Assignment to var or initializing assignment to let. | 1892     // Assignment to var or initializing assignment to let/const | 
|  | 1893     // in harmony mode. | 
| 1810     if (var->IsStackAllocated() || var->IsContextSlot()) { | 1894     if (var->IsStackAllocated() || var->IsContextSlot()) { | 
| 1811       MemOperand location = VarOperand(var, rcx); | 1895       MemOperand location = VarOperand(var, rcx); | 
| 1812       if (FLAG_debug_code && op == Token::INIT_LET) { | 1896       if (FLAG_debug_code && op == Token::INIT_LET) { | 
| 1813         // Check for an uninitialized let binding. | 1897         // Check for an uninitialized let binding. | 
| 1814         __ movq(rdx, location); | 1898         __ movq(rdx, location); | 
| 1815         __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 1899         __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 
| 1816         __ Check(equal, "Let binding re-initialization."); | 1900         __ Check(equal, "Let binding re-initialization."); | 
| 1817       } | 1901       } | 
| 1818       // Perform the assignment. | 1902       // Perform the assignment. | 
| 1819       __ movq(location, rax); | 1903       __ movq(location, rax); | 
| (...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2650   // Allocate a heap number. | 2734   // Allocate a heap number. | 
| 2651   __ CallRuntime(Runtime::kNumberAlloc, 0); | 2735   __ CallRuntime(Runtime::kNumberAlloc, 0); | 
| 2652   __ movq(rbx, rax); | 2736   __ movq(rbx, rax); | 
| 2653 | 2737 | 
| 2654   __ bind(&heapnumber_allocated); | 2738   __ bind(&heapnumber_allocated); | 
| 2655 | 2739 | 
| 2656   // Return a random uint32 number in rax. | 2740   // Return a random uint32 number in rax. | 
| 2657   // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. | 2741   // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. | 
| 2658   __ PrepareCallCFunction(1); | 2742   __ PrepareCallCFunction(1); | 
| 2659 #ifdef _WIN64 | 2743 #ifdef _WIN64 | 
| 2660   __ LoadAddress(rcx, ExternalReference::isolate_address()); | 2744   __ movq(rcx, ContextOperand(context_register(), Context::GLOBAL_INDEX)); | 
|  | 2745   __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); | 
|  | 2746 | 
| 2661 #else | 2747 #else | 
| 2662   __ LoadAddress(rdi, ExternalReference::isolate_address()); | 2748   __ movq(rdi, ContextOperand(context_register(), Context::GLOBAL_INDEX)); | 
|  | 2749   __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset)); | 
| 2663 #endif | 2750 #endif | 
| 2664   __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 2751   __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 
| 2665 | 2752 | 
| 2666   // Convert 32 random bits in rax to 0.(32 random bits) in a double | 2753   // Convert 32 random bits in rax to 0.(32 random bits) in a double | 
| 2667   // by computing: | 2754   // by computing: | 
| 2668   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2755   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 
| 2669   __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single. | 2756   __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single. | 
| 2670   __ movd(xmm1, rcx); | 2757   __ movd(xmm1, rcx); | 
| 2671   __ movd(xmm0, rax); | 2758   __ movd(xmm0, rax); | 
| 2672   __ cvtss2sd(xmm1, xmm1); | 2759   __ cvtss2sd(xmm1, xmm1); | 
| (...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3990       break; | 4077       break; | 
| 3991     } | 4078     } | 
| 3992 | 4079 | 
| 3993     default: { | 4080     default: { | 
| 3994       VisitForAccumulatorValue(expr->right()); | 4081       VisitForAccumulatorValue(expr->right()); | 
| 3995       Condition cc = no_condition; | 4082       Condition cc = no_condition; | 
| 3996       switch (op) { | 4083       switch (op) { | 
| 3997         case Token::EQ_STRICT: | 4084         case Token::EQ_STRICT: | 
| 3998         case Token::EQ: | 4085         case Token::EQ: | 
| 3999           cc = equal; | 4086           cc = equal; | 
| 4000           __ pop(rdx); |  | 
| 4001           break; | 4087           break; | 
| 4002         case Token::LT: | 4088         case Token::LT: | 
| 4003           cc = less; | 4089           cc = less; | 
| 4004           __ pop(rdx); |  | 
| 4005           break; | 4090           break; | 
| 4006         case Token::GT: | 4091         case Token::GT: | 
| 4007           // Reverse left and right sizes to obtain ECMA-262 conversion order. | 4092           cc = greater; | 
| 4008           cc = less; |  | 
| 4009           __ movq(rdx, result_register()); |  | 
| 4010           __ pop(rax); |  | 
| 4011          break; | 4093          break; | 
| 4012         case Token::LTE: | 4094         case Token::LTE: | 
| 4013           // Reverse left and right sizes to obtain ECMA-262 conversion order. | 4095           cc = less_equal; | 
| 4014           cc = greater_equal; |  | 
| 4015           __ movq(rdx, result_register()); |  | 
| 4016           __ pop(rax); |  | 
| 4017           break; | 4096           break; | 
| 4018         case Token::GTE: | 4097         case Token::GTE: | 
| 4019           cc = greater_equal; | 4098           cc = greater_equal; | 
| 4020           __ pop(rdx); |  | 
| 4021           break; | 4099           break; | 
| 4022         case Token::IN: | 4100         case Token::IN: | 
| 4023         case Token::INSTANCEOF: | 4101         case Token::INSTANCEOF: | 
| 4024         default: | 4102         default: | 
| 4025           UNREACHABLE(); | 4103           UNREACHABLE(); | 
| 4026       } | 4104       } | 
|  | 4105       __ pop(rdx); | 
| 4027 | 4106 | 
| 4028       bool inline_smi_code = ShouldInlineSmiCase(op); | 4107       bool inline_smi_code = ShouldInlineSmiCase(op); | 
| 4029       JumpPatchSite patch_site(masm_); | 4108       JumpPatchSite patch_site(masm_); | 
| 4030       if (inline_smi_code) { | 4109       if (inline_smi_code) { | 
| 4031         Label slow_case; | 4110         Label slow_case; | 
| 4032         __ movq(rcx, rdx); | 4111         __ movq(rcx, rdx); | 
| 4033         __ or_(rcx, rax); | 4112         __ or_(rcx, rax); | 
| 4034         patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); | 4113         patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); | 
| 4035         __ cmpq(rdx, rax); | 4114         __ cmpq(rdx, rax); | 
| 4036         Split(cc, if_true, if_false, NULL); | 4115         Split(cc, if_true, if_false, NULL); | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4195   *context_length = 0; | 4274   *context_length = 0; | 
| 4196   return previous_; | 4275   return previous_; | 
| 4197 } | 4276 } | 
| 4198 | 4277 | 
| 4199 | 4278 | 
| 4200 #undef __ | 4279 #undef __ | 
| 4201 | 4280 | 
| 4202 } }  // namespace v8::internal | 4281 } }  // namespace v8::internal | 
| 4203 | 4282 | 
| 4204 #endif  // V8_TARGET_ARCH_X64 | 4283 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW | 
|---|