Index: src/ppc/full-codegen-ppc.cc |
diff --git a/src/ppc/full-codegen-ppc.cc b/src/ppc/full-codegen-ppc.cc |
index 6f43313026952d4da836a8b210b373f5c1fcd429..b7a5d3e33c5c023365816e742b1e8cbd7f714e4c 100644 |
--- a/src/ppc/full-codegen-ppc.cc |
+++ b/src/ppc/full-codegen-ppc.cc |
@@ -123,7 +123,7 @@ void FullCodeGenerator::Generate() { |
// Sloppy mode functions and builtins need to replace the receiver with the |
// global proxy when called as functions (without an explicit receiver |
// object). |
- if (info->strict_mode() == SLOPPY && !info->is_native()) { |
+ if (is_sloppy(info->language_mode()) && !info->is_native()) { |
Label ok; |
int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
__ LoadP(r5, MemOperand(sp, receiver_offset), r0); |
@@ -267,7 +267,7 @@ void FullCodeGenerator::Generate() { |
// The stub will rewrite receiever and parameter count if the previous |
// stack frame was an arguments adapter frame. |
ArgumentsAccessStub::Type type; |
- if (strict_mode() == STRICT) { |
+ if (is_strict(language_mode())) { |
type = ArgumentsAccessStub::NEW_STRICT; |
} else if (function()->has_duplicate_parameters()) { |
type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
@@ -1066,6 +1066,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
// Get the object to enumerate over. If the object is null or undefined, skip |
// over the loop. See ECMA-262 version 5, section 12.6.4. |
+ SetExpressionPosition(stmt->enumerable()); |
VisitForAccumulatorValue(stmt->enumerable()); |
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
__ cmp(r3, ip); |
@@ -1171,6 +1172,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
// Generate code for doing the condition check. |
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
__ bind(&loop); |
+ SetExpressionPosition(stmt->each()); |
+ |
// Load the current count to r3, load the length to r4. |
__ LoadP(r3, MemOperand(sp, 0 * kPointerSize)); |
__ LoadP(r4, MemOperand(sp, 1 * kPointerSize)); |
@@ -1244,46 +1247,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
} |
-void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
- Comment cmnt(masm_, "[ ForOfStatement"); |
- SetStatementPosition(stmt); |
- |
- Iteration loop_statement(this, stmt); |
- increment_loop_depth(); |
- |
- // var iterator = iterable[Symbol.iterator](); |
- VisitForEffect(stmt->assign_iterator()); |
- |
- // Loop entry. |
- __ bind(loop_statement.continue_label()); |
- |
- // result = iterator.next() |
- VisitForEffect(stmt->next_result()); |
- |
- // if (result.done) break; |
- Label result_not_done; |
- VisitForControl(stmt->result_done(), loop_statement.break_label(), |
- &result_not_done, &result_not_done); |
- __ bind(&result_not_done); |
- |
- // each = result.value |
- VisitForEffect(stmt->assign_each()); |
- |
- // Generate code for the body of the loop. |
- Visit(stmt->body()); |
- |
- // Check stack before looping. |
- PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
- EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); |
- __ b(loop_statement.continue_label()); |
- |
- // Exit and decrement the loop depth. |
- PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
- __ bind(loop_statement.break_label()); |
- decrement_loop_depth(); |
-} |
- |
- |
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
bool pretenure) { |
// Use the fast case closure allocation code that allocates in new |
@@ -1294,7 +1257,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
// doesn't just get a copy of the existing unoptimized code. |
if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && |
scope()->is_function_scope() && info->num_literals() == 0) { |
- FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); |
+ FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
__ mov(r5, Operand(info)); |
__ CallStub(&stub); |
} else { |
@@ -1339,6 +1302,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { |
} |
+void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
+ int offset) { |
+ if (NeedsHomeObject(initializer)) { |
+ __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
+ __ mov(StoreDescriptor::NameRegister(), |
+ Operand(isolate()->factory()->home_object_symbol())); |
+ __ LoadP(StoreDescriptor::ValueRegister(), |
+ MemOperand(sp, offset * kPointerSize)); |
+ CallStoreIC(); |
+ } |
+} |
+ |
+ |
void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, |
TypeofState typeof_state, |
Label* slow) { |
@@ -1517,6 +1493,11 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
bool skip_init_check; |
if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
skip_init_check = false; |
+ } else if (var->is_this()) { |
+ CHECK(info_->function() != nullptr && |
+ (info_->function()->kind() & kSubclassConstructor) != 0); |
+ // TODO(dslomov): implement 'this' hole check elimination. |
+ skip_init_check = false; |
} else { |
// Check that we always have valid source position. |
DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
@@ -1664,11 +1645,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
expr->CalculateEmitStore(zone()); |
AccessorTable accessor_table(zone()); |
- for (int i = 0; i < expr->properties()->length(); i++) { |
- ObjectLiteral::Property* property = expr->properties()->at(i); |
+ int property_index = 0; |
+ for (; property_index < expr->properties()->length(); property_index++) { |
+ ObjectLiteral::Property* property = expr->properties()->at(property_index); |
+ if (property->is_computed_name()) break; |
if (property->IsCompileTimeValue()) continue; |
- Literal* key = property->key(); |
+ Literal* key = property->key()->AsLiteral(); |
Expression* value = property->value(); |
if (!result_saved) { |
__ push(r3); // Save result on stack |
@@ -1691,6 +1674,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
__ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
CallStoreIC(key->LiteralFeedbackId()); |
PrepareForBailoutForId(key->id(), NO_REGISTERS); |
+ |
+ if (NeedsHomeObject(value)) { |
+ __ Move(StoreDescriptor::ReceiverRegister(), r3); |
+ __ mov(StoreDescriptor::NameRegister(), |
+ Operand(isolate()->factory()->home_object_symbol())); |
+ __ LoadP(StoreDescriptor::ValueRegister(), MemOperand(sp)); |
+ CallStoreIC(); |
+ } |
} else { |
VisitForEffect(value); |
} |
@@ -1702,6 +1693,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
VisitForStackValue(key); |
VisitForStackValue(value); |
if (property->emit_store()) { |
+ EmitSetHomeObjectIfNeeded(value, 2); |
__ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes |
__ push(r3); |
__ CallRuntime(Runtime::kSetProperty, 4); |
@@ -1738,12 +1730,76 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
__ push(r3); |
VisitForStackValue(it->first); |
EmitAccessor(it->second->getter); |
+ EmitSetHomeObjectIfNeeded(it->second->getter, 2); |
EmitAccessor(it->second->setter); |
+ EmitSetHomeObjectIfNeeded(it->second->setter, 3); |
__ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
__ push(r3); |
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
} |
+ // Object literals have two parts. The "static" part on the left contains no |
+ // computed property names, and so we can compute its map ahead of time; see |
+ // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
+ // starts with the first computed property name, and continues with all |
+ // properties to its right. All the code from above initializes the static |
+ // component of the object literal, and arranges for the map of the result to |
+ // reflect the static order in which the keys appear. For the dynamic |
+ // properties, we compile them into a series of "SetOwnProperty" runtime |
+ // calls. This will preserve insertion order. |
+ for (; property_index < expr->properties()->length(); property_index++) { |
+ ObjectLiteral::Property* property = expr->properties()->at(property_index); |
+ |
+ Expression* value = property->value(); |
+ if (!result_saved) { |
+ __ push(r3); // Save result on the stack |
+ result_saved = true; |
+ } |
+ |
+ __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
+ __ push(r3); |
+ |
+ if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
+ DCHECK(!property->is_computed_name()); |
+ VisitForStackValue(value); |
+ DCHECK(property->emit_store()); |
+ __ CallRuntime(Runtime::kInternalSetPrototype, 2); |
+ } else { |
+ EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
+ VisitForStackValue(value); |
+ |
+ switch (property->kind()) { |
+ case ObjectLiteral::Property::CONSTANT: |
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
+ case ObjectLiteral::Property::COMPUTED: |
+ if (property->emit_store()) { |
+ __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
+ __ push(r3); |
+ __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); |
+ } else { |
+ __ Drop(3); |
+ } |
+ break; |
+ |
+ case ObjectLiteral::Property::PROTOTYPE: |
+ UNREACHABLE(); |
+ break; |
+ |
+ case ObjectLiteral::Property::GETTER: |
+ __ mov(r3, Operand(Smi::FromInt(NONE))); |
+ __ push(r3); |
+ __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); |
+ break; |
+ |
+ case ObjectLiteral::Property::SETTER: |
+ __ mov(r3, Operand(Smi::FromInt(NONE))); |
+ __ push(r3); |
+ __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); |
+ break; |
+ } |
+ } |
+ } |
+ |
if (expr->has_function()) { |
DCHECK(result_saved); |
__ LoadP(r3, MemOperand(sp)); |
@@ -1934,16 +1990,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
__ push(r3); // Left operand goes on the stack. |
VisitForAccumulatorValue(expr->value()); |
- OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
- ? OVERWRITE_RIGHT |
- : NO_OVERWRITE; |
SetSourcePosition(expr->position() + 1); |
AccumulatorValueContext context(this); |
if (ShouldInlineSmiCase(op)) { |
- EmitInlineSmiBinaryOp(expr->binary_operation(), op, mode, expr->target(), |
+ EmitInlineSmiBinaryOp(expr->binary_operation(), op, expr->target(), |
expr->value()); |
} else { |
- EmitBinaryOp(expr->binary_operation(), op, mode); |
+ EmitBinaryOp(expr->binary_operation(), op); |
} |
// Deoptimization point in case the binary operation may have side effects. |
@@ -2159,15 +2212,6 @@ void FullCodeGenerator::EmitGeneratorResume( |
VisitForAccumulatorValue(value); |
__ pop(r4); |
- // Check generator state. |
- Label wrong_state, closed_state, done; |
- __ LoadP(r6, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset)); |
- STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
- STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
- __ CmpSmiLiteral(r6, Smi::FromInt(0), r0); |
- __ beq(&closed_state); |
- __ blt(&wrong_state); |
- |
// Load suspended function and context. |
__ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset)); |
__ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset)); |
@@ -2196,7 +2240,7 @@ void FullCodeGenerator::EmitGeneratorResume( |
// Enter a new JavaScript frame, and initialize its slots as they were when |
// the generator was suspended. |
- Label resume_frame; |
+ Label resume_frame, done; |
__ bind(&push_frame); |
__ b(&resume_frame, SetLK); |
__ b(&done); |
@@ -2260,26 +2304,6 @@ void FullCodeGenerator::EmitGeneratorResume( |
// Not reached: the runtime call returns elsewhere. |
__ stop("not-reached"); |
- // Reach here when generator is closed. |
- __ bind(&closed_state); |
- if (resume_mode == JSGeneratorObject::NEXT) { |
- // Return completed iterator result when generator is closed. |
- __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
- __ push(r5); |
- // Pop value from top-of-stack slot; box result into result register. |
- EmitCreateIteratorResult(true); |
- } else { |
- // Throw the provided value. |
- __ push(r3); |
- __ CallRuntime(Runtime::kThrow, 1); |
- } |
- __ b(&done); |
- |
- // Throw error if we attempt to operate on a running generator. |
- __ bind(&wrong_state); |
- __ push(r4); |
- __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
- |
__ bind(&done); |
context()->Plug(result_register()); |
} |
@@ -2377,7 +2401,6 @@ void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
Token::Value op, |
- OverwriteMode mode, |
Expression* left_expr, |
Expression* right_expr) { |
Label done, smi_case, stub_call; |
@@ -2397,7 +2420,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
__ bind(&stub_call); |
- Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); |
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
CallIC(code, expr->BinaryOperationFeedbackId()); |
patch_site.EmitPatchInfo(); |
__ b(&done); |
@@ -2435,13 +2458,13 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
} |
case Token::ADD: { |
__ AddAndCheckForOverflow(scratch1, left, right, scratch2, r0); |
- __ bne(&stub_call, cr0); |
+ __ BranchOnOverflow(&stub_call); |
__ mr(right, scratch1); |
break; |
} |
case Token::SUB: { |
__ SubAndCheckForOverflow(scratch1, left, right, scratch2, r0); |
- __ bne(&stub_call, cr0); |
+ __ BranchOnOverflow(&stub_call); |
__ mr(right, scratch1); |
break; |
} |
@@ -2454,7 +2477,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
__ Mul(scratch1, r0, ip); |
// Check for overflowing the smi range - no overflow if higher 33 bits of |
// the result are identical. |
- __ TestIfInt32(scratch1, scratch2, ip); |
+ __ TestIfInt32(scratch1, r0); |
__ bne(&stub_call); |
#else |
__ SmiUntag(ip, right); |
@@ -2515,9 +2538,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
for (int i = 0; i < lit->properties()->length(); i++) { |
ObjectLiteral::Property* property = lit->properties()->at(i); |
- Literal* key = property->key()->AsLiteral(); |
Expression* value = property->value(); |
- DCHECK(key != NULL); |
if (property->is_static()) { |
__ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor |
@@ -2525,8 +2546,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
__ LoadP(scratch, MemOperand(sp, 0)); // prototype |
} |
__ push(scratch); |
- VisitForStackValue(key); |
+ EmitPropertyKey(property, lit->GetIdForProperty(i)); |
VisitForStackValue(value); |
+ EmitSetHomeObjectIfNeeded(value, 2); |
switch (property->kind()) { |
case ObjectLiteral::Property::CONSTANT: |
@@ -2538,11 +2560,15 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
break; |
case ObjectLiteral::Property::GETTER: |
- __ CallRuntime(Runtime::kDefineClassGetter, 3); |
+ __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
+ __ push(r3); |
+ __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); |
break; |
case ObjectLiteral::Property::SETTER: |
- __ CallRuntime(Runtime::kDefineClassSetter, 3); |
+ __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
+ __ push(r3); |
+ __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); |
break; |
default: |
@@ -2558,10 +2584,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
} |
-void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op, |
- OverwriteMode mode) { |
+void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
__ pop(r4); |
- Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); |
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
CallIC(code, expr->BinaryOperationFeedbackId()); |
patch_site.EmitPatchInfo(); |
@@ -2636,7 +2661,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { |
__ Pop(StoreDescriptor::ValueRegister(), |
StoreDescriptor::ReceiverRegister()); |
Handle<Code> ic = |
- CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); |
+ CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
CallIC(ic); |
break; |
} |
@@ -2705,8 +2730,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
// Assignment to var. |
__ push(r3); // Value. |
__ mov(r4, Operand(var->name())); |
- __ mov(r3, Operand(Smi::FromInt(strict_mode()))); |
- __ Push(cp, r4, r3); // Context, name, strict mode. |
+ __ mov(r3, Operand(Smi::FromInt(language_mode()))); |
+ __ Push(cp, r4, r3); // Context, name, language mode. |
__ CallRuntime(Runtime::kStoreLookupSlot, 4); |
} else { |
// Assignment to var or initializing assignment to let/const in harmony |
@@ -2721,8 +2746,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
} |
EmitStoreToStackLocalOrContextSlot(var, location); |
} |
+ } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { |
+ __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
} |
- // Non-initializing assignments to consts are ignored. |
} |
@@ -2754,8 +2780,8 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { |
__ Push(key->value()); |
__ Push(r3); |
- __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict |
- : Runtime::kStoreToSuper_Sloppy), |
+ __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
+ : Runtime::kStoreToSuper_Sloppy), |
4); |
} |
@@ -2767,9 +2793,10 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
DCHECK(prop != NULL); |
__ Push(r3); |
- __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict |
- : Runtime::kStoreKeyedToSuper_Sloppy), |
- 4); |
+ __ CallRuntime( |
+ (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
+ : Runtime::kStoreKeyedToSuper_Sloppy), |
+ 4); |
} |
@@ -2781,7 +2808,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
__ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); |
DCHECK(StoreDescriptor::ValueRegister().is(r3)); |
- Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); |
+ Handle<Code> ic = |
+ CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
CallIC(ic, expr->AssignmentFeedbackId()); |
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
@@ -2973,8 +3001,8 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { |
// Record source position of the IC call. |
SetSourcePosition(expr->position()); |
- Handle<Code> ic = CallIC::initialize_stub(isolate(), arg_count, call_type); |
- __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackSlot())); |
+ Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); |
+ __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackICSlot())); |
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
// Don't assign a type feedback id to the IC, since type feedback is provided |
// by the vector above. |
@@ -3002,8 +3030,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
int receiver_offset = 2 + info_->scope()->num_parameters(); |
__ LoadP(r6, MemOperand(fp, receiver_offset * kPointerSize), r0); |
- // r5: strict mode. |
- __ LoadSmiLiteral(r5, Smi::FromInt(strict_mode())); |
+ // r5: language mode. |
+ __ LoadSmiLiteral(r5, Smi::FromInt(language_mode())); |
// r4: the start position of the scope the calls resides in. |
__ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); |
@@ -3140,11 +3168,15 @@ void FullCodeGenerator::VisitCall(Call* expr) { |
} |
} |
} else if (call_type == Call::SUPER_CALL) { |
- SuperReference* super_ref = callee->AsSuperReference(); |
- EmitLoadSuperConstructor(super_ref); |
- __ Push(result_register()); |
- VisitForStackValue(super_ref->this_var()); |
- EmitCall(expr, CallICState::METHOD); |
+ if (FLAG_experimental_classes) { |
+ EmitSuperConstructorCall(expr); |
+ } else { |
+ SuperReference* super_ref = callee->AsSuperReference(); |
+ EmitLoadSuperConstructor(super_ref); |
+ __ Push(result_register()); |
+ VisitForStackValue(super_ref->this_var()); |
+ EmitCall(expr, CallICState::METHOD); |
+ } |
} else { |
DCHECK(call_type == Call::OTHER_CALL); |
// Call to an arbitrary expression not handled specially above. |
@@ -3213,6 +3245,61 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
} |
+void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
+ SuperReference* super_ref = expr->expression()->AsSuperReference(); |
+ EmitLoadSuperConstructor(super_ref); |
+ __ push(result_register()); |
+ |
+ Variable* this_var = super_ref->this_var()->var(); |
+ |
+ GetVar(r3, this_var); |
+ __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
+ Label uninitialized_this; |
+ __ beq(&uninitialized_this); |
+ __ mov(r3, Operand(this_var->name())); |
+ __ push(r3); |
+ __ CallRuntime(Runtime::kThrowReferenceError, 1); |
+ __ bind(&uninitialized_this); |
+ |
+ // Push the arguments ("left-to-right") on the stack. |
+ ZoneList<Expression*>* args = expr->arguments(); |
+ int arg_count = args->length(); |
+ for (int i = 0; i < arg_count; i++) { |
+ VisitForStackValue(args->at(i)); |
+ } |
+ |
+ // Call the construct call builtin that handles allocation and |
+ // constructor invocation. |
+ SetSourcePosition(expr->position()); |
+ |
+ // Load function and argument count into r1 and r0. |
+ __ mov(r3, Operand(arg_count)); |
+ __ LoadP(r4, MemOperand(sp, arg_count * kPointerSize)); |
+ |
+ // Record call targets in unoptimized code. |
+ if (FLAG_pretenuring_call_new) { |
+ UNREACHABLE(); |
+ /* TODO(dslomov): support pretenuring. |
+ EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
+ DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() == |
+ expr->CallNewFeedbackSlot().ToInt() + 1); |
+ */ |
+ } |
+ |
+ __ Move(r5, FeedbackVector()); |
+ __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackSlot())); |
+ |
+ // TODO(dslomov): use a different stub and propagate new.target. |
+ CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
+ __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
+ |
+ RecordJSReturnSite(expr); |
+ |
+ EmitVariableAssignment(this_var, Token::INIT_CONST); |
+ context()->Plug(r3); |
+} |
+ |
+ |
void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
ZoneList<Expression*>* args = expr->arguments(); |
DCHECK(args->length() == 1); |
@@ -4512,7 +4599,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
if (property != NULL) { |
VisitForStackValue(property->obj()); |
VisitForStackValue(property->key()); |
- __ LoadSmiLiteral(r4, Smi::FromInt(strict_mode())); |
+ __ LoadSmiLiteral(r4, Smi::FromInt(language_mode())); |
__ push(r4); |
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
context()->Plug(r3); |
@@ -4520,7 +4607,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
Variable* var = proxy->var(); |
// Delete of an unqualified identifier is disallowed in strict mode |
// but "delete this" is allowed. |
- DCHECK(strict_mode() == SLOPPY || var->is_this()); |
+ DCHECK(is_sloppy(language_mode()) || var->is_this()); |
if (var->IsUnallocated()) { |
__ LoadP(r5, GlobalObjectOperand()); |
__ mov(r4, Operand(var->name())); |
@@ -4768,8 +4855,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
// Record position before stub call. |
SetSourcePosition(expr->position()); |
- Handle<Code> code = |
- CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code(); |
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); |
CallIC(code, expr->CountBinOpFeedbackId()); |
patch_site.EmitPatchInfo(); |
__ bind(&done); |
@@ -4838,7 +4924,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
__ Pop(StoreDescriptor::ReceiverRegister(), |
StoreDescriptor::NameRegister()); |
Handle<Code> ic = |
- CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); |
+ CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
CallIC(ic, expr->CountStoreFeedbackId()); |
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
if (expr->is_postfix()) { |