Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 925 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 936 __ movq(rax, CodeGenerator::GlobalObject()); | 936 __ movq(rax, CodeGenerator::GlobalObject()); |
| 937 __ Move(rcx, slot->var()->name()); | 937 __ Move(rcx, slot->var()->name()); |
| 938 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 938 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 939 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 939 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 940 ? RelocInfo::CODE_TARGET | 940 ? RelocInfo::CODE_TARGET |
| 941 : RelocInfo::CODE_TARGET_CONTEXT; | 941 : RelocInfo::CODE_TARGET_CONTEXT; |
| 942 __ call(ic, mode); | 942 __ call(ic, mode); |
| 943 } | 943 } |
| 944 | 944 |
| 945 | 945 |
| 946 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | |
| 947 Slot* slot, | |
| 948 Label* slow) { | |
| 949 ASSERT(slot->type() == Slot::CONTEXT); | |
| 950 Register context = rsi; | |
| 951 Register temp = rbx; | |
| 952 | |
| 953 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { | |
| 954 if (s->num_heap_slots() > 0) { | |
| 955 if (s->calls_eval()) { | |
| 956 // Check that extension is NULL. | |
| 957 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | |
| 958 Immediate(0)); | |
| 959 __ j(not_equal, slow); | |
| 960 } | |
| 961 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX)); | |
| 962 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset)); | |
| 963 // Walk the rest of the chain using a single register without | |
| 964 // clobbering esi. | |
|
Søren Thygesen Gjesse
2010/09/10 07:44:24
esi -> rsi
Mads Ager (chromium)
2010/09/10 10:51:43
Done.
| |
| 965 context = temp; | |
| 966 } | |
| 967 } | |
| 968 // Check that last extension is NULL. | |
| 969 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); | |
| 970 __ j(not_equal, slow); | |
| 971 __ movq(temp, ContextOperand(context, Context::FCONTEXT_INDEX)); | |
| 972 return ContextOperand(temp, slot->index()); | |
| 973 } | |
| 974 | |
| 975 | |
| 976 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( | |
| 977 Slot* slot, | |
| 978 TypeofState typeof_state, | |
| 979 Label* slow, | |
| 980 Label* done) { | |
| 981 // Generate fast-case code for variables that might be shadowed by | |
| 982 // eval-introduced variables. Eval is used a lot without | |
| 983 // introducing variables. In those cases, we do not want to | |
| 984 // perform a runtime call for all variables in the scope | |
| 985 // containing the eval. | |
| 986 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | |
| 987 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | |
| 988 __ jmp(done); | |
| 989 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | |
| 990 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | |
| 991 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | |
| 992 if (potential_slot != NULL) { | |
| 993 // Generate fast case for locals that rewrite to slots. | |
| 994 __ movq(rax, | |
| 995 ContextSlotOperandCheckExtensions(potential_slot, slow)); | |
| 996 if (potential_slot->var()->mode() == Variable::CONST) { | |
| 997 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | |
| 998 __ j(not_equal, done); | |
| 999 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | |
| 1000 } | |
| 1001 __ jmp(done); | |
| 1002 } else if (rewrite != NULL) { | |
| 1003 // Generate fast case for calls of an argument function. | |
| 1004 Property* property = rewrite->AsProperty(); | |
| 1005 if (property != NULL) { | |
| 1006 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | |
| 1007 Literal* key_literal = property->key()->AsLiteral(); | |
| 1008 if (obj_proxy != NULL && | |
| 1009 key_literal != NULL && | |
| 1010 obj_proxy->IsArguments() && | |
| 1011 key_literal->handle()->IsSmi()) { | |
| 1012 // Load arguments object if there are no eval-introduced | |
| 1013 // variables. Then load the argument from the arguments | |
| 1014 // object using keyed load. | |
| 1015 __ movq(rdx, | |
| 1016 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | |
| 1017 slow)); | |
| 1018 __ Move(rax, key_literal->handle()); | |
| 1019 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | |
| 1020 __ call(ic, RelocInfo::CODE_TARGET); | |
| 1021 __ jmp(done); | |
| 1022 } | |
| 1023 } | |
| 1024 } | |
| 1025 } | |
| 1026 } | |
| 1027 | |
| 1028 | |
| 946 void FullCodeGenerator::EmitVariableLoad(Variable* var, | 1029 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
| 947 Expression::Context context) { | 1030 Expression::Context context) { |
| 948 // Four cases: non-this global variables, lookup slots, all other | 1031 // Four cases: non-this global variables, lookup slots, all other |
| 949 // types of slots, and parameters that rewrite to explicit property | 1032 // types of slots, and parameters that rewrite to explicit property |
| 950 // accesses on the arguments object. | 1033 // accesses on the arguments object. |
| 951 Slot* slot = var->slot(); | 1034 Slot* slot = var->slot(); |
| 952 Property* property = var->AsProperty(); | 1035 Property* property = var->AsProperty(); |
| 953 | 1036 |
| 954 if (var->is_global() && !var->is_this()) { | 1037 if (var->is_global() && !var->is_this()) { |
| 955 Comment cmnt(masm_, "Global variable"); | 1038 Comment cmnt(masm_, "Global variable"); |
| 956 // Use inline caching. Variable name is passed in rcx and the global | 1039 // Use inline caching. Variable name is passed in rcx and the global |
| 957 // object on the stack. | 1040 // object on the stack. |
| 958 __ Move(rcx, var->name()); | 1041 __ Move(rcx, var->name()); |
| 959 __ movq(rax, CodeGenerator::GlobalObject()); | 1042 __ movq(rax, CodeGenerator::GlobalObject()); |
| 960 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1043 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 961 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1044 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 962 // A test rax instruction following the call is used by the IC to | 1045 // A test rax instruction following the call is used by the IC to |
| 963 // indicate that the inobject property case was inlined. Ensure there | 1046 // indicate that the inobject property case was inlined. Ensure there |
| 964 // is no test rax instruction here. | 1047 // is no test rax instruction here. |
| 965 __ nop(); | 1048 __ nop(); |
| 966 Apply(context, rax); | 1049 Apply(context, rax); |
| 967 | 1050 |
| 968 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1051 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 969 Label done, slow; | 1052 Label done, slow; |
| 970 | 1053 |
| 971 // Generate fast-case code for variables that might be shadowed by | 1054 // Generate code for loading from variables potentially shadowed |
| 972 // eval-introduced variables. Eval is used a lot without | 1055 // by eval-introduced variables. |
| 973 // introducing variables. In those cases, we do not want to | 1056 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
| 974 // perform a runtime call for all variables in the scope | |
| 975 // containing the eval. | |
| 976 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | |
| 977 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow); | |
| 978 Apply(context, rax); | |
| 979 __ jmp(&done); | |
| 980 } | |
| 981 | 1057 |
| 982 __ bind(&slow); | 1058 __ bind(&slow); |
| 983 Comment cmnt(masm_, "Lookup slot"); | 1059 Comment cmnt(masm_, "Lookup slot"); |
| 984 __ push(rsi); // Context. | 1060 __ push(rsi); // Context. |
| 985 __ Push(var->name()); | 1061 __ Push(var->name()); |
| 986 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1062 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 1063 __ bind(&done); | |
| 1064 | |
| 987 Apply(context, rax); | 1065 Apply(context, rax); |
| 988 __ bind(&done); | |
| 989 | 1066 |
| 990 } else if (slot != NULL) { | 1067 } else if (slot != NULL) { |
| 991 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 1068 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
| 992 ? "Context slot" | 1069 ? "Context slot" |
| 993 : "Stack slot"); | 1070 : "Stack slot"); |
| 994 if (var->mode() == Variable::CONST) { | 1071 if (var->mode() == Variable::CONST) { |
| 995 // Constants may be the hole value if they have not been initialized. | 1072 // Constants may be the hole value if they have not been initialized. |
| 996 // Unhole them. | 1073 // Unhole them. |
| 997 Label done; | 1074 Label done; |
| 998 MemOperand slot_operand = EmitSlotSearch(slot, rax); | 1075 MemOperand slot_operand = EmitSlotSearch(slot, rax); |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1783 // Restore context register. | 1860 // Restore context register. |
| 1784 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1861 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1785 DropAndApply(1, context_, rax); | 1862 DropAndApply(1, context_, rax); |
| 1786 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1863 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 1787 // Call to a global variable. | 1864 // Call to a global variable. |
| 1788 // Push global object as receiver for the call IC lookup. | 1865 // Push global object as receiver for the call IC lookup. |
| 1789 __ push(CodeGenerator::GlobalObject()); | 1866 __ push(CodeGenerator::GlobalObject()); |
| 1790 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1867 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 1791 } else if (var != NULL && var->slot() != NULL && | 1868 } else if (var != NULL && var->slot() != NULL && |
| 1792 var->slot()->type() == Slot::LOOKUP) { | 1869 var->slot()->type() == Slot::LOOKUP) { |
| 1793 // Call to a lookup slot (dynamically introduced variable). Call | 1870 // Call to a lookup slot (dynamically introduced variable). |
| 1794 // the runtime to find the function to call (returned in rax) and | 1871 Label slow, done; |
| 1795 // the object holding it (returned in rdx). | 1872 |
| 1873 // Generate code for loading from variables potentially shadowed | |
| 1874 // by eval-introduced variables. | |
| 1875 EmitDynamicLoadFromSlotFastCase(var->slot(), | |
| 1876 NOT_INSIDE_TYPEOF, | |
| 1877 &slow, | |
| 1878 &done); | |
| 1879 | |
| 1880 __ bind(&slow); | |
| 1881 // Call the runtime to find the function to call (returned in rax) | |
| 1882 // and the object holding it (returned in rdx). | |
| 1796 __ push(context_register()); | 1883 __ push(context_register()); |
| 1797 __ Push(var->name()); | 1884 __ Push(var->name()); |
| 1798 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1885 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 1799 __ push(rax); // Function. | 1886 __ push(rax); // Function. |
| 1800 __ push(rdx); // Receiver. | 1887 __ push(rdx); // Receiver. |
| 1888 | |
| 1889 // If fast case code has been generated, emit code to push the | |
| 1890 // function and receiver and have the slow path jump around this | |
| 1891 // code. | |
| 1892 if (done.is_linked()) { | |
| 1893 Label call; | |
| 1894 __ jmp(&call); | |
| 1895 __ bind(&done); | |
| 1896 // Push function. | |
| 1897 __ push(rax); | |
| 1898 // Push global receiver. | |
| 1899 __ movq(rbx, CodeGenerator::GlobalObject()); | |
| 1900 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | |
| 1901 __ bind(&call); | |
| 1902 } | |
| 1903 | |
| 1801 EmitCallWithStub(expr); | 1904 EmitCallWithStub(expr); |
| 1905 | |
| 1802 } else if (fun->AsProperty() != NULL) { | 1906 } else if (fun->AsProperty() != NULL) { |
| 1803 // Call to an object property. | 1907 // Call to an object property. |
| 1804 Property* prop = fun->AsProperty(); | 1908 Property* prop = fun->AsProperty(); |
| 1805 Literal* key = prop->key()->AsLiteral(); | 1909 Literal* key = prop->key()->AsLiteral(); |
| 1806 if (key != NULL && key->handle()->IsSymbol()) { | 1910 if (key != NULL && key->handle()->IsSymbol()) { |
| 1807 // Call to a named property, use call IC. | 1911 // Call to a named property, use call IC. |
| 1808 VisitForValue(prop->obj(), kStack); | 1912 VisitForValue(prop->obj(), kStack); |
| 1809 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 1913 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 1810 } else { | 1914 } else { |
| 1811 // Call to a keyed property. | 1915 // Call to a keyed property. |
| (...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3070 __ Move(rcx, proxy->name()); | 3174 __ Move(rcx, proxy->name()); |
| 3071 __ movq(rax, CodeGenerator::GlobalObject()); | 3175 __ movq(rax, CodeGenerator::GlobalObject()); |
| 3072 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3176 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 3073 // Use a regular load, not a contextual load, to avoid a reference | 3177 // Use a regular load, not a contextual load, to avoid a reference |
| 3074 // error. | 3178 // error. |
| 3075 __ Call(ic, RelocInfo::CODE_TARGET); | 3179 __ Call(ic, RelocInfo::CODE_TARGET); |
| 3076 if (where == kStack) __ push(rax); | 3180 if (where == kStack) __ push(rax); |
| 3077 } else if (proxy != NULL && | 3181 } else if (proxy != NULL && |
| 3078 proxy->var()->slot() != NULL && | 3182 proxy->var()->slot() != NULL && |
| 3079 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3183 proxy->var()->slot()->type() == Slot::LOOKUP) { |
| 3184 Label done, slow; | |
| 3185 | |
| 3186 // Generate code for loading from variables potentially shadowed | |
| 3187 // by eval-introduced variables. | |
| 3188 Slot* slot = proxy->var()->slot(); | |
| 3189 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | |
| 3190 | |
| 3191 __ bind(&slow); | |
| 3080 __ push(rsi); | 3192 __ push(rsi); |
| 3081 __ Push(proxy->name()); | 3193 __ Push(proxy->name()); |
| 3082 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 3194 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 3195 __ bind(&done); | |
| 3196 | |
| 3083 if (where == kStack) __ push(rax); | 3197 if (where == kStack) __ push(rax); |
| 3084 } else { | 3198 } else { |
| 3085 // This expression cannot throw a reference error at the top level. | 3199 // This expression cannot throw a reference error at the top level. |
| 3086 VisitForValue(expr, where); | 3200 VisitForValue(expr, where); |
| 3087 } | 3201 } |
| 3088 } | 3202 } |
| 3089 | 3203 |
| 3090 | 3204 |
| 3091 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, | 3205 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, |
| 3092 Expression* left, | 3206 Expression* left, |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3356 __ ret(0); | 3470 __ ret(0); |
| 3357 } | 3471 } |
| 3358 | 3472 |
| 3359 | 3473 |
| 3360 #undef __ | 3474 #undef __ |
| 3361 | 3475 |
| 3362 | 3476 |
| 3363 } } // namespace v8::internal | 3477 } } // namespace v8::internal |
| 3364 | 3478 |
| 3365 #endif // V8_TARGET_ARCH_X64 | 3479 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |