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 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |