| Index: src/builtins/builtins.cc
|
| diff --git a/src/builtins/builtins.cc b/src/builtins/builtins.cc
|
| index 71aacb6affe519e18f70dfaa743491fbb912c1ce..fa8ea3e4eac3e6ba6932f40d2979b65bcba909f9 100644
|
| --- a/src/builtins/builtins.cc
|
| +++ b/src/builtins/builtins.cc
|
| @@ -6,7 +6,6 @@
|
|
|
| #include "src/api-arguments.h"
|
| #include "src/api-natives.h"
|
| -#include "src/api.h"
|
| #include "src/base/ieee754.h"
|
| #include "src/base/once.h"
|
| #include "src/bootstrapper.h"
|
| @@ -389,6 +388,254 @@ void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
|
| context, object, key));
|
| }
|
|
|
| +namespace { // anonymous namespace for ObjectProtoToString()
|
| +
|
| +void IsString(CodeStubAssembler* assembler, compiler::Node* object,
|
| + CodeStubAssembler::Label* if_string,
|
| + CodeStubAssembler::Label* if_notstring) {
|
| + typedef compiler::Node Node;
|
| + typedef CodeStubAssembler::Label Label;
|
| +
|
| + Label if_notsmi(assembler);
|
| + assembler->Branch(assembler->WordIsSmi(object), if_notstring, &if_notsmi);
|
| +
|
| + assembler->Bind(&if_notsmi);
|
| + {
|
| + Node* instance_type = assembler->LoadInstanceType(object);
|
| +
|
| + assembler->Branch(
|
| + assembler->Int32LessThan(
|
| + instance_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
|
| + if_string, if_notstring);
|
| + }
|
| +}
|
| +
|
| +void ReturnToStringFormat(CodeStubAssembler* assembler, compiler::Node* context,
|
| + compiler::Node* string) {
|
| + typedef compiler::Node Node;
|
| +
|
| + Node* lhs = assembler->HeapConstant(
|
| + assembler->factory()->NewStringFromStaticChars("[object "));
|
| + Node* rhs = assembler->HeapConstant(
|
| + assembler->factory()->NewStringFromStaticChars("]"));
|
| +
|
| + Callable callable = CodeFactory::StringAdd(
|
| + assembler->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
|
| +
|
| + assembler->Return(assembler->CallStub(
|
| + callable, context, assembler->CallStub(callable, context, lhs, string),
|
| + rhs));
|
| +}
|
| +
|
| +void ReturnIfPrimitive(CodeStubAssembler* assembler,
|
| + compiler::Node* instance_type,
|
| + CodeStubAssembler::Label* return_string,
|
| + CodeStubAssembler::Label* return_boolean,
|
| + CodeStubAssembler::Label* return_number) {
|
| + assembler->GotoIf(
|
| + assembler->Int32LessThan(instance_type,
|
| + assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
|
| + return_string);
|
| +
|
| + assembler->GotoIf(assembler->Word32Equal(
|
| + instance_type, assembler->Int32Constant(ODDBALL_TYPE)),
|
| + return_boolean);
|
| +
|
| + assembler->GotoIf(
|
| + assembler->Word32Equal(instance_type,
|
| + assembler->Int32Constant(HEAP_NUMBER_TYPE)),
|
| + return_number);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// ES6 section 19.1.3.6 Object.prototype.toString
|
| +void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
|
| + typedef compiler::Node Node;
|
| + typedef CodeStubAssembler::Label Label;
|
| + typedef CodeStubAssembler::Variable Variable;
|
| +
|
| + Label return_undefined(assembler, Label::kDeferred),
|
| + return_null(assembler, Label::kDeferred),
|
| + return_arguments(assembler, Label::kDeferred), return_array(assembler),
|
| + return_api(assembler, Label::kDeferred), return_object(assembler),
|
| + return_regexp(assembler), return_function(assembler),
|
| + return_error(assembler), return_date(assembler), return_string(assembler),
|
| + return_boolean(assembler), return_jsvalue(assembler),
|
| + return_jsproxy(assembler, Label::kDeferred), return_number(assembler);
|
| +
|
| + Label if_isproxy(assembler, Label::kDeferred);
|
| +
|
| + Label checkstringtag(assembler);
|
| + Label if_tostringtag(assembler), if_notostringtag(assembler);
|
| +
|
| + Node* receiver = assembler->Parameter(0);
|
| + Node* context = assembler->Parameter(3);
|
| +
|
| + assembler->GotoIf(
|
| + assembler->Word32Equal(receiver, assembler->UndefinedConstant()),
|
| + &return_undefined);
|
| +
|
| + assembler->GotoIf(assembler->Word32Equal(receiver, assembler->NullConstant()),
|
| + &return_null);
|
| +
|
| + assembler->GotoIf(assembler->WordIsSmi(receiver), &return_number);
|
| +
|
| + Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
|
| + ReturnIfPrimitive(assembler, receiver_instance_type, &return_string,
|
| + &return_boolean, &return_number);
|
| +
|
| + // for proxies, check IsArray before getting @@toStringTag
|
| + Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged);
|
| + var_proxy_is_array.Bind(assembler->BooleanConstant(false));
|
| +
|
| + assembler->Branch(
|
| + assembler->Word32Equal(receiver_instance_type,
|
| + assembler->Int32Constant(JS_PROXY_TYPE)),
|
| + &if_isproxy, &checkstringtag);
|
| +
|
| + assembler->Bind(&if_isproxy);
|
| + {
|
| + // This can throw
|
| + var_proxy_is_array.Bind(
|
| + assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver));
|
| + assembler->Goto(&checkstringtag);
|
| + }
|
| +
|
| + assembler->Bind(&checkstringtag);
|
| + {
|
| + Node* to_string_tag_symbol = assembler->HeapConstant(
|
| + assembler->isolate()->factory()->to_string_tag_symbol());
|
| +
|
| + GetPropertyStub stub(assembler->isolate());
|
| + Callable get_property =
|
| + Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
| + Node* to_string_tag_value = assembler->CallStub(
|
| + get_property, context, receiver, to_string_tag_symbol);
|
| +
|
| + IsString(assembler, to_string_tag_value, &if_tostringtag,
|
| + &if_notostringtag);
|
| +
|
| + assembler->Bind(&if_tostringtag);
|
| + ReturnToStringFormat(assembler, context, to_string_tag_value);
|
| + }
|
| + assembler->Bind(&if_notostringtag);
|
| + {
|
| + size_t const kNumCases = 11;
|
| + Label* case_labels[kNumCases];
|
| + int32_t case_values[kNumCases];
|
| + case_labels[0] = &return_api;
|
| + case_values[0] = JS_API_OBJECT_TYPE;
|
| + case_labels[1] = &return_api;
|
| + case_values[1] = JS_SPECIAL_API_OBJECT_TYPE;
|
| + case_labels[2] = &return_arguments;
|
| + case_values[2] = JS_ARGUMENTS_TYPE;
|
| + case_labels[3] = &return_array;
|
| + case_values[3] = JS_ARRAY_TYPE;
|
| + case_labels[4] = &return_function;
|
| + case_values[4] = JS_BOUND_FUNCTION_TYPE;
|
| + case_labels[5] = &return_function;
|
| + case_values[5] = JS_FUNCTION_TYPE;
|
| + case_labels[6] = &return_error;
|
| + case_values[6] = JS_ERROR_TYPE;
|
| + case_labels[7] = &return_date;
|
| + case_values[7] = JS_DATE_TYPE;
|
| + case_labels[8] = &return_regexp;
|
| + case_values[8] = JS_REGEXP_TYPE;
|
| + case_labels[9] = &return_jsvalue;
|
| + case_values[9] = JS_VALUE_TYPE;
|
| + case_labels[10] = &return_jsproxy;
|
| + case_values[10] = JS_PROXY_TYPE;
|
| +
|
| + assembler->Switch(receiver_instance_type, &return_object, case_values,
|
| + case_labels, arraysize(case_values));
|
| +
|
| + assembler->Bind(&return_undefined);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->undefined_to_string()));
|
| +
|
| + assembler->Bind(&return_null);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->null_to_string()));
|
| +
|
| + assembler->Bind(&return_number);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->number_to_string()));
|
| +
|
| + assembler->Bind(&return_string);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->string_to_string()));
|
| +
|
| + assembler->Bind(&return_boolean);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->boolean_to_string()));
|
| +
|
| + assembler->Bind(&return_arguments);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->arguments_to_string()));
|
| +
|
| + assembler->Bind(&return_array);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->array_to_string()));
|
| +
|
| + assembler->Bind(&return_function);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->function_to_string()));
|
| +
|
| + assembler->Bind(&return_error);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->error_to_string()));
|
| +
|
| + assembler->Bind(&return_date);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->date_to_string()));
|
| +
|
| + assembler->Bind(&return_regexp);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->regexp_to_string()));
|
| +
|
| + assembler->Bind(&return_api);
|
| + {
|
| + Node* class_name =
|
| + assembler->CallRuntime(Runtime::kClassOf, context, receiver);
|
| + ReturnToStringFormat(assembler, context, class_name);
|
| + }
|
| +
|
| + assembler->Bind(&return_jsvalue);
|
| + {
|
| + Node* value = assembler->LoadJSValueValue(receiver);
|
| + assembler->GotoIf(assembler->WordIsSmi(value), &return_number);
|
| +
|
| + ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value),
|
| + &return_string, &return_boolean, &return_number);
|
| + assembler->Goto(&return_object);
|
| + }
|
| +
|
| + assembler->Bind(&return_jsproxy);
|
| + {
|
| + assembler->GotoIf(assembler->WordEqual(var_proxy_is_array.value(),
|
| + assembler->BooleanConstant(true)),
|
| + &return_array);
|
| +
|
| + Node* map = assembler->LoadMap(receiver);
|
| +
|
| + // Return object if the proxy {receiver} is not callable.
|
| + assembler->Branch(
|
| + assembler->Word32Equal(
|
| + assembler->Word32And(
|
| + assembler->LoadMapBitField(map),
|
| + assembler->Int32Constant(1 << Map::kIsCallable)),
|
| + assembler->Int32Constant(0)),
|
| + &return_object, &return_function);
|
| + }
|
| +
|
| + // Default
|
| + assembler->Bind(&return_object);
|
| + assembler->Return(assembler->HeapConstant(
|
| + assembler->isolate()->factory()->object_to_string()));
|
| + }
|
| +}
|
| +
|
| namespace {
|
|
|
| Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) {
|
| @@ -4893,14 +5140,6 @@ BUILTIN(ObjectPrototypePropertyIsEnumerable) {
|
| return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
|
| }
|
|
|
| -// ES6 section 19.1.3.6 Object.prototype.toString
|
| -BUILTIN(ObjectProtoToString) {
|
| - HandleScope scope(isolate);
|
| - Handle<Object> object = args.at<Object>(0);
|
| - RETURN_RESULT_OR_FAILURE(isolate,
|
| - Object::ObjectProtoToString(isolate, object));
|
| -}
|
| -
|
| // -----------------------------------------------------------------------------
|
| // ES6 section 19.4 Symbol Objects
|
|
|
|
|