| 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 14 matching lines...) Expand all Loading... |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
| 31 #include "compiler.h" | 31 #include "compiler.h" |
| 32 #include "full-codegen.h" | 32 #include "full-codegen.h" |
| 33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
| 34 #include "debug.h" | 34 #include "debug.h" |
| 35 #include "liveedit.h" |
| 35 | 36 |
| 36 namespace v8 { | 37 namespace v8 { |
| 37 namespace internal { | 38 namespace internal { |
| 38 | 39 |
| 39 #define BAILOUT(reason) \ | 40 #define BAILOUT(reason) \ |
| 40 do { \ | 41 do { \ |
| 41 if (FLAG_trace_bailout) { \ | 42 if (FLAG_trace_bailout) { \ |
| 42 PrintF("%s\n", reason); \ | 43 PrintF("%s\n", reason); \ |
| 43 } \ | 44 } \ |
| 44 has_supported_syntax_ = false; \ | 45 has_supported_syntax_ = false; \ |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 | 442 |
| 442 Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) { | 443 Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) { |
| 443 Handle<Script> script = info->script(); | 444 Handle<Script> script = info->script(); |
| 444 if (!script->IsUndefined() && !script->source()->IsUndefined()) { | 445 if (!script->IsUndefined() && !script->source()->IsUndefined()) { |
| 445 int len = String::cast(script->source())->length(); | 446 int len = String::cast(script->source())->length(); |
| 446 Counters::total_full_codegen_source_size.Increment(len); | 447 Counters::total_full_codegen_source_size.Increment(len); |
| 447 } | 448 } |
| 448 CodeGenerator::MakeCodePrologue(info); | 449 CodeGenerator::MakeCodePrologue(info); |
| 449 const int kInitialBufferSize = 4 * KB; | 450 const int kInitialBufferSize = 4 * KB; |
| 450 MacroAssembler masm(NULL, kInitialBufferSize); | 451 MacroAssembler masm(NULL, kInitialBufferSize); |
| 452 LiveEditFunctionTracker live_edit_tracker(info->function()); |
| 453 |
| 451 FullCodeGenerator cgen(&masm); | 454 FullCodeGenerator cgen(&masm); |
| 452 cgen.Generate(info, PRIMARY); | 455 cgen.Generate(info, PRIMARY); |
| 453 if (cgen.HasStackOverflow()) { | 456 if (cgen.HasStackOverflow()) { |
| 454 ASSERT(!Top::has_pending_exception()); | 457 ASSERT(!Top::has_pending_exception()); |
| 455 return Handle<Code>::null(); | 458 return Handle<Code>::null(); |
| 456 } | 459 } |
| 457 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); | 460 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); |
| 458 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info); | 461 Handle<Code> result = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
| 462 live_edit_tracker.RecordFunctionCode(result); |
| 463 return result; |
| 459 } | 464 } |
| 460 | 465 |
| 461 | 466 |
| 462 int FullCodeGenerator::SlotOffset(Slot* slot) { | 467 int FullCodeGenerator::SlotOffset(Slot* slot) { |
| 463 ASSERT(slot != NULL); | 468 ASSERT(slot != NULL); |
| 464 // Offset is negative because higher indexes are at lower addresses. | 469 // Offset is negative because higher indexes are at lower addresses. |
| 465 int offset = -slot->index() * kPointerSize; | 470 int offset = -slot->index() * kPointerSize; |
| 466 // Adjust by a (parameter or local) base offset. | 471 // Adjust by a (parameter or local) base offset. |
| 467 switch (slot->type()) { | 472 switch (slot->type()) { |
| 468 case Slot::PARAMETER: | 473 case Slot::PARAMETER: |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 // Execute the finally block on the way out. | 984 // Execute the finally block on the way out. |
| 980 __ Call(&finally_entry); | 985 __ Call(&finally_entry); |
| 981 } | 986 } |
| 982 | 987 |
| 983 | 988 |
| 984 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 989 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 985 #ifdef ENABLE_DEBUGGER_SUPPORT | 990 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 986 Comment cmnt(masm_, "[ DebuggerStatement"); | 991 Comment cmnt(masm_, "[ DebuggerStatement"); |
| 987 SetStatementPosition(stmt); | 992 SetStatementPosition(stmt); |
| 988 | 993 |
| 989 DebuggerStatementStub ces; | 994 __ DebugBreak(); |
| 990 __ CallStub(&ces); | |
| 991 // Ignore the return value. | 995 // Ignore the return value. |
| 992 #endif | 996 #endif |
| 993 } | 997 } |
| 994 | 998 |
| 995 | 999 |
| 996 void FullCodeGenerator::VisitFunctionBoilerplateLiteral( | 1000 void FullCodeGenerator::VisitFunctionBoilerplateLiteral( |
| 997 FunctionBoilerplateLiteral* expr) { | 1001 FunctionBoilerplateLiteral* expr) { |
| 998 UNREACHABLE(); | 1002 UNREACHABLE(); |
| 999 } | 1003 } |
| 1000 | 1004 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1025 UNREACHABLE(); | 1029 UNREACHABLE(); |
| 1026 } | 1030 } |
| 1027 | 1031 |
| 1028 | 1032 |
| 1029 void FullCodeGenerator::VisitLiteral(Literal* expr) { | 1033 void FullCodeGenerator::VisitLiteral(Literal* expr) { |
| 1030 Comment cmnt(masm_, "[ Literal"); | 1034 Comment cmnt(masm_, "[ Literal"); |
| 1031 Apply(context_, expr); | 1035 Apply(context_, expr); |
| 1032 } | 1036 } |
| 1033 | 1037 |
| 1034 | 1038 |
| 1035 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | |
| 1036 Comment cmnt(masm_, "[ Assignment"); | |
| 1037 ASSERT(expr->op() != Token::INIT_CONST); | |
| 1038 // Left-hand side can only be a property, a global or a (parameter or local) | |
| 1039 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | |
| 1040 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | |
| 1041 LhsKind assign_type = VARIABLE; | |
| 1042 Property* prop = expr->target()->AsProperty(); | |
| 1043 if (prop != NULL) { | |
| 1044 assign_type = | |
| 1045 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | |
| 1046 } | |
| 1047 | |
| 1048 // Evaluate LHS expression. | |
| 1049 switch (assign_type) { | |
| 1050 case VARIABLE: | |
| 1051 // Nothing to do here. | |
| 1052 break; | |
| 1053 case NAMED_PROPERTY: | |
| 1054 VisitForValue(prop->obj(), kStack); | |
| 1055 break; | |
| 1056 case KEYED_PROPERTY: | |
| 1057 VisitForValue(prop->obj(), kStack); | |
| 1058 VisitForValue(prop->key(), kStack); | |
| 1059 break; | |
| 1060 } | |
| 1061 | |
| 1062 // If we have a compound assignment: Get value of LHS expression and | |
| 1063 // store in on top of the stack. | |
| 1064 if (expr->is_compound()) { | |
| 1065 Location saved_location = location_; | |
| 1066 location_ = kStack; | |
| 1067 switch (assign_type) { | |
| 1068 case VARIABLE: | |
| 1069 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), | |
| 1070 Expression::kValue); | |
| 1071 break; | |
| 1072 case NAMED_PROPERTY: | |
| 1073 EmitNamedPropertyLoad(prop); | |
| 1074 __ push(result_register()); | |
| 1075 break; | |
| 1076 case KEYED_PROPERTY: | |
| 1077 EmitKeyedPropertyLoad(prop); | |
| 1078 __ push(result_register()); | |
| 1079 break; | |
| 1080 } | |
| 1081 location_ = saved_location; | |
| 1082 } | |
| 1083 | |
| 1084 // Evaluate RHS expression. | |
| 1085 Expression* rhs = expr->value(); | |
| 1086 VisitForValue(rhs, kAccumulator); | |
| 1087 | |
| 1088 // If we have a compound assignment: Apply operator. | |
| 1089 if (expr->is_compound()) { | |
| 1090 Location saved_location = location_; | |
| 1091 location_ = kAccumulator; | |
| 1092 EmitBinaryOp(expr->binary_op(), Expression::kValue); | |
| 1093 location_ = saved_location; | |
| 1094 } | |
| 1095 | |
| 1096 // Record source position before possible IC call. | |
| 1097 SetSourcePosition(expr->position()); | |
| 1098 | |
| 1099 // Store the value. | |
| 1100 switch (assign_type) { | |
| 1101 case VARIABLE: | |
| 1102 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | |
| 1103 context_); | |
| 1104 break; | |
| 1105 case NAMED_PROPERTY: | |
| 1106 EmitNamedPropertyAssignment(expr); | |
| 1107 break; | |
| 1108 case KEYED_PROPERTY: | |
| 1109 EmitKeyedPropertyAssignment(expr); | |
| 1110 break; | |
| 1111 } | |
| 1112 } | |
| 1113 | |
| 1114 | |
| 1115 void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 1039 void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 1116 // Call runtime routine to allocate the catch extension object and | 1040 // Call runtime routine to allocate the catch extension object and |
| 1117 // assign the exception value to the catch variable. | 1041 // assign the exception value to the catch variable. |
| 1118 Comment cmnt(masm_, "[ CatchExtensionObject"); | 1042 Comment cmnt(masm_, "[ CatchExtensionObject"); |
| 1119 VisitForValue(expr->key(), kStack); | 1043 VisitForValue(expr->key(), kStack); |
| 1120 VisitForValue(expr->value(), kStack); | 1044 VisitForValue(expr->value(), kStack); |
| 1121 // Create catch extension object. | 1045 // Create catch extension object. |
| 1122 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 1046 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
| 1123 Apply(context_, result_register()); | 1047 Apply(context_, result_register()); |
| 1124 } | 1048 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1145 // The macros used here must preserve the result register. | 1069 // The macros used here must preserve the result register. |
| 1146 __ Drop(stack_depth); | 1070 __ Drop(stack_depth); |
| 1147 __ PopTryHandler(); | 1071 __ PopTryHandler(); |
| 1148 return 0; | 1072 return 0; |
| 1149 } | 1073 } |
| 1150 | 1074 |
| 1151 #undef __ | 1075 #undef __ |
| 1152 | 1076 |
| 1153 | 1077 |
| 1154 } } // namespace v8::internal | 1078 } } // namespace v8::internal |
| OLD | NEW |