Index: src/code-stubs-hydrogen.cc |
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc |
index 65bcd4561063f23b7ec3053bcce6b24c2875636c..e431a73f2ed13f4913e1b9ec952784092b4cd5f9 100644 |
--- a/src/code-stubs-hydrogen.cc |
+++ b/src/code-stubs-hydrogen.cc |
@@ -299,6 +299,125 @@ Handle<Code> NumberToStringStub::GenerateCode() { |
} |
+// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47). |
+// Possible optimizations: put the type string into the oddballs. |
+template <> |
+HValue* CodeStubGraphBuilder<TypeofStub>::BuildCodeStub() { |
+ Factory* factory = isolate()->factory(); |
+ HConstant* number_string = Add<HConstant>(factory->number_string()); |
+ HValue* object = GetParameter(TypeofStub::kObject); |
+ |
+ IfBuilder is_smi(this); |
+ HValue* smi_check = is_smi.If<HIsSmiAndBranch>(object); |
+ is_smi.Then(); |
+ { Push(number_string); } |
+ is_smi.Else(); |
+ { |
+ HValue* map = AddLoadMap(object, smi_check); |
+ HConstant* number_map = |
+ Add<HConstant>(isolate()->factory()->heap_number_map()); |
+ IfBuilder is_number(this); |
+ is_number.If<HCompareObjectEqAndBranch>(map, number_map); |
+ is_number.Then(); |
+ { Push(number_string); } |
+ is_number.Else(); |
+ { |
+ // Is it an undetectable object? |
+ HConstant* undefined_string = Add<HConstant>(factory->undefined_string()); |
+ HValue* bit_field = |
+ Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField()); |
+ HValue* is_undetectable_mask = Add<HConstant>(1 << Map::kIsUndetectable); |
+ HValue* is_undetectable_test = AddUncasted<HBitwise>( |
+ Token::BIT_AND, bit_field, is_undetectable_mask); |
+ IfBuilder is_undetectable(this); |
+ is_undetectable.If<HCompareNumericAndBranch>( |
+ is_undetectable_test, graph()->GetConstant0(), Token::NE); |
+ is_undetectable.Then(); |
+ { |
+ // typeof an undetectable object is 'undefined'. |
+ Push(undefined_string); |
+ } |
+ is_undetectable.Else(); |
+ { |
+ HValue* instance_type = Add<HLoadNamedField>( |
+ map, nullptr, HObjectAccess::ForMapInstanceType()); |
+ IfBuilder is_string(this); |
+ is_string.If<HCompareNumericAndBranch>( |
+ instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE), Token::LT); |
+ is_string.Then(); |
+ { Push(Add<HConstant>(factory->string_string())); } |
+ is_string.Else(); |
+ |
+ HConstant* object_string = Add<HConstant>(factory->object_string()); |
+ IfBuilder is_oddball(this); |
+ is_oddball.If<HCompareNumericAndBranch>( |
+ instance_type, Add<HConstant>(ODDBALL_TYPE), Token::EQ); |
+ is_oddball.Then(); |
+ { |
+ IfBuilder is_true_or_false(this); |
+ is_true_or_false.If<HCompareObjectEqAndBranch>( |
+ object, graph()->GetConstantTrue()); |
+ is_true_or_false.OrIf<HCompareObjectEqAndBranch>( |
+ object, graph()->GetConstantFalse()); |
+ is_true_or_false.Then(); |
+ { Push(Add<HConstant>(factory->boolean_string())); } |
+ is_true_or_false.Else(); |
+ { |
+ IfBuilder is_null(this); |
+ is_null.If<HCompareObjectEqAndBranch>(object, |
+ graph()->GetConstantNull()); |
+ is_null.Then(); |
+ { Push(object_string); } |
+ is_null.Else(); |
+ { Push(undefined_string); } |
+ } |
+ is_true_or_false.End(); |
+ } |
+ is_oddball.Else(); |
+ { |
+ IfBuilder is_symbol(this); |
+ is_symbol.If<HCompareNumericAndBranch>( |
+ instance_type, Add<HConstant>(SYMBOL_TYPE), Token::EQ); |
+ is_symbol.Then(); |
+ { Push(Add<HConstant>(factory->symbol_string())); } |
+ is_symbol.Else(); |
+ { |
+ IfBuilder is_function(this); |
+ HConstant* js_function = Add<HConstant>(JS_FUNCTION_TYPE); |
+ HConstant* js_function_proxy = |
+ Add<HConstant>(JS_FUNCTION_PROXY_TYPE); |
+ is_function.If<HCompareNumericAndBranch>(instance_type, js_function, |
+ Token::EQ); |
+ is_function.OrIf<HCompareNumericAndBranch>( |
+ instance_type, js_function_proxy, Token::EQ); |
+ is_function.Then(); |
+ { Push(Add<HConstant>(factory->function_string())); } |
+ is_function.Else(); |
+ { |
+ // For any kind of object not handled above, the spec rule for |
+ // host objects gives that it is okay to return "object". |
+ Push(object_string); |
+ } |
+ is_function.End(); |
+ } |
+ is_symbol.End(); |
+ } |
+ is_oddball.End(); |
+ is_string.End(); |
+ } |
+ is_undetectable.End(); |
+ } |
+ is_number.End(); |
+ } |
+ is_smi.End(); |
+ |
+ return environment()->Pop(); |
+} |
+ |
+ |
+Handle<Code> TypeofStub::GenerateCode() { return DoGenerateCode(this); } |
+ |
+ |
template <> |
HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { |
Factory* factory = isolate()->factory(); |