| Index: src/hydrogen.cc
|
| ===================================================================
|
| --- src/hydrogen.cc (revision 7161)
|
| +++ src/hydrogen.cc (working copy)
|
| @@ -2136,6 +2136,8 @@
|
|
|
| HGraph* HGraphBuilder::CreateGraph() {
|
| graph_ = new HGraph(info());
|
| + if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info());
|
| +
|
| {
|
| HPhase phase("Block building");
|
| current_block_ = graph()->entry_block();
|
| @@ -3701,6 +3703,13 @@
|
| FIRST_STRING_TYPE,
|
| LAST_STRING_TYPE));
|
| instr = new HStringLength(string);
|
| + } else if (expr->IsStringAccess()) {
|
| + VISIT_FOR_VALUE(expr->key());
|
| + HValue* index = Pop();
|
| + HValue* string = Pop();
|
| + HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
|
| + AddInstruction(char_code);
|
| + instr = new HStringCharFromCode(char_code);
|
|
|
| } else if (expr->IsFunctionPrototype()) {
|
| HValue* function = Pop();
|
| @@ -4081,6 +4090,7 @@
|
| int argument_count = expr->arguments()->length() + 1; // Plus receiver.
|
| switch (id) {
|
| case kStringCharCodeAt:
|
| + case kStringCharAt:
|
| if (argument_count == 2 && check_type == STRING_CHECK) {
|
| HValue* index = Pop();
|
| HValue* string = Pop();
|
| @@ -4088,7 +4098,13 @@
|
| AddInstruction(new HCheckPrototypeMaps(
|
| oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
|
| expr->holder()));
|
| - HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
|
| + HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
|
| + if (id == kStringCharCodeAt) {
|
| + ast_context()->ReturnInstruction(char_code, expr->id());
|
| + return true;
|
| + }
|
| + AddInstruction(char_code);
|
| + HStringCharFromCode* result = new HStringCharFromCode(char_code);
|
| ast_context()->ReturnInstruction(result, expr->id());
|
| return true;
|
| }
|
| @@ -4265,10 +4281,12 @@
|
| }
|
|
|
| if (HasCustomCallGenerator(expr->target()) ||
|
| + CallOptimization(*expr->target()).is_simple_api_call() ||
|
| expr->check_type() != RECEIVER_MAP_CHECK) {
|
| // When the target has a custom call IC generator, use the IC,
|
| - // because it is likely to generate better code. Also use the
|
| - // IC when a primitive receiver check is required.
|
| + // because it is likely to generate better code. Similarly, we
|
| + // generate better call stubs for some API functions.
|
| + // Also use the IC when a primitive receiver check is required.
|
| HContext* context = new HContext;
|
| AddInstruction(context);
|
| call = PreProcessCall(new HCallNamed(context, name, argument_count));
|
| @@ -5174,19 +5192,24 @@
|
|
|
| // Fast support for string.charAt(n) and string[n].
|
| void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
|
| - BAILOUT("inlined runtime function: StringCharFromCode");
|
| + ASSERT(call->arguments()->length() == 1);
|
| + VISIT_FOR_VALUE(call->arguments()->at(0));
|
| + HValue* char_code = Pop();
|
| + HStringCharFromCode* result = new HStringCharFromCode(char_code);
|
| + ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
|
|
| // Fast support for string.charAt(n) and string[n].
|
| void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
|
| - ASSERT_EQ(2, call->arguments()->length());
|
| - VisitArgumentList(call->arguments());
|
| - CHECK_BAILOUT;
|
| - HContext* context = new HContext;
|
| - AddInstruction(context);
|
| - HCallStub* result = new HCallStub(context, CodeStub::StringCharAt, 2);
|
| - Drop(2);
|
| + ASSERT(call->arguments()->length() == 2);
|
| + VISIT_FOR_VALUE(call->arguments()->at(0));
|
| + VISIT_FOR_VALUE(call->arguments()->at(1));
|
| + HValue* index = Pop();
|
| + HValue* string = Pop();
|
| + HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
|
| + AddInstruction(char_code);
|
| + HStringCharFromCode* result = new HStringCharFromCode(char_code);
|
| ast_context()->ReturnInstruction(result, call->id());
|
| }
|
|
|
| @@ -5736,12 +5759,12 @@
|
| Tag tag(this, "intervals");
|
| PrintStringProperty("name", name);
|
|
|
| - const ZoneList<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
|
| + const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
|
| for (int i = 0; i < fixed_d->length(); ++i) {
|
| TraceLiveRange(fixed_d->at(i), "fixed");
|
| }
|
|
|
| - const ZoneList<LiveRange*>* fixed = allocator->fixed_live_ranges();
|
| + const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
|
| for (int i = 0; i < fixed->length(); ++i) {
|
| TraceLiveRange(fixed->at(i), "fixed");
|
| }
|
| @@ -5812,6 +5835,11 @@
|
| }
|
|
|
|
|
| +void HStatistics::Initialize(CompilationInfo* info) {
|
| + source_size_ += info->shared_info()->SourceSize();
|
| +}
|
| +
|
| +
|
| void HStatistics::Print() {
|
| PrintF("Timing results:\n");
|
| int64_t sum = 0;
|
| @@ -5829,9 +5857,10 @@
|
| double size_percent = static_cast<double>(size) * 100 / total_size_;
|
| PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
|
| }
|
| - PrintF("%30s - %7.3f ms %8u bytes\n", "Sum",
|
| - static_cast<double>(sum) / 1000,
|
| - total_size_);
|
| + double source_size_in_kb = static_cast<double>(source_size_) / 1024;
|
| + PrintF("%30s - %7.3f ms %7.3f bytes\n", "Sum",
|
| + (static_cast<double>(sum) / 1000) / source_size_in_kb,
|
| + total_size_ / source_size_in_kb);
|
| PrintF("---------------------------------------------------------------\n");
|
| PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
|
| "Total",
|
| @@ -5876,13 +5905,13 @@
|
| if (allocator != NULL && chunk_ == NULL) {
|
| chunk_ = allocator->chunk();
|
| }
|
| - if (FLAG_time_hydrogen) start_ = OS::Ticks();
|
| + if (FLAG_hydrogen_stats) start_ = OS::Ticks();
|
| start_allocation_size_ = Zone::allocation_size_;
|
| }
|
|
|
|
|
| void HPhase::End() const {
|
| - if (FLAG_time_hydrogen) {
|
| + if (FLAG_hydrogen_stats) {
|
| int64_t end = OS::Ticks();
|
| unsigned size = Zone::allocation_size_ - start_allocation_size_;
|
| HStatistics::Instance()->SaveTiming(name_, end - start_, size);
|
|
|