Revision: 3437 Author: [email protected] Date: Wed Dec 9 05:06:08 2009 Log: Create literal boilerplate as part of cloning in the top-level compiler.
When generating code for object and array literals we performed the check if the a boilerplate already exists in generated code. In the top-level compiler we now do this check in a new runtime function. This makes the generated code more compact for top-level code. Review URL: http://codereview.chromium.org/465148 http://code.google.com/p/v8/source/detail?r=3437 Modified: /branches/bleeding_edge/src/arm/fast-codegen-arm.cc /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc /branches/bleeding_edge/src/runtime.cc /branches/bleeding_edge/src/runtime.h /branches/bleeding_edge/src/x64/fast-codegen-x64.cc ======================================= --- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Dec 7 07:10:39 2009 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Dec 9 05:06:08 2009 @@ -657,32 +657,15 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { Comment cmnt(masm_, "[ ObjectLiteral"); - Label boilerplate_exists; __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); - // r2 = literal array (0). __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); - int literal_offset = - FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; - __ ldr(r0, FieldMemOperand(r2, literal_offset)); - // Check whether we need to materialize the object literal boilerplate. - __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); - __ cmp(r0, Operand(ip)); - __ b(ne, &boilerplate_exists); - // Create boilerplate if it does not exist. - // r1 = literal index (1). __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); - // r0 = constant properties (2). __ mov(r0, Operand(expr->constant_properties())); __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); - __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); - __ bind(&boilerplate_exists); - // r0 contains boilerplate. - // Clone boilerplate. - __ push(r0); if (expr->depth() > 1) { - __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateObjectLiteral, 3); } else { - __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); } // If result_saved == true: The result is saved on top of the @@ -783,32 +766,15 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { Comment cmnt(masm_, "[ ArrayLiteral"); - Label make_clone; - - // Fetch the function's literals array. __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); - // Check if the literal's boilerplate has been instantiated. - int offset = - FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); - __ ldr(r0, FieldMemOperand(r3, offset)); - __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); - __ cmp(r0, ip); - __ b(&make_clone, ne); - - // Instantiate the boilerplate. __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); __ mov(r1, Operand(expr->literals())); __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); - __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); - - __ bind(&make_clone); - // Clone the boilerplate. - __ push(r0); if (expr->depth() > 1) { - __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateArrayLiteral, 3); } else { - __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } bool result_saved = false; // Is the result saved to the stack? ======================================= --- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Mon Dec 7 07:10:39 2009 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Wed Dec 9 05:06:08 2009 @@ -656,35 +656,14 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { Comment cmnt(masm_, "[ ObjectLiteral"); - Label exists; - // Registers will be used as follows: - // edi = JS function. - // ebx = literals array. - // eax = boilerplate - __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); - __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); - int literal_offset = - FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; - __ mov(eax, FieldOperand(ebx, literal_offset)); - __ cmp(eax, Factory::undefined_value()); - __ j(not_equal, &exists); - // Create boilerplate if it does not exist. - // Literal array (0). - __ push(ebx); - // Literal index (1). + __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); __ push(Immediate(Smi::FromInt(expr->literal_index()))); - // Constant properties (2). __ push(Immediate(expr->constant_properties())); - __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); - __ bind(&exists); - // eax contains boilerplate. - // Clone boilerplate. - __ push(eax); - if (expr->depth() == 1) { - __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); + if (expr->depth() > 1) { + __ CallRuntime(Runtime::kCreateObjectLiteral, 3); } else { - __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); } // If result_saved == true: The result is saved on top of the @@ -780,31 +759,14 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { Comment cmnt(masm_, "[ ArrayLiteral"); - Label make_clone; - - // Fetch the function's literals array. __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); - __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset)); - // Check if the literal's boilerplate has been instantiated. - int offset = - FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); - __ mov(eax, FieldOperand(ebx, offset)); - __ cmp(eax, Factory::undefined_value()); - __ j(not_equal, &make_clone); - - // Instantiate the boilerplate. - __ push(ebx); + __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); __ push(Immediate(Smi::FromInt(expr->literal_index()))); __ push(Immediate(expr->literals())); - __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); - - __ bind(&make_clone); - // Clone the boilerplate. - __ push(eax); if (expr->depth() > 1) { - __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateArrayLiteral, 3); } else { - __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } bool result_saved = false; // Is the result saved to the stack? ======================================= --- /branches/bleeding_edge/src/runtime.cc Fri Dec 4 03:59:09 2009 +++ /branches/bleeding_edge/src/runtime.cc Wed Dec 9 05:06:08 2009 @@ -396,6 +396,82 @@ literals->set(literals_index, *object); return *object; } + + +static Object* Runtime_CreateObjectLiteral(Arguments args) { + HandleScope scope; + ASSERT(args.length() == 3); + CONVERT_ARG_CHECKED(FixedArray, literals, 0); + CONVERT_SMI_CHECKED(literals_index, args[1]); + CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); + + // Check if boilerplate exists. If not, create it first. + Handle<Object> boilerplate(literals->get(literals_index)); + if (*boilerplate == Heap::undefined_value()) { + boilerplate = CreateObjectLiteralBoilerplate(literals, constant_properties); + if (boilerplate.is_null()) return Failure::Exception(); + // Update the functions literal and return the boilerplate. + literals->set(literals_index, *boilerplate); + } + return DeepCopyBoilerplate(JSObject::cast(*boilerplate)); +} + + +static Object* Runtime_CreateObjectLiteralShallow(Arguments args) { + HandleScope scope; + ASSERT(args.length() == 3); + CONVERT_ARG_CHECKED(FixedArray, literals, 0); + CONVERT_SMI_CHECKED(literals_index, args[1]); + CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); + + // Check if boilerplate exists. If not, create it first. + Handle<Object> boilerplate(literals->get(literals_index)); + if (*boilerplate == Heap::undefined_value()) { + boilerplate = CreateObjectLiteralBoilerplate(literals, constant_properties); + if (boilerplate.is_null()) return Failure::Exception(); + // Update the functions literal and return the boilerplate. + literals->set(literals_index, *boilerplate); + } + return Heap::CopyJSObject(JSObject::cast(*boilerplate)); +} + + +static Object* Runtime_CreateArrayLiteral(Arguments args) { + HandleScope scope; + ASSERT(args.length() == 3); + CONVERT_ARG_CHECKED(FixedArray, literals, 0); + CONVERT_SMI_CHECKED(literals_index, args[1]); + CONVERT_ARG_CHECKED(FixedArray, elements, 2); + + // Check if boilerplate exists. If not, create it first. + Handle<Object> boilerplate(literals->get(literals_index)); + if (*boilerplate == Heap::undefined_value()) { + boilerplate = CreateArrayLiteralBoilerplate(literals, elements); + if (boilerplate.is_null()) return Failure::Exception(); + // Update the functions literal and return the boilerplate. + literals->set(literals_index, *boilerplate); + } + return DeepCopyBoilerplate(JSObject::cast(*boilerplate)); +} + + +static Object* Runtime_CreateArrayLiteralShallow(Arguments args) { + HandleScope scope; + ASSERT(args.length() == 3); + CONVERT_ARG_CHECKED(FixedArray, literals, 0); + CONVERT_SMI_CHECKED(literals_index, args[1]); + CONVERT_ARG_CHECKED(FixedArray, elements, 2); + + // Check if boilerplate exists. If not, create it first. + Handle<Object> boilerplate(literals->get(literals_index)); + if (*boilerplate == Heap::undefined_value()) { + boilerplate = CreateArrayLiteralBoilerplate(literals, elements); + if (boilerplate.is_null()) return Failure::Exception(); + // Update the functions literal and return the boilerplate. + literals->set(literals_index, *boilerplate); + } + return Heap::CopyJSObject(JSObject::cast(*boilerplate)); +} static Object* Runtime_CreateCatchExtensionObject(Arguments args) { ======================================= --- /branches/bleeding_edge/src/runtime.h Mon Nov 30 06:56:20 2009 +++ /branches/bleeding_edge/src/runtime.h Wed Dec 9 05:06:08 2009 @@ -223,6 +223,10 @@ F(CreateObjectLiteralBoilerplate, 3, 1) \ F(CloneLiteralBoilerplate, 1, 1) \ F(CloneShallowLiteralBoilerplate, 1, 1) \ + F(CreateObjectLiteral, 3, 1) \ + F(CreateObjectLiteralShallow, 3, 1) \ + F(CreateArrayLiteral, 3, 1) \ + F(CreateArrayLiteralShallow, 3, 1) \ \ /* Catch context extension objects */ \ F(CreateCatchExtensionObject, 2, 1) \ ======================================= --- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Dec 7 07:10:39 2009 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Dec 9 05:06:08 2009 @@ -663,31 +663,14 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { Comment cmnt(masm_, "[ ObjectLiteral"); - Label boilerplate_exists; - __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); - __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); - int literal_offset = - FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; - __ movq(rax, FieldOperand(rbx, literal_offset)); - __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); - __ j(not_equal, &boilerplate_exists); - // Create boilerplate if it does not exist. - // Literal array (0). - __ push(rbx); - // Literal index (1). + __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); __ Push(Smi::FromInt(expr->literal_index())); - // Constant properties (2). __ Push(expr->constant_properties()); - __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); - __ bind(&boilerplate_exists); - // rax contains boilerplate. - // Clone boilerplate. - __ push(rax); - if (expr->depth() == 1) { - __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); + if (expr->depth() > 1) { + __ CallRuntime(Runtime::kCreateObjectLiteral, 3); } else { - __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); } // If result_saved == true: The result is saved on top of the @@ -783,31 +766,14 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { Comment cmnt(masm_, "[ ArrayLiteral"); - Label make_clone; - - // Fetch the function's literals array. __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); - __ movq(rbx, FieldOperand(rbx, JSFunction::kLiteralsOffset)); - // Check if the literal's boilerplate has been instantiated. - int offset = - FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); - __ movq(rax, FieldOperand(rbx, offset)); - __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); - __ j(not_equal, &make_clone); - - // Instantiate the boilerplate. - __ push(rbx); + __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); __ Push(Smi::FromInt(expr->literal_index())); __ Push(expr->literals()); - __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); - - __ bind(&make_clone); - // Clone the boilerplate. - __ push(rax); if (expr->depth() > 1) { - __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateArrayLiteral, 3); } else { - __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); + __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } bool result_saved = false; // Is the result saved to the stack? -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev
