summaryrefslogtreecommitdiff
path: root/deps/v8/src/mips/full-codegen-mips.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/mips/full-codegen-mips.cc')
-rw-r--r--deps/v8/src/mips/full-codegen-mips.cc179
1 files changed, 141 insertions, 38 deletions
diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc
index bdfa43b2e..7368eada6 100644
--- a/deps/v8/src/mips/full-codegen-mips.cc
+++ b/deps/v8/src/mips/full-codegen-mips.cc
@@ -677,8 +677,9 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_true,
Label* if_false,
Label* fall_through) {
- ToBooleanStub stub(result_register());
- __ CallStub(&stub, condition->test_id());
+ __ mov(a0, result_register());
+ Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
__ mov(at, zero_reg);
Split(ne, v0, Operand(at), if_true, if_false, fall_through);
}
@@ -1083,9 +1084,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ForIn loop_statement(this, stmt);
increment_loop_depth();
- // Get the object to enumerate over. Both SpiderMonkey and JSC
- // ignore null and undefined in contrast to the specification; see
- // ECMA-262 section 12.6.4.
+ // 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.
VisitForAccumulatorValue(stmt->enumerable());
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
@@ -1259,6 +1259,67 @@ 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[@@iterator]()
+ VisitForAccumulatorValue(stmt->assign_iterator());
+ __ mov(a0, v0);
+
+ // As with for-in, skip the loop if the iterator is null or undefined.
+ __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+ __ Branch(loop_statement.break_label(), eq, a0, Operand(at));
+ __ LoadRoot(at, Heap::kNullValueRootIndex);
+ __ Branch(loop_statement.break_label(), eq, a0, Operand(at));
+
+ // Convert the iterator to a JS object.
+ Label convert, done_convert;
+ __ JumpIfSmi(a0, &convert);
+ __ GetObjectType(a0, a1, a1);
+ __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
+ __ bind(&convert);
+ __ push(a0);
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(a0, v0);
+ __ bind(&done_convert);
+ __ push(a0);
+
+ // 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());
+ __ jmp(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
@@ -1975,10 +2036,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// [sp + 1 * kPointerSize] iter
// [sp + 0 * kPointerSize] g
- Label l_catch, l_try, l_resume, l_send, l_call, l_loop;
+ Label l_catch, l_try, l_resume, l_next, l_call, l_loop;
// Initial send value is undefined.
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
- __ Branch(&l_send);
+ __ Branch(&l_next);
// catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
__ bind(&l_catch);
@@ -1988,12 +2049,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ push(a3); // iter
__ push(a0); // exception
__ mov(a0, a3); // iter
- __ push(a0); // push LoadIC state
__ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw"
Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(throw_ic); // iter.throw in a0
__ mov(a0, v0);
- __ Addu(sp, sp, Operand(kPointerSize)); // drop LoadIC state
__ jmp(&l_call);
// try { received = yield result.value }
@@ -2015,18 +2074,16 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ bind(&l_resume); // received in a0
__ PopTryHandler();
- // receiver = iter; f = iter.send; arg = received;
- __ bind(&l_send);
+ // receiver = iter; f = iter.next; arg = received;
+ __ bind(&l_next);
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
__ push(a3); // iter
__ push(a0); // received
__ mov(a0, a3); // iter
- __ push(a0); // push LoadIC state
- __ LoadRoot(a2, Heap::ksend_stringRootIndex); // "send"
- Handle<Code> send_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(send_ic); // iter.send in a0
+ __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next"
+ Handle<Code> next_ic = isolate()->builtins()->LoadIC_Initialize();
+ CallIC(next_ic); // iter.next in a0
__ mov(a0, v0);
- __ Addu(sp, sp, Operand(kPointerSize)); // drop LoadIC state
// result = f.call(receiver, arg);
__ bind(&l_call);
@@ -2056,13 +2113,12 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ pop(a1); // result
__ push(a0); // result.value
__ mov(a0, a1); // result
- __ push(a0); // push LoadIC state
__ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done"
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(done_ic); // result.done in v0
- __ Addu(sp, sp, Operand(kPointerSize)); // drop LoadIC state
- ToBooleanStub stub(v0);
- __ CallStub(&stub);
+ __ mov(a0, v0);
+ Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(bool_ic);
__ Branch(&l_try, eq, v0, Operand(zero_reg));
// result.value
@@ -2131,7 +2187,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
// If we are sending a value and there is no operand stack, we can jump back
// in directly.
- if (resume_mode == JSGeneratorObject::SEND) {
+ if (resume_mode == JSGeneratorObject::NEXT) {
Label slow_resume;
__ Branch(&slow_resume, ne, a3, Operand(zero_reg));
__ lw(a3, FieldMemOperand(t0, JSFunction::kCodeEntryOffset));
@@ -3037,7 +3093,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
// string "valueOf" the result is false.
// The use of t2 to store the valueOf string assumes that it is not otherwise
// used in the loop below.
- __ li(t2, Operand(FACTORY->value_of_string()));
+ __ li(t2, Operand(isolate()->factory()->value_of_string()));
__ jmp(&entry);
__ bind(&loop);
__ lw(a3, MemOperand(t0, 0));
@@ -3445,19 +3501,56 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
}
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+ Register index,
+ Register value,
+ uint32_t encoding_mask) {
+ __ And(at, index, Operand(kSmiTagMask));
+ __ Check(eq, "Non-smi index", at, Operand(zero_reg));
+ __ And(at, value, Operand(kSmiTagMask));
+ __ Check(eq, "Non-smi value", at, Operand(zero_reg));
+
+ __ lw(at, FieldMemOperand(string, String::kLengthOffset));
+ __ Check(lt, "Index is too large", index, Operand(at));
+
+ __ Check(ge, "Index is negative", index, Operand(zero_reg));
+
+ __ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
+ __ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
+
+ __ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
+ __ Subu(at, at, Operand(encoding_mask));
+ __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
+}
+
+
void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(3, args->length());
+ Register string = v0;
+ Register index = a1;
+ Register value = a2;
+
VisitForStackValue(args->at(1)); // index
VisitForStackValue(args->at(2)); // value
- __ pop(a2);
- __ pop(a1);
+ __ pop(value);
+ __ pop(index);
VisitForAccumulatorValue(args->at(0)); // string
- static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
- SeqStringSetCharGenerator::Generate(masm_, encoding, v0, a1, a2);
- context()->Plug(v0);
+ if (FLAG_debug_code) {
+ static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+ }
+
+ __ SmiUntag(value, value);
+ __ Addu(at,
+ string,
+ Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
+ __ SmiUntag(index);
+ __ Addu(at, at, index);
+ __ sb(value, MemOperand(at));
+ context()->Plug(string);
}
@@ -3465,15 +3558,29 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(3, args->length());
+ Register string = v0;
+ Register index = a1;
+ Register value = a2;
+
VisitForStackValue(args->at(1)); // index
VisitForStackValue(args->at(2)); // value
- __ pop(a2);
- __ pop(a1);
+ __ pop(value);
+ __ pop(index);
VisitForAccumulatorValue(args->at(0)); // string
- static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
- SeqStringSetCharGenerator::Generate(masm_, encoding, v0, a1, a2);
- context()->Plug(v0);
+ if (FLAG_debug_code) {
+ static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+ }
+
+ __ SmiUntag(value, value);
+ __ Addu(at,
+ string,
+ Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+ __ Addu(at, at, index);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ __ sh(value, MemOperand(at));
+ context()->Plug(string);
}
@@ -4692,19 +4799,15 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- EqualityKind kind = expr->op() == Token::EQ_STRICT
- ? kStrictEquality : kNonStrictEquality;
__ mov(a0, result_register());
- if (kind == kStrictEquality) {
+ if (expr->op() == Token::EQ_STRICT) {
Heap::RootListIndex nil_value = nil == kNullValue ?
Heap::kNullValueRootIndex :
Heap::kUndefinedValueRootIndex;
__ LoadRoot(a1, nil_value);
Split(eq, a0, Operand(a1), if_true, if_false, fall_through);
} else {
- Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(),
- kNonStrictEquality,
- nil);
+ Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through);
}