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

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