OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
872 Apply(context_, r0); | 872 Apply(context_, r0); |
873 } | 873 } |
874 | 874 |
875 | 875 |
876 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 876 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
877 Comment cmnt(masm_, "[ VariableProxy"); | 877 Comment cmnt(masm_, "[ VariableProxy"); |
878 EmitVariableLoad(expr->var(), context_); | 878 EmitVariableLoad(expr->var(), context_); |
879 } | 879 } |
880 | 880 |
881 | 881 |
882 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | |
883 Slot* slot, | |
884 Label* slow) { | |
885 ASSERT(slot->type() == Slot::CONTEXT); | |
886 Register current = cp; | |
887 Register next = r3; | |
888 Register temp = r4; | |
889 | |
890 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { | |
891 if (s->num_heap_slots() > 0) { | |
892 if (s->calls_eval()) { | |
893 // Check that extension is NULL. | |
894 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); | |
895 __ tst(temp, temp); | |
896 __ b(ne, slow); | |
897 } | |
898 __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX)); | |
899 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); | |
900 // Walk the rest of the chain using a single register without | |
Søren Thygesen Gjesse
2010/09/10 07:44:24
delete "using a single register"
Mads Ager (chromium)
2010/09/10 10:51:43
Done.
| |
901 // clobbering esi. | |
Søren Thygesen Gjesse
2010/09/10 07:44:24
esi -> cp
Mads Ager (chromium)
2010/09/10 10:51:43
Done.
| |
902 current = next; | |
903 } | |
904 } | |
905 // Check that last extension is NULL. | |
906 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); | |
907 __ tst(temp, temp); | |
908 __ b(ne, slow); | |
909 __ ldr(temp, ContextOperand(current, Context::FCONTEXT_INDEX)); | |
910 return ContextOperand(temp, slot->index()); | |
911 } | |
912 | |
913 | |
914 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( | |
915 Slot* slot, | |
916 TypeofState typeof_state, | |
917 Label* slow, | |
918 Label* done) { | |
919 // Generate fast-case code for variables that might be shadowed by | |
920 // eval-introduced variables. Eval is used a lot without | |
921 // introducing variables. In those cases, we do not want to | |
922 // perform a runtime call for all variables in the scope | |
923 // containing the eval. | |
924 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | |
925 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | |
926 __ jmp(done); | |
927 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | |
928 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | |
929 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | |
930 if (potential_slot != NULL) { | |
931 // Generate fast case for locals that rewrite to slots. | |
932 __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow)); | |
933 if (potential_slot->var()->mode() == Variable::CONST) { | |
Søren Thygesen Gjesse
2010/09/10 07:44:24
Line 1071 below could use the same pattern (a cond
Mads Ager (chromium)
2010/09/10 10:51:43
Good catch. Done. :)
| |
934 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
935 __ cmp(r0, ip); | |
936 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | |
937 } | |
938 __ jmp(done); | |
939 } else if (rewrite != NULL) { | |
940 // Generate fast case for calls of an argument function. | |
941 Property* property = rewrite->AsProperty(); | |
942 if (property != NULL) { | |
943 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | |
944 Literal* key_literal = property->key()->AsLiteral(); | |
945 if (obj_proxy != NULL && | |
946 key_literal != NULL && | |
947 obj_proxy->IsArguments() && | |
948 key_literal->handle()->IsSmi()) { | |
949 // Load arguments object if there are no eval-introduced | |
950 // variables. Then load the argument from the arguments | |
951 // object using keyed load. | |
952 __ ldr(r1, | |
953 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | |
954 slow)); | |
955 __ mov(r0, Operand(key_literal->handle())); | |
956 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | |
957 __ Call(ic, RelocInfo::CODE_TARGET); | |
958 __ jmp(done); | |
959 } | |
960 } | |
961 } | |
962 } | |
963 } | |
964 | |
965 | |
882 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( | 966 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( |
883 Slot* slot, | 967 Slot* slot, |
884 TypeofState typeof_state, | 968 TypeofState typeof_state, |
885 Label* slow) { | 969 Label* slow) { |
886 Register current = cp; | 970 Register current = cp; |
887 Register next = r1; | 971 Register next = r1; |
888 Register temp = r2; | 972 Register temp = r2; |
889 | 973 |
890 Scope* s = scope(); | 974 Scope* s = scope(); |
891 while (s != NULL) { | 975 while (s != NULL) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
955 // object (receiver) in r0. | 1039 // object (receiver) in r0. |
956 __ ldr(r0, CodeGenerator::GlobalObject()); | 1040 __ ldr(r0, CodeGenerator::GlobalObject()); |
957 __ mov(r2, Operand(var->name())); | 1041 __ mov(r2, Operand(var->name())); |
958 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1042 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
959 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1043 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
960 Apply(context, r0); | 1044 Apply(context, r0); |
961 | 1045 |
962 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1046 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
963 Label done, slow; | 1047 Label done, slow; |
964 | 1048 |
965 // Generate fast-case code for variables that might be shadowed by | 1049 // Generate code for loading from variables potentially shadowed |
966 // eval-introduced variables. Eval is used a lot without | 1050 // by eval-introduced variables. |
967 // introducing variables. In those cases, we do not want to | 1051 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
968 // perform a runtime call for all variables in the scope | |
969 // containing the eval. | |
970 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | |
971 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow); | |
972 Apply(context, r0); | |
973 __ jmp(&done); | |
974 } | |
975 | 1052 |
976 __ bind(&slow); | 1053 __ bind(&slow); |
977 Comment cmnt(masm_, "Lookup slot"); | 1054 Comment cmnt(masm_, "Lookup slot"); |
978 __ mov(r1, Operand(var->name())); | 1055 __ mov(r1, Operand(var->name())); |
979 __ Push(cp, r1); // Context and name. | 1056 __ Push(cp, r1); // Context and name. |
980 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1057 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
1058 __ bind(&done); | |
1059 | |
981 Apply(context, r0); | 1060 Apply(context, r0); |
982 __ bind(&done); | |
983 | 1061 |
984 } else if (slot != NULL) { | 1062 } else if (slot != NULL) { |
985 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 1063 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
986 ? "Context slot" | 1064 ? "Context slot" |
987 : "Stack slot"); | 1065 : "Stack slot"); |
988 if (var->mode() == Variable::CONST) { | 1066 if (var->mode() == Variable::CONST) { |
989 // Constants may be the hole value if they have not been initialized. | 1067 // Constants may be the hole value if they have not been initialized. |
990 // Unhole them. | 1068 // Unhole them. |
991 Label done; | 1069 Label done; |
992 MemOperand slot_operand = EmitSlotSearch(slot, r0); | 1070 MemOperand slot_operand = EmitSlotSearch(slot, r0); |
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1715 // Restore context register. | 1793 // Restore context register. |
1716 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1794 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1717 DropAndApply(1, context_, r0); | 1795 DropAndApply(1, context_, r0); |
1718 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1796 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1719 // Push global object as receiver for the call IC. | 1797 // Push global object as receiver for the call IC. |
1720 __ ldr(r0, CodeGenerator::GlobalObject()); | 1798 __ ldr(r0, CodeGenerator::GlobalObject()); |
1721 __ push(r0); | 1799 __ push(r0); |
1722 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1800 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
1723 } else if (var != NULL && var->slot() != NULL && | 1801 } else if (var != NULL && var->slot() != NULL && |
1724 var->slot()->type() == Slot::LOOKUP) { | 1802 var->slot()->type() == Slot::LOOKUP) { |
1725 // Call to a lookup slot (dynamically introduced variable). Call the | 1803 // Call to a lookup slot (dynamically introduced variable). |
1726 // runtime to find the function to call (returned in eax) and the object | 1804 Label slow, done; |
1727 // holding it (returned in edx). | 1805 |
1806 // Generate code for loading from variables potentially shadowed | |
1807 // by eval-introduced variables. | |
1808 EmitDynamicLoadFromSlotFastCase(var->slot(), | |
1809 NOT_INSIDE_TYPEOF, | |
1810 &slow, | |
1811 &done); | |
1812 | |
1813 __ bind(&slow); | |
1814 // Call the runtime to find the function to call (returned in eax) | |
1815 // and the object holding it (returned in edx). | |
1728 __ push(context_register()); | 1816 __ push(context_register()); |
1729 __ mov(r2, Operand(var->name())); | 1817 __ mov(r2, Operand(var->name())); |
1730 __ push(r2); | 1818 __ push(r2); |
1731 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1819 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
Søren Thygesen Gjesse
2010/09/10 07:44:24
Maybe change these two pushes to Push(r0, r1). It
Mads Ager (chromium)
2010/09/10 10:51:43
Done.
| |
1732 __ push(r0); // Function. | 1820 __ push(r0); // Function. |
1733 __ push(r1); // Receiver. | 1821 __ push(r1); // Receiver. |
1822 | |
1823 // If fast case code has been generated, emit code to push the | |
1824 // function and receiver and have the slow path jump around this | |
1825 // code. | |
1826 if (done.is_linked()) { | |
1827 Label call; | |
1828 __ b(&call); | |
1829 __ bind(&done); | |
1830 // Push function. | |
1831 __ push(r0); | |
1832 // Push global receiver. | |
1833 __ ldr(r1, CodeGenerator::GlobalObject()); | |
1834 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | |
Søren Thygesen Gjesse
2010/09/10 07:44:24
Maybe change to Push(r0, r1), or even better have
Mads Ager (chromium)
2010/09/10 10:51:43
That would be neat. I made it Push(r0, r1) for now
| |
1835 __ push(r1); | |
1836 __ bind(&call); | |
1837 } | |
1838 | |
1734 EmitCallWithStub(expr); | 1839 EmitCallWithStub(expr); |
1735 } else if (fun->AsProperty() != NULL) { | 1840 } else if (fun->AsProperty() != NULL) { |
1736 // Call to an object property. | 1841 // Call to an object property. |
1737 Property* prop = fun->AsProperty(); | 1842 Property* prop = fun->AsProperty(); |
1738 Literal* key = prop->key()->AsLiteral(); | 1843 Literal* key = prop->key()->AsLiteral(); |
1739 if (key != NULL && key->handle()->IsSymbol()) { | 1844 if (key != NULL && key->handle()->IsSymbol()) { |
1740 // Call to a named property, use call IC. | 1845 // Call to a named property, use call IC. |
1741 VisitForValue(prop->obj(), kStack); | 1846 VisitForValue(prop->obj(), kStack); |
1742 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 1847 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
1743 } else { | 1848 } else { |
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2995 __ ldr(r0, CodeGenerator::GlobalObject()); | 3100 __ ldr(r0, CodeGenerator::GlobalObject()); |
2996 __ mov(r2, Operand(proxy->name())); | 3101 __ mov(r2, Operand(proxy->name())); |
2997 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3102 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
2998 // Use a regular load, not a contextual load, to avoid a reference | 3103 // Use a regular load, not a contextual load, to avoid a reference |
2999 // error. | 3104 // error. |
3000 __ Call(ic, RelocInfo::CODE_TARGET); | 3105 __ Call(ic, RelocInfo::CODE_TARGET); |
3001 if (where == kStack) __ push(r0); | 3106 if (where == kStack) __ push(r0); |
3002 } else if (proxy != NULL && | 3107 } else if (proxy != NULL && |
3003 proxy->var()->slot() != NULL && | 3108 proxy->var()->slot() != NULL && |
3004 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3109 proxy->var()->slot()->type() == Slot::LOOKUP) { |
3110 Label done, slow; | |
3111 | |
3112 // Generate code for loading from variables potentially shadowed | |
3113 // by eval-introduced variables. | |
3114 Slot* slot = proxy->var()->slot(); | |
3115 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | |
3116 | |
3117 __ bind(&slow); | |
3005 __ mov(r0, Operand(proxy->name())); | 3118 __ mov(r0, Operand(proxy->name())); |
3006 __ Push(cp, r0); | 3119 __ Push(cp, r0); |
3007 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 3120 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
3121 __ bind(&done); | |
3122 | |
3008 if (where == kStack) __ push(r0); | 3123 if (where == kStack) __ push(r0); |
3009 } else { | 3124 } else { |
3010 // This expression cannot throw a reference error at the top level. | 3125 // This expression cannot throw a reference error at the top level. |
3011 VisitForValue(expr, where); | 3126 VisitForValue(expr, where); |
3012 } | 3127 } |
3013 } | 3128 } |
3014 | 3129 |
3015 | 3130 |
3016 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, | 3131 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, |
3017 Expression* left, | 3132 Expression* left, |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3290 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3405 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
3291 __ add(pc, r1, Operand(masm_->CodeObject())); | 3406 __ add(pc, r1, Operand(masm_->CodeObject())); |
3292 } | 3407 } |
3293 | 3408 |
3294 | 3409 |
3295 #undef __ | 3410 #undef __ |
3296 | 3411 |
3297 } } // namespace v8::internal | 3412 } } // namespace v8::internal |
3298 | 3413 |
3299 #endif // V8_TARGET_ARCH_ARM | 3414 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |