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 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 Handle<JSFunction> boilerplate = | 655 Handle<JSFunction> boilerplate = |
656 Compiler::BuildBoilerplate(expr, script_, this); | 656 Compiler::BuildBoilerplate(expr, script_, this); |
657 if (HasStackOverflow()) return; | 657 if (HasStackOverflow()) return; |
658 | 658 |
659 ASSERT(boilerplate->IsBoilerplate()); | 659 ASSERT(boilerplate->IsBoilerplate()); |
660 | 660 |
661 // Create a new closure. | 661 // Create a new closure. |
662 __ mov(r0, Operand(boilerplate)); | 662 __ mov(r0, Operand(boilerplate)); |
663 __ stm(db_w, sp, cp.bit() | r0.bit()); | 663 __ stm(db_w, sp, cp.bit() | r0.bit()); |
664 __ CallRuntime(Runtime::kNewClosure, 2); | 664 __ CallRuntime(Runtime::kNewClosure, 2); |
665 Apply(expr->context(), r0); | 665 Apply(context_, r0); |
666 } | 666 } |
667 | 667 |
668 | 668 |
669 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 669 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
670 Comment cmnt(masm_, "[ VariableProxy"); | 670 Comment cmnt(masm_, "[ VariableProxy"); |
671 EmitVariableLoad(expr->var(), expr->context()); | 671 EmitVariableLoad(expr->var(), context_); |
672 } | 672 } |
673 | 673 |
674 | 674 |
675 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 675 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
676 Expression::Context context) { | 676 Expression::Context context) { |
677 Expression* rewrite = var->rewrite(); | 677 Expression* rewrite = var->rewrite(); |
678 if (rewrite == NULL) { | 678 if (rewrite == NULL) { |
679 ASSERT(var->is_global()); | 679 ASSERT(var->is_global()); |
680 Comment cmnt(masm_, "Global variable"); | 680 Comment cmnt(masm_, "Global variable"); |
681 // Use inline caching. Variable name is passed in r2 and the global | 681 // Use inline caching. Variable name is passed in r2 and the global |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 761 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
762 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 762 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
763 __ cmp(r0, ip); | 763 __ cmp(r0, ip); |
764 __ b(ne, &done); | 764 __ b(ne, &done); |
765 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 765 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
766 __ mov(r2, Operand(expr->pattern())); | 766 __ mov(r2, Operand(expr->pattern())); |
767 __ mov(r1, Operand(expr->flags())); | 767 __ mov(r1, Operand(expr->flags())); |
768 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 768 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
769 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 769 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
770 __ bind(&done); | 770 __ bind(&done); |
771 Apply(expr->context(), r0); | 771 Apply(context_, r0); |
772 } | 772 } |
773 | 773 |
774 | 774 |
775 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 775 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
776 Comment cmnt(masm_, "[ ObjectLiteral"); | 776 Comment cmnt(masm_, "[ ObjectLiteral"); |
777 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 777 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); | 779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); |
780 __ mov(r0, Operand(expr->constant_properties())); | 780 __ mov(r0, Operand(expr->constant_properties())); |
781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); | 781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 Smi::FromInt(1) : | 833 Smi::FromInt(1) : |
834 Smi::FromInt(0))); | 834 Smi::FromInt(0))); |
835 __ push(r1); | 835 __ push(r1); |
836 VisitForValue(value, kStack); | 836 VisitForValue(value, kStack); |
837 __ CallRuntime(Runtime::kDefineAccessor, 4); | 837 __ CallRuntime(Runtime::kDefineAccessor, 4); |
838 break; | 838 break; |
839 } | 839 } |
840 } | 840 } |
841 | 841 |
842 if (result_saved) { | 842 if (result_saved) { |
843 ApplyTOS(expr->context()); | 843 ApplyTOS(context_); |
844 } else { | 844 } else { |
845 Apply(expr->context(), r0); | 845 Apply(context_, r0); |
846 } | 846 } |
847 } | 847 } |
848 | 848 |
849 | 849 |
850 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 850 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
851 Comment cmnt(masm_, "[ ArrayLiteral"); | 851 Comment cmnt(masm_, "[ ArrayLiteral"); |
852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
855 __ mov(r1, Operand(expr->constant_elements())); | 855 __ mov(r1, Operand(expr->constant_elements())); |
(...skipping 30 matching lines...) Expand all Loading... |
886 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 886 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
887 __ str(result_register(), FieldMemOperand(r1, offset)); | 887 __ str(result_register(), FieldMemOperand(r1, offset)); |
888 | 888 |
889 // Update the write barrier for the array store with r0 as the scratch | 889 // Update the write barrier for the array store with r0 as the scratch |
890 // register. | 890 // register. |
891 __ mov(r2, Operand(offset)); | 891 __ mov(r2, Operand(offset)); |
892 __ RecordWrite(r1, r2, result_register()); | 892 __ RecordWrite(r1, r2, result_register()); |
893 } | 893 } |
894 | 894 |
895 if (result_saved) { | 895 if (result_saved) { |
896 ApplyTOS(expr->context()); | 896 ApplyTOS(context_); |
897 } else { | 897 } else { |
898 Apply(expr->context(), r0); | 898 Apply(context_, r0); |
899 } | 899 } |
900 } | 900 } |
901 | 901 |
902 | 902 |
903 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 903 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
904 SetSourcePosition(prop->position()); | 904 SetSourcePosition(prop->position()); |
905 Literal* key = prop->key()->AsLiteral(); | 905 Literal* key = prop->key()->AsLiteral(); |
906 __ mov(r2, Operand(key->handle())); | 906 __ mov(r2, Operand(key->handle())); |
907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
908 __ Call(ic, RelocInfo::CODE_TARGET); | 908 __ Call(ic, RelocInfo::CODE_TARGET); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 | 1000 |
1001 // If the assignment ends an initialization block, revert to fast case. | 1001 // If the assignment ends an initialization block, revert to fast case. |
1002 if (expr->ends_initialization_block()) { | 1002 if (expr->ends_initialization_block()) { |
1003 __ push(r0); // Result of assignment, saved even if not needed. | 1003 __ push(r0); // Result of assignment, saved even if not needed. |
1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. |
1005 __ push(ip); | 1005 __ push(ip); |
1006 __ CallRuntime(Runtime::kToFastProperties, 1); | 1006 __ CallRuntime(Runtime::kToFastProperties, 1); |
1007 __ pop(r0); | 1007 __ pop(r0); |
1008 } | 1008 } |
1009 | 1009 |
1010 DropAndApply(1, expr->context(), r0); | 1010 DropAndApply(1, context_, r0); |
1011 } | 1011 } |
1012 | 1012 |
1013 | 1013 |
1014 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1014 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1015 // Assignment to a property, using a keyed store IC. | 1015 // Assignment to a property, using a keyed store IC. |
1016 | 1016 |
1017 // If the assignment starts a block of assignments to the same object, | 1017 // If the assignment starts a block of assignments to the same object, |
1018 // change to slow case to avoid the quadratic behavior of repeatedly | 1018 // change to slow case to avoid the quadratic behavior of repeatedly |
1019 // adding fast properties. | 1019 // adding fast properties. |
1020 if (expr->starts_initialization_block()) { | 1020 if (expr->starts_initialization_block()) { |
(...skipping 14 matching lines...) Expand all Loading... |
1035 if (expr->ends_initialization_block()) { | 1035 if (expr->ends_initialization_block()) { |
1036 __ push(r0); // Result of assignment, saved even if not needed. | 1036 __ push(r0); // Result of assignment, saved even if not needed. |
1037 // Receiver is under the key and value. | 1037 // Receiver is under the key and value. |
1038 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1038 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
1039 __ push(ip); | 1039 __ push(ip); |
1040 __ CallRuntime(Runtime::kToFastProperties, 1); | 1040 __ CallRuntime(Runtime::kToFastProperties, 1); |
1041 __ pop(r0); | 1041 __ pop(r0); |
1042 } | 1042 } |
1043 | 1043 |
1044 // Receiver and key are still on stack. | 1044 // Receiver and key are still on stack. |
1045 DropAndApply(2, expr->context(), r0); | 1045 DropAndApply(2, context_, r0); |
1046 } | 1046 } |
1047 | 1047 |
1048 | 1048 |
1049 void FastCodeGenerator::VisitProperty(Property* expr) { | 1049 void FastCodeGenerator::VisitProperty(Property* expr) { |
1050 Comment cmnt(masm_, "[ Property"); | 1050 Comment cmnt(masm_, "[ Property"); |
1051 Expression* key = expr->key(); | 1051 Expression* key = expr->key(); |
1052 | 1052 |
1053 // Evaluate receiver. | 1053 // Evaluate receiver. |
1054 VisitForValue(expr->obj(), kStack); | 1054 VisitForValue(expr->obj(), kStack); |
1055 | 1055 |
1056 if (key->IsPropertyName()) { | 1056 if (key->IsPropertyName()) { |
1057 EmitNamedPropertyLoad(expr); | 1057 EmitNamedPropertyLoad(expr); |
1058 // Drop receiver left on the stack by IC. | 1058 // Drop receiver left on the stack by IC. |
1059 DropAndApply(1, expr->context(), r0); | 1059 DropAndApply(1, context_, r0); |
1060 } else { | 1060 } else { |
1061 VisitForValue(expr->key(), kStack); | 1061 VisitForValue(expr->key(), kStack); |
1062 EmitKeyedPropertyLoad(expr); | 1062 EmitKeyedPropertyLoad(expr); |
1063 // Drop key and receiver left on the stack by IC. | 1063 // Drop key and receiver left on the stack by IC. |
1064 DropAndApply(2, expr->context(), r0); | 1064 DropAndApply(2, context_, r0); |
1065 } | 1065 } |
1066 } | 1066 } |
1067 | 1067 |
1068 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1068 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
1069 Handle<Object> ignored, | 1069 Handle<Object> ignored, |
1070 RelocInfo::Mode mode) { | 1070 RelocInfo::Mode mode) { |
1071 // Code common for calls using the IC. | 1071 // Code common for calls using the IC. |
1072 ZoneList<Expression*>* args = expr->arguments(); | 1072 ZoneList<Expression*>* args = expr->arguments(); |
1073 int arg_count = args->length(); | 1073 int arg_count = args->length(); |
1074 for (int i = 0; i < arg_count; i++) { | 1074 for (int i = 0; i < arg_count; i++) { |
1075 VisitForValue(args->at(i), kStack); | 1075 VisitForValue(args->at(i), kStack); |
1076 } | 1076 } |
1077 // Record source position for debugger. | 1077 // Record source position for debugger. |
1078 SetSourcePosition(expr->position()); | 1078 SetSourcePosition(expr->position()); |
1079 // Call the IC initialization code. | 1079 // Call the IC initialization code. |
1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1081 NOT_IN_LOOP); | 1081 NOT_IN_LOOP); |
1082 __ Call(ic, mode); | 1082 __ Call(ic, mode); |
1083 // Restore context register. | 1083 // Restore context register. |
1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1085 // Discard the function left on TOS. | 1085 // Discard the function left on TOS. |
1086 DropAndApply(1, expr->context(), r0); | 1086 DropAndApply(1, context_, r0); |
1087 } | 1087 } |
1088 | 1088 |
1089 | 1089 |
1090 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1090 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
1091 // Code common for calls using the call stub. | 1091 // Code common for calls using the call stub. |
1092 ZoneList<Expression*>* args = expr->arguments(); | 1092 ZoneList<Expression*>* args = expr->arguments(); |
1093 int arg_count = args->length(); | 1093 int arg_count = args->length(); |
1094 for (int i = 0; i < arg_count; i++) { | 1094 for (int i = 0; i < arg_count; i++) { |
1095 VisitForValue(args->at(i), kStack); | 1095 VisitForValue(args->at(i), kStack); |
1096 } | 1096 } |
1097 // Record source position for debugger. | 1097 // Record source position for debugger. |
1098 SetSourcePosition(expr->position()); | 1098 SetSourcePosition(expr->position()); |
1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
1100 __ CallStub(&stub); | 1100 __ CallStub(&stub); |
1101 // Restore context register. | 1101 // Restore context register. |
1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1103 // Discard the function left on TOS. | 1103 // Discard the function left on TOS. |
1104 DropAndApply(1, expr->context(), r0); | 1104 DropAndApply(1, context_, r0); |
1105 } | 1105 } |
1106 | 1106 |
1107 | 1107 |
1108 void FastCodeGenerator::VisitCall(Call* expr) { | 1108 void FastCodeGenerator::VisitCall(Call* expr) { |
1109 Comment cmnt(masm_, "[ Call"); | 1109 Comment cmnt(masm_, "[ Call"); |
1110 Expression* fun = expr->expression(); | 1110 Expression* fun = expr->expression(); |
1111 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1111 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1112 | 1112 |
1113 if (var != NULL && var->is_possibly_eval()) { | 1113 if (var != NULL && var->is_possibly_eval()) { |
1114 // Call to the identifier 'eval'. | 1114 // Call to the identifier 'eval'. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 | 1200 |
1201 // Load function, arg_count into r1 and r0. | 1201 // Load function, arg_count into r1 and r0. |
1202 __ mov(r0, Operand(arg_count)); | 1202 __ mov(r0, Operand(arg_count)); |
1203 // Function is in sp[arg_count + 1]. | 1203 // Function is in sp[arg_count + 1]. |
1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
1205 | 1205 |
1206 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1206 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1207 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1207 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1208 | 1208 |
1209 // Replace function on TOS with result in r0, or pop it. | 1209 // Replace function on TOS with result in r0, or pop it. |
1210 DropAndApply(1, expr->context(), r0); | 1210 DropAndApply(1, context_, r0); |
1211 } | 1211 } |
1212 | 1212 |
1213 | 1213 |
1214 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1214 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1215 Comment cmnt(masm_, "[ CallRuntime"); | 1215 Comment cmnt(masm_, "[ CallRuntime"); |
1216 ZoneList<Expression*>* args = expr->arguments(); | 1216 ZoneList<Expression*>* args = expr->arguments(); |
1217 | 1217 |
1218 if (expr->is_jsruntime()) { | 1218 if (expr->is_jsruntime()) { |
1219 // Prepare for calling JS runtime function. | 1219 // Prepare for calling JS runtime function. |
1220 __ mov(r1, Operand(expr->name())); | 1220 __ mov(r1, Operand(expr->name())); |
1221 __ ldr(r0, CodeGenerator::GlobalObject()); | 1221 __ ldr(r0, CodeGenerator::GlobalObject()); |
1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); |
1223 __ stm(db_w, sp, r1.bit() | r0.bit()); | 1223 __ stm(db_w, sp, r1.bit() | r0.bit()); |
1224 } | 1224 } |
1225 | 1225 |
1226 // Push the arguments ("left-to-right"). | 1226 // Push the arguments ("left-to-right"). |
1227 int arg_count = args->length(); | 1227 int arg_count = args->length(); |
1228 for (int i = 0; i < arg_count; i++) { | 1228 for (int i = 0; i < arg_count; i++) { |
1229 VisitForValue(args->at(i), kStack); | 1229 VisitForValue(args->at(i), kStack); |
1230 } | 1230 } |
1231 | 1231 |
1232 if (expr->is_jsruntime()) { | 1232 if (expr->is_jsruntime()) { |
1233 // Call the JS runtime function. | 1233 // Call the JS runtime function. |
1234 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1234 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1235 NOT_IN_LOOP); | 1235 NOT_IN_LOOP); |
1236 __ Call(ic, RelocInfo::CODE_TARGET); | 1236 __ Call(ic, RelocInfo::CODE_TARGET); |
1237 // Restore context register. | 1237 // Restore context register. |
1238 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1238 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1239 // Discard the function left on TOS. | 1239 // Discard the function left on TOS. |
1240 DropAndApply(1, expr->context(), r0); | 1240 DropAndApply(1, context_, r0); |
1241 } else { | 1241 } else { |
1242 // Call the C runtime function. | 1242 // Call the C runtime function. |
1243 __ CallRuntime(expr->function(), arg_count); | 1243 __ CallRuntime(expr->function(), arg_count); |
1244 Apply(expr->context(), r0); | 1244 Apply(context_, r0); |
1245 } | 1245 } |
1246 } | 1246 } |
1247 | 1247 |
1248 | 1248 |
1249 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1249 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1250 switch (expr->op()) { | 1250 switch (expr->op()) { |
1251 case Token::VOID: { | 1251 case Token::VOID: { |
1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1253 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1253 VisitForEffect(expr->expression()); |
1254 Visit(expr->expression()); | 1254 switch (context_) { |
1255 switch (expr->context()) { | |
1256 case Expression::kUninitialized: | 1255 case Expression::kUninitialized: |
1257 UNREACHABLE(); | 1256 UNREACHABLE(); |
1258 break; | 1257 break; |
1259 case Expression::kEffect: | 1258 case Expression::kEffect: |
1260 break; | 1259 break; |
1261 case Expression::kValue: | 1260 case Expression::kValue: |
1262 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | 1261 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); |
1263 switch (location_) { | 1262 switch (location_) { |
1264 case kAccumulator: | 1263 case kAccumulator: |
1265 break; | 1264 break; |
(...skipping 16 matching lines...) Expand all Loading... |
1282 case Expression::kTest: | 1281 case Expression::kTest: |
1283 case Expression::kValueTest: | 1282 case Expression::kValueTest: |
1284 __ jmp(false_label_); | 1283 __ jmp(false_label_); |
1285 break; | 1284 break; |
1286 } | 1285 } |
1287 break; | 1286 break; |
1288 } | 1287 } |
1289 | 1288 |
1290 case Token::NOT: { | 1289 case Token::NOT: { |
1291 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 1290 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
1292 ASSERT_EQ(Expression::kTest, expr->expression()->context()); | |
1293 | |
1294 Label materialize_true, materialize_false, done; | 1291 Label materialize_true, materialize_false, done; |
1295 // Initially assume a pure test context. Notice that the labels are | 1292 // Initially assume a pure test context. Notice that the labels are |
1296 // swapped. | 1293 // swapped. |
1297 Label* if_true = false_label_; | 1294 Label* if_true = false_label_; |
1298 Label* if_false = true_label_; | 1295 Label* if_false = true_label_; |
1299 switch (expr->context()) { | 1296 switch (context_) { |
1300 case Expression::kUninitialized: | 1297 case Expression::kUninitialized: |
1301 UNREACHABLE(); | 1298 UNREACHABLE(); |
1302 break; | 1299 break; |
1303 case Expression::kEffect: | 1300 case Expression::kEffect: |
1304 if_true = &done; | 1301 if_true = &done; |
1305 if_false = &done; | 1302 if_false = &done; |
1306 break; | 1303 break; |
1307 case Expression::kValue: | 1304 case Expression::kValue: |
1308 if_true = &materialize_false; | 1305 if_true = &materialize_false; |
1309 if_false = &materialize_true; | 1306 if_false = &materialize_true; |
1310 break; | 1307 break; |
1311 case Expression::kTest: | 1308 case Expression::kTest: |
1312 break; | 1309 break; |
1313 case Expression::kValueTest: | 1310 case Expression::kValueTest: |
1314 if_false = &materialize_true; | 1311 if_false = &materialize_true; |
1315 break; | 1312 break; |
1316 case Expression::kTestValue: | 1313 case Expression::kTestValue: |
1317 if_true = &materialize_false; | 1314 if_true = &materialize_false; |
1318 break; | 1315 break; |
1319 } | 1316 } |
1320 VisitForControl(expr->expression(), if_true, if_false); | 1317 VisitForControl(expr->expression(), if_true, if_false); |
1321 Apply(expr->context(), if_false, if_true); // Labels swapped. | 1318 Apply(context_, if_false, if_true); // Labels swapped. |
1322 break; | 1319 break; |
1323 } | 1320 } |
1324 | 1321 |
1325 case Token::TYPEOF: { | 1322 case Token::TYPEOF: { |
1326 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 1323 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
1327 ASSERT_EQ(Expression::kValue, expr->expression()->context()); | |
1328 | |
1329 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1324 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
1330 if (proxy != NULL && | 1325 if (proxy != NULL && |
1331 !proxy->var()->is_this() && | 1326 !proxy->var()->is_this() && |
1332 proxy->var()->is_global()) { | 1327 proxy->var()->is_global()) { |
1333 Comment cmnt(masm_, "Global variable"); | 1328 Comment cmnt(masm_, "Global variable"); |
1334 __ ldr(r0, CodeGenerator::GlobalObject()); | 1329 __ ldr(r0, CodeGenerator::GlobalObject()); |
1335 __ push(r0); | 1330 __ push(r0); |
1336 __ mov(r2, Operand(proxy->name())); | 1331 __ mov(r2, Operand(proxy->name())); |
1337 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1332 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1338 // Use a regular load, not a contextual load, to avoid a reference | 1333 // Use a regular load, not a contextual load, to avoid a reference |
1339 // error. | 1334 // error. |
1340 __ Call(ic, RelocInfo::CODE_TARGET); | 1335 __ Call(ic, RelocInfo::CODE_TARGET); |
1341 __ str(r0, MemOperand(sp)); | 1336 __ str(r0, MemOperand(sp)); |
1342 } else if (proxy != NULL && | 1337 } else if (proxy != NULL && |
1343 proxy->var()->slot() != NULL && | 1338 proxy->var()->slot() != NULL && |
1344 proxy->var()->slot()->type() == Slot::LOOKUP) { | 1339 proxy->var()->slot()->type() == Slot::LOOKUP) { |
1345 __ mov(r0, Operand(proxy->name())); | 1340 __ mov(r0, Operand(proxy->name())); |
1346 __ stm(db_w, sp, cp.bit() | r0.bit()); | 1341 __ stm(db_w, sp, cp.bit() | r0.bit()); |
1347 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1342 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
1348 __ push(r0); | 1343 __ push(r0); |
1349 } else { | 1344 } else { |
1350 // This expression cannot throw a reference error at the top level. | 1345 // This expression cannot throw a reference error at the top level. |
1351 VisitForValue(expr->expression(), kStack); | 1346 VisitForValue(expr->expression(), kStack); |
1352 } | 1347 } |
1353 | 1348 |
1354 __ CallRuntime(Runtime::kTypeof, 1); | 1349 __ CallRuntime(Runtime::kTypeof, 1); |
1355 Apply(expr->context(), r0); | 1350 Apply(context_, r0); |
1356 break; | 1351 break; |
1357 } | 1352 } |
1358 | 1353 |
1359 default: | 1354 default: |
1360 UNREACHABLE(); | 1355 UNREACHABLE(); |
1361 } | 1356 } |
1362 } | 1357 } |
1363 | 1358 |
1364 | 1359 |
1365 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1360 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1366 Comment cmnt(masm_, "[ CountOperation"); | 1361 Comment cmnt(masm_, "[ CountOperation"); |
1367 | 1362 |
1368 // Expression can only be a property, a global or a (parameter or local) | 1363 // Expression can only be a property, a global or a (parameter or local) |
1369 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1364 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1370 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1365 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1371 LhsKind assign_type = VARIABLE; | 1366 LhsKind assign_type = VARIABLE; |
1372 Property* prop = expr->expression()->AsProperty(); | 1367 Property* prop = expr->expression()->AsProperty(); |
1373 // In case of a property we use the uninitialized expression context | 1368 // In case of a property we use the uninitialized expression context |
1374 // of the key to detect a named property. | 1369 // of the key to detect a named property. |
1375 if (prop != NULL) { | 1370 if (prop != NULL) { |
1376 assign_type = (prop->key()->context() == Expression::kUninitialized) | 1371 assign_type = |
1377 ? NAMED_PROPERTY | 1372 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
1378 : KEYED_PROPERTY; | |
1379 } | 1373 } |
1380 | 1374 |
1381 // Evaluate expression and get value. | 1375 // Evaluate expression and get value. |
1382 if (assign_type == VARIABLE) { | 1376 if (assign_type == VARIABLE) { |
1383 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 1377 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
1384 Location saved_location = location_; | 1378 Location saved_location = location_; |
1385 location_ = kStack; | 1379 location_ = kStack; |
1386 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), | 1380 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), |
1387 Expression::kValue); | 1381 Expression::kValue); |
1388 location_ = saved_location; | 1382 location_ = saved_location; |
1389 } else { | 1383 } else { |
1390 // Reserve space for result of postfix operation. | 1384 // Reserve space for result of postfix operation. |
1391 if (expr->is_postfix() && expr->context() != Expression::kEffect) { | 1385 if (expr->is_postfix() && context_ != Expression::kEffect) { |
1392 ASSERT(expr->context() != Expression::kUninitialized); | |
1393 __ mov(ip, Operand(Smi::FromInt(0))); | 1386 __ mov(ip, Operand(Smi::FromInt(0))); |
1394 __ push(ip); | 1387 __ push(ip); |
1395 } | 1388 } |
1396 VisitForValue(prop->obj(), kStack); | 1389 VisitForValue(prop->obj(), kStack); |
1397 if (assign_type == NAMED_PROPERTY) { | 1390 if (assign_type == NAMED_PROPERTY) { |
1398 EmitNamedPropertyLoad(prop); | 1391 EmitNamedPropertyLoad(prop); |
1399 } else { | 1392 } else { |
1400 VisitForValue(prop->key(), kStack); | 1393 VisitForValue(prop->key(), kStack); |
1401 EmitKeyedPropertyLoad(prop); | 1394 EmitKeyedPropertyLoad(prop); |
1402 } | 1395 } |
1403 __ push(r0); | 1396 __ push(r0); |
1404 } | 1397 } |
1405 | 1398 |
1406 // Convert to number. | 1399 // Convert to number. |
1407 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 1400 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); |
1408 | 1401 |
1409 // Save result for postfix expressions. | 1402 // Save result for postfix expressions. |
1410 if (expr->is_postfix()) { | 1403 if (expr->is_postfix()) { |
1411 switch (expr->context()) { | 1404 switch (context_) { |
1412 case Expression::kUninitialized: | 1405 case Expression::kUninitialized: |
1413 UNREACHABLE(); | 1406 UNREACHABLE(); |
1414 case Expression::kEffect: | 1407 case Expression::kEffect: |
1415 // Do not save result. | 1408 // Do not save result. |
1416 break; | 1409 break; |
1417 case Expression::kValue: | 1410 case Expression::kValue: |
1418 case Expression::kTest: | 1411 case Expression::kTest: |
1419 case Expression::kValueTest: | 1412 case Expression::kValueTest: |
1420 case Expression::kTestValue: | 1413 case Expression::kTestValue: |
1421 // Save the result on the stack. If we have a named or keyed property | 1414 // Save the result on the stack. If we have a named or keyed property |
(...skipping 22 matching lines...) Expand all Loading... |
1444 __ CallStub(&stub); | 1437 __ CallStub(&stub); |
1445 | 1438 |
1446 // Store the value returned in r0. | 1439 // Store the value returned in r0. |
1447 switch (assign_type) { | 1440 switch (assign_type) { |
1448 case VARIABLE: | 1441 case VARIABLE: |
1449 if (expr->is_postfix()) { | 1442 if (expr->is_postfix()) { |
1450 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1443 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1451 Expression::kEffect); | 1444 Expression::kEffect); |
1452 // For all contexts except kEffect: We have the result on | 1445 // For all contexts except kEffect: We have the result on |
1453 // top of the stack. | 1446 // top of the stack. |
1454 if (expr->context() != Expression::kEffect) { | 1447 if (context_ != Expression::kEffect) { |
1455 ApplyTOS(expr->context()); | 1448 ApplyTOS(context_); |
1456 } | 1449 } |
1457 } else { | 1450 } else { |
1458 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1451 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1459 expr->context()); | 1452 context_); |
1460 } | 1453 } |
1461 break; | 1454 break; |
1462 case NAMED_PROPERTY: { | 1455 case NAMED_PROPERTY: { |
1463 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1456 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
1464 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1457 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1465 __ Call(ic, RelocInfo::CODE_TARGET); | 1458 __ Call(ic, RelocInfo::CODE_TARGET); |
1466 if (expr->is_postfix()) { | 1459 if (expr->is_postfix()) { |
1467 __ Drop(1); // Result is on the stack under the receiver. | 1460 __ Drop(1); // Result is on the stack under the receiver. |
1468 if (expr->context() != Expression::kEffect) { | 1461 if (context_ != Expression::kEffect) { |
1469 ApplyTOS(expr->context()); | 1462 ApplyTOS(context_); |
1470 } | 1463 } |
1471 } else { | 1464 } else { |
1472 DropAndApply(1, expr->context(), r0); | 1465 DropAndApply(1, context_, r0); |
1473 } | 1466 } |
1474 break; | 1467 break; |
1475 } | 1468 } |
1476 case KEYED_PROPERTY: { | 1469 case KEYED_PROPERTY: { |
1477 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1470 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1478 __ Call(ic, RelocInfo::CODE_TARGET); | 1471 __ Call(ic, RelocInfo::CODE_TARGET); |
1479 if (expr->is_postfix()) { | 1472 if (expr->is_postfix()) { |
1480 __ Drop(2); // Result is on the stack under the key and the receiver. | 1473 __ Drop(2); // Result is on the stack under the key and the receiver. |
1481 if (expr->context() != Expression::kEffect) { | 1474 if (context_ != Expression::kEffect) { |
1482 ApplyTOS(expr->context()); | 1475 ApplyTOS(context_); |
1483 } | 1476 } |
1484 } else { | 1477 } else { |
1485 DropAndApply(2, expr->context(), r0); | 1478 DropAndApply(2, context_, r0); |
1486 } | 1479 } |
1487 break; | 1480 break; |
1488 } | 1481 } |
1489 } | 1482 } |
1490 } | 1483 } |
1491 | 1484 |
1492 | 1485 |
1493 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1486 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1494 Comment cmnt(masm_, "[ BinaryOperation"); | 1487 Comment cmnt(masm_, "[ BinaryOperation"); |
1495 switch (expr->op()) { | 1488 switch (expr->op()) { |
1496 case Token::COMMA: | 1489 case Token::COMMA: |
1497 ASSERT_EQ(Expression::kEffect, expr->left()->context()); | 1490 VisitForEffect(expr->left()); |
1498 ASSERT_EQ(expr->context(), expr->right()->context()); | |
1499 Visit(expr->left()); | |
1500 Visit(expr->right()); | 1491 Visit(expr->right()); |
1501 break; | 1492 break; |
1502 | 1493 |
1503 case Token::OR: | 1494 case Token::OR: |
1504 case Token::AND: | 1495 case Token::AND: |
1505 EmitLogicalOperation(expr); | 1496 EmitLogicalOperation(expr); |
1506 break; | 1497 break; |
1507 | 1498 |
1508 case Token::ADD: | 1499 case Token::ADD: |
1509 case Token::SUB: | 1500 case Token::SUB: |
1510 case Token::DIV: | 1501 case Token::DIV: |
1511 case Token::MOD: | 1502 case Token::MOD: |
1512 case Token::MUL: | 1503 case Token::MUL: |
1513 case Token::BIT_OR: | 1504 case Token::BIT_OR: |
1514 case Token::BIT_AND: | 1505 case Token::BIT_AND: |
1515 case Token::BIT_XOR: | 1506 case Token::BIT_XOR: |
1516 case Token::SHL: | 1507 case Token::SHL: |
1517 case Token::SHR: | 1508 case Token::SHR: |
1518 case Token::SAR: | 1509 case Token::SAR: |
1519 VisitForValue(expr->left(), kStack); | 1510 VisitForValue(expr->left(), kStack); |
1520 VisitForValue(expr->right(), kAccumulator); | 1511 VisitForValue(expr->right(), kAccumulator); |
1521 EmitBinaryOp(expr->op(), expr->context()); | 1512 EmitBinaryOp(expr->op(), context_); |
1522 break; | 1513 break; |
1523 | 1514 |
1524 default: | 1515 default: |
1525 UNREACHABLE(); | 1516 UNREACHABLE(); |
1526 } | 1517 } |
1527 } | 1518 } |
1528 | 1519 |
1529 | 1520 |
1530 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1521 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1531 Comment cmnt(masm_, "[ CompareOperation"); | 1522 Comment cmnt(masm_, "[ CompareOperation"); |
1532 | 1523 |
1533 // Always perform the comparison for its control flow. Pack the result | 1524 // Always perform the comparison for its control flow. Pack the result |
1534 // into the expression's context after the comparison is performed. | 1525 // into the expression's context after the comparison is performed. |
1535 Label materialize_true, materialize_false, done; | 1526 Label materialize_true, materialize_false, done; |
1536 // Initially assume we are in a test context. | 1527 // Initially assume we are in a test context. |
1537 Label* if_true = true_label_; | 1528 Label* if_true = true_label_; |
1538 Label* if_false = false_label_; | 1529 Label* if_false = false_label_; |
1539 switch (expr->context()) { | 1530 switch (context_) { |
1540 case Expression::kUninitialized: | 1531 case Expression::kUninitialized: |
1541 UNREACHABLE(); | 1532 UNREACHABLE(); |
1542 break; | 1533 break; |
1543 case Expression::kEffect: | 1534 case Expression::kEffect: |
1544 if_true = &done; | 1535 if_true = &done; |
1545 if_false = &done; | 1536 if_false = &done; |
1546 break; | 1537 break; |
1547 case Expression::kValue: | 1538 case Expression::kValue: |
1548 if_true = &materialize_true; | 1539 if_true = &materialize_true; |
1549 if_false = &materialize_false; | 1540 if_false = &materialize_false; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 CompareStub stub(cc, strict); | 1622 CompareStub stub(cc, strict); |
1632 __ CallStub(&stub); | 1623 __ CallStub(&stub); |
1633 __ cmp(r0, Operand(0)); | 1624 __ cmp(r0, Operand(0)); |
1634 __ b(cc, if_true); | 1625 __ b(cc, if_true); |
1635 __ jmp(if_false); | 1626 __ jmp(if_false); |
1636 } | 1627 } |
1637 } | 1628 } |
1638 | 1629 |
1639 // Convert the result of the comparison into one expected for this | 1630 // Convert the result of the comparison into one expected for this |
1640 // expression's context. | 1631 // expression's context. |
1641 Apply(expr->context(), if_true, if_false); | 1632 Apply(context_, if_true, if_false); |
1642 } | 1633 } |
1643 | 1634 |
1644 | 1635 |
1645 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1636 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1646 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1637 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1647 Apply(expr->context(), r0); | 1638 Apply(context_, r0); |
1648 } | 1639 } |
1649 | 1640 |
1650 | 1641 |
1651 Register FastCodeGenerator::result_register() { return r0; } | 1642 Register FastCodeGenerator::result_register() { return r0; } |
1652 | 1643 |
1653 | 1644 |
1654 Register FastCodeGenerator::context_register() { return cp; } | 1645 Register FastCodeGenerator::context_register() { return cp; } |
1655 | 1646 |
1656 | 1647 |
1657 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1648 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1689 __ pop(result_register()); | 1680 __ pop(result_register()); |
1690 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1681 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
1691 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1682 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
1692 __ add(pc, r1, Operand(masm_->CodeObject())); | 1683 __ add(pc, r1, Operand(masm_->CodeObject())); |
1693 } | 1684 } |
1694 | 1685 |
1695 | 1686 |
1696 #undef __ | 1687 #undef __ |
1697 | 1688 |
1698 } } // namespace v8::internal | 1689 } } // namespace v8::internal |
OLD | NEW |