Permalink
Browse files

candor: all tests pass

  • Loading branch information...
indutny committed Oct 29, 2012
1 parent c0b04db commit c2d28eebbdd6cfb97ad6367fe4877e53e771d98b
Showing with 216 additions and 18 deletions.
  1. +5 −3 src/ast.h
  2. +16 −1 src/hir.cc
  3. +7 −3 src/x64/lir-builder-x64.cc
  4. +175 −0 src/x64/lir-x64.cc
  5. +13 −11 test/test-hir.cc
View
@@ -461,9 +461,11 @@ class FunctionLiteral : public AstNode {
// VarArg should be the last argument of a call statement
AstList::Item* head;
- for (head = children()->head(); head != NULL; head = head->next()) {
- if (head->value()->is(kVarArg) && head->next() != NULL) {
- return false;
+ bool varg = false;
+ for (head = args_.head(); head != NULL; head = head->next()) {
+ if (head->value()->is(kVarArg)) {
+ if (varg) return false;
+ varg = true;
}
}
View
@@ -87,7 +87,7 @@ HIRInstruction* HIRGen::VisitFunction(AstNode* stmt) {
}
AstList::Item* args_head = fn->args()->head();
- for (; args_head != NULL; args_head = args_head->next()) {
+ for (int i = 0; args_head != NULL; args_head = args_head->next(), i++) {
AstNode* arg = args_head->value();
HIRInstruction::Type type;
bool varg = false;
@@ -105,7 +105,22 @@ HIRInstruction* HIRGen::VisitFunction(AstNode* stmt) {
AstValue* value = AstValue::Cast(arg);
+ HIRInstruction* varg_rest = NULL;
+ HIRInstruction* varg_arr = NULL;
+ if (varg) {
+ // Result vararg array
+ varg_arr = Add(HIRInstruction::kAllocateArray);
+
+ // Add number of arguments that are following varg
+ varg_rest = GetNumber(fn->args()->length() - i - 1);
+ }
HIRInstruction* load_arg = Add(type)->AddArg(index);
+
+ if (varg) {
+ load_arg->AddArg(varg_rest)->AddArg(varg_arr);
+ load_arg = varg_arr;
+ }
+
if (value->slot()->is_stack()) {
// No instruction is needed
Assign(value->slot(), load_arg);
View
@@ -184,8 +184,10 @@ void LGen::VisitLoadArg(HIRInstruction* instr) {
void LGen::VisitLoadVarArg(HIRInstruction* instr) {
Bind(new LLoadVarArg())
- ->AddArg(instr->left(), LUse::kRegister)
- ->SetResult(CreateVirtual(), LUse::kAny);
+ ->MarkHasCall()
+ ->AddArg(ToFixed(instr->left(), rax), LUse::kRegister)
+ ->AddArg(ToFixed(instr->right(), rbx), LUse::kRegister)
+ ->SetResult(ToFixed(instr->third(), rcx), LUse::kAny);
}
@@ -203,7 +205,9 @@ void LGen::VisitAlignStack(HIRInstruction* instr) {
void LGen::VisitStoreVarArg(HIRInstruction* instr) {
Bind(new LStoreVarArg())
- ->AddArg(instr->left(), LUse::kRegister);
+ ->MarkHasCall()
+ ->AddScratch(CreateVirtual())
+ ->AddArg(ToFixed(instr->left(), rax), LUse::kRegister);
}
View
@@ -333,6 +333,90 @@ void LLoadArg::Generate(Masm* masm) {
void LLoadVarArg::Generate(Masm* masm) {
+ // offset and rest are unboxed
+ Register offset = rax;
+ Register rest = rbx;
+ Register arr = rcx;
+ Operand argc(rbp, -HValue::kPointerSize * 2);
+ Operand qmap(arr, HObject::kMapOffset);
+ Operand slot(scratch, 0);
+ Operand stack_slot(offset, 0);
+
+ Label loop, preloop, end;
+
+ // Calculate length of vararg array
+ __ mov(scratch, offset);
+ __ addq(scratch, rest);
+
+ // If offset + rest <= argc - return immediately
+ __ cmpq(scratch, argc);
+ __ jmp(kGe, &end);
+
+ // rdx = argc - offset - rest
+ __ mov(rdx, argc);
+ __ subq(rdx, scratch);
+
+ // Array index
+ __ mov(rbx, Immediate(HNumber::Tag(0)));
+
+ Masm::Spill arr_s(masm, arr), rdx_s(masm);
+ Masm::Spill offset_s(masm, offset), rbx_s(masm);
+
+ __ bind(&loop);
+
+ // while (rdx > 0)
+ __ cmpq(rdx, Immediate(HNumber::Tag(0)));
+ __ jmp(kEq, &end);
+
+ rdx_s.SpillReg(rdx);
+ rbx_s.SpillReg(rbx);
+
+ __ mov(rax, arr);
+
+ // rax <- object
+ // rbx <- property
+ __ mov(rcx, Immediate(1));
+ __ Call(masm->stubs()->GetLookupPropertyStub());
+
+ arr_s.Unspill();
+ rbx_s.Unspill();
+
+ // Make rax look like unboxed number to GC
+ __ dec(rax);
+ __ CheckGC();
+ __ inc(rax);
+
+ __ IsNil(rax, NULL, &preloop);
+
+ __ mov(arr, qmap);
+ __ addq(rax, arr);
+ __ mov(scratch, rax);
+
+ // Get stack offset
+ offset_s.Unspill();
+ __ addq(offset, Immediate(4));
+ __ addq(offset, rbx);
+ __ shl(offset, 2);
+ __ addq(offset, rbp);
+ __ mov(offset, stack_slot);
+
+ // Put argument in array
+ __ mov(slot, offset);
+
+ arr_s.Unspill();
+
+ __ bind(&preloop);
+
+ // Increment array index
+ __ addq(rbx, Immediate(HNumber::Tag(1)));
+
+ // rdx --
+ rdx_s.Unspill();
+ __ subq(rdx, Immediate(HNumber::Tag(1)));
+ __ jmp(&loop);
+
+ __ bind(&end);
+ // rcx <- holds result
}
@@ -342,6 +426,97 @@ void LStoreArg::Generate(Masm* masm) {
void LStoreVarArg::Generate(Masm* masm) {
+ Register varg = rax;
+ Register index = rbx;
+ Register map = rcx;
+
+ // rax <- varg
+ Label loop, not_array, odd_end, r1_nil, r2_nil;
+ Masm::Spill index_s(masm), map_s(masm), array_s(masm), r1(masm);
+ Operand slot(rax, 0);
+
+ __ IsUnboxed(varg, NULL, &not_array);
+ __ IsNil(varg, NULL, &not_array);
+ __ IsHeapObject(Heap::kTagArray, varg, &not_array, NULL);
+
+ Operand qmap(varg, HObject::kMapOffset);
+ __ mov(map, qmap);
+ map_s.SpillReg(map);
+
+ // index = sizeof(array)
+ Operand qlength(varg, HArray::kLengthOffset);
+ __ mov(index, qlength);
+ __ TagNumber(index);
+
+ // while ...
+ __ bind(&loop);
+
+ array_s.SpillReg(varg);
+
+ // while ... (index != 0) {
+ __ cmpq(index, Immediate(HNumber::Tag(0)));
+ __ jmp(kEq, &not_array);
+
+ // index--;
+ __ subq(index, Immediate(HNumber::Tag(1)));
+
+ index_s.SpillReg(index);
+
+ // odd case: array[index]
+ __ mov(rbx, index);
+ __ mov(rcx, Immediate(0));
+ __ Call(masm->stubs()->GetLookupPropertyStub());
+
+ __ IsNil(rax, NULL, &r1_nil);
+ map_s.Unspill();
+ __ addq(rax, map);
+ __ mov(rax, slot);
+
+ __ bind(&r1_nil);
+ r1.SpillReg(rax);
+
+ index_s.Unspill();
+
+ // if (index == 0) goto odd_end;
+ __ cmpq(index, Immediate(HNumber::Tag(0)));
+ __ jmp(kEq, &odd_end);
+
+ // index--;
+ __ subq(index, Immediate(HNumber::Tag(1)));
+
+ array_s.Unspill();
+ index_s.SpillReg(index);
+
+ // even case: array[index]
+ __ mov(rbx, index);
+ __ mov(rcx, Immediate(0));
+ __ Call(masm->stubs()->GetLookupPropertyStub());
+
+ __ IsNil(rax, NULL, &r2_nil);
+ map_s.Unspill();
+ __ addq(rax, map);
+ __ mov(rax, slot);
+
+ __ bind(&r2_nil);
+
+ // Push two item at the same time (to preserve alignment)
+ r1.Unspill(index);
+ __ push(index);
+ __ push(rax);
+
+ index_s.Unspill();
+ array_s.Unspill();
+
+ __ jmp(&loop);
+
+ __ bind(&odd_end);
+
+ r1.Unspill(rax);
+ __ push(rax);
+
+ __ bind(&not_array);
+
+ __ xorq(map, map);
}
View
@@ -94,18 +94,20 @@ TEST_START(hir)
"i42 = Literal[0]\n"
"i44 = LoadArg(i42)\n"
"i46 = Literal[1]\n"
- "i48 = LoadVarArg(i46)\n"
- "i50 = Sizeof(i48)\n"
- "i52 = BinOp(i46, i50)\n"
- "i54 = LoadArg(i52)\n"
- "i56 = Literal[0]\n"
- "i58 = LoadProperty(i48, i56)\n"
- "i60 = Literal[1]\n"
+ "i48 = AllocateArray\n"
+ "i50 = Literal[1]\n"
+ "i52 = LoadVarArg(i46, i50, i48)\n"
+ "i54 = Sizeof(i48)\n"
+ "i56 = BinOp(i46, i54)\n"
+ "i58 = LoadArg(i56)\n"
+ "i60 = Literal[0]\n"
"i62 = LoadProperty(i48, i60)\n"
- "i64 = BinOp(i62, i54)\n"
- "i66 = BinOp(i58, i64)\n"
- "i68 = BinOp(i44, i66)\n"
- "i70 = Return(i68)\n")
+ "i64 = Literal[1]\n"
+ "i66 = LoadProperty(i48, i64)\n"
+ "i68 = BinOp(i66, i58)\n"
+ "i70 = BinOp(i62, i68)\n"
+ "i72 = BinOp(i44, i70)\n"
+ "i74 = Return(i72)\n")
// Unary operations
HIR_TEST("i = 0\nreturn !i",

0 comments on commit c2d28ee

Please sign in to comment.