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

Side by Side Diff: src/hydrogen.cc

Issue 7112032: Re-land r8140: 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4220 matching lines...) Expand 10 before | Expand all | Expand 10 after
4303 4302
4304 empty_true->Goto(inlined_test_context()->if_true(), false); 4303 empty_true->Goto(inlined_test_context()->if_true(), false);
4305 empty_false->Goto(inlined_test_context()->if_false(), false); 4304 empty_false->Goto(inlined_test_context()->if_false(), false);
4306 } 4305 }
4307 } 4306 }
4308 4307
4309 // Fix up the function exits. 4308 // Fix up the function exits.
4310 if (inlined_test_context() != NULL) { 4309 if (inlined_test_context() != NULL) {
4311 HBasicBlock* if_true = inlined_test_context()->if_true(); 4310 HBasicBlock* if_true = inlined_test_context()->if_true();
4312 HBasicBlock* if_false = inlined_test_context()->if_false(); 4311 HBasicBlock* if_false = inlined_test_context()->if_false();
4313 if_true->SetJoinId(expr->id()); 4312
4314 if_false->SetJoinId(expr->id()); 4313 // Pop the return test context from the expression context stack.
4315 ASSERT(ast_context() == inlined_test_context()); 4314 ASSERT(ast_context() == inlined_test_context());
4316 // Pop the return test context from the expression context stack.
4317 ClearInlinedTestContext(); 4315 ClearInlinedTestContext();
4318 4316
4319 // Forward to the real test context. 4317 // Forward to the real test context.
4320 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4318 if (if_true->HasPredecessor()) {
4321 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4319 if_true->SetJoinId(expr->id());
4322 if_true->Goto(true_target, false); 4320 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4323 if_false->Goto(false_target, false); 4321 if_true->Goto(true_target, false);
4324 4322 }
4325 // TODO(kmillikin): Come up with a better way to handle this. It is too 4323 if (if_false->HasPredecessor()) {
4326 // subtle. NULL here indicates that the enclosing context has no control 4324 if_false->SetJoinId(expr->id());
4327 // flow to handle. 4325 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4326 if_false->Goto(false_target, false);
4327 }
4328 set_current_block(NULL); 4328 set_current_block(NULL);
4329 4329
4330 } else if (function_return()->HasPredecessor()) { 4330 } else if (function_return()->HasPredecessor()) {
4331 function_return()->SetJoinId(expr->id()); 4331 function_return()->SetJoinId(expr->id());
4332 set_current_block(function_return()); 4332 set_current_block(function_return());
4333 } else { 4333 } else {
4334 set_current_block(NULL); 4334 set_current_block(NULL);
4335 } 4335 }
4336 4336
4337 return true; 4337 return true;
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
4784 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1()); 4784 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1());
4785 ast_context()->ReturnInstruction(instr, expr->id()); 4785 ast_context()->ReturnInstruction(instr, expr->id());
4786 } 4786 }
4787 4787
4788 4788
4789 void HGraphBuilder::VisitSub(UnaryOperation* expr) { 4789 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
4790 CHECK_ALIVE(VisitForValue(expr->expression())); 4790 CHECK_ALIVE(VisitForValue(expr->expression()));
4791 HValue* value = Pop(); 4791 HValue* value = Pop();
4792 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); 4792 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
4793 TypeInfo info = oracle()->UnaryType(expr); 4793 TypeInfo info = oracle()->UnaryType(expr);
4794 if (info.IsUninitialized()) {
4795 AddInstruction(new(zone()) HSoftDeoptimize);
4796 info = TypeInfo::Unknown();
4797 }
4794 Representation rep = ToRepresentation(info); 4798 Representation rep = ToRepresentation(info);
4795 TraceRepresentation(expr->op(), info, instr, rep); 4799 TraceRepresentation(expr->op(), info, instr, rep);
4796 instr->AssumeRepresentation(rep); 4800 instr->AssumeRepresentation(rep);
4797 ast_context()->ReturnInstruction(instr, expr->id()); 4801 ast_context()->ReturnInstruction(instr, expr->id());
4798 } 4802 }
4799 4803
4800 4804
4801 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { 4805 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
4802 CHECK_ALIVE(VisitForValue(expr->expression())); 4806 CHECK_ALIVE(VisitForValue(expr->expression()));
4803 HValue* value = Pop(); 4807 HValue* value = Pop();
4808 TypeInfo info = oracle()->UnaryType(expr);
4809 if (info.IsUninitialized()) {
4810 AddInstruction(new(zone()) HSoftDeoptimize);
4811 }
4804 HInstruction* instr = new(zone()) HBitNot(value); 4812 HInstruction* instr = new(zone()) HBitNot(value);
4805 ast_context()->ReturnInstruction(instr, expr->id()); 4813 ast_context()->ReturnInstruction(instr, expr->id());
4806 } 4814 }
4807 4815
4808 4816
4809 void HGraphBuilder::VisitNot(UnaryOperation* expr) { 4817 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
4810 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. 4818 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
4811 if (ast_context()->IsTest()) { 4819 if (ast_context()->IsTest()) {
4812 TestContext* context = TestContext::cast(ast_context()); 4820 TestContext* context = TestContext::cast(ast_context());
4813 VisitForControl(expr->expression(), 4821 VisitForControl(expr->expression(),
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
5025 AddInstruction(length); 5033 AddInstruction(length);
5026 AddInstruction(new(zone()) HBoundsCheck(index, length)); 5034 AddInstruction(new(zone()) HBoundsCheck(index, length));
5027 return new(zone()) HStringCharCodeAt(string, index); 5035 return new(zone()) HStringCharCodeAt(string, index);
5028 } 5036 }
5029 5037
5030 5038
5031 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 5039 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
5032 HValue* left, 5040 HValue* left,
5033 HValue* right) { 5041 HValue* right) {
5034 TypeInfo info = oracle()->BinaryType(expr); 5042 TypeInfo info = oracle()->BinaryType(expr);
5035 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info); 5043 if (info.IsUninitialized()) {
5044 AddInstruction(new(zone()) HSoftDeoptimize);
5045 info = TypeInfo::Unknown();
5046 }
5047 HInstruction* instr = NULL;
5048 switch (expr->op()) {
5049 case Token::ADD:
5050 if (info.IsString()) {
5051 AddInstruction(new(zone()) HCheckNonSmi(left));
5052 AddInstruction(HCheckInstanceType::NewIsString(left));
5053 AddInstruction(new(zone()) HCheckNonSmi(right));
5054 AddInstruction(HCheckInstanceType::NewIsString(right));
5055 instr = new(zone()) HStringAdd(left, right);
5056 } else {
5057 instr = new(zone()) HAdd(left, right);
5058 }
5059 break;
5060 case Token::SUB:
5061 instr = new(zone()) HSub(left, right);
5062 break;
5063 case Token::MUL:
5064 instr = new(zone()) HMul(left, right);
5065 break;
5066 case Token::MOD:
5067 instr = new(zone()) HMod(left, right);
5068 break;
5069 case Token::DIV:
5070 instr = new(zone()) HDiv(left, right);
5071 break;
5072 case Token::BIT_XOR:
5073 instr = new(zone()) HBitXor(left, right);
5074 break;
5075 case Token::BIT_AND:
5076 instr = new(zone()) HBitAnd(left, right);
5077 break;
5078 case Token::BIT_OR:
5079 instr = new(zone()) HBitOr(left, right);
5080 break;
5081 case Token::SAR:
5082 instr = new(zone()) HSar(left, right);
5083 break;
5084 case Token::SHR:
5085 instr = new(zone()) HShr(left, right);
5086 break;
5087 case Token::SHL:
5088 instr = new(zone()) HShl(left, right);
5089 break;
5090 default:
5091 UNREACHABLE();
5092 }
5093
5036 // If we hit an uninitialized binary op stub we will get type info 5094 // If we hit an uninitialized binary op stub we will get type info
5037 // for a smi operation. If one of the operands is a constant string 5095 // for a smi operation. If one of the operands is a constant string
5038 // do not generate code assuming it is a smi operation. 5096 // do not generate code assuming it is a smi operation.
5039 if (info.IsSmi() && 5097 if (info.IsSmi() &&
5040 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 5098 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
5041 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 5099 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
5042 return instr; 5100 return instr;
5043 } 5101 }
5044 Representation rep = ToRepresentation(info); 5102 Representation rep = ToRepresentation(info);
5045 // We only generate either int32 or generic tagged bitwise operations. 5103 // We only generate either int32 or generic tagged bitwise operations.
5046 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 5104 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
5047 rep = Representation::Integer32(); 5105 rep = Representation::Integer32();
5048 } 5106 }
5049 TraceRepresentation(expr->op(), info, instr, rep); 5107 TraceRepresentation(expr->op(), info, instr, rep);
5050 instr->AssumeRepresentation(rep); 5108 instr->AssumeRepresentation(rep);
5051 return instr; 5109 return instr;
5052 } 5110 }
5053 5111
5054 5112
5055 HInstruction* HGraphBuilder::BuildBinaryOperation(
5056 Token::Value op, HValue* left, HValue* right, TypeInfo info) {
5057 switch (op) {
5058 case Token::ADD:
5059 if (info.IsString()) {
5060 AddInstruction(new(zone()) HCheckNonSmi(left));
5061 AddInstruction(HCheckInstanceType::NewIsString(left));
5062 AddInstruction(new(zone()) HCheckNonSmi(right));
5063 AddInstruction(HCheckInstanceType::NewIsString(right));
5064 return new(zone()) HStringAdd(left, right);
5065 } else {
5066 return new(zone()) HAdd(left, right);
5067 }
5068 case Token::SUB: return new(zone()) HSub(left, right);
5069 case Token::MUL: return new(zone()) HMul(left, right);
5070 case Token::MOD: return new(zone()) HMod(left, right);
5071 case Token::DIV: return new(zone()) HDiv(left, right);
5072 case Token::BIT_XOR: return new(zone()) HBitXor(left, right);
5073 case Token::BIT_AND: return new(zone()) HBitAnd(left, right);
5074 case Token::BIT_OR: return new(zone()) HBitOr(left, right);
5075 case Token::SAR: return new(zone()) HSar(left, right);
5076 case Token::SHR: return new(zone()) HShr(left, right);
5077 case Token::SHL: return new(zone()) HShl(left, right);
5078 default:
5079 UNREACHABLE();
5080 return NULL;
5081 }
5082 }
5083
5084
5085 // Check for the form (%_ClassOf(foo) === 'BarClass'). 5113 // Check for the form (%_ClassOf(foo) === 'BarClass').
5086 static bool IsClassOfTest(CompareOperation* expr) { 5114 static bool IsClassOfTest(CompareOperation* expr) {
5087 if (expr->op() != Token::EQ_STRICT) return false; 5115 if (expr->op() != Token::EQ_STRICT) return false;
5088 CallRuntime* call = expr->left()->AsCallRuntime(); 5116 CallRuntime* call = expr->left()->AsCallRuntime();
5089 if (call == NULL) return false; 5117 if (call == NULL) return false;
5090 Literal* literal = expr->right()->AsLiteral(); 5118 Literal* literal = expr->right()->AsLiteral();
5091 if (literal == NULL) return false; 5119 if (literal == NULL) return false;
5092 if (!literal->handle()->IsString()) return false; 5120 if (!literal->handle()->IsString()) return false;
5093 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 5121 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
5094 ASSERT(call->arguments()->length() == 1); 5122 ASSERT(call->arguments()->length() == 1);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
5272 right_literal != NULL && right_literal->handle()->IsString()) { 5300 right_literal != NULL && right_literal->handle()->IsString()) {
5273 CHECK_ALIVE(VisitForTypeOf(left_unary->expression())); 5301 CHECK_ALIVE(VisitForTypeOf(left_unary->expression()));
5274 HValue* left = Pop(); 5302 HValue* left = Pop();
5275 HInstruction* instr = new(zone()) HTypeofIs(left, 5303 HInstruction* instr = new(zone()) HTypeofIs(left,
5276 Handle<String>::cast(right_literal->handle())); 5304 Handle<String>::cast(right_literal->handle()));
5277 instr->set_position(expr->position()); 5305 instr->set_position(expr->position());
5278 ast_context()->ReturnInstruction(instr, expr->id()); 5306 ast_context()->ReturnInstruction(instr, expr->id());
5279 return; 5307 return;
5280 } 5308 }
5281 5309
5310 TypeInfo type_info = oracle()->CompareType(expr);
5311 // Check if this expression was ever executed according to type feedback.
5312 if (type_info.IsUninitialized()) {
5313 AddInstruction(new(zone()) HSoftDeoptimize);
5314 type_info = TypeInfo::Unknown();
5315 }
5316
5282 CHECK_ALIVE(VisitForValue(expr->left())); 5317 CHECK_ALIVE(VisitForValue(expr->left()));
5283 CHECK_ALIVE(VisitForValue(expr->right())); 5318 CHECK_ALIVE(VisitForValue(expr->right()));
5284 5319
5285 HValue* right = Pop(); 5320 HValue* right = Pop();
5286 HValue* left = Pop(); 5321 HValue* left = Pop();
5287 Token::Value op = expr->op(); 5322 Token::Value op = expr->op();
5288 5323
5289 TypeInfo type_info = oracle()->CompareType(expr);
5290 HInstruction* instr = NULL; 5324 HInstruction* instr = NULL;
5291 if (op == Token::INSTANCEOF) { 5325 if (op == Token::INSTANCEOF) {
5292 // Check to see if the rhs of the instanceof is a global function not 5326 // Check to see if the rhs of the instanceof is a global function not
5293 // residing in new space. If it is we assume that the function will stay the 5327 // residing in new space. If it is we assume that the function will stay the
5294 // same. 5328 // same.
5295 Handle<JSFunction> target = Handle<JSFunction>::null(); 5329 Handle<JSFunction> target = Handle<JSFunction>::null();
5296 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5330 Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5297 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5331 bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5298 if (global_function && 5332 if (global_function &&
5299 info()->has_global_object() && 5333 info()->has_global_object() &&
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after
6313 } 6347 }
6314 } 6348 }
6315 6349
6316 #ifdef DEBUG 6350 #ifdef DEBUG
6317 if (graph_ != NULL) graph_->Verify(); 6351 if (graph_ != NULL) graph_->Verify();
6318 if (allocator_ != NULL) allocator_->Verify(); 6352 if (allocator_ != NULL) allocator_->Verify();
6319 #endif 6353 #endif
6320 } 6354 }
6321 6355
6322 } } // namespace v8::internal 6356 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698