diff options
Diffstat (limited to 'deps/v8/src/ia32/full-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/full-codegen-ia32.cc | 212 |
1 files changed, 102 insertions, 110 deletions
diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc index 8596705512..1e578b4141 100644 --- a/deps/v8/src/ia32/full-codegen-ia32.cc +++ b/deps/v8/src/ia32/full-codegen-ia32.cc @@ -95,7 +95,8 @@ class JumpPatchSite BASE_EMBEDDED { void FullCodeGenerator::Generate() { CompilationInfo* info = info_; handler_table_ = - isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); + Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( + HandlerTable::LengthForRange(function()->handler_count()), TENURED)); profiling_counter_ = isolate()->factory()->NewCell( Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); @@ -188,7 +189,7 @@ void FullCodeGenerator::Generate() { Comment cmnt(masm_, "[ Allocate context"); bool need_write_barrier = true; // Argument to NewContext is the function, which is still in edi. - if (FLAG_harmony_scoping && info->scope()->is_script_scope()) { + if (info->scope()->is_script_scope()) { __ push(edi); __ Push(info->scope()->GetScopeInfo(info->isolate())); __ CallRuntime(Runtime::kNewScriptContext, 2); @@ -236,6 +237,11 @@ void FullCodeGenerator::Generate() { } } + ArgumentsAccessStub::HasNewTarget has_new_target = + IsSubclassConstructor(info->function()->kind()) + ? ArgumentsAccessStub::HAS_NEW_TARGET + : ArgumentsAccessStub::NO_NEW_TARGET; + // Possibly allocate RestParameters int rest_index; Variable* rest_param = scope()->rest_parameter(&rest_index); @@ -244,6 +250,11 @@ void FullCodeGenerator::Generate() { int num_parameters = info->scope()->num_parameters(); int offset = num_parameters * kPointerSize; + if (has_new_target == ArgumentsAccessStub::HAS_NEW_TARGET) { + --num_parameters; + ++rest_index; + } + __ lea(edx, Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); __ push(edx); @@ -284,10 +295,7 @@ void FullCodeGenerator::Generate() { } else { type = ArgumentsAccessStub::NEW_SLOPPY_FAST; } - ArgumentsAccessStub::HasNewTarget has_new_target = - IsSubclassConstructor(info->function()->kind()) - ? ArgumentsAccessStub::HAS_NEW_TARGET - : ArgumentsAccessStub::NO_NEW_TARGET; + ArgumentsAccessStub stub(isolate(), type, has_new_target); __ CallStub(&stub); @@ -1453,7 +1461,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { __ mov(VectorLoadICDescriptor::SlotRegister(), Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); } - CallLoadIC(CONTEXTUAL); + CallGlobalLoadIC(var->name()); context()->Plug(eax); break; } @@ -2098,7 +2106,6 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } __ bind(&l_catch); - handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); __ mov(load_name, isolate()->factory()->throw_string()); // "throw" __ push(load_name); // "throw" __ push(Operand(esp, 2 * kPointerSize)); // iter @@ -2110,16 +2117,17 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // re-boxing. __ bind(&l_try); __ pop(eax); // result - __ PushTryHandler(StackHandler::CATCH, expr->index()); - const int handler_size = StackHandlerConstants::kSize; + EnterTryBlock(expr->index(), &l_catch); + const int try_block_size = TryCatch::kElementCount * kPointerSize; __ push(eax); // result __ jmp(&l_suspend); __ bind(&l_continuation); __ jmp(&l_resume); __ bind(&l_suspend); - const int generator_object_depth = kPointerSize + handler_size; + const int generator_object_depth = kPointerSize + try_block_size; __ mov(eax, Operand(esp, generator_object_depth)); __ push(eax); // g + __ push(Immediate(Smi::FromInt(expr->index()))); // handler-index DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), Immediate(Smi::FromInt(l_continuation.pos()))); @@ -2127,13 +2135,13 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ mov(ecx, esi); __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, kDontSaveFPRegs); - __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); + __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2); __ mov(context_register(), Operand(ebp, StandardFrameConstants::kContextOffset)); __ pop(eax); // result EmitReturnSequence(); __ bind(&l_resume); // received in eax - __ PopTryHandler(); + ExitTryBlock(expr->index()); // receiver = iter; f = iter.next; arg = received; __ bind(&l_next); @@ -2479,6 +2487,16 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { __ push(Operand(esp, 0)); // prototype } EmitPropertyKey(property, lit->GetIdForProperty(i)); + + // The static prototype property is read only. We handle the non computed + // property name case in the parser. Since this is the only case where we + // need to check for an own read only property we special case this so we do + // not need to do this for every property. + if (property->is_static() && property->is_computed_name()) { + __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); + __ push(eax); + } + VisitForStackValue(value); EmitSetHomeObjectIfNeeded(value, 2); @@ -2616,25 +2634,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); CallStoreIC(); - } else if (op == Token::INIT_CONST_LEGACY) { - // Const initializers need a write barrier. - DCHECK(!var->IsParameter()); // No const parameters. - if (var->IsLookupSlot()) { - __ push(eax); - __ push(esi); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); - } else { - DCHECK(var->IsStackLocal() || var->IsContextSlot()); - Label skip; - MemOperand location = VarOperand(var, ecx); - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ j(not_equal, &skip, Label::kNear); - EmitStoreToStackLocalOrContextSlot(var, location); - __ bind(&skip); - } - } else if (var->mode() == LET && op != Token::INIT_LET) { // Non-initializing assignment to let variable needs a write barrier. DCHECK(!var->IsLookupSlot()); @@ -2648,6 +2647,21 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&assign); EmitStoreToStackLocalOrContextSlot(var, location); + + } else if (var->mode() == CONST && op != Token::INIT_CONST) { + // Assignment to const variable needs a write barrier. + DCHECK(!var->IsLookupSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); + Label const_error; + MemOperand location = VarOperand(var, ecx); + __ mov(edx, location); + __ cmp(edx, isolate()->factory()->the_hole_value()); + __ j(not_equal, &const_error, Label::kNear); + __ push(Immediate(var->name())); + __ CallRuntime(Runtime::kThrowReferenceError, 1); + __ bind(&const_error); + __ CallRuntime(Runtime::kThrowConstAssignError, 0); + } else if (!var->is_const_mode() || op == Token::INIT_CONST) { if (var->IsLookupSlot()) { // Assignment to var. @@ -2669,8 +2683,33 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, } EmitStoreToStackLocalOrContextSlot(var, location); } - } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError, 0); + + } else if (op == Token::INIT_CONST_LEGACY) { + // Const initializers need a write barrier. + DCHECK(var->mode() == CONST_LEGACY); + DCHECK(!var->IsParameter()); // No const parameters. + if (var->IsLookupSlot()) { + __ push(eax); + __ push(esi); + __ push(Immediate(var->name())); + __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); + } else { + DCHECK(var->IsStackLocal() || var->IsContextSlot()); + Label skip; + MemOperand location = VarOperand(var, ecx); + __ mov(edx, location); + __ cmp(edx, isolate()->factory()->the_hole_value()); + __ j(not_equal, &skip, Label::kNear); + EmitStoreToStackLocalOrContextSlot(var, location); + __ bind(&skip); + } + + } else { + DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY); + if (is_strict(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError, 0); + } + // Silently ignore store in sloppy mode. } } @@ -3138,8 +3177,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { - if (!ValidateSuperCall(expr)) return; - Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); GetVar(eax, new_target_var); __ push(eax); @@ -3651,8 +3688,8 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); // Check if the constructor in the map is a JS function. - __ mov(eax, FieldOperand(eax, Map::kConstructorOffset)); - __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); + __ GetMapConstructor(eax, eax, ebx); + __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); __ j(not_equal, &non_function_constructor); // eax now contains the constructor function. Grab the @@ -3955,7 +3992,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { __ jmp(&done); NopRuntimeCallHelper call_helper; - generator.GenerateSlow(masm_, call_helper); + generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper); __ bind(&done); context()->Plug(result); @@ -4003,7 +4040,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { __ jmp(&done); NopRuntimeCallHelper call_helper; - generator.GenerateSlow(masm_, call_helper); + generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper); __ bind(&done); context()->Plug(result); @@ -4175,7 +4212,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { // Call runtime to perform the lookup. __ push(cache); __ push(key); - __ CallRuntime(Runtime::kGetFromCache, 2); + __ CallRuntime(Runtime::kGetFromCacheRT, 2); __ bind(&done); context()->Plug(eax); @@ -4495,17 +4532,11 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { - if (expr->function() != NULL && - expr->function()->intrinsic_type == Runtime::INLINE) { - Comment cmnt(masm_, "[ InlineRuntimeCall"); - EmitInlineRuntimeCall(expr); - return; - } - - Comment cmnt(masm_, "[ CallRuntime"); ZoneList<Expression*>* args = expr->arguments(); + int arg_count = args->length(); if (expr->is_jsruntime()) { + Comment cmnt(masm_, "[ CallRuntime"); // Push the builtins object as receiver. __ mov(eax, GlobalObjectOperand()); __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); @@ -4525,9 +4556,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ push(Operand(esp, 0)); __ mov(Operand(esp, kPointerSize), eax); - // Code common for calls using the IC. - ZoneList<Expression*>* args = expr->arguments(); - int arg_count = args->length(); + // Push the arguments ("left-to-right"). for (int i = 0; i < arg_count; i++) { VisitForStackValue(args->at(i)); } @@ -4537,21 +4566,33 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); __ CallStub(&stub); + // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, eax); } else { - // Push the arguments ("left-to-right"). - int arg_count = args->length(); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - - // Call the C runtime function. - __ CallRuntime(expr->function(), arg_count); + const Runtime::Function* function = expr->function(); + switch (function->function_id) { +#define CALL_INTRINSIC_GENERATOR(Name) \ + case Runtime::kInline##Name: { \ + Comment cmnt(masm_, "[ Inline" #Name); \ + return Emit##Name(expr); \ + } + FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR) +#undef CALL_INTRINSIC_GENERATOR + default: { + Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic"); + // Push the arguments ("left-to-right"). + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); + } - context()->Plug(eax); + // Call the C runtime function. + __ CallRuntime(expr->function(), arg_count); + context()->Plug(eax); + } + } } } @@ -5203,17 +5244,6 @@ void FullCodeGenerator::EnterFinallyBlock() { ExternalReference::address_of_pending_message_obj(isolate()); __ mov(edx, Operand::StaticVariable(pending_message_obj)); __ push(edx); - - ExternalReference has_pending_message = - ExternalReference::address_of_has_pending_message(isolate()); - __ mov(edx, Operand::StaticVariable(has_pending_message)); - __ SmiTag(edx); - __ push(edx); - - ExternalReference pending_message_script = - ExternalReference::address_of_pending_message_script(isolate()); - __ mov(edx, Operand::StaticVariable(pending_message_script)); - __ push(edx); } @@ -5221,17 +5251,6 @@ void FullCodeGenerator::ExitFinallyBlock() { DCHECK(!result_register().is(edx)); // Restore pending message from stack. __ pop(edx); - ExternalReference pending_message_script = - ExternalReference::address_of_pending_message_script(isolate()); - __ mov(Operand::StaticVariable(pending_message_script), edx); - - __ pop(edx); - __ SmiUntag(edx); - ExternalReference has_pending_message = - ExternalReference::address_of_has_pending_message(isolate()); - __ mov(Operand::StaticVariable(has_pending_message), edx); - - __ pop(edx); ExternalReference pending_message_obj = ExternalReference::address_of_pending_message_obj(isolate()); __ mov(Operand::StaticVariable(pending_message_obj), edx); @@ -5249,33 +5268,6 @@ void FullCodeGenerator::ExitFinallyBlock() { #undef __ -#define __ ACCESS_MASM(masm()) - -FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( - int* stack_depth, - int* context_length) { - // The macros used here must preserve the result register. - - // Because the handler block contains the context of the finally - // code, we can restore it directly from there for the finally code - // rather than iteratively unwinding contexts via their previous - // links. - __ Drop(*stack_depth); // Down to the handler block. - if (*context_length > 0) { - // Restore the context to its dedicated register and the stack. - __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset)); - __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); - } - __ PopTryHandler(); - __ call(finally_entry_); - - *stack_depth = 0; - *context_length = 0; - return previous_; -} - -#undef __ - static const byte kJnsInstruction = 0x79; static const byte kJnsOffset = 0x11; |