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 |