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 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 Handle<JSFunction> boilerplate = | 768 Handle<JSFunction> boilerplate = |
769 Compiler::BuildBoilerplate(expr, script_, this); | 769 Compiler::BuildBoilerplate(expr, script_, this); |
770 if (HasStackOverflow()) return; | 770 if (HasStackOverflow()) return; |
771 | 771 |
772 ASSERT(boilerplate->IsBoilerplate()); | 772 ASSERT(boilerplate->IsBoilerplate()); |
773 | 773 |
774 // Create a new closure. | 774 // Create a new closure. |
775 __ push(esi); | 775 __ push(esi); |
776 __ push(Immediate(boilerplate)); | 776 __ push(Immediate(boilerplate)); |
777 __ CallRuntime(Runtime::kNewClosure, 2); | 777 __ CallRuntime(Runtime::kNewClosure, 2); |
778 Apply(expr->context(), eax); | 778 Apply(context_, eax); |
779 } | 779 } |
780 | 780 |
781 | 781 |
782 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 782 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
783 Comment cmnt(masm_, "[ VariableProxy"); | 783 Comment cmnt(masm_, "[ VariableProxy"); |
784 EmitVariableLoad(expr->var(), expr->context()); | 784 EmitVariableLoad(expr->var(), context_); |
785 } | 785 } |
786 | 786 |
787 | 787 |
788 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 788 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
789 Expression::Context context) { | 789 Expression::Context context) { |
790 Expression* rewrite = var->rewrite(); | 790 Expression* rewrite = var->rewrite(); |
791 if (rewrite == NULL) { | 791 if (rewrite == NULL) { |
792 ASSERT(var->is_global()); | 792 ASSERT(var->is_global()); |
793 Comment cmnt(masm_, "Global variable"); | 793 Comment cmnt(masm_, "Global variable"); |
794 // Use inline caching. Variable name is passed in ecx and the global | 794 // Use inline caching. Variable name is passed in ecx and the global |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 __ j(not_equal, &done); | 878 __ j(not_equal, &done); |
879 // Create regexp literal using runtime function | 879 // Create regexp literal using runtime function |
880 // Result will be in eax. | 880 // Result will be in eax. |
881 __ push(ebx); | 881 __ push(ebx); |
882 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 882 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
883 __ push(Immediate(expr->pattern())); | 883 __ push(Immediate(expr->pattern())); |
884 __ push(Immediate(expr->flags())); | 884 __ push(Immediate(expr->flags())); |
885 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 885 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
886 // Label done: | 886 // Label done: |
887 __ bind(&done); | 887 __ bind(&done); |
888 Apply(expr->context(), eax); | 888 Apply(context_, eax); |
889 } | 889 } |
890 | 890 |
891 | 891 |
892 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 892 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
893 Comment cmnt(masm_, "[ ObjectLiteral"); | 893 Comment cmnt(masm_, "[ ObjectLiteral"); |
894 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 894 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
895 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); | 895 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); |
896 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 896 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
897 __ push(Immediate(expr->constant_properties())); | 897 __ push(Immediate(expr->constant_properties())); |
898 if (expr->depth() > 1) { | 898 if (expr->depth() > 1) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 Smi::FromInt(1) : | 944 Smi::FromInt(1) : |
945 Smi::FromInt(0))); | 945 Smi::FromInt(0))); |
946 VisitForValue(value, kStack); | 946 VisitForValue(value, kStack); |
947 __ CallRuntime(Runtime::kDefineAccessor, 4); | 947 __ CallRuntime(Runtime::kDefineAccessor, 4); |
948 break; | 948 break; |
949 default: UNREACHABLE(); | 949 default: UNREACHABLE(); |
950 } | 950 } |
951 } | 951 } |
952 | 952 |
953 if (result_saved) { | 953 if (result_saved) { |
954 ApplyTOS(expr->context()); | 954 ApplyTOS(context_); |
955 } else { | 955 } else { |
956 Apply(expr->context(), eax); | 956 Apply(context_, eax); |
957 } | 957 } |
958 } | 958 } |
959 | 959 |
960 | 960 |
961 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 961 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
962 Comment cmnt(masm_, "[ ArrayLiteral"); | 962 Comment cmnt(masm_, "[ ArrayLiteral"); |
963 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 963 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
964 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 964 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
965 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 965 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
966 __ push(Immediate(expr->constant_elements())); | 966 __ push(Immediate(expr->constant_elements())); |
(...skipping 27 matching lines...) Expand all Loading... |
994 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. | 994 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
995 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 995 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
996 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 996 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
997 __ mov(FieldOperand(ebx, offset), result_register()); | 997 __ mov(FieldOperand(ebx, offset), result_register()); |
998 | 998 |
999 // Update the write barrier for the array store. | 999 // Update the write barrier for the array store. |
1000 __ RecordWrite(ebx, offset, result_register(), ecx); | 1000 __ RecordWrite(ebx, offset, result_register(), ecx); |
1001 } | 1001 } |
1002 | 1002 |
1003 if (result_saved) { | 1003 if (result_saved) { |
1004 ApplyTOS(expr->context()); | 1004 ApplyTOS(context_); |
1005 } else { | 1005 } else { |
1006 Apply(expr->context(), eax); | 1006 Apply(context_, eax); |
1007 } | 1007 } |
1008 } | 1008 } |
1009 | 1009 |
1010 | 1010 |
1011 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1011 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1012 SetSourcePosition(prop->position()); | 1012 SetSourcePosition(prop->position()); |
1013 Literal* key = prop->key()->AsLiteral(); | 1013 Literal* key = prop->key()->AsLiteral(); |
1014 __ mov(ecx, Immediate(key->handle())); | 1014 __ mov(ecx, Immediate(key->handle())); |
1015 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1015 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1016 __ call(ic, RelocInfo::CODE_TARGET); | 1016 __ call(ic, RelocInfo::CODE_TARGET); |
(...skipping 93 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(eax); // Result of assignment, saved even if not needed. | 1114 __ push(eax); // Result of assignment, saved even if not needed. |
1115 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1115 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
1116 __ CallRuntime(Runtime::kToFastProperties, 1); | 1116 __ CallRuntime(Runtime::kToFastProperties, 1); |
1117 __ pop(eax); | 1117 __ pop(eax); |
1118 } | 1118 } |
1119 | 1119 |
1120 DropAndApply(1, expr->context(), eax); | 1120 DropAndApply(1, context_, eax); |
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(eax); // Result of assignment, saved even if not needed. | 1148 __ push(eax); // 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(esp, 2 * kPointerSize)); | 1150 __ push(Operand(esp, 2 * kPointerSize)); |
1151 __ CallRuntime(Runtime::kToFastProperties, 1); | 1151 __ CallRuntime(Runtime::kToFastProperties, 1); |
1152 __ pop(eax); | 1152 __ pop(eax); |
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(), eax); | 1156 DropAndApply(2, context_, eax); |
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 the receiver. | 1164 // Evaluate the 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(), eax); | 1170 DropAndApply(1, context_, eax); |
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(), eax); | 1175 DropAndApply(2, context_, eax); |
1176 } | 1176 } |
1177 } | 1177 } |
1178 | 1178 |
1179 | 1179 |
1180 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1180 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
1181 Handle<Object> name, | 1181 Handle<Object> name, |
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 __ Set(ecx, Immediate(name)); | 1189 __ Set(ecx, Immediate(name)); |
1190 // Record source position of the IC call. | 1190 // Record source position of the IC call. |
1191 SetSourcePosition(expr->position()); | 1191 SetSourcePosition(expr->position()); |
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, in_loop); | 1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1194 __ call(ic, mode); | 1194 __ call(ic, mode); |
1195 // Restore context register. | 1195 // Restore context register. |
1196 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1196 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1197 Apply(expr->context(), eax); | 1197 Apply(context_, eax); |
1198 } | 1198 } |
1199 | 1199 |
1200 | 1200 |
1201 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1201 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
1202 // Code common for calls using the call stub. | 1202 // Code common for calls using the call stub. |
1203 ZoneList<Expression*>* args = expr->arguments(); | 1203 ZoneList<Expression*>* args = expr->arguments(); |
1204 int arg_count = args->length(); | 1204 int arg_count = args->length(); |
1205 for (int i = 0; i < arg_count; i++) { | 1205 for (int i = 0; i < arg_count; i++) { |
1206 VisitForValue(args->at(i), kStack); | 1206 VisitForValue(args->at(i), kStack); |
1207 } | 1207 } |
1208 // Record source position for debugger. | 1208 // Record source position for debugger. |
1209 SetSourcePosition(expr->position()); | 1209 SetSourcePosition(expr->position()); |
1210 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1210 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
1211 __ CallStub(&stub); | 1211 __ CallStub(&stub); |
1212 // Restore context register. | 1212 // Restore context register. |
1213 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1213 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1214 DropAndApply(1, expr->context(), eax); | 1214 DropAndApply(1, context_, eax); |
1215 } | 1215 } |
1216 | 1216 |
1217 | 1217 |
1218 void FastCodeGenerator::VisitCall(Call* expr) { | 1218 void FastCodeGenerator::VisitCall(Call* expr) { |
1219 Comment cmnt(masm_, "[ Call"); | 1219 Comment cmnt(masm_, "[ Call"); |
1220 Expression* fun = expr->expression(); | 1220 Expression* fun = expr->expression(); |
1221 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1221 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1222 | 1222 |
1223 if (var != NULL && var->is_possibly_eval()) { | 1223 if (var != NULL && var->is_possibly_eval()) { |
1224 // Call to the identifier 'eval'. | 1224 // Call to the identifier 'eval'. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 | 1310 |
1311 // Load function, arg_count into edi and eax. | 1311 // Load function, arg_count into edi and eax. |
1312 __ Set(eax, Immediate(arg_count)); | 1312 __ Set(eax, Immediate(arg_count)); |
1313 // Function is in esp[arg_count + 1]. | 1313 // Function is in esp[arg_count + 1]. |
1314 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1314 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1315 | 1315 |
1316 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1316 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1317 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1317 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1318 | 1318 |
1319 // Replace function on TOS with result in eax, or pop it. | 1319 // Replace function on TOS with result in eax, or pop it. |
1320 DropAndApply(1, expr->context(), eax); | 1320 DropAndApply(1, context_, eax); |
1321 } | 1321 } |
1322 | 1322 |
1323 | 1323 |
1324 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1324 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1325 Comment cmnt(masm_, "[ CallRuntime"); | 1325 Comment cmnt(masm_, "[ CallRuntime"); |
1326 ZoneList<Expression*>* args = expr->arguments(); | 1326 ZoneList<Expression*>* args = expr->arguments(); |
1327 | 1327 |
1328 if (expr->is_jsruntime()) { | 1328 if (expr->is_jsruntime()) { |
1329 // Prepare for calling JS runtime function. | 1329 // Prepare for calling JS runtime function. |
1330 __ mov(eax, CodeGenerator::GlobalObject()); | 1330 __ mov(eax, CodeGenerator::GlobalObject()); |
(...skipping 11 matching lines...) Expand all Loading... |
1342 __ Set(ecx, Immediate(expr->name())); | 1342 __ Set(ecx, Immediate(expr->name())); |
1343 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1343 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1344 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1344 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1345 __ call(ic, RelocInfo::CODE_TARGET); | 1345 __ call(ic, RelocInfo::CODE_TARGET); |
1346 // Restore context register. | 1346 // Restore context register. |
1347 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1347 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1348 } else { | 1348 } else { |
1349 // Call the C runtime function. | 1349 // Call the C runtime function. |
1350 __ CallRuntime(expr->function(), arg_count); | 1350 __ CallRuntime(expr->function(), arg_count); |
1351 } | 1351 } |
1352 Apply(expr->context(), eax); | 1352 Apply(context_, eax); |
1353 } | 1353 } |
1354 | 1354 |
1355 | 1355 |
1356 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1356 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1357 switch (expr->op()) { | 1357 switch (expr->op()) { |
1358 case Token::VOID: { | 1358 case Token::VOID: { |
1359 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1359 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1360 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1360 VisitForEffect(expr->expression()); |
1361 Visit(expr->expression()); | 1361 switch (context_) { |
1362 switch (expr->context()) { | |
1363 case Expression::kUninitialized: | 1362 case Expression::kUninitialized: |
1364 UNREACHABLE(); | 1363 UNREACHABLE(); |
1365 break; | 1364 break; |
1366 case Expression::kEffect: | 1365 case Expression::kEffect: |
1367 break; | 1366 break; |
1368 case Expression::kValue: | 1367 case Expression::kValue: |
1369 switch (location_) { | 1368 switch (location_) { |
1370 case kAccumulator: | 1369 case kAccumulator: |
1371 __ mov(result_register(), Factory::undefined_value()); | 1370 __ mov(result_register(), Factory::undefined_value()); |
1372 break; | 1371 break; |
(...skipping 16 matching lines...) Expand all Loading... |
1389 case Expression::kTest: | 1388 case Expression::kTest: |
1390 case Expression::kValueTest: | 1389 case Expression::kValueTest: |
1391 __ jmp(false_label_); | 1390 __ jmp(false_label_); |
1392 break; | 1391 break; |
1393 } | 1392 } |
1394 break; | 1393 break; |
1395 } | 1394 } |
1396 | 1395 |
1397 case Token::NOT: { | 1396 case Token::NOT: { |
1398 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 1397 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
1399 ASSERT_EQ(Expression::kTest, expr->expression()->context()); | |
1400 | |
1401 Label materialize_true, materialize_false, done; | 1398 Label materialize_true, materialize_false, done; |
1402 // Initially assume a pure test context. Notice that the labels are | 1399 // Initially assume a pure test context. Notice that the labels are |
1403 // swapped. | 1400 // swapped. |
1404 Label* if_true = false_label_; | 1401 Label* if_true = false_label_; |
1405 Label* if_false = true_label_; | 1402 Label* if_false = true_label_; |
1406 switch (expr->context()) { | 1403 switch (context_) { |
1407 case Expression::kUninitialized: | 1404 case Expression::kUninitialized: |
1408 UNREACHABLE(); | 1405 UNREACHABLE(); |
1409 break; | 1406 break; |
1410 case Expression::kEffect: | 1407 case Expression::kEffect: |
1411 if_true = &done; | 1408 if_true = &done; |
1412 if_false = &done; | 1409 if_false = &done; |
1413 break; | 1410 break; |
1414 case Expression::kValue: | 1411 case Expression::kValue: |
1415 if_true = &materialize_false; | 1412 if_true = &materialize_false; |
1416 if_false = &materialize_true; | 1413 if_false = &materialize_true; |
1417 break; | 1414 break; |
1418 case Expression::kTest: | 1415 case Expression::kTest: |
1419 break; | 1416 break; |
1420 case Expression::kValueTest: | 1417 case Expression::kValueTest: |
1421 if_false = &materialize_true; | 1418 if_false = &materialize_true; |
1422 break; | 1419 break; |
1423 case Expression::kTestValue: | 1420 case Expression::kTestValue: |
1424 if_true = &materialize_false; | 1421 if_true = &materialize_false; |
1425 break; | 1422 break; |
1426 } | 1423 } |
1427 VisitForControl(expr->expression(), if_true, if_false); | 1424 VisitForControl(expr->expression(), if_true, if_false); |
1428 Apply(expr->context(), if_false, if_true); // Labels swapped. | 1425 Apply(context_, if_false, if_true); // Labels swapped. |
1429 break; | 1426 break; |
1430 } | 1427 } |
1431 | 1428 |
1432 case Token::TYPEOF: { | 1429 case Token::TYPEOF: { |
1433 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 1430 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
1434 ASSERT_EQ(Expression::kValue, expr->expression()->context()); | |
1435 | |
1436 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1431 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
1437 if (proxy != NULL && | 1432 if (proxy != NULL && |
1438 !proxy->var()->is_this() && | 1433 !proxy->var()->is_this() && |
1439 proxy->var()->is_global()) { | 1434 proxy->var()->is_global()) { |
1440 Comment cmnt(masm_, "Global variable"); | 1435 Comment cmnt(masm_, "Global variable"); |
1441 __ push(CodeGenerator::GlobalObject()); | 1436 __ push(CodeGenerator::GlobalObject()); |
1442 __ mov(ecx, Immediate(proxy->name())); | 1437 __ mov(ecx, Immediate(proxy->name())); |
1443 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1438 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1444 // Use a regular load, not a contextual load, to avoid a reference | 1439 // Use a regular load, not a contextual load, to avoid a reference |
1445 // error. | 1440 // error. |
1446 __ call(ic, RelocInfo::CODE_TARGET); | 1441 __ call(ic, RelocInfo::CODE_TARGET); |
1447 __ mov(Operand(esp, 0), eax); | 1442 __ mov(Operand(esp, 0), eax); |
1448 } else if (proxy != NULL && | 1443 } else if (proxy != NULL && |
1449 proxy->var()->slot() != NULL && | 1444 proxy->var()->slot() != NULL && |
1450 proxy->var()->slot()->type() == Slot::LOOKUP) { | 1445 proxy->var()->slot()->type() == Slot::LOOKUP) { |
1451 __ push(esi); | 1446 __ push(esi); |
1452 __ push(Immediate(proxy->name())); | 1447 __ push(Immediate(proxy->name())); |
1453 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1448 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
1454 __ push(eax); | 1449 __ push(eax); |
1455 } else { | 1450 } else { |
1456 // This expression cannot throw a reference error at the top level. | 1451 // This expression cannot throw a reference error at the top level. |
1457 VisitForValue(expr->expression(), kStack); | 1452 VisitForValue(expr->expression(), kStack); |
1458 } | 1453 } |
1459 | 1454 |
1460 __ CallRuntime(Runtime::kTypeof, 1); | 1455 __ CallRuntime(Runtime::kTypeof, 1); |
1461 Apply(expr->context(), eax); | 1456 Apply(context_, eax); |
1462 break; | 1457 break; |
1463 } | 1458 } |
1464 | 1459 |
1465 default: | 1460 default: |
1466 UNREACHABLE(); | 1461 UNREACHABLE(); |
1467 } | 1462 } |
1468 } | 1463 } |
1469 | 1464 |
1470 | 1465 |
1471 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1466 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1472 Comment cmnt(masm_, "[ CountOperation"); | 1467 Comment cmnt(masm_, "[ CountOperation"); |
1473 | 1468 |
1474 // Expression can only be a property, a global or a (parameter or local) | 1469 // Expression can only be a property, a global or a (parameter or local) |
1475 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1470 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1476 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1471 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1477 LhsKind assign_type = VARIABLE; | 1472 LhsKind assign_type = VARIABLE; |
1478 Property* prop = expr->expression()->AsProperty(); | 1473 Property* prop = expr->expression()->AsProperty(); |
1479 // In case of a property we use the uninitialized expression context | 1474 // In case of a property we use the uninitialized expression context |
1480 // of the key to detect a named property. | 1475 // of the key to detect a named property. |
1481 if (prop != NULL) { | 1476 if (prop != NULL) { |
1482 assign_type = (prop->key()->context() == Expression::kUninitialized) | 1477 assign_type = |
1483 ? NAMED_PROPERTY | 1478 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
1484 : KEYED_PROPERTY; | |
1485 } | 1479 } |
1486 | 1480 |
1487 // Evaluate expression and get value. | 1481 // Evaluate expression and get value. |
1488 if (assign_type == VARIABLE) { | 1482 if (assign_type == VARIABLE) { |
1489 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 1483 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
1490 Location saved_location = location_; | 1484 Location saved_location = location_; |
1491 location_ = kStack; | 1485 location_ = kStack; |
1492 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), | 1486 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), |
1493 Expression::kValue); | 1487 Expression::kValue); |
1494 location_ = saved_location; | 1488 location_ = saved_location; |
1495 } else { | 1489 } else { |
1496 // Reserve space for result of postfix operation. | 1490 // Reserve space for result of postfix operation. |
1497 if (expr->is_postfix() && expr->context() != Expression::kEffect) { | 1491 if (expr->is_postfix() && context_ != Expression::kEffect) { |
1498 ASSERT(expr->context() != Expression::kUninitialized); | |
1499 __ push(Immediate(Smi::FromInt(0))); | 1492 __ push(Immediate(Smi::FromInt(0))); |
1500 } | 1493 } |
1501 VisitForValue(prop->obj(), kStack); | 1494 VisitForValue(prop->obj(), kStack); |
1502 if (assign_type == NAMED_PROPERTY) { | 1495 if (assign_type == NAMED_PROPERTY) { |
1503 EmitNamedPropertyLoad(prop); | 1496 EmitNamedPropertyLoad(prop); |
1504 } else { | 1497 } else { |
1505 VisitForValue(prop->key(), kStack); | 1498 VisitForValue(prop->key(), kStack); |
1506 EmitKeyedPropertyLoad(prop); | 1499 EmitKeyedPropertyLoad(prop); |
1507 } | 1500 } |
1508 __ push(eax); | 1501 __ push(eax); |
1509 } | 1502 } |
1510 | 1503 |
1511 // Convert to number. | 1504 // Convert to number. |
1512 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 1505 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
1513 | 1506 |
1514 // Save result for postfix expressions. | 1507 // Save result for postfix expressions. |
1515 if (expr->is_postfix()) { | 1508 if (expr->is_postfix()) { |
1516 switch (expr->context()) { | 1509 switch (context_) { |
1517 case Expression::kUninitialized: | 1510 case Expression::kUninitialized: |
1518 UNREACHABLE(); | 1511 UNREACHABLE(); |
1519 case Expression::kEffect: | 1512 case Expression::kEffect: |
1520 // Do not save result. | 1513 // Do not save result. |
1521 break; | 1514 break; |
1522 case Expression::kValue: | 1515 case Expression::kValue: |
1523 case Expression::kTest: | 1516 case Expression::kTest: |
1524 case Expression::kValueTest: | 1517 case Expression::kValueTest: |
1525 case Expression::kTestValue: | 1518 case Expression::kTestValue: |
1526 // Save the result on the stack. If we have a named or keyed property | 1519 // Save the result on the stack. If we have a named or keyed property |
(...skipping 23 matching lines...) Expand all Loading... |
1550 __ CallStub(&stub); | 1543 __ CallStub(&stub); |
1551 | 1544 |
1552 // Store the value returned in eax. | 1545 // Store the value returned in eax. |
1553 switch (assign_type) { | 1546 switch (assign_type) { |
1554 case VARIABLE: | 1547 case VARIABLE: |
1555 if (expr->is_postfix()) { | 1548 if (expr->is_postfix()) { |
1556 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1549 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1557 Expression::kEffect); | 1550 Expression::kEffect); |
1558 // For all contexts except kEffect: We have the result on | 1551 // For all contexts except kEffect: We have the result on |
1559 // top of the stack. | 1552 // top of the stack. |
1560 if (expr->context() != Expression::kEffect) { | 1553 if (context_ != Expression::kEffect) { |
1561 ApplyTOS(expr->context()); | 1554 ApplyTOS(context_); |
1562 } | 1555 } |
1563 } else { | 1556 } else { |
1564 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1557 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1565 expr->context()); | 1558 context_); |
1566 } | 1559 } |
1567 break; | 1560 break; |
1568 case NAMED_PROPERTY: { | 1561 case NAMED_PROPERTY: { |
1569 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1562 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1570 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1563 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1571 __ call(ic, RelocInfo::CODE_TARGET); | 1564 __ call(ic, RelocInfo::CODE_TARGET); |
1572 // This nop signals to the IC that there is no inlined code at the call | 1565 // This nop signals to the IC that there is no inlined code at the call |
1573 // site for it to patch. | 1566 // site for it to patch. |
1574 __ nop(); | 1567 __ nop(); |
1575 if (expr->is_postfix()) { | 1568 if (expr->is_postfix()) { |
1576 __ Drop(1); // Result is on the stack under the receiver. | 1569 __ Drop(1); // Result is on the stack under the receiver. |
1577 if (expr->context() != Expression::kEffect) { | 1570 if (context_ != Expression::kEffect) { |
1578 ApplyTOS(expr->context()); | 1571 ApplyTOS(context_); |
1579 } | 1572 } |
1580 } else { | 1573 } else { |
1581 DropAndApply(1, expr->context(), eax); | 1574 DropAndApply(1, context_, eax); |
1582 } | 1575 } |
1583 break; | 1576 break; |
1584 } | 1577 } |
1585 case KEYED_PROPERTY: { | 1578 case KEYED_PROPERTY: { |
1586 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1579 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1587 __ call(ic, RelocInfo::CODE_TARGET); | 1580 __ call(ic, RelocInfo::CODE_TARGET); |
1588 // This nop signals to the IC that there is no inlined code at the call | 1581 // This nop signals to the IC that there is no inlined code at the call |
1589 // site for it to patch. | 1582 // site for it to patch. |
1590 __ nop(); | 1583 __ nop(); |
1591 if (expr->is_postfix()) { | 1584 if (expr->is_postfix()) { |
1592 __ Drop(2); // Result is on the stack under the key and the receiver. | 1585 __ Drop(2); // Result is on the stack under the key and the receiver. |
1593 if (expr->context() != Expression::kEffect) { | 1586 if (context_ != Expression::kEffect) { |
1594 ApplyTOS(expr->context()); | 1587 ApplyTOS(context_); |
1595 } | 1588 } |
1596 } else { | 1589 } else { |
1597 DropAndApply(2, expr->context(), eax); | 1590 DropAndApply(2, context_, eax); |
1598 } | 1591 } |
1599 break; | 1592 break; |
1600 } | 1593 } |
1601 } | 1594 } |
1602 } | 1595 } |
1603 | 1596 |
1604 | 1597 |
1605 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1598 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1606 Comment cmnt(masm_, "[ BinaryOperation"); | 1599 Comment cmnt(masm_, "[ BinaryOperation"); |
1607 switch (expr->op()) { | 1600 switch (expr->op()) { |
1608 case Token::COMMA: | 1601 case Token::COMMA: |
1609 ASSERT_EQ(Expression::kEffect, expr->left()->context()); | 1602 VisitForEffect(expr->left()); |
1610 ASSERT_EQ(expr->context(), expr->right()->context()); | |
1611 Visit(expr->left()); | |
1612 Visit(expr->right()); | 1603 Visit(expr->right()); |
1613 break; | 1604 break; |
1614 | 1605 |
1615 case Token::OR: | 1606 case Token::OR: |
1616 case Token::AND: | 1607 case Token::AND: |
1617 EmitLogicalOperation(expr); | 1608 EmitLogicalOperation(expr); |
1618 break; | 1609 break; |
1619 | 1610 |
1620 case Token::ADD: | 1611 case Token::ADD: |
1621 case Token::SUB: | 1612 case Token::SUB: |
1622 case Token::DIV: | 1613 case Token::DIV: |
1623 case Token::MOD: | 1614 case Token::MOD: |
1624 case Token::MUL: | 1615 case Token::MUL: |
1625 case Token::BIT_OR: | 1616 case Token::BIT_OR: |
1626 case Token::BIT_AND: | 1617 case Token::BIT_AND: |
1627 case Token::BIT_XOR: | 1618 case Token::BIT_XOR: |
1628 case Token::SHL: | 1619 case Token::SHL: |
1629 case Token::SHR: | 1620 case Token::SHR: |
1630 case Token::SAR: | 1621 case Token::SAR: |
1631 VisitForValue(expr->left(), kStack); | 1622 VisitForValue(expr->left(), kStack); |
1632 VisitForValue(expr->right(), kAccumulator); | 1623 VisitForValue(expr->right(), kAccumulator); |
1633 EmitBinaryOp(expr->op(), expr->context()); | 1624 EmitBinaryOp(expr->op(), context_); |
1634 break; | 1625 break; |
1635 | 1626 |
1636 default: | 1627 default: |
1637 UNREACHABLE(); | 1628 UNREACHABLE(); |
1638 } | 1629 } |
1639 } | 1630 } |
1640 | 1631 |
1641 | 1632 |
1642 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1633 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1643 Comment cmnt(masm_, "[ CompareOperation"); | 1634 Comment cmnt(masm_, "[ CompareOperation"); |
1644 | 1635 |
1645 // Always perform the comparison for its control flow. Pack the result | 1636 // Always perform the comparison for its control flow. Pack the result |
1646 // into the expression's context after the comparison is performed. | 1637 // into the expression's context after the comparison is performed. |
1647 Label materialize_true, materialize_false, done; | 1638 Label materialize_true, materialize_false, done; |
1648 // Initially assume we are in a test context. | 1639 // Initially assume we are in a test context. |
1649 Label* if_true = true_label_; | 1640 Label* if_true = true_label_; |
1650 Label* if_false = false_label_; | 1641 Label* if_false = false_label_; |
1651 switch (expr->context()) { | 1642 switch (context_) { |
1652 case Expression::kUninitialized: | 1643 case Expression::kUninitialized: |
1653 UNREACHABLE(); | 1644 UNREACHABLE(); |
1654 break; | 1645 break; |
1655 case Expression::kEffect: | 1646 case Expression::kEffect: |
1656 if_true = &done; | 1647 if_true = &done; |
1657 if_false = &done; | 1648 if_false = &done; |
1658 break; | 1649 break; |
1659 case Expression::kValue: | 1650 case Expression::kValue: |
1660 if_true = &materialize_true; | 1651 if_true = &materialize_true; |
1661 if_false = &materialize_false; | 1652 if_false = &materialize_false; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1743 CompareStub stub(cc, strict); | 1734 CompareStub stub(cc, strict); |
1744 __ CallStub(&stub); | 1735 __ CallStub(&stub); |
1745 __ test(eax, Operand(eax)); | 1736 __ test(eax, Operand(eax)); |
1746 __ j(cc, if_true); | 1737 __ j(cc, if_true); |
1747 __ jmp(if_false); | 1738 __ jmp(if_false); |
1748 } | 1739 } |
1749 } | 1740 } |
1750 | 1741 |
1751 // Convert the result of the comparison into one expected for this | 1742 // Convert the result of the comparison into one expected for this |
1752 // expression's context. | 1743 // expression's context. |
1753 Apply(expr->context(), if_true, if_false); | 1744 Apply(context_, if_true, if_false); |
1754 } | 1745 } |
1755 | 1746 |
1756 | 1747 |
1757 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1748 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1758 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1749 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1759 Apply(expr->context(), eax); | 1750 Apply(context_, eax); |
1760 } | 1751 } |
1761 | 1752 |
1762 | 1753 |
1763 Register FastCodeGenerator::result_register() { return eax; } | 1754 Register FastCodeGenerator::result_register() { return eax; } |
1764 | 1755 |
1765 | 1756 |
1766 Register FastCodeGenerator::context_register() { return esi; } | 1757 Register FastCodeGenerator::context_register() { return esi; } |
1767 | 1758 |
1768 | 1759 |
1769 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1760 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1804 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1795 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
1805 __ mov(Operand(esp, 0), edx); | 1796 __ mov(Operand(esp, 0), edx); |
1806 // And return. | 1797 // And return. |
1807 __ ret(0); | 1798 __ ret(0); |
1808 } | 1799 } |
1809 | 1800 |
1810 | 1801 |
1811 #undef __ | 1802 #undef __ |
1812 | 1803 |
1813 } } // namespace v8::internal | 1804 } } // namespace v8::internal |
OLD | NEW |