Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 1989012: Add complete implementation of full compiler for the ia32 architecture... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 770 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
771 // Call the runtime to declare the globals. 771 // Call the runtime to declare the globals.
772 __ push(rsi); // The context is the first argument. 772 __ push(rsi); // The context is the first argument.
773 __ Push(pairs); 773 __ Push(pairs);
774 __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 774 __ Push(Smi::FromInt(is_eval() ? 1 : 0));
775 __ CallRuntime(Runtime::kDeclareGlobals, 3); 775 __ CallRuntime(Runtime::kDeclareGlobals, 3);
776 // Return value is ignored. 776 // Return value is ignored.
777 } 777 }
778 778
779 779
780 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 780 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
781 Comment cmnt(masm_, "[ FunctionLiteral"); 781 UNREACHABLE();
782 }
782 783
783 // Build the shared function info and instantiate the function based
784 // on it.
785 Handle<SharedFunctionInfo> function_info =
786 Compiler::BuildFunctionInfo(expr, script(), this);
787 if (HasStackOverflow()) return;
788 784
789 // Create a new closure. 785 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
790 __ push(rsi); 786 UNREACHABLE();
791 __ Push(function_info); 787 }
792 __ CallRuntime(Runtime::kNewClosure, 2); 788
789
790 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
791 // Use the fast case closure allocation code that allocates in new
792 // space for nested functions that don't need literals cloning.
793 if (scope()->is_function_scope() && info->num_literals() == 0) {
794 FastNewClosureStub stub;
795 __ Push(info);
796 __ CallStub(&stub);
797 } else {
798 __ push(rsi);
799 __ Push(info);
800 __ CallRuntime(Runtime::kNewClosure, 2);
801 }
793 Apply(context_, rax); 802 Apply(context_, rax);
794 } 803 }
795 804
796 805
797 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 806 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
798 Comment cmnt(masm_, "[ VariableProxy"); 807 Comment cmnt(masm_, "[ VariableProxy");
799 EmitVariableLoad(expr->var(), context_); 808 EmitVariableLoad(expr->var(), context_);
800 } 809 }
801 810
802 811
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 if (result_saved) { 1021 if (result_saved) {
1013 ApplyTOS(context_); 1022 ApplyTOS(context_);
1014 } else { 1023 } else {
1015 Apply(context_, rax); 1024 Apply(context_, rax);
1016 } 1025 }
1017 } 1026 }
1018 1027
1019 1028
1020 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1029 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1021 Comment cmnt(masm_, "[ Assignment"); 1030 Comment cmnt(masm_, "[ Assignment");
1022 ASSERT(expr->op() != Token::INIT_CONST); 1031 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1032 // on the left-hand side.
1033 if (!expr->target()->IsValidLeftHandSide()) {
1034 VisitForEffect(expr->target());
1035 return;
1036 }
1037
1023 // Left-hand side can only be a property, a global or a (parameter or local) 1038 // Left-hand side can only be a property, a global or a (parameter or local)
1024 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1039 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1025 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1040 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1026 LhsKind assign_type = VARIABLE; 1041 LhsKind assign_type = VARIABLE;
1027 Property* prop = expr->target()->AsProperty(); 1042 Property* prop = expr->target()->AsProperty();
1028 if (prop != NULL) { 1043 if (prop != NULL) {
1029 assign_type = 1044 assign_type =
1030 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1045 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1031 } 1046 }
1032 1047
1033 // Evaluate LHS expression. 1048 // Evaluate LHS expression.
1034 switch (assign_type) { 1049 switch (assign_type) {
1035 case VARIABLE: 1050 case VARIABLE:
1036 // Nothing to do here. 1051 // Nothing to do here.
1037 break; 1052 break;
1038 case NAMED_PROPERTY: 1053 case NAMED_PROPERTY:
1039 if (expr->is_compound()) { 1054 if (expr->is_compound()) {
1040 // We need the receiver both on the stack and in the accumulator. 1055 // We need the receiver both on the stack and in the accumulator.
1041 VisitForValue(prop->obj(), kAccumulator); 1056 VisitForValue(prop->obj(), kAccumulator);
1042 __ push(result_register()); 1057 __ push(result_register());
1043 } else { 1058 } else {
1044 VisitForValue(prop->obj(), kStack); 1059 VisitForValue(prop->obj(), kStack);
1045 } 1060 }
1046 break; 1061 break;
1047 case KEYED_PROPERTY: 1062 case KEYED_PROPERTY:
1048 VisitForValue(prop->obj(), kStack); 1063 if (expr->is_compound()) {
1049 VisitForValue(prop->key(), kStack); 1064 VisitForValue(prop->obj(), kStack);
1065 VisitForValue(prop->key(), kAccumulator);
1066 __ movq(rdx, Operand(rsp, 0));
1067 __ push(rax);
1068 } else {
1069 VisitForValue(prop->obj(), kStack);
1070 VisitForValue(prop->key(), kStack);
1071 }
1050 break; 1072 break;
1051 } 1073 }
1052 1074
1053 // If we have a compound assignment: Get value of LHS expression and 1075 // If we have a compound assignment: Get value of LHS expression and
1054 // store in on top of the stack. 1076 // store in on top of the stack.
1055 if (expr->is_compound()) { 1077 if (expr->is_compound()) {
1056 Location saved_location = location_; 1078 Location saved_location = location_;
1057 location_ = kStack; 1079 location_ = kStack;
1058 switch (assign_type) { 1080 switch (assign_type) {
1059 case VARIABLE: 1081 case VARIABLE:
(...skipping 24 matching lines...) Expand all
1084 location_ = saved_location; 1106 location_ = saved_location;
1085 } 1107 }
1086 1108
1087 // Record source position before possible IC call. 1109 // Record source position before possible IC call.
1088 SetSourcePosition(expr->position()); 1110 SetSourcePosition(expr->position());
1089 1111
1090 // Store the value. 1112 // Store the value.
1091 switch (assign_type) { 1113 switch (assign_type) {
1092 case VARIABLE: 1114 case VARIABLE:
1093 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1115 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1116 expr->op(),
1094 context_); 1117 context_);
1095 break; 1118 break;
1096 case NAMED_PROPERTY: 1119 case NAMED_PROPERTY:
1097 EmitNamedPropertyAssignment(expr); 1120 EmitNamedPropertyAssignment(expr);
1098 break; 1121 break;
1099 case KEYED_PROPERTY: 1122 case KEYED_PROPERTY:
1100 EmitKeyedPropertyAssignment(expr); 1123 EmitKeyedPropertyAssignment(expr);
1101 break; 1124 break;
1102 } 1125 }
1103 } 1126 }
(...skipping 22 matching lines...) Expand all
1126 __ push(result_register()); 1149 __ push(result_register());
1127 GenericBinaryOpStub stub(op, 1150 GenericBinaryOpStub stub(op,
1128 NO_OVERWRITE, 1151 NO_OVERWRITE,
1129 NO_GENERIC_BINARY_FLAGS); 1152 NO_GENERIC_BINARY_FLAGS);
1130 __ CallStub(&stub); 1153 __ CallStub(&stub);
1131 Apply(context, rax); 1154 Apply(context, rax);
1132 } 1155 }
1133 1156
1134 1157
1135 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1158 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1159 Token::Value op,
1136 Expression::Context context) { 1160 Expression::Context context) {
1137 // Three main cases: non-this global variables, lookup slots, and 1161 // Left-hand sides that rewrite to explicit property accesses do not reach
1138 // all other types of slots. Left-hand-side parameters that rewrite 1162 // here.
1139 // to explicit property accesses do not reach here.
1140 ASSERT(var != NULL); 1163 ASSERT(var != NULL);
1141 ASSERT(var->is_global() || var->slot() != NULL); 1164 ASSERT(var->is_global() || var->slot() != NULL);
1142 Slot* slot = var->slot(); 1165
1143 if (var->is_global()) { 1166 if (var->is_global()) {
1144 ASSERT(!var->is_this()); 1167 ASSERT(!var->is_this());
1145 // Assignment to a global variable. Use inline caching for the 1168 // Assignment to a global variable. Use inline caching for the
1146 // assignment. Right-hand-side value is passed in rax, variable name in 1169 // assignment. Right-hand-side value is passed in rax, variable name in
1147 // rcx, and the global object in rdx. 1170 // rcx, and the global object on the stack.
1148 __ Move(rcx, var->name()); 1171 __ Move(rcx, var->name());
1149 __ movq(rdx, CodeGenerator::GlobalObject()); 1172 __ movq(rdx, CodeGenerator::GlobalObject());
1150 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1173 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1151 __ Call(ic, RelocInfo::CODE_TARGET); 1174 __ Call(ic, RelocInfo::CODE_TARGET);
1152 Apply(context, rax); 1175 __ nop();
1153 1176
1154 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1177 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
1155 __ push(result_register()); // Value. 1178 // Perform the assignment for non-const variables and for initialization
1156 __ push(rsi); // Context. 1179 // of const variables. Const assignments are simply skipped.
1157 __ Push(var->name()); 1180 Label done;
1158 __ CallRuntime(Runtime::kStoreContextSlot, 3); 1181 Slot* slot = var->slot();
1159 Apply(context, rax);
1160
1161 } else if (var->slot() != NULL) {
1162 switch (slot->type()) { 1182 switch (slot->type()) {
1183 case Slot::PARAMETER:
1163 case Slot::LOCAL: 1184 case Slot::LOCAL:
1164 case Slot::PARAMETER: 1185 if (op == Token::INIT_CONST) {
1165 __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 1186 // Detect const reinitialization by checking for the hole value.
1187 __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1188 __ Cmp(rdx, Factory::the_hole_value());
1189 __ j(not_equal, &done);
1190 }
1191 // Perform the assignment.
1192 __ movq(Operand(rbp, SlotOffset(slot)), rax);
1166 break; 1193 break;
1167 1194
1168 case Slot::CONTEXT: { 1195 case Slot::CONTEXT: {
1169 MemOperand target = EmitSlotSearch(slot, rcx); 1196 MemOperand target = EmitSlotSearch(slot, rcx);
1170 __ movq(target, result_register()); 1197 if (op == Token::INIT_CONST) {
1171 1198 // Detect const reinitialization by checking for the hole value.
1172 // RecordWrite may destroy all its register arguments. 1199 __ movq(rdx, target);
1173 __ movq(rdx, result_register()); 1200 __ Cmp(rdx, Factory::the_hole_value());
1201 __ j(not_equal, &done);
1202 }
1203 // Perform the assignment and issue the write barrier.
1204 __ movq(target, rax);
1205 // The value of the assignment is in rax. RecordWrite clobbers its
1206 // register arguments.
1207 __ movq(rdx, rax);
1174 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1208 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
1175 __ RecordWrite(rcx, offset, rdx, rbx); 1209 __ RecordWrite(rcx, offset, rdx, rbx);
1176 break; 1210 break;
1177 } 1211 }
1178 1212
1179 case Slot::LOOKUP: 1213 case Slot::LOOKUP:
1180 UNREACHABLE(); 1214 // Call the runtime for the assignment. The runtime will ignore
1215 // const reinitialization.
1216 __ push(rax); // Value.
1217 __ push(rsi); // Context.
1218 __ Push(var->name());
1219 if (op == Token::INIT_CONST) {
1220 // The runtime will ignore const redeclaration.
1221 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1222 } else {
1223 __ CallRuntime(Runtime::kStoreContextSlot, 3);
1224 }
1181 break; 1225 break;
1182 } 1226 }
1183 Apply(context, result_register()); 1227 __ bind(&done);
1228 }
1184 1229
1185 } else { 1230 Apply(context, rax);
1186 // Variables rewritten as properties are not treated as variables in
1187 // assignments.
1188 UNREACHABLE();
1189 }
1190 } 1231 }
1191 1232
1192 1233
1193 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1234 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1194 // Assignment to a property, using a named store IC. 1235 // Assignment to a property, using a named store IC.
1195 Property* prop = expr->target()->AsProperty(); 1236 Property* prop = expr->target()->AsProperty();
1196 ASSERT(prop != NULL); 1237 ASSERT(prop != NULL);
1197 ASSERT(prop->key()->AsLiteral() != NULL); 1238 ASSERT(prop->key()->AsLiteral() != NULL);
1198 1239
1199 // If the assignment starts a block of assignments to the same object, 1240 // If the assignment starts a block of assignments to the same object,
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1728 GenericBinaryOpStub stub(expr->binary_op(), 1769 GenericBinaryOpStub stub(expr->binary_op(),
1729 NO_OVERWRITE, 1770 NO_OVERWRITE,
1730 NO_GENERIC_BINARY_FLAGS); 1771 NO_GENERIC_BINARY_FLAGS);
1731 stub.GenerateCall(masm_, rax, Smi::FromInt(1)); 1772 stub.GenerateCall(masm_, rax, Smi::FromInt(1));
1732 __ bind(&done); 1773 __ bind(&done);
1733 1774
1734 // Store the value returned in rax. 1775 // Store the value returned in rax.
1735 switch (assign_type) { 1776 switch (assign_type) {
1736 case VARIABLE: 1777 case VARIABLE:
1737 if (expr->is_postfix()) { 1778 if (expr->is_postfix()) {
1779 // Perform the assignment as if via '='.
1738 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1780 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1781 Token::ASSIGN,
1739 Expression::kEffect); 1782 Expression::kEffect);
1740 // For all contexts except kEffect: We have the result on 1783 // For all contexts except kEffect: We have the result on
1741 // top of the stack. 1784 // top of the stack.
1742 if (context_ != Expression::kEffect) { 1785 if (context_ != Expression::kEffect) {
1743 ApplyTOS(context_); 1786 ApplyTOS(context_);
1744 } 1787 }
1745 } else { 1788 } else {
1789 // Perform the assignment as if via '='.
1746 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1790 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1791 Token::ASSIGN,
1747 context_); 1792 context_);
1748 } 1793 }
1749 break; 1794 break;
1750 case NAMED_PROPERTY: { 1795 case NAMED_PROPERTY: {
1751 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1796 __ Move(rcx, prop->key()->AsLiteral()->handle());
1752 __ pop(rdx); 1797 __ pop(rdx);
1753 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1798 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1754 __ call(ic, RelocInfo::CODE_TARGET); 1799 __ call(ic, RelocInfo::CODE_TARGET);
1755 // This nop signals to the IC that there is no inlined code at the call 1800 // This nop signals to the IC that there is no inlined code at the call
1756 // site for it to patch. 1801 // site for it to patch.
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 __ movq(Operand(rsp, 0), rdx); 2029 __ movq(Operand(rsp, 0), rdx);
1985 // And return. 2030 // And return.
1986 __ ret(0); 2031 __ ret(0);
1987 } 2032 }
1988 2033
1989 2034
1990 #undef __ 2035 #undef __
1991 2036
1992 2037
1993 } } // namespace v8::internal 2038 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698