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

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

Issue 546075: First step of refactoring expression contexts in the toplevel code... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 11 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
« src/compiler.cc ('K') | « src/ia32/fast-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 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 760 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 Handle<JSFunction> boilerplate = 771 Handle<JSFunction> boilerplate =
772 Compiler::BuildBoilerplate(expr, script_, this); 772 Compiler::BuildBoilerplate(expr, script_, this);
773 if (HasStackOverflow()) return; 773 if (HasStackOverflow()) return;
774 774
775 ASSERT(boilerplate->IsBoilerplate()); 775 ASSERT(boilerplate->IsBoilerplate());
776 776
777 // Create a new closure. 777 // Create a new closure.
778 __ push(rsi); 778 __ push(rsi);
779 __ Push(boilerplate); 779 __ Push(boilerplate);
780 __ CallRuntime(Runtime::kNewClosure, 2); 780 __ CallRuntime(Runtime::kNewClosure, 2);
781 Apply(expr->context(), rax); 781 Apply(context_, rax);
782 } 782 }
783 783
784 784
785 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 785 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
786 Comment cmnt(masm_, "[ VariableProxy"); 786 Comment cmnt(masm_, "[ VariableProxy");
787 EmitVariableLoad(expr->var(), expr->context()); 787 EmitVariableLoad(expr->var(), context_);
788 } 788 }
789 789
790 790
791 void FastCodeGenerator::EmitVariableLoad(Variable* var, 791 void FastCodeGenerator::EmitVariableLoad(Variable* var,
792 Expression::Context context) { 792 Expression::Context context) {
793 Expression* rewrite = var->rewrite(); 793 Expression* rewrite = var->rewrite();
794 if (rewrite == NULL) { 794 if (rewrite == NULL) {
795 ASSERT(var->is_global()); 795 ASSERT(var->is_global());
796 Comment cmnt(masm_, "Global variable"); 796 Comment cmnt(masm_, "Global variable");
797 // Use inline caching. Variable name is passed in rcx and the global 797 // Use inline caching. Variable name is passed in rcx and the global
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 879 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
880 __ j(not_equal, &done); 880 __ j(not_equal, &done);
881 // Create regexp literal using runtime function 881 // Create regexp literal using runtime function
882 // Result will be in rax. 882 // Result will be in rax.
883 __ push(rbx); 883 __ push(rbx);
884 __ Push(Smi::FromInt(expr->literal_index())); 884 __ Push(Smi::FromInt(expr->literal_index()));
885 __ Push(expr->pattern()); 885 __ Push(expr->pattern());
886 __ Push(expr->flags()); 886 __ Push(expr->flags());
887 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 887 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
888 __ bind(&done); 888 __ bind(&done);
889 Apply(expr->context(), rax); 889 Apply(context_, rax);
890 } 890 }
891 891
892 892
893 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 893 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
894 Comment cmnt(masm_, "[ ObjectLiteral"); 894 Comment cmnt(masm_, "[ ObjectLiteral");
895 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 895 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
896 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 896 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
897 __ Push(Smi::FromInt(expr->literal_index())); 897 __ Push(Smi::FromInt(expr->literal_index()));
898 __ Push(expr->constant_properties()); 898 __ Push(expr->constant_properties());
899 if (expr->depth() > 1) { 899 if (expr->depth() > 1) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 __ Push(property->kind() == ObjectLiteral::Property::SETTER ? 946 __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
947 Smi::FromInt(1) : 947 Smi::FromInt(1) :
948 Smi::FromInt(0)); 948 Smi::FromInt(0));
949 VisitForValue(value, kStack); 949 VisitForValue(value, kStack);
950 __ CallRuntime(Runtime::kDefineAccessor, 4); 950 __ CallRuntime(Runtime::kDefineAccessor, 4);
951 break; 951 break;
952 } 952 }
953 } 953 }
954 954
955 if (result_saved) { 955 if (result_saved) {
956 ApplyTOS(expr->context()); 956 ApplyTOS(context_);
957 } else { 957 } else {
958 Apply(expr->context(), rax); 958 Apply(context_, rax);
959 } 959 }
960 } 960 }
961 961
962 962
963 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 963 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
964 Comment cmnt(masm_, "[ ArrayLiteral"); 964 Comment cmnt(masm_, "[ ArrayLiteral");
965 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 965 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
966 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 966 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
967 __ Push(Smi::FromInt(expr->literal_index())); 967 __ Push(Smi::FromInt(expr->literal_index()));
968 __ Push(expr->constant_elements()); 968 __ Push(expr->constant_elements());
(...skipping 27 matching lines...) Expand all
996 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 996 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
997 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 997 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
998 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 998 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
999 __ movq(FieldOperand(rbx, offset), result_register()); 999 __ movq(FieldOperand(rbx, offset), result_register());
1000 1000
1001 // Update the write barrier for the array store. 1001 // Update the write barrier for the array store.
1002 __ RecordWrite(rbx, offset, result_register(), rcx); 1002 __ RecordWrite(rbx, offset, result_register(), rcx);
1003 } 1003 }
1004 1004
1005 if (result_saved) { 1005 if (result_saved) {
1006 ApplyTOS(expr->context()); 1006 ApplyTOS(context_);
1007 } else { 1007 } else {
1008 Apply(expr->context(), rax); 1008 Apply(context_, rax);
1009 } 1009 }
1010 } 1010 }
1011 1011
1012 1012
1013 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1013 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1014 SetSourcePosition(prop->position()); 1014 SetSourcePosition(prop->position());
1015 Literal* key = prop->key()->AsLiteral(); 1015 Literal* key = prop->key()->AsLiteral();
1016 __ Move(rcx, key->handle()); 1016 __ Move(rcx, key->handle());
1017 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1017 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1018 __ Call(ic, RelocInfo::CODE_TARGET); 1018 __ Call(ic, RelocInfo::CODE_TARGET);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 __ nop(); 1110 __ nop();
1111 1111
1112 // If the assignment ends an initialization block, revert to fast case. 1112 // If the assignment ends an initialization block, revert to fast case.
1113 if (expr->ends_initialization_block()) { 1113 if (expr->ends_initialization_block()) {
1114 __ push(rax); // Result of assignment, saved even if not needed. 1114 __ push(rax); // Result of assignment, saved even if not needed.
1115 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1115 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1116 __ CallRuntime(Runtime::kToFastProperties, 1); 1116 __ CallRuntime(Runtime::kToFastProperties, 1);
1117 __ pop(rax); 1117 __ pop(rax);
1118 } 1118 }
1119 1119
1120 DropAndApply(1, expr->context(), rax); 1120 DropAndApply(1, context_, rax);
1121 } 1121 }
1122 1122
1123 1123
1124 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1124 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1125 // Assignment to a property, using a keyed store IC. 1125 // Assignment to a property, using a keyed store IC.
1126 1126
1127 // If the assignment starts a block of assignments to the same object, 1127 // If the assignment starts a block of assignments to the same object,
1128 // change to slow case to avoid the quadratic behavior of repeatedly 1128 // change to slow case to avoid the quadratic behavior of repeatedly
1129 // adding fast properties. 1129 // adding fast properties.
1130 if (expr->starts_initialization_block()) { 1130 if (expr->starts_initialization_block()) {
(...skipping 15 matching lines...) Expand all
1146 // If the assignment ends an initialization block, revert to fast case. 1146 // If the assignment ends an initialization block, revert to fast case.
1147 if (expr->ends_initialization_block()) { 1147 if (expr->ends_initialization_block()) {
1148 __ push(rax); // Result of assignment, saved even if not needed. 1148 __ push(rax); // Result of assignment, saved even if not needed.
1149 // Receiver is under the key and value. 1149 // Receiver is under the key and value.
1150 __ push(Operand(rsp, 2 * kPointerSize)); 1150 __ push(Operand(rsp, 2 * kPointerSize));
1151 __ CallRuntime(Runtime::kToFastProperties, 1); 1151 __ CallRuntime(Runtime::kToFastProperties, 1);
1152 __ pop(rax); 1152 __ pop(rax);
1153 } 1153 }
1154 1154
1155 // Receiver and key are still on stack. 1155 // Receiver and key are still on stack.
1156 DropAndApply(2, expr->context(), rax); 1156 DropAndApply(2, context_, rax);
1157 } 1157 }
1158 1158
1159 1159
1160 void FastCodeGenerator::VisitProperty(Property* expr) { 1160 void FastCodeGenerator::VisitProperty(Property* expr) {
1161 Comment cmnt(masm_, "[ Property"); 1161 Comment cmnt(masm_, "[ Property");
1162 Expression* key = expr->key(); 1162 Expression* key = expr->key();
1163 1163
1164 // Evaluate receiver. 1164 // Evaluate receiver.
1165 VisitForValue(expr->obj(), kStack); 1165 VisitForValue(expr->obj(), kStack);
1166 1166
1167 if (key->IsPropertyName()) { 1167 if (key->IsPropertyName()) {
1168 EmitNamedPropertyLoad(expr); 1168 EmitNamedPropertyLoad(expr);
1169 // Drop receiver left on the stack by IC. 1169 // Drop receiver left on the stack by IC.
1170 DropAndApply(1, expr->context(), rax); 1170 DropAndApply(1, context_, rax);
1171 } else { 1171 } else {
1172 VisitForValue(expr->key(), kStack); 1172 VisitForValue(expr->key(), kStack);
1173 EmitKeyedPropertyLoad(expr); 1173 EmitKeyedPropertyLoad(expr);
1174 // Drop key and receiver left on the stack by IC. 1174 // Drop key and receiver left on the stack by IC.
1175 DropAndApply(2, expr->context(), rax); 1175 DropAndApply(2, context_, rax);
1176 } 1176 }
1177 } 1177 }
1178 1178
1179 1179
1180 void FastCodeGenerator::EmitCallWithIC(Call* expr, 1180 void FastCodeGenerator::EmitCallWithIC(Call* expr,
1181 Handle<Object> ignored, 1181 Handle<Object> ignored,
1182 RelocInfo::Mode mode) { 1182 RelocInfo::Mode mode) {
1183 // Code common for calls using the IC. 1183 // Code common for calls using the IC.
1184 ZoneList<Expression*>* args = expr->arguments(); 1184 ZoneList<Expression*>* args = expr->arguments();
1185 int arg_count = args->length(); 1185 int arg_count = args->length();
1186 for (int i = 0; i < arg_count; i++) { 1186 for (int i = 0; i < arg_count; i++) {
1187 VisitForValue(args->at(i), kStack); 1187 VisitForValue(args->at(i), kStack);
1188 } 1188 }
1189 // Record source position for debugger. 1189 // Record source position for debugger.
1190 SetSourcePosition(expr->position()); 1190 SetSourcePosition(expr->position());
1191 // Call the IC initialization code. 1191 // Call the IC initialization code.
1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1194 in_loop); 1194 in_loop);
1195 __ Call(ic, mode); 1195 __ Call(ic, mode);
1196 // Restore context register. 1196 // Restore context register.
1197 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1197 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1198 // Discard the function left on TOS. 1198 // Discard the function left on TOS.
1199 DropAndApply(1, expr->context(), rax); 1199 DropAndApply(1, context_, rax);
1200 } 1200 }
1201 1201
1202 1202
1203 void FastCodeGenerator::EmitCallWithStub(Call* expr) { 1203 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
1204 // Code common for calls using the call stub. 1204 // Code common for calls using the call stub.
1205 ZoneList<Expression*>* args = expr->arguments(); 1205 ZoneList<Expression*>* args = expr->arguments();
1206 int arg_count = args->length(); 1206 int arg_count = args->length();
1207 for (int i = 0; i < arg_count; i++) { 1207 for (int i = 0; i < arg_count; i++) {
1208 VisitForValue(args->at(i), kStack); 1208 VisitForValue(args->at(i), kStack);
1209 } 1209 }
1210 // Record source position for debugger. 1210 // Record source position for debugger.
1211 SetSourcePosition(expr->position()); 1211 SetSourcePosition(expr->position());
1212 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); 1212 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
1213 __ CallStub(&stub); 1213 __ CallStub(&stub);
1214 // Restore context register. 1214 // Restore context register.
1215 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1215 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1216 // Discard the function left on TOS. 1216 // Discard the function left on TOS.
1217 DropAndApply(1, expr->context(), rax); 1217 DropAndApply(1, context_, rax);
1218 } 1218 }
1219 1219
1220 1220
1221 void FastCodeGenerator::VisitCall(Call* expr) { 1221 void FastCodeGenerator::VisitCall(Call* expr) {
1222 Comment cmnt(masm_, "[ Call"); 1222 Comment cmnt(masm_, "[ Call");
1223 Expression* fun = expr->expression(); 1223 Expression* fun = expr->expression();
1224 Variable* var = fun->AsVariableProxy()->AsVariable(); 1224 Variable* var = fun->AsVariableProxy()->AsVariable();
1225 1225
1226 if (var != NULL && var->is_possibly_eval()) { 1226 if (var != NULL && var->is_possibly_eval()) {
1227 // Call to the identifier 'eval'. 1227 // Call to the identifier 'eval'.
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 1316
1317 // Load function, arg_count into rdi and rax. 1317 // Load function, arg_count into rdi and rax.
1318 __ Set(rax, arg_count); 1318 __ Set(rax, arg_count);
1319 // Function is in rsp[arg_count + 1]. 1319 // Function is in rsp[arg_count + 1].
1320 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); 1320 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize));
1321 1321
1322 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1322 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1323 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1323 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1324 1324
1325 // Replace function on TOS with result in rax, or pop it. 1325 // Replace function on TOS with result in rax, or pop it.
1326 DropAndApply(1, expr->context(), rax); 1326 DropAndApply(1, context_, rax);
1327 } 1327 }
1328 1328
1329 1329
1330 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 1330 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1331 Comment cmnt(masm_, "[ CallRuntime"); 1331 Comment cmnt(masm_, "[ CallRuntime");
1332 ZoneList<Expression*>* args = expr->arguments(); 1332 ZoneList<Expression*>* args = expr->arguments();
1333 1333
1334 if (expr->is_jsruntime()) { 1334 if (expr->is_jsruntime()) {
1335 // Prepare for calling JS runtime function. 1335 // Prepare for calling JS runtime function.
1336 __ Push(expr->name()); 1336 __ Push(expr->name());
1337 __ movq(rax, CodeGenerator::GlobalObject()); 1337 __ movq(rax, CodeGenerator::GlobalObject());
1338 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 1338 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
1339 } 1339 }
1340 1340
1341 // Push the arguments ("left-to-right"). 1341 // Push the arguments ("left-to-right").
1342 int arg_count = args->length(); 1342 int arg_count = args->length();
1343 for (int i = 0; i < arg_count; i++) { 1343 for (int i = 0; i < arg_count; i++) {
1344 VisitForValue(args->at(i), kStack); 1344 VisitForValue(args->at(i), kStack);
1345 } 1345 }
1346 1346
1347 if (expr->is_jsruntime()) { 1347 if (expr->is_jsruntime()) {
1348 // Call the JS runtime function. 1348 // Call the JS runtime function.
1349 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1349 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1350 NOT_IN_LOOP); 1350 NOT_IN_LOOP);
1351 __ call(ic, RelocInfo::CODE_TARGET); 1351 __ call(ic, RelocInfo::CODE_TARGET);
1352 // Restore context register. 1352 // Restore context register.
1353 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1353 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1354 // Discard the function left on TOS. 1354 // Discard the function left on TOS.
1355 DropAndApply(1, expr->context(), rax); 1355 DropAndApply(1, context_, rax);
1356 } else { 1356 } else {
1357 __ CallRuntime(expr->function(), arg_count); 1357 __ CallRuntime(expr->function(), arg_count);
1358 Apply(expr->context(), rax); 1358 Apply(context_, rax);
1359 } 1359 }
1360 } 1360 }
1361 1361
1362 1362
1363 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1363 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1364 switch (expr->op()) { 1364 switch (expr->op()) {
1365 case Token::VOID: { 1365 case Token::VOID: {
1366 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1366 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1367 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); 1367 VisitForEffect(expr->expression());
1368 Visit(expr->expression()); 1368 switch (context_) {
1369 switch (expr->context()) {
1370 case Expression::kUninitialized: 1369 case Expression::kUninitialized:
1371 UNREACHABLE(); 1370 UNREACHABLE();
1372 break; 1371 break;
1373 case Expression::kEffect: 1372 case Expression::kEffect:
1374 break; 1373 break;
1375 case Expression::kValue: 1374 case Expression::kValue:
1376 switch (location_) { 1375 switch (location_) {
1377 case kAccumulator: 1376 case kAccumulator:
1378 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 1377 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1379 break; 1378 break;
(...skipping 16 matching lines...) Expand all
1396 case Expression::kTest: 1395 case Expression::kTest:
1397 case Expression::kValueTest: 1396 case Expression::kValueTest:
1398 __ jmp(false_label_); 1397 __ jmp(false_label_);
1399 break; 1398 break;
1400 } 1399 }
1401 break; 1400 break;
1402 } 1401 }
1403 1402
1404 case Token::NOT: { 1403 case Token::NOT: {
1405 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 1404 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1406 ASSERT_EQ(Expression::kTest, expr->expression()->context());
1407
1408 Label materialize_true, materialize_false, done; 1405 Label materialize_true, materialize_false, done;
1409 // Initially assume a pure test context. Notice that the labels are 1406 // Initially assume a pure test context. Notice that the labels are
1410 // swapped. 1407 // swapped.
1411 Label* if_true = false_label_; 1408 Label* if_true = false_label_;
1412 Label* if_false = true_label_; 1409 Label* if_false = true_label_;
1413 switch (expr->context()) { 1410 switch (context_) {
1414 case Expression::kUninitialized: 1411 case Expression::kUninitialized:
1415 UNREACHABLE(); 1412 UNREACHABLE();
1416 break; 1413 break;
1417 case Expression::kEffect: 1414 case Expression::kEffect:
1418 if_true = &done; 1415 if_true = &done;
1419 if_false = &done; 1416 if_false = &done;
1420 break; 1417 break;
1421 case Expression::kValue: 1418 case Expression::kValue:
1422 if_true = &materialize_false; 1419 if_true = &materialize_false;
1423 if_false = &materialize_true; 1420 if_false = &materialize_true;
1424 break; 1421 break;
1425 case Expression::kTest: 1422 case Expression::kTest:
1426 break; 1423 break;
1427 case Expression::kValueTest: 1424 case Expression::kValueTest:
1428 if_false = &materialize_true; 1425 if_false = &materialize_true;
1429 break; 1426 break;
1430 case Expression::kTestValue: 1427 case Expression::kTestValue:
1431 if_true = &materialize_false; 1428 if_true = &materialize_false;
1432 break; 1429 break;
1433 } 1430 }
1434 VisitForControl(expr->expression(), if_true, if_false); 1431 VisitForControl(expr->expression(), if_true, if_false);
1435 Apply(expr->context(), if_false, if_true); // Labels swapped. 1432 Apply(context_, if_false, if_true); // Labels swapped.
1436 break; 1433 break;
1437 } 1434 }
1438 1435
1439 case Token::TYPEOF: { 1436 case Token::TYPEOF: {
1440 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 1437 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
1441 ASSERT_EQ(Expression::kValue, expr->expression()->context());
1442
1443 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1438 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1444 if (proxy != NULL && 1439 if (proxy != NULL &&
1445 !proxy->var()->is_this() && 1440 !proxy->var()->is_this() &&
1446 proxy->var()->is_global()) { 1441 proxy->var()->is_global()) {
1447 Comment cmnt(masm_, "Global variable"); 1442 Comment cmnt(masm_, "Global variable");
1448 __ push(CodeGenerator::GlobalObject()); 1443 __ push(CodeGenerator::GlobalObject());
1449 __ Move(rcx, proxy->name()); 1444 __ Move(rcx, proxy->name());
1450 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1445 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1451 // Use a regular load, not a contextual load, to avoid a reference 1446 // Use a regular load, not a contextual load, to avoid a reference
1452 // error. 1447 // error.
1453 __ Call(ic, RelocInfo::CODE_TARGET); 1448 __ Call(ic, RelocInfo::CODE_TARGET);
1454 __ movq(Operand(rsp, 0), rax); 1449 __ movq(Operand(rsp, 0), rax);
1455 } else if (proxy != NULL && 1450 } else if (proxy != NULL &&
1456 proxy->var()->slot() != NULL && 1451 proxy->var()->slot() != NULL &&
1457 proxy->var()->slot()->type() == Slot::LOOKUP) { 1452 proxy->var()->slot()->type() == Slot::LOOKUP) {
1458 __ push(rsi); 1453 __ push(rsi);
1459 __ Push(proxy->name()); 1454 __ Push(proxy->name());
1460 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1455 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1461 __ push(rax); 1456 __ push(rax);
1462 } else { 1457 } else {
1463 // This expression cannot throw a reference error at the top level. 1458 // This expression cannot throw a reference error at the top level.
1464 VisitForValue(expr->expression(), kStack); 1459 VisitForValue(expr->expression(), kStack);
1465 } 1460 }
1466 1461
1467 __ CallRuntime(Runtime::kTypeof, 1); 1462 __ CallRuntime(Runtime::kTypeof, 1);
1468 Apply(expr->context(), rax); 1463 Apply(context_, rax);
1469 break; 1464 break;
1470 } 1465 }
1471 1466
1472 default: 1467 default:
1473 UNREACHABLE(); 1468 UNREACHABLE();
1474 } 1469 }
1475 } 1470 }
1476 1471
1477 1472
1478 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 1473 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
1479 Comment cmnt(masm_, "[ CountOperation"); 1474 Comment cmnt(masm_, "[ CountOperation");
1480 1475
1481 // Expression can only be a property, a global or a (parameter or local) 1476 // Expression can only be a property, a global or a (parameter or local)
1482 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1477 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1483 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1478 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1484 LhsKind assign_type = VARIABLE; 1479 LhsKind assign_type = VARIABLE;
1485 Property* prop = expr->expression()->AsProperty(); 1480 Property* prop = expr->expression()->AsProperty();
1486 // In case of a property we use the uninitialized expression context 1481 // In case of a property we use the uninitialized expression context
1487 // of the key to detect a named property. 1482 // of the key to detect a named property.
1488 if (prop != NULL) { 1483 if (prop != NULL) {
1489 assign_type = (prop->key()->context() == Expression::kUninitialized) 1484 assign_type =
1490 ? NAMED_PROPERTY 1485 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
1491 : KEYED_PROPERTY;
1492 } 1486 }
1493 1487
1494 // Evaluate expression and get value. 1488 // Evaluate expression and get value.
1495 if (assign_type == VARIABLE) { 1489 if (assign_type == VARIABLE) {
1496 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 1490 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
1497 Location saved_location = location_; 1491 Location saved_location = location_;
1498 location_ = kStack; 1492 location_ = kStack;
1499 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 1493 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1500 Expression::kValue); 1494 Expression::kValue);
1501 location_ = saved_location; 1495 location_ = saved_location;
1502 } else { 1496 } else {
1503 // Reserve space for result of postfix operation. 1497 // Reserve space for result of postfix operation.
1504 if (expr->is_postfix() && expr->context() != Expression::kEffect) { 1498 if (expr->is_postfix() && context_ != Expression::kEffect) {
1505 ASSERT(expr->context() != Expression::kUninitialized);
1506 __ Push(Smi::FromInt(0)); 1499 __ Push(Smi::FromInt(0));
1507 } 1500 }
1508 VisitForValue(prop->obj(), kStack); 1501 VisitForValue(prop->obj(), kStack);
1509 if (assign_type == NAMED_PROPERTY) { 1502 if (assign_type == NAMED_PROPERTY) {
1510 EmitNamedPropertyLoad(prop); 1503 EmitNamedPropertyLoad(prop);
1511 } else { 1504 } else {
1512 VisitForValue(prop->key(), kStack); 1505 VisitForValue(prop->key(), kStack);
1513 EmitKeyedPropertyLoad(prop); 1506 EmitKeyedPropertyLoad(prop);
1514 } 1507 }
1515 __ push(rax); 1508 __ push(rax);
1516 } 1509 }
1517 1510
1518 // Convert to number. 1511 // Convert to number.
1519 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1512 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1520 1513
1521 // Save result for postfix expressions. 1514 // Save result for postfix expressions.
1522 if (expr->is_postfix()) { 1515 if (expr->is_postfix()) {
1523 switch (expr->context()) { 1516 switch (context_) {
1524 case Expression::kUninitialized: 1517 case Expression::kUninitialized:
1525 UNREACHABLE(); 1518 UNREACHABLE();
1526 case Expression::kEffect: 1519 case Expression::kEffect:
1527 // Do not save result. 1520 // Do not save result.
1528 break; 1521 break;
1529 case Expression::kValue: 1522 case Expression::kValue:
1530 case Expression::kTest: 1523 case Expression::kTest:
1531 case Expression::kValueTest: 1524 case Expression::kValueTest:
1532 case Expression::kTestValue: 1525 case Expression::kTestValue:
1533 // Save the result on the stack. If we have a named or keyed property 1526 // Save the result on the stack. If we have a named or keyed property
(...skipping 23 matching lines...) Expand all
1557 __ CallStub(&stub); 1550 __ CallStub(&stub);
1558 1551
1559 // Store the value returned in rax. 1552 // Store the value returned in rax.
1560 switch (assign_type) { 1553 switch (assign_type) {
1561 case VARIABLE: 1554 case VARIABLE:
1562 if (expr->is_postfix()) { 1555 if (expr->is_postfix()) {
1563 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1556 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1564 Expression::kEffect); 1557 Expression::kEffect);
1565 // For all contexts except kEffect: We have the result on 1558 // For all contexts except kEffect: We have the result on
1566 // top of the stack. 1559 // top of the stack.
1567 if (expr->context() != Expression::kEffect) { 1560 if (context_ != Expression::kEffect) {
1568 ApplyTOS(expr->context()); 1561 ApplyTOS(context_);
1569 } 1562 }
1570 } else { 1563 } else {
1571 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1564 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1572 expr->context()); 1565 context_);
1573 } 1566 }
1574 break; 1567 break;
1575 case NAMED_PROPERTY: { 1568 case NAMED_PROPERTY: {
1576 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1569 __ Move(rcx, prop->key()->AsLiteral()->handle());
1577 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1570 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1578 __ call(ic, RelocInfo::CODE_TARGET); 1571 __ call(ic, RelocInfo::CODE_TARGET);
1579 // This nop signals to the IC that there is no inlined code at the call 1572 // This nop signals to the IC that there is no inlined code at the call
1580 // site for it to patch. 1573 // site for it to patch.
1581 __ nop(); 1574 __ nop();
1582 if (expr->is_postfix()) { 1575 if (expr->is_postfix()) {
1583 __ Drop(1); // Result is on the stack under the receiver. 1576 __ Drop(1); // Result is on the stack under the receiver.
1584 if (expr->context() != Expression::kEffect) { 1577 if (context_ != Expression::kEffect) {
1585 ApplyTOS(expr->context()); 1578 ApplyTOS(context_);
1586 } 1579 }
1587 } else { 1580 } else {
1588 DropAndApply(1, expr->context(), rax); 1581 DropAndApply(1, context_, rax);
1589 } 1582 }
1590 break; 1583 break;
1591 } 1584 }
1592 case KEYED_PROPERTY: { 1585 case KEYED_PROPERTY: {
1593 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1586 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1594 __ call(ic, RelocInfo::CODE_TARGET); 1587 __ call(ic, RelocInfo::CODE_TARGET);
1595 // This nop signals to the IC that there is no inlined code at the call 1588 // This nop signals to the IC that there is no inlined code at the call
1596 // site for it to patch. 1589 // site for it to patch.
1597 __ nop(); 1590 __ nop();
1598 if (expr->is_postfix()) { 1591 if (expr->is_postfix()) {
1599 __ Drop(2); // Result is on the stack under the key and the receiver. 1592 __ Drop(2); // Result is on the stack under the key and the receiver.
1600 if (expr->context() != Expression::kEffect) { 1593 if (context_ != Expression::kEffect) {
1601 ApplyTOS(expr->context()); 1594 ApplyTOS(context_);
1602 } 1595 }
1603 } else { 1596 } else {
1604 DropAndApply(2, expr->context(), rax); 1597 DropAndApply(2, context_, rax);
1605 } 1598 }
1606 break; 1599 break;
1607 } 1600 }
1608 } 1601 }
1609 } 1602 }
1610 1603
1611 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 1604 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1612 Comment cmnt(masm_, "[ BinaryOperation"); 1605 Comment cmnt(masm_, "[ BinaryOperation");
1613 switch (expr->op()) { 1606 switch (expr->op()) {
1614 case Token::COMMA: 1607 case Token::COMMA:
1615 ASSERT_EQ(Expression::kEffect, expr->left()->context()); 1608 VisitForEffect(expr->left());
1616 ASSERT_EQ(expr->context(), expr->right()->context());
1617 Visit(expr->left());
1618 Visit(expr->right()); 1609 Visit(expr->right());
1619 break; 1610 break;
1620 1611
1621 case Token::OR: 1612 case Token::OR:
1622 case Token::AND: 1613 case Token::AND:
1623 EmitLogicalOperation(expr); 1614 EmitLogicalOperation(expr);
1624 break; 1615 break;
1625 1616
1626 case Token::ADD: 1617 case Token::ADD:
1627 case Token::SUB: 1618 case Token::SUB:
1628 case Token::DIV: 1619 case Token::DIV:
1629 case Token::MOD: 1620 case Token::MOD:
1630 case Token::MUL: 1621 case Token::MUL:
1631 case Token::BIT_OR: 1622 case Token::BIT_OR:
1632 case Token::BIT_AND: 1623 case Token::BIT_AND:
1633 case Token::BIT_XOR: 1624 case Token::BIT_XOR:
1634 case Token::SHL: 1625 case Token::SHL:
1635 case Token::SHR: 1626 case Token::SHR:
1636 case Token::SAR: 1627 case Token::SAR:
1637 VisitForValue(expr->left(), kStack); 1628 VisitForValue(expr->left(), kStack);
1638 VisitForValue(expr->right(), kAccumulator); 1629 VisitForValue(expr->right(), kAccumulator);
1639 EmitBinaryOp(expr->op(), expr->context()); 1630 EmitBinaryOp(expr->op(), context_);
1640 break; 1631 break;
1641 1632
1642 default: 1633 default:
1643 UNREACHABLE(); 1634 UNREACHABLE();
1644 } 1635 }
1645 } 1636 }
1646 1637
1647 1638
1648 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1639 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1649 Comment cmnt(masm_, "[ CompareOperation"); 1640 Comment cmnt(masm_, "[ CompareOperation");
1650 1641
1651 // Always perform the comparison for its control flow. Pack the result 1642 // Always perform the comparison for its control flow. Pack the result
1652 // into the expression's context after the comparison is performed. 1643 // into the expression's context after the comparison is performed.
1653 Label materialize_true, materialize_false, done; 1644 Label materialize_true, materialize_false, done;
1654 // Initially assume we are in a test context. 1645 // Initially assume we are in a test context.
1655 Label* if_true = true_label_; 1646 Label* if_true = true_label_;
1656 Label* if_false = false_label_; 1647 Label* if_false = false_label_;
1657 switch (expr->context()) { 1648 switch (context_) {
1658 case Expression::kUninitialized: 1649 case Expression::kUninitialized:
1659 UNREACHABLE(); 1650 UNREACHABLE();
1660 break; 1651 break;
1661 case Expression::kEffect: 1652 case Expression::kEffect:
1662 if_true = &done; 1653 if_true = &done;
1663 if_false = &done; 1654 if_false = &done;
1664 break; 1655 break;
1665 case Expression::kValue: 1656 case Expression::kValue:
1666 if_true = &materialize_true; 1657 if_true = &materialize_true;
1667 if_false = &materialize_false; 1658 if_false = &materialize_false;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1746 CompareStub stub(cc, strict); 1737 CompareStub stub(cc, strict);
1747 __ CallStub(&stub); 1738 __ CallStub(&stub);
1748 __ testq(rax, rax); 1739 __ testq(rax, rax);
1749 __ j(cc, if_true); 1740 __ j(cc, if_true);
1750 __ jmp(if_false); 1741 __ jmp(if_false);
1751 } 1742 }
1752 } 1743 }
1753 1744
1754 // Convert the result of the comparison into one expected for this 1745 // Convert the result of the comparison into one expected for this
1755 // expression's context. 1746 // expression's context.
1756 Apply(expr->context(), if_true, if_false); 1747 Apply(context_, if_true, if_false);
1757 } 1748 }
1758 1749
1759 1750
1760 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1751 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1761 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1752 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1762 Apply(expr->context(), rax); 1753 Apply(context_, rax);
1763 } 1754 }
1764 1755
1765 1756
1766 Register FastCodeGenerator::result_register() { return rax; } 1757 Register FastCodeGenerator::result_register() { return rax; }
1767 1758
1768 1759
1769 Register FastCodeGenerator::context_register() { return rsi; } 1760 Register FastCodeGenerator::context_register() { return rsi; }
1770 1761
1771 1762
1772 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 1763 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 __ movq(Operand(rsp, 0), rdx); 1802 __ movq(Operand(rsp, 0), rdx);
1812 // And return. 1803 // And return.
1813 __ ret(0); 1804 __ ret(0);
1814 } 1805 }
1815 1806
1816 1807
1817 #undef __ 1808 #undef __
1818 1809
1819 1810
1820 } } // namespace v8::internal 1811 } } // namespace v8::internal
OLDNEW
« src/compiler.cc ('K') | « src/ia32/fast-codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698