OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 6266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6277 Drop(1); | 6277 Drop(1); |
6278 } | 6278 } |
6279 } | 6279 } |
6280 return ast_context()->ReturnValue(load); | 6280 return ast_context()->ReturnValue(load); |
6281 } | 6281 } |
6282 instr->set_position(expr->position()); | 6282 instr->set_position(expr->position()); |
6283 return ast_context()->ReturnInstruction(instr, expr->id()); | 6283 return ast_context()->ReturnInstruction(instr, expr->id()); |
6284 } | 6284 } |
6285 | 6285 |
6286 | 6286 |
6287 void HGraphBuilder::AddCheckConstantFunction(Call* expr, | 6287 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, |
6288 HValue* receiver, | 6288 HValue* receiver, |
6289 Handle<Map> receiver_map, | 6289 Handle<Map> receiver_map, |
6290 bool smi_and_map_check) { | 6290 bool smi_and_map_check) { |
6291 // Constant functions have the nice property that the map will change if they | 6291 // Constant functions have the nice property that the map will change if they |
6292 // are overwritten. Therefore it is enough to check the map of the holder and | 6292 // are overwritten. Therefore it is enough to check the map of the holder and |
6293 // its prototypes. | 6293 // its prototypes. |
6294 if (smi_and_map_check) { | 6294 if (smi_and_map_check) { |
6295 AddInstruction(new(zone()) HCheckNonSmi(receiver)); | 6295 AddInstruction(new(zone()) HCheckNonSmi(receiver)); |
6296 AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map, | 6296 AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map, |
6297 zone())); | 6297 zone())); |
6298 } | 6298 } |
6299 if (!expr->holder().is_null()) { | 6299 if (!holder.is_null()) { |
6300 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6300 AddInstruction(new(zone()) HCheckPrototypeMaps( |
6301 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), | 6301 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
6302 expr->holder())); | |
6303 } | 6302 } |
6304 } | 6303 } |
6305 | 6304 |
6306 | 6305 |
6307 class FunctionSorter { | 6306 class FunctionSorter { |
6308 public: | 6307 public: |
6309 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } | 6308 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } |
6310 FunctionSorter(int index, int ticks, int ast_length, int src_length) | 6309 FunctionSorter(int index, int ticks, int ast_length, int src_length) |
6311 : index_(index), | 6310 : index_(index), |
6312 ticks_(ticks), | 6311 ticks_(ticks), |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6375 join = graph()->CreateBasicBlock(); | 6374 join = graph()->CreateBasicBlock(); |
6376 } | 6375 } |
6377 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6376 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
6378 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6377 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
6379 HCompareMap* compare = | 6378 HCompareMap* compare = |
6380 new(zone()) HCompareMap(receiver, map, if_true, if_false); | 6379 new(zone()) HCompareMap(receiver, map, if_true, if_false); |
6381 current_block()->Finish(compare); | 6380 current_block()->Finish(compare); |
6382 | 6381 |
6383 set_current_block(if_true); | 6382 set_current_block(if_true); |
6384 expr->ComputeTarget(map, name); | 6383 expr->ComputeTarget(map, name); |
6385 AddCheckConstantFunction(expr, receiver, map, false); | 6384 AddCheckConstantFunction(expr->holder(), receiver, map, false); |
6386 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 6385 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
6387 Handle<JSFunction> caller = info()->closure(); | 6386 Handle<JSFunction> caller = info()->closure(); |
6388 SmartArrayPointer<char> caller_name = | 6387 SmartArrayPointer<char> caller_name = |
6389 caller->shared()->DebugName()->ToCString(); | 6388 caller->shared()->DebugName()->ToCString(); |
6390 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6389 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
6391 *name->ToCString(), | 6390 *name->ToCString(), |
6392 *caller_name); | 6391 *caller_name); |
6393 } | 6392 } |
6394 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6393 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
6395 // Trying to inline will signal that we should bailout from the | 6394 // Trying to inline will signal that we should bailout from the |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6882 break; | 6881 break; |
6883 case kMathRound: | 6882 case kMathRound: |
6884 case kMathFloor: | 6883 case kMathFloor: |
6885 case kMathAbs: | 6884 case kMathAbs: |
6886 case kMathSqrt: | 6885 case kMathSqrt: |
6887 case kMathLog: | 6886 case kMathLog: |
6888 case kMathSin: | 6887 case kMathSin: |
6889 case kMathCos: | 6888 case kMathCos: |
6890 case kMathTan: | 6889 case kMathTan: |
6891 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6890 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
6892 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 6891 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
6893 HValue* argument = Pop(); | 6892 HValue* argument = Pop(); |
6894 HValue* context = environment()->LookupContext(); | 6893 HValue* context = environment()->LookupContext(); |
6895 Drop(1); // Receiver. | 6894 Drop(1); // Receiver. |
6896 HUnaryMathOperation* op = | 6895 HUnaryMathOperation* op = |
6897 new(zone()) HUnaryMathOperation(context, argument, id); | 6896 new(zone()) HUnaryMathOperation(context, argument, id); |
6898 op->set_position(expr->position()); | 6897 op->set_position(expr->position()); |
6899 ast_context()->ReturnInstruction(op, expr->id()); | 6898 ast_context()->ReturnInstruction(op, expr->id()); |
6900 return true; | 6899 return true; |
6901 } | 6900 } |
6902 break; | 6901 break; |
6903 case kMathPow: | 6902 case kMathPow: |
6904 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6903 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6905 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 6904 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
6906 HValue* right = Pop(); | 6905 HValue* right = Pop(); |
6907 HValue* left = Pop(); | 6906 HValue* left = Pop(); |
6908 Pop(); // Pop receiver. | 6907 Pop(); // Pop receiver. |
6909 HValue* context = environment()->LookupContext(); | 6908 HValue* context = environment()->LookupContext(); |
6910 HInstruction* result = NULL; | 6909 HInstruction* result = NULL; |
6911 // Use sqrt() if exponent is 0.5 or -0.5. | 6910 // Use sqrt() if exponent is 0.5 or -0.5. |
6912 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 6911 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
6913 double exponent = HConstant::cast(right)->DoubleValue(); | 6912 double exponent = HConstant::cast(right)->DoubleValue(); |
6914 if (exponent == 0.5) { | 6913 if (exponent == 0.5) { |
6915 result = | 6914 result = |
(...skipping 21 matching lines...) Expand all Loading... |
6937 | 6936 |
6938 if (result == NULL) { | 6937 if (result == NULL) { |
6939 result = new(zone()) HPower(left, right); | 6938 result = new(zone()) HPower(left, right); |
6940 } | 6939 } |
6941 ast_context()->ReturnInstruction(result, expr->id()); | 6940 ast_context()->ReturnInstruction(result, expr->id()); |
6942 return true; | 6941 return true; |
6943 } | 6942 } |
6944 break; | 6943 break; |
6945 case kMathRandom: | 6944 case kMathRandom: |
6946 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | 6945 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
6947 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 6946 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
6948 Drop(1); // Receiver. | 6947 Drop(1); // Receiver. |
6949 HValue* context = environment()->LookupContext(); | 6948 HValue* context = environment()->LookupContext(); |
6950 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 6949 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
6951 AddInstruction(global_object); | 6950 AddInstruction(global_object); |
6952 HRandom* result = new(zone()) HRandom(global_object); | 6951 HRandom* result = new(zone()) HRandom(global_object); |
6953 ast_context()->ReturnInstruction(result, expr->id()); | 6952 ast_context()->ReturnInstruction(result, expr->id()); |
6954 return true; | 6953 return true; |
6955 } | 6954 } |
6956 break; | 6955 break; |
6957 case kMathMax: | 6956 case kMathMax: |
6958 case kMathMin: | 6957 case kMathMin: |
6959 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6958 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6960 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 6959 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
6961 HValue* right = Pop(); | 6960 HValue* right = Pop(); |
6962 HValue* left = Pop(); | 6961 HValue* left = Pop(); |
6963 Pop(); // Pop receiver. | 6962 Pop(); // Pop receiver. |
6964 | 6963 |
6965 HValue* left_operand = left; | 6964 HValue* left_operand = left; |
6966 HValue* right_operand = right; | 6965 HValue* right_operand = right; |
6967 | 6966 |
6968 // If we do not have two integers, we convert to double for comparison. | 6967 // If we do not have two integers, we convert to double for comparison. |
6969 if (!left->representation().IsInteger32() || | 6968 if (!left->representation().IsInteger32() || |
6970 !right->representation().IsInteger32()) { | 6969 !right->representation().IsInteger32()) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7066 | 7065 |
7067 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 7066 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
7068 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 7067 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
7069 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 7068 HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
7070 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 7069 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
7071 | 7070 |
7072 // Found pattern f.apply(receiver, arguments). | 7071 // Found pattern f.apply(receiver, arguments). |
7073 VisitForValue(prop->obj()); | 7072 VisitForValue(prop->obj()); |
7074 if (HasStackOverflow() || current_block() == NULL) return true; | 7073 if (HasStackOverflow() || current_block() == NULL) return true; |
7075 HValue* function = Top(); | 7074 HValue* function = Top(); |
7076 AddCheckConstantFunction(expr, function, function_map, true); | 7075 AddCheckConstantFunction(expr->holder(), function, function_map, true); |
7077 Drop(1); | 7076 Drop(1); |
7078 | 7077 |
7079 VisitForValue(args->at(0)); | 7078 VisitForValue(args->at(0)); |
7080 if (HasStackOverflow() || current_block() == NULL) return true; | 7079 if (HasStackOverflow() || current_block() == NULL) return true; |
7081 HValue* receiver = Pop(); | 7080 HValue* receiver = Pop(); |
7082 | 7081 |
7083 if (function_state()->outer() == NULL) { | 7082 if (function_state()->outer() == NULL) { |
7084 HInstruction* elements = AddInstruction( | 7083 HInstruction* elements = AddInstruction( |
7085 new(zone()) HArgumentsElements(false)); | 7084 new(zone()) HArgumentsElements(false)); |
7086 HInstruction* length = | 7085 HInstruction* length = |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7185 | 7184 |
7186 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 7185 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
7187 expr->check_type() != RECEIVER_MAP_CHECK) { | 7186 expr->check_type() != RECEIVER_MAP_CHECK) { |
7188 // When the target has a custom call IC generator, use the IC, | 7187 // When the target has a custom call IC generator, use the IC, |
7189 // because it is likely to generate better code. Also use the IC | 7188 // because it is likely to generate better code. Also use the IC |
7190 // when a primitive receiver check is required. | 7189 // when a primitive receiver check is required. |
7191 HValue* context = environment()->LookupContext(); | 7190 HValue* context = environment()->LookupContext(); |
7192 call = PreProcessCall( | 7191 call = PreProcessCall( |
7193 new(zone()) HCallNamed(context, name, argument_count)); | 7192 new(zone()) HCallNamed(context, name, argument_count)); |
7194 } else { | 7193 } else { |
7195 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 7194 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
7196 | 7195 |
7197 if (TryInlineCall(expr)) return; | 7196 if (TryInlineCall(expr)) return; |
7198 call = PreProcessCall( | 7197 call = PreProcessCall( |
7199 new(zone()) HCallConstantFunction(expr->target(), | 7198 new(zone()) HCallConstantFunction(expr->target(), |
7200 argument_count)); | 7199 argument_count)); |
7201 } | 7200 } |
7202 } else if (types != NULL && types->length() > 1) { | 7201 } else if (types != NULL && types->length() > 1) { |
7203 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7202 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
7204 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7203 HandlePolymorphicCallNamed(expr, receiver, types, name); |
7205 return; | 7204 return; |
(...skipping 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9519 } | 9518 } |
9520 } | 9519 } |
9521 | 9520 |
9522 #ifdef DEBUG | 9521 #ifdef DEBUG |
9523 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9522 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9524 if (allocator_ != NULL) allocator_->Verify(); | 9523 if (allocator_ != NULL) allocator_->Verify(); |
9525 #endif | 9524 #endif |
9526 } | 9525 } |
9527 | 9526 |
9528 } } // namespace v8::internal | 9527 } } // namespace v8::internal |
OLD | NEW |