| 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 4220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |