Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(442)

Unified Diff: src/hydrogen.cc

Issue 23726041: Turn the NumberToStringStub into a hydrogen stub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Using IfBuilder with JoinContinuation Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index b5cebbe327e10f9612bfd8cdee581ed7fc80b0d2..30824dad09cdc798e83a3bdf707be52da7fbed5a 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -804,6 +804,28 @@ void HGraphBuilder::IfBuilder::CaptureContinuation(
}
+void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
+ ASSERT(!finished_);
+ ASSERT(!captured_);
+ HBasicBlock* true_block = last_true_block_ == NULL
+ ? first_true_block_
+ : last_true_block_;
+ HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL)
+ ? builder_->current_block()
+ : first_false_block_;
+ if (true_block != NULL && !true_block->IsFinished()) {
+ ASSERT(continuation->IsTrueReachable());
+ true_block->GotoNoSimulate(continuation->true_branch());
+ }
+ if (false_block != NULL && !false_block->IsFinished()) {
+ ASSERT(continuation->IsFalseReachable());
+ false_block->GotoNoSimulate(continuation->false_branch());
+ }
+ captured_ = true;
+ End();
+}
+
+
void HGraphBuilder::IfBuilder::Then() {
ASSERT(!captured_);
ASSERT(!finished_);
@@ -1249,6 +1271,142 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
}
+HValue* HGraphBuilder::BuildLookupNumberStringCache(
+ HValue* object,
+ HIfContinuation* continuation) {
+ // Create a joinable continuation.
+ HIfContinuation found(graph()->CreateBasicBlock(),
+ graph()->CreateBasicBlock());
+
+ // Load the number string cache.
+ HValue* number_string_cache =
+ Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
+
+ // Make the hash maks from the length of the number string cache. It
+ // contains two elements (number and string) for each cache entry.
+ HValue* mask = AddLoadFixedArrayLength(number_string_cache);
+ mask->set_type(HType::Smi());
+ mask = Add<HSar>(mask, graph()->GetConstant1());
+ mask = Add<HSub>(mask, graph()->GetConstant1());
+
+ // Check whether object is a smi.
+ IfBuilder if_objectissmi(this);
+ if_objectissmi.If<HIsSmiAndBranch>(object);
+ if_objectissmi.Then();
+ {
+ // Compute hash for smi similar to smi_get_hash().
+ HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask);
+
+ // Load the key.
+ HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
+ HValue* key = AddFastElementAccess(number_string_cache, key_index,
+ NULL, NULL, FAST_ELEMENTS, false,
+ ALLOW_RETURN_HOLE, STANDARD_STORE);
+
+ // Check if object == key.
+ IfBuilder if_objectiskey(this);
+ if_objectiskey.If<HCompareObjectEqAndBranch>(key, object);
+ if_objectiskey.Then();
+ {
+ // Make the key_index available.
+ Push(key_index);
+ }
+ if_objectiskey.JoinContinuation(&found);
+ }
+ if_objectissmi.Else();
mvstanton 2013/09/23 09:32:34 All this is really nice that you can use the IfBui
+ {
+ // Check if object is a heap number.
+ IfBuilder if_objectisnumber(this);
+ if_objectisnumber.If<HCompareMap>(
+ object, isolate()->factory()->heap_number_map());
+ if_objectisnumber.Then();
+ {
+ // Compute hash for heap number similar to double_get_hash().
+ HValue* low = Add<HLoadNamedField>(
+ object, HObjectAccess::ForHeapNumberValueLowestBits());
+ HValue* high = Add<HLoadNamedField>(
+ object, HObjectAccess::ForHeapNumberValueHighestBits());
+ HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high);
+ hash = Add<HBitwise>(Token::BIT_AND, hash, mask);
+
+ // Load the key.
+ HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
+ HValue* key = AddFastElementAccess(number_string_cache, key_index,
+ NULL, NULL, FAST_ELEMENTS, false,
+ ALLOW_RETURN_HOLE, STANDARD_STORE);
+
+ // Check if key is a heap number.
+ IfBuilder if_keyisnumber(this);
+ if_keyisnumber.IfNot<HIsSmiAndBranch>(key);
+ if_keyisnumber.AndIf<HCompareMap>(
+ key, isolate()->factory()->heap_number_map());
+ if_keyisnumber.Then();
+ {
+ // Check if values of key and object match.
+ IfBuilder if_keyeqobject(this);
+ if_keyeqobject.If<HCompareNumericAndBranch>(
+ Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()),
+ Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()),
+ Token::EQ);
+ if_keyeqobject.Then();
+ {
+ // Make the key_index available.
+ Push(key_index);
+ }
+ if_keyeqobject.JoinContinuation(&found);
+ }
+ if_keyisnumber.JoinContinuation(&found);
+ }
+ if_objectisnumber.JoinContinuation(&found);
+ }
+ if_objectissmi.End();
+
+ // Check for cache hit.
+ IfBuilder if_found(this, &found);
+ if_found.Then();
+
+ // Load the value in case of cache hit.
+ HValue* key_index = Pop();
+ HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1());
+ HValue* value = AddFastElementAccess(number_string_cache, value_index,
+ NULL, NULL, FAST_ELEMENTS, false,
+ ALLOW_RETURN_HOLE, STANDARD_STORE);
+ AddIncrementCounter(isolate()->counters()->number_to_string_native());
+
+ if_found.CaptureContinuation(continuation);
+
+ // The value is only available in true branch of continuation.
+ return value;
+}
+
+
+HValue* HGraphBuilder::BuildNumberToString(HValue* number) {
+ NoObservableSideEffectsScope scope(this);
+
+ // Lookup the number in the number string cache.
+ HIfContinuation continuation;
+ HValue* value = BuildLookupNumberStringCache(number, &continuation);
+ IfBuilder if_found(this, &continuation);
+ if_found.Then();
+
+ // Cache hit.
+ Push(value);
+
+ if_found.Else();
+
+ // Cache miss, fallback to runtime.
+ Add<HPushArgument>(number);
+ Push(Add<HCallRuntime>(
+ isolate()->factory()->empty_string(),
+ Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
+ 1));
+
+ if_found.End();
+
+ return Pop();
+}
+
+
HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HValue* checked_object,
HValue* key,
@@ -8868,12 +9026,8 @@ void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
// Fast support for number to string.
void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
ASSERT_EQ(1, call->arguments()->length());
- CHECK_ALIVE(VisitArgumentList(call->arguments()));
- HValue* context = environment()->context();
- HCallStub* result =
- new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
- Drop(1);
- return ast_context()->ReturnInstruction(result, call->id());
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+ return ast_context()->ReturnValue(BuildNumberToString(Pop()));
mvstanton 2013/09/23 09:32:34 Paranoia: This code reminds me of the problem that
Benedikt Meurer 2013/09/23 10:53:31 Done.
}
« src/code-stubs-hydrogen.cc ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698