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

Side by Side Diff: src/hydrogen.cc

Issue 7105015: Eagerly deoptimize on never-executed code-paths. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 loop_information_(NULL), 61 loop_information_(NULL),
62 predecessors_(2), 62 predecessors_(2),
63 dominator_(NULL), 63 dominator_(NULL),
64 dominated_blocks_(4), 64 dominated_blocks_(4),
65 last_environment_(NULL), 65 last_environment_(NULL),
66 argument_count_(-1), 66 argument_count_(-1),
67 first_instruction_index_(-1), 67 first_instruction_index_(-1),
68 last_instruction_index_(-1), 68 last_instruction_index_(-1),
69 deleted_phis_(4), 69 deleted_phis_(4),
70 parent_loop_header_(NULL), 70 parent_loop_header_(NULL),
71 is_inline_return_target_(false) { 71 is_inline_return_target_(false) { }
72 }
73 72
74 73
75 void HBasicBlock::AttachLoopInformation() { 74 void HBasicBlock::AttachLoopInformation() {
76 ASSERT(!IsLoopHeader()); 75 ASSERT(!IsLoopHeader());
77 loop_information_ = new(zone()) HLoopInformation(this); 76 loop_information_ = new(zone()) HLoopInformation(this);
78 } 77 }
79 78
80 79
81 void HBasicBlock::DetachLoopInformation() { 80 void HBasicBlock::DetachLoopInformation() {
82 ASSERT(IsLoopHeader()); 81 ASSERT(IsLoopHeader());
(...skipping 4186 matching lines...) Expand 10 before | Expand all | Expand 10 after
4269 4268
4270 empty_true->Goto(inlined_test_context()->if_true(), false); 4269 empty_true->Goto(inlined_test_context()->if_true(), false);
4271 empty_false->Goto(inlined_test_context()->if_false(), false); 4270 empty_false->Goto(inlined_test_context()->if_false(), false);
4272 } 4271 }
4273 } 4272 }
4274 4273
4275 // Fix up the function exits. 4274 // Fix up the function exits.
4276 if (inlined_test_context() != NULL) { 4275 if (inlined_test_context() != NULL) {
4277 HBasicBlock* if_true = inlined_test_context()->if_true(); 4276 HBasicBlock* if_true = inlined_test_context()->if_true();
4278 HBasicBlock* if_false = inlined_test_context()->if_false(); 4277 HBasicBlock* if_false = inlined_test_context()->if_false();
4279 if_true->SetJoinId(expr->id()); 4278
4280 if_false->SetJoinId(expr->id()); 4279 // Pop the return test context from the expression context stack.
4281 ASSERT(ast_context() == inlined_test_context()); 4280 ASSERT(ast_context() == inlined_test_context());
4282 // Pop the return test context from the expression context stack.
4283 ClearInlinedTestContext(); 4281 ClearInlinedTestContext();
4284 4282
4285 // Forward to the real test context. 4283 // Forward to the real test context.
4286 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4284 if (if_true->HasPredecessor()) {
4287 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4285 if_true->SetJoinId(expr->id());
4288 if_true->Goto(true_target, false); 4286 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4289 if_false->Goto(false_target, false); 4287 if_true->Goto(true_target, false);
4290 4288 }
4291 // TODO(kmillikin): Come up with a better way to handle this. It is too 4289 if (if_false->HasPredecessor()) {
4292 // subtle. NULL here indicates that the enclosing context has no control 4290 if_false->SetJoinId(expr->id());
4293 // flow to handle. 4291 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4292 if_false->Goto(false_target, false);
4293 }
4294 set_current_block(NULL); 4294 set_current_block(NULL);
4295 4295
4296 } else if (function_return()->HasPredecessor()) { 4296 } else if (function_return()->HasPredecessor()) {
4297 function_return()->SetJoinId(expr->id()); 4297 function_return()->SetJoinId(expr->id());
4298 set_current_block(function_return()); 4298 set_current_block(function_return());
4299 } else { 4299 } else {
4300 set_current_block(NULL); 4300 set_current_block(NULL);
4301 } 4301 }
4302 4302
4303 return true; 4303 return true;
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
4750 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1()); 4750 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1());
4751 ast_context()->ReturnInstruction(instr, expr->id()); 4751 ast_context()->ReturnInstruction(instr, expr->id());
4752 } 4752 }
4753 4753
4754 4754
4755 void HGraphBuilder::VisitSub(UnaryOperation* expr) { 4755 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
4756 CHECK_ALIVE(VisitForValue(expr->expression())); 4756 CHECK_ALIVE(VisitForValue(expr->expression()));
4757 HValue* value = Pop(); 4757 HValue* value = Pop();
4758 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); 4758 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
4759 TypeInfo info = oracle()->UnaryType(expr); 4759 TypeInfo info = oracle()->UnaryType(expr);
4760 if (info.IsUninitialized()) {
4761 AddInstruction(new(zone()) HEagerDeoptimize);
4762 info = TypeInfo::Unknown();
4763 }
4760 Representation rep = ToRepresentation(info); 4764 Representation rep = ToRepresentation(info);
4761 TraceRepresentation(expr->op(), info, instr, rep); 4765 TraceRepresentation(expr->op(), info, instr, rep);
4762 instr->AssumeRepresentation(rep); 4766 instr->AssumeRepresentation(rep);
4763 ast_context()->ReturnInstruction(instr, expr->id()); 4767 ast_context()->ReturnInstruction(instr, expr->id());
4764 } 4768 }
4765 4769
4766 4770
4767 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { 4771 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
4768 CHECK_ALIVE(VisitForValue(expr->expression())); 4772 CHECK_ALIVE(VisitForValue(expr->expression()));
4769 HValue* value = Pop(); 4773 HValue* value = Pop();
4774 TypeInfo info = oracle()->UnaryType(expr);
4775 if (info.IsUninitialized()) {
4776 AddInstruction(new(zone()) HEagerDeoptimize);
4777 }
4770 HInstruction* instr = new(zone()) HBitNot(value); 4778 HInstruction* instr = new(zone()) HBitNot(value);
4771 ast_context()->ReturnInstruction(instr, expr->id()); 4779 ast_context()->ReturnInstruction(instr, expr->id());
4772 } 4780 }
4773 4781
4774 4782
4775 void HGraphBuilder::VisitNot(UnaryOperation* expr) { 4783 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
4776 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. 4784 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
4777 if (ast_context()->IsTest()) { 4785 if (ast_context()->IsTest()) {
4778 TestContext* context = TestContext::cast(ast_context()); 4786 TestContext* context = TestContext::cast(ast_context());
4779 VisitForControl(expr->expression(), 4787 VisitForControl(expr->expression(),
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
4988 AddInstruction(length); 4996 AddInstruction(length);
4989 AddInstruction(new(zone()) HBoundsCheck(index, length)); 4997 AddInstruction(new(zone()) HBoundsCheck(index, length));
4990 return new(zone()) HStringCharCodeAt(string, index); 4998 return new(zone()) HStringCharCodeAt(string, index);
4991 } 4999 }
4992 5000
4993 5001
4994 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 5002 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4995 HValue* left, 5003 HValue* left,
4996 HValue* right) { 5004 HValue* right) {
4997 TypeInfo info = oracle()->BinaryType(expr); 5005 TypeInfo info = oracle()->BinaryType(expr);
4998 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info); 5006 if (info.IsUninitialized()) {
5007 AddInstruction(new(zone()) HEagerDeoptimize);
5008 info = TypeInfo::Unknown();
5009 }
5010 HInstruction* instr = NULL;
5011 switch (expr->op()) {
5012 case Token::ADD:
5013 if (info.IsString()) {
5014 AddInstruction(new(zone()) HCheckNonSmi(left));
5015 AddInstruction(HCheckInstanceType::NewIsString(left));
5016 AddInstruction(new(zone()) HCheckNonSmi(right));
5017 AddInstruction(HCheckInstanceType::NewIsString(right));
5018 instr = new(zone()) HStringAdd(left, right);
5019 } else {
5020 instr = new(zone()) HAdd(left, right);
5021 }
5022 break;
5023 case Token::SUB:
5024 instr = new(zone()) HSub(left, right);
5025 break;
5026 case Token::MUL:
5027 instr = new(zone()) HMul(left, right);
5028 break;
5029 case Token::MOD:
5030 instr = new(zone()) HMod(left, right);
5031 break;
5032 case Token::DIV:
5033 instr = new(zone()) HDiv(left, right);
5034 break;
5035 case Token::BIT_XOR:
5036 instr = new(zone()) HBitXor(left, right);
5037 break;
5038 case Token::BIT_AND:
5039 instr = new(zone()) HBitAnd(left, right);
5040 break;
5041 case Token::BIT_OR:
5042 instr = new(zone()) HBitOr(left, right);
5043 break;
5044 case Token::SAR:
5045 instr = new(zone()) HSar(left, right);
5046 break;
5047 case Token::SHR:
5048 instr = new(zone()) HShr(left, right);
5049 break;
5050 case Token::SHL:
5051 instr = new(zone()) HShl(left, right);
5052 break;
5053 default:
5054 UNREACHABLE();
5055 }
5056
4999 // If we hit an uninitialized binary op stub we will get type info 5057 // If we hit an uninitialized binary op stub we will get type info
5000 // for a smi operation. If one of the operands is a constant string 5058 // for a smi operation. If one of the operands is a constant string
5001 // do not generate code assuming it is a smi operation. 5059 // do not generate code assuming it is a smi operation.
5002 if (info.IsSmi() && 5060 if (info.IsSmi() &&
5003 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 5061 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
5004 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 5062 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
5005 return instr; 5063 return instr;
5006 } 5064 }
5007 Representation rep = ToRepresentation(info); 5065 Representation rep = ToRepresentation(info);
5008 // We only generate either int32 or generic tagged bitwise operations. 5066 // We only generate either int32 or generic tagged bitwise operations.
5009 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 5067 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
5010 rep = Representation::Integer32(); 5068 rep = Representation::Integer32();
5011 } 5069 }
5012 TraceRepresentation(expr->op(), info, instr, rep); 5070 TraceRepresentation(expr->op(), info, instr, rep);
5013 instr->AssumeRepresentation(rep); 5071 instr->AssumeRepresentation(rep);
5014 return instr; 5072 return instr;
5015 } 5073 }
5016 5074
5017 5075
5018 HInstruction* HGraphBuilder::BuildBinaryOperation(
5019 Token::Value op, HValue* left, HValue* right, TypeInfo info) {
5020 switch (op) {
5021 case Token::ADD:
5022 if (info.IsString()) {
5023 AddInstruction(new(zone()) HCheckNonSmi(left));
5024 AddInstruction(HCheckInstanceType::NewIsString(left));
5025 AddInstruction(new(zone()) HCheckNonSmi(right));
5026 AddInstruction(HCheckInstanceType::NewIsString(right));
5027 return new(zone()) HStringAdd(left, right);
5028 } else {
5029 return new(zone()) HAdd(left, right);
5030 }
5031 case Token::SUB: return new(zone()) HSub(left, right);
5032 case Token::MUL: return new(zone()) HMul(left, right);
5033 case Token::MOD: return new(zone()) HMod(left, right);
5034 case Token::DIV: return new(zone()) HDiv(left, right);
5035 case Token::BIT_XOR: return new(zone()) HBitXor(left, right);
5036 case Token::BIT_AND: return new(zone()) HBitAnd(left, right);
5037 case Token::BIT_OR: return new(zone()) HBitOr(left, right);
5038 case Token::SAR: return new(zone()) HSar(left, right);
5039 case Token::SHR: return new(zone()) HShr(left, right);
5040 case Token::SHL: return new(zone()) HShl(left, right);
5041 default:
5042 UNREACHABLE();
5043 return NULL;
5044 }
5045 }
5046
5047
5048 // Check for the form (%_ClassOf(foo) === 'BarClass'). 5076 // Check for the form (%_ClassOf(foo) === 'BarClass').
5049 static bool IsClassOfTest(CompareOperation* expr) { 5077 static bool IsClassOfTest(CompareOperation* expr) {
5050 if (expr->op() != Token::EQ_STRICT) return false; 5078 if (expr->op() != Token::EQ_STRICT) return false;
5051 CallRuntime* call = expr->left()->AsCallRuntime(); 5079 CallRuntime* call = expr->left()->AsCallRuntime();
5052 if (call == NULL) return false; 5080 if (call == NULL) return false;
5053 Literal* literal = expr->right()->AsLiteral(); 5081 Literal* literal = expr->right()->AsLiteral();
5054 if (literal == NULL) return false; 5082 if (literal == NULL) return false;
5055 if (!literal->handle()->IsString()) return false; 5083 if (!literal->handle()->IsString()) return false;
5056 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 5084 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
5057 ASSERT(call->arguments()->length() == 1); 5085 ASSERT(call->arguments()->length() == 1);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
5231 right_literal != NULL && right_literal->handle()->IsString()) { 5259 right_literal != NULL && right_literal->handle()->IsString()) {
5232 CHECK_ALIVE(VisitForTypeOf(left_unary->expression())); 5260 CHECK_ALIVE(VisitForTypeOf(left_unary->expression()));
5233 HValue* left = Pop(); 5261 HValue* left = Pop();
5234 HInstruction* instr = new(zone()) HTypeofIs(left, 5262 HInstruction* instr = new(zone()) HTypeofIs(left,
5235 Handle<String>::cast(right_literal->handle())); 5263 Handle<String>::cast(right_literal->handle()));
5236 instr->set_position(expr->position()); 5264 instr->set_position(expr->position());
5237 ast_context()->ReturnInstruction(instr, expr->id()); 5265 ast_context()->ReturnInstruction(instr, expr->id());
5238 return; 5266 return;
5239 } 5267 }
5240 5268
5269 TypeInfo type_info = oracle()->CompareType(expr);
5270 // Check if this expression was ever executed according to type feedback.
5271 if (type_info.IsUninitialized()) {
5272 AddInstruction(new(zone()) HEagerDeoptimize);
5273 type_info = TypeInfo::Unknown();
5274 }
5275
5241 CHECK_ALIVE(VisitForValue(expr->left())); 5276 CHECK_ALIVE(VisitForValue(expr->left()));
5242 CHECK_ALIVE(VisitForValue(expr->right())); 5277 CHECK_ALIVE(VisitForValue(expr->right()));
5243 5278
5244 HValue* right = Pop(); 5279 HValue* right = Pop();
5245 HValue* left = Pop(); 5280 HValue* left = Pop();
5246 Token::Value op = expr->op(); 5281 Token::Value op = expr->op();
5247 5282
5248 TypeInfo type_info = oracle()->CompareType(expr);
5249 HInstruction* instr = NULL; 5283 HInstruction* instr = NULL;
5250 if (op == Token::INSTANCEOF) { 5284 if (op == Token::INSTANCEOF) {
5251 // Check to see if the rhs of the instanceof is a global function not 5285 // Check to see if the rhs of the instanceof is a global function not
5252 // residing in new space. If it is we assume that the function will stay the 5286 // residing in new space. If it is we assume that the function will stay the
5253 // same. 5287 // same.
5254 Handle<JSFunction> target = Handle<JSFunction>::null(); 5288 Handle<JSFunction> target = Handle<JSFunction>::null();
5255 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5289 Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5256 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5290 bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5257 if (global_function && 5291 if (global_function &&
5258 info()->has_global_object() && 5292 info()->has_global_object() &&
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after
6270 } 6304 }
6271 } 6305 }
6272 6306
6273 #ifdef DEBUG 6307 #ifdef DEBUG
6274 if (graph_ != NULL) graph_->Verify(); 6308 if (graph_ != NULL) graph_->Verify();
6275 if (allocator_ != NULL) allocator_->Verify(); 6309 if (allocator_ != NULL) allocator_->Verify();
6276 #endif 6310 #endif
6277 } 6311 }
6278 6312
6279 } } // namespace v8::internal 6313 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698