OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |