| 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 2118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2129 | 2129 |
| 2130 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { | 2130 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { |
| 2131 for (int i = 0; i < exprs->length(); ++i) { | 2131 for (int i = 0; i < exprs->length(); ++i) { |
| 2132 VISIT_FOR_VALUE(exprs->at(i)); | 2132 VISIT_FOR_VALUE(exprs->at(i)); |
| 2133 } | 2133 } |
| 2134 } | 2134 } |
| 2135 | 2135 |
| 2136 | 2136 |
| 2137 HGraph* HGraphBuilder::CreateGraph() { | 2137 HGraph* HGraphBuilder::CreateGraph() { |
| 2138 graph_ = new HGraph(info()); | 2138 graph_ = new HGraph(info()); |
| 2139 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); |
| 2140 |
| 2139 { | 2141 { |
| 2140 HPhase phase("Block building"); | 2142 HPhase phase("Block building"); |
| 2141 current_block_ = graph()->entry_block(); | 2143 current_block_ = graph()->entry_block(); |
| 2142 | 2144 |
| 2143 Scope* scope = info()->scope(); | 2145 Scope* scope = info()->scope(); |
| 2144 if (scope->HasIllegalRedeclaration()) { | 2146 if (scope->HasIllegalRedeclaration()) { |
| 2145 Bailout("function with illegal redeclaration"); | 2147 Bailout("function with illegal redeclaration"); |
| 2146 return NULL; | 2148 return NULL; |
| 2147 } | 2149 } |
| 2148 SetupScope(scope); | 2150 SetupScope(scope); |
| (...skipping 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3694 AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE)); | 3696 AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE)); |
| 3695 instr = new HJSArrayLength(array); | 3697 instr = new HJSArrayLength(array); |
| 3696 | 3698 |
| 3697 } else if (expr->IsStringLength()) { | 3699 } else if (expr->IsStringLength()) { |
| 3698 HValue* string = Pop(); | 3700 HValue* string = Pop(); |
| 3699 AddInstruction(new HCheckNonSmi(string)); | 3701 AddInstruction(new HCheckNonSmi(string)); |
| 3700 AddInstruction(new HCheckInstanceType(string, | 3702 AddInstruction(new HCheckInstanceType(string, |
| 3701 FIRST_STRING_TYPE, | 3703 FIRST_STRING_TYPE, |
| 3702 LAST_STRING_TYPE)); | 3704 LAST_STRING_TYPE)); |
| 3703 instr = new HStringLength(string); | 3705 instr = new HStringLength(string); |
| 3706 } else if (expr->IsStringAccess()) { |
| 3707 VISIT_FOR_VALUE(expr->key()); |
| 3708 HValue* index = Pop(); |
| 3709 HValue* string = Pop(); |
| 3710 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| 3711 AddInstruction(char_code); |
| 3712 instr = new HStringCharFromCode(char_code); |
| 3704 | 3713 |
| 3705 } else if (expr->IsFunctionPrototype()) { | 3714 } else if (expr->IsFunctionPrototype()) { |
| 3706 HValue* function = Pop(); | 3715 HValue* function = Pop(); |
| 3707 AddInstruction(new HCheckNonSmi(function)); | 3716 AddInstruction(new HCheckNonSmi(function)); |
| 3708 instr = new HLoadFunctionPrototype(function); | 3717 instr = new HLoadFunctionPrototype(function); |
| 3709 | 3718 |
| 3710 } else if (expr->key()->IsPropertyName()) { | 3719 } else if (expr->key()->IsPropertyName()) { |
| 3711 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3720 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 3712 ZoneMapList* types = expr->GetReceiverTypes(); | 3721 ZoneMapList* types = expr->GetReceiverTypes(); |
| 3713 | 3722 |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4074 HValue* receiver, | 4083 HValue* receiver, |
| 4075 Handle<Map> receiver_map, | 4084 Handle<Map> receiver_map, |
| 4076 CheckType check_type) { | 4085 CheckType check_type) { |
| 4077 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | 4086 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); |
| 4078 // Try to inline calls like Math.* as operations in the calling function. | 4087 // Try to inline calls like Math.* as operations in the calling function. |
| 4079 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 4088 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 4080 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 4089 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 4081 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4090 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 4082 switch (id) { | 4091 switch (id) { |
| 4083 case kStringCharCodeAt: | 4092 case kStringCharCodeAt: |
| 4093 case kStringCharAt: |
| 4084 if (argument_count == 2 && check_type == STRING_CHECK) { | 4094 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 4085 HValue* index = Pop(); | 4095 HValue* index = Pop(); |
| 4086 HValue* string = Pop(); | 4096 HValue* string = Pop(); |
| 4087 ASSERT(!expr->holder().is_null()); | 4097 ASSERT(!expr->holder().is_null()); |
| 4088 AddInstruction(new HCheckPrototypeMaps( | 4098 AddInstruction(new HCheckPrototypeMaps( |
| 4089 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), | 4099 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), |
| 4090 expr->holder())); | 4100 expr->holder())); |
| 4091 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); | 4101 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| 4102 if (id == kStringCharCodeAt) { |
| 4103 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 4104 return true; |
| 4105 } |
| 4106 AddInstruction(char_code); |
| 4107 HStringCharFromCode* result = new HStringCharFromCode(char_code); |
| 4092 ast_context()->ReturnInstruction(result, expr->id()); | 4108 ast_context()->ReturnInstruction(result, expr->id()); |
| 4093 return true; | 4109 return true; |
| 4094 } | 4110 } |
| 4095 break; | 4111 break; |
| 4096 case kMathRound: | 4112 case kMathRound: |
| 4097 case kMathFloor: | 4113 case kMathFloor: |
| 4098 case kMathAbs: | 4114 case kMathAbs: |
| 4099 case kMathSqrt: | 4115 case kMathSqrt: |
| 4100 case kMathLog: | 4116 case kMathLog: |
| 4101 case kMathSin: | 4117 case kMathSin: |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4258 Handle<Map> receiver_map = | 4274 Handle<Map> receiver_map = |
| 4259 (types == NULL) ? Handle<Map>::null() : types->first(); | 4275 (types == NULL) ? Handle<Map>::null() : types->first(); |
| 4260 if (TryInlineBuiltinFunction(expr, | 4276 if (TryInlineBuiltinFunction(expr, |
| 4261 receiver, | 4277 receiver, |
| 4262 receiver_map, | 4278 receiver_map, |
| 4263 expr->check_type())) { | 4279 expr->check_type())) { |
| 4264 return; | 4280 return; |
| 4265 } | 4281 } |
| 4266 | 4282 |
| 4267 if (HasCustomCallGenerator(expr->target()) || | 4283 if (HasCustomCallGenerator(expr->target()) || |
| 4284 CallOptimization(*expr->target()).is_simple_api_call() || |
| 4268 expr->check_type() != RECEIVER_MAP_CHECK) { | 4285 expr->check_type() != RECEIVER_MAP_CHECK) { |
| 4269 // When the target has a custom call IC generator, use the IC, | 4286 // When the target has a custom call IC generator, use the IC, |
| 4270 // because it is likely to generate better code. Also use the | 4287 // because it is likely to generate better code. Similarly, we |
| 4271 // IC when a primitive receiver check is required. | 4288 // generate better call stubs for some API functions. |
| 4289 // Also use the IC when a primitive receiver check is required. |
| 4272 HContext* context = new HContext; | 4290 HContext* context = new HContext; |
| 4273 AddInstruction(context); | 4291 AddInstruction(context); |
| 4274 call = PreProcessCall(new HCallNamed(context, name, argument_count)); | 4292 call = PreProcessCall(new HCallNamed(context, name, argument_count)); |
| 4275 } else { | 4293 } else { |
| 4276 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4294 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
| 4277 | 4295 |
| 4278 if (TryInline(expr)) { | 4296 if (TryInline(expr)) { |
| 4279 return; | 4297 return; |
| 4280 } else { | 4298 } else { |
| 4281 // Check for bailout, as the TryInline call in the if condition above | 4299 // Check for bailout, as the TryInline call in the if condition above |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5167 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5185 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5168 HValue* index = Pop(); | 5186 HValue* index = Pop(); |
| 5169 HValue* string = Pop(); | 5187 HValue* string = Pop(); |
| 5170 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); | 5188 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); |
| 5171 ast_context()->ReturnInstruction(result, call->id()); | 5189 ast_context()->ReturnInstruction(result, call->id()); |
| 5172 } | 5190 } |
| 5173 | 5191 |
| 5174 | 5192 |
| 5175 // Fast support for string.charAt(n) and string[n]. | 5193 // Fast support for string.charAt(n) and string[n]. |
| 5176 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 5194 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
| 5177 BAILOUT("inlined runtime function: StringCharFromCode"); | 5195 ASSERT(call->arguments()->length() == 1); |
| 5196 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5197 HValue* char_code = Pop(); |
| 5198 HStringCharFromCode* result = new HStringCharFromCode(char_code); |
| 5199 ast_context()->ReturnInstruction(result, call->id()); |
| 5178 } | 5200 } |
| 5179 | 5201 |
| 5180 | 5202 |
| 5181 // Fast support for string.charAt(n) and string[n]. | 5203 // Fast support for string.charAt(n) and string[n]. |
| 5182 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 5204 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
| 5183 ASSERT_EQ(2, call->arguments()->length()); | 5205 ASSERT(call->arguments()->length() == 2); |
| 5184 VisitArgumentList(call->arguments()); | 5206 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5185 CHECK_BAILOUT; | 5207 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5186 HContext* context = new HContext; | 5208 HValue* index = Pop(); |
| 5187 AddInstruction(context); | 5209 HValue* string = Pop(); |
| 5188 HCallStub* result = new HCallStub(context, CodeStub::StringCharAt, 2); | 5210 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| 5189 Drop(2); | 5211 AddInstruction(char_code); |
| 5212 HStringCharFromCode* result = new HStringCharFromCode(char_code); |
| 5190 ast_context()->ReturnInstruction(result, call->id()); | 5213 ast_context()->ReturnInstruction(result, call->id()); |
| 5191 } | 5214 } |
| 5192 | 5215 |
| 5193 | 5216 |
| 5194 // Fast support for object equality testing. | 5217 // Fast support for object equality testing. |
| 5195 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 5218 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
| 5196 ASSERT(call->arguments()->length() == 2); | 5219 ASSERT(call->arguments()->length() == 2); |
| 5197 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5220 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5198 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5221 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5199 HValue* right = Pop(); | 5222 HValue* right = Pop(); |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5729 } | 5752 } |
| 5730 } | 5753 } |
| 5731 } | 5754 } |
| 5732 } | 5755 } |
| 5733 | 5756 |
| 5734 | 5757 |
| 5735 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { | 5758 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { |
| 5736 Tag tag(this, "intervals"); | 5759 Tag tag(this, "intervals"); |
| 5737 PrintStringProperty("name", name); | 5760 PrintStringProperty("name", name); |
| 5738 | 5761 |
| 5739 const ZoneList<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); | 5762 const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); |
| 5740 for (int i = 0; i < fixed_d->length(); ++i) { | 5763 for (int i = 0; i < fixed_d->length(); ++i) { |
| 5741 TraceLiveRange(fixed_d->at(i), "fixed"); | 5764 TraceLiveRange(fixed_d->at(i), "fixed"); |
| 5742 } | 5765 } |
| 5743 | 5766 |
| 5744 const ZoneList<LiveRange*>* fixed = allocator->fixed_live_ranges(); | 5767 const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges(); |
| 5745 for (int i = 0; i < fixed->length(); ++i) { | 5768 for (int i = 0; i < fixed->length(); ++i) { |
| 5746 TraceLiveRange(fixed->at(i), "fixed"); | 5769 TraceLiveRange(fixed->at(i), "fixed"); |
| 5747 } | 5770 } |
| 5748 | 5771 |
| 5749 const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); | 5772 const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); |
| 5750 for (int i = 0; i < live_ranges->length(); ++i) { | 5773 for (int i = 0; i < live_ranges->length(); ++i) { |
| 5751 TraceLiveRange(live_ranges->at(i), "object"); | 5774 TraceLiveRange(live_ranges->at(i), "object"); |
| 5752 } | 5775 } |
| 5753 } | 5776 } |
| 5754 | 5777 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5805 } | 5828 } |
| 5806 } | 5829 } |
| 5807 | 5830 |
| 5808 | 5831 |
| 5809 void HTracer::FlushToFile() { | 5832 void HTracer::FlushToFile() { |
| 5810 AppendChars(filename_, *trace_.ToCString(), trace_.length(), false); | 5833 AppendChars(filename_, *trace_.ToCString(), trace_.length(), false); |
| 5811 trace_.Reset(); | 5834 trace_.Reset(); |
| 5812 } | 5835 } |
| 5813 | 5836 |
| 5814 | 5837 |
| 5838 void HStatistics::Initialize(CompilationInfo* info) { |
| 5839 source_size_ += info->shared_info()->SourceSize(); |
| 5840 } |
| 5841 |
| 5842 |
| 5815 void HStatistics::Print() { | 5843 void HStatistics::Print() { |
| 5816 PrintF("Timing results:\n"); | 5844 PrintF("Timing results:\n"); |
| 5817 int64_t sum = 0; | 5845 int64_t sum = 0; |
| 5818 for (int i = 0; i < timing_.length(); ++i) { | 5846 for (int i = 0; i < timing_.length(); ++i) { |
| 5819 sum += timing_[i]; | 5847 sum += timing_[i]; |
| 5820 } | 5848 } |
| 5821 | 5849 |
| 5822 for (int i = 0; i < names_.length(); ++i) { | 5850 for (int i = 0; i < names_.length(); ++i) { |
| 5823 PrintF("%30s", names_[i]); | 5851 PrintF("%30s", names_[i]); |
| 5824 double ms = static_cast<double>(timing_[i]) / 1000; | 5852 double ms = static_cast<double>(timing_[i]) / 1000; |
| 5825 double percent = static_cast<double>(timing_[i]) * 100 / sum; | 5853 double percent = static_cast<double>(timing_[i]) * 100 / sum; |
| 5826 PrintF(" - %7.3f ms / %4.1f %% ", ms, percent); | 5854 PrintF(" - %7.3f ms / %4.1f %% ", ms, percent); |
| 5827 | 5855 |
| 5828 unsigned size = sizes_[i]; | 5856 unsigned size = sizes_[i]; |
| 5829 double size_percent = static_cast<double>(size) * 100 / total_size_; | 5857 double size_percent = static_cast<double>(size) * 100 / total_size_; |
| 5830 PrintF(" %8u bytes / %4.1f %%\n", size, size_percent); | 5858 PrintF(" %8u bytes / %4.1f %%\n", size, size_percent); |
| 5831 } | 5859 } |
| 5832 PrintF("%30s - %7.3f ms %8u bytes\n", "Sum", | 5860 double source_size_in_kb = static_cast<double>(source_size_) / 1024; |
| 5833 static_cast<double>(sum) / 1000, | 5861 PrintF("%30s - %7.3f ms %7.3f bytes\n", "Sum", |
| 5834 total_size_); | 5862 (static_cast<double>(sum) / 1000) / source_size_in_kb, |
| 5863 total_size_ / source_size_in_kb); |
| 5835 PrintF("---------------------------------------------------------------\n"); | 5864 PrintF("---------------------------------------------------------------\n"); |
| 5836 PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n", | 5865 PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n", |
| 5837 "Total", | 5866 "Total", |
| 5838 static_cast<double>(total_) / 1000, | 5867 static_cast<double>(total_) / 1000, |
| 5839 static_cast<double>(total_) / full_code_gen_); | 5868 static_cast<double>(total_) / full_code_gen_); |
| 5840 } | 5869 } |
| 5841 | 5870 |
| 5842 | 5871 |
| 5843 void HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { | 5872 void HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { |
| 5844 if (name == HPhase::kFullCodeGen) { | 5873 if (name == HPhase::kFullCodeGen) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 5869 HGraph* graph, | 5898 HGraph* graph, |
| 5870 LChunk* chunk, | 5899 LChunk* chunk, |
| 5871 LAllocator* allocator) { | 5900 LAllocator* allocator) { |
| 5872 name_ = name; | 5901 name_ = name; |
| 5873 graph_ = graph; | 5902 graph_ = graph; |
| 5874 chunk_ = chunk; | 5903 chunk_ = chunk; |
| 5875 allocator_ = allocator; | 5904 allocator_ = allocator; |
| 5876 if (allocator != NULL && chunk_ == NULL) { | 5905 if (allocator != NULL && chunk_ == NULL) { |
| 5877 chunk_ = allocator->chunk(); | 5906 chunk_ = allocator->chunk(); |
| 5878 } | 5907 } |
| 5879 if (FLAG_time_hydrogen) start_ = OS::Ticks(); | 5908 if (FLAG_hydrogen_stats) start_ = OS::Ticks(); |
| 5880 start_allocation_size_ = Zone::allocation_size_; | 5909 start_allocation_size_ = Zone::allocation_size_; |
| 5881 } | 5910 } |
| 5882 | 5911 |
| 5883 | 5912 |
| 5884 void HPhase::End() const { | 5913 void HPhase::End() const { |
| 5885 if (FLAG_time_hydrogen) { | 5914 if (FLAG_hydrogen_stats) { |
| 5886 int64_t end = OS::Ticks(); | 5915 int64_t end = OS::Ticks(); |
| 5887 unsigned size = Zone::allocation_size_ - start_allocation_size_; | 5916 unsigned size = Zone::allocation_size_ - start_allocation_size_; |
| 5888 HStatistics::Instance()->SaveTiming(name_, end - start_, size); | 5917 HStatistics::Instance()->SaveTiming(name_, end - start_, size); |
| 5889 } | 5918 } |
| 5890 | 5919 |
| 5891 if (FLAG_trace_hydrogen) { | 5920 if (FLAG_trace_hydrogen) { |
| 5892 if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); | 5921 if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); |
| 5893 if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); | 5922 if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); |
| 5894 if (allocator_ != NULL) { | 5923 if (allocator_ != NULL) { |
| 5895 HTracer::Instance()->TraceLiveRanges(name_, allocator_); | 5924 HTracer::Instance()->TraceLiveRanges(name_, allocator_); |
| 5896 } | 5925 } |
| 5897 } | 5926 } |
| 5898 | 5927 |
| 5899 #ifdef DEBUG | 5928 #ifdef DEBUG |
| 5900 if (graph_ != NULL) graph_->Verify(); | 5929 if (graph_ != NULL) graph_->Verify(); |
| 5901 if (allocator_ != NULL) allocator_->Verify(); | 5930 if (allocator_ != NULL) allocator_->Verify(); |
| 5902 #endif | 5931 #endif |
| 5903 } | 5932 } |
| 5904 | 5933 |
| 5905 } } // namespace v8::internal | 5934 } } // namespace v8::internal |
| OLD | NEW |