| 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()) {
|
|
|