Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Unified Diff: src/x64/codegen-x64.cc

Issue 146029: x64 code generation for construct calls, declaring global variables... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/x64/codegen-x64.cc
===================================================================
--- src/x64/codegen-x64.cc (revision 2254)
+++ src/x64/codegen-x64.cc (working copy)
@@ -123,10 +123,21 @@
}
-void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) {
- UNIMPLEMENTED();
+void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
+ // Call the runtime to declare the globals. The inevitable call
+ // will sync frame elements to memory anyway, so we do it eagerly to
+ // allow us to push the arguments directly into place.
+ frame_->SyncRange(0, frame_->element_count() - 1);
+
+ __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT);
+ frame_->EmitPush(kScratchRegister);
+ frame_->EmitPush(rsi); // The context is the second argument.
+ frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
+ Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+ // Return value is ignored.
}
+
void CodeGenerator::TestCodeGenerator() {
// Compile a function from a string, and run it.
@@ -286,10 +297,35 @@
// Ignore the return value.
}
#endif
+ VisitStatements(body);
+
+ // Handle the return from the function.
+ if (has_valid_frame()) {
+ // If there is a valid frame, control flow can fall off the end of
+ // the body. In that case there is an implicit return statement.
+ ASSERT(!function_return_is_shadowed_);
+ CodeForReturnPosition(function);
+ frame_->PrepareForReturn();
+ Result undefined(Factory::undefined_value());
+ if (function_return_.is_bound()) {
+ function_return_.Jump(&undefined);
+ } else {
+ function_return_.Bind(&undefined);
+ GenerateReturnSequence(&undefined);
+ }
+ } else if (function_return_.is_linked()) {
+ // If the return target has dangling jumps to it, then we have not
+ // yet generated the return sequence. This can happen when (a)
+ // control does not flow off the end of the body so we did not
+ // compile an artificial return statement just above, and (b) there
+ // are return statements in the body but (c) they are all shadowed.
+ Result return_value;
+ function_return_.Bind(&return_value);
+ GenerateReturnSequence(&return_value);
+ }
}
+ }
- VisitStatements(body);
- }
// Adjust for function-level loop nesting.
loop_nesting_ -= function->loop_nesting();
@@ -1319,13 +1355,77 @@
}
-void CodeGenerator::VisitCallNew(CallNew* a) {
- UNIMPLEMENTED();
+void CodeGenerator::VisitCallNew(CallNew* node) {
+ Comment cmnt(masm_, "[ CallNew");
+ CodeForStatementPosition(node);
+
+ // According to ECMA-262, section 11.2.2, page 44, the function
+ // expression in new calls must be evaluated before the
+ // arguments. This is different from ordinary calls, where the
+ // actual function to call is resolved after the arguments have been
+ // evaluated.
+
+ // Compute function to call and use the global object as the
+ // receiver. There is no need to use the global proxy here because
+ // it will always be replaced with a newly allocated object.
+ Load(node->expression());
+ LoadGlobal();
+
+ // Push the arguments ("left-to-right") on the stack.
+ ZoneList<Expression*>* args = node->arguments();
+ int arg_count = args->length();
+ for (int i = 0; i < arg_count; i++) {
+ Load(args->at(i));
+ }
+
+ // Call the construct call builtin that handles allocation and
+ // constructor invocation.
+ CodeForSourcePosition(node->position());
+ Result result = frame_->CallConstructor(arg_count);
+ // Replace the function on the stack with the result.
+ frame_->SetElementAt(0, &result);
}
-void CodeGenerator::VisitCallRuntime(CallRuntime* a) {
- UNIMPLEMENTED();
+void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
+ if (CheckForInlineRuntimeCall(node)) {
+ return;
+ }
+
+ ZoneList<Expression*>* args = node->arguments();
+ Comment cmnt(masm_, "[ CallRuntime");
+ Runtime::Function* function = node->function();
+
+ if (function == NULL) {
+ // Prepare stack for calling JS runtime function.
+ frame_->Push(node->name());
+ // Push the builtins object found in the current global object.
+ Result temp = allocator()->Allocate();
William Hesse 2009/06/24 07:55:57 Use kScratchRegister here.
Mads Ager (chromium) 2009/06/24 08:18:50 Done.
+ ASSERT(temp.is_valid());
+ __ movq(temp.reg(), GlobalObject());
+ __ movq(temp.reg(),
+ FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset));
+ frame_->Push(&temp);
+ }
+
+ // Push the arguments ("left-to-right").
+ int arg_count = args->length();
+ for (int i = 0; i < arg_count; i++) {
+ Load(args->at(i));
+ }
+
+ if (function == NULL) {
+ // Call the JS runtime function.
+ Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET,
+ arg_count,
+ loop_nesting_);
+ frame_->RestoreContextRegister();
+ frame_->SetElementAt(0, &answer);
+ } else {
+ // Call the C runtime function.
+ Result answer = frame_->CallRuntime(function, arg_count);
+ frame_->Push(&answer);
+ }
}
@@ -1345,10 +1445,12 @@
UNIMPLEMENTED();
}
-void CodeGenerator::VisitThisFunction(ThisFunction* a) {
- UNIMPLEMENTED();
+
+void CodeGenerator::VisitThisFunction(ThisFunction* node) {
+ frame_->PushFunction();
}
+
void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
UNIMPLEMENTED();
}
@@ -1542,7 +1644,7 @@
ASSERT(kSmiTag == 0);
__ testq(value.reg(), value.reg());
dest->false_target()->Branch(zero);
- __ testq(value.reg(), Immediate(kSmiTagMask));
+ __ testl(value.reg(), Immediate(kSmiTagMask));
William Hesse 2009/06/24 07:55:57 We have many of these throughout the code, and hav
Mads Ager (chromium) 2009/06/24 08:18:50 We were using it inconsistently before. There was
dest->true_target()->Branch(zero);
// Call the stub for all other cases.
@@ -2056,7 +2158,7 @@
GetName());
// Check that the receiver is a heap object.
- __ testq(receiver.reg(), Immediate(kSmiTagMask));
+ __ testl(receiver.reg(), Immediate(kSmiTagMask));
deferred->Branch(zero);
__ bind(deferred->patch_site());
@@ -2370,8 +2472,8 @@
// Check for negative zero result.
__ NegativeZeroTest(rax, rcx, slow); // use ecx = x | y
// Tag the result and store it in register rax.
- ASSERT(kSmiTagSize == kTimes2); // adjust code if not the case
- __ lea(rax, Operand(rax, rax, kTimes1, kSmiTag));
+ ASSERT(kSmiTagSize == times_2); // adjust code if not the case
+ __ lea(rax, Operand(rax, rax, times_1, kSmiTag));
break;
case Token::MOD:
@@ -2435,8 +2537,8 @@
UNREACHABLE();
}
// Tag the result and store it in register eax.
- ASSERT(kSmiTagSize == kTimes2); // adjust code if not the case
- __ lea(rax, Operand(rax, rax, kTimes1, kSmiTag));
+ ASSERT(kSmiTagSize == times_2); // adjust code if not the case
+ __ lea(rax, Operand(rax, rax, times_1, kSmiTag));
break;
default:
@@ -2518,7 +2620,7 @@
__ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
// Check that the function really is a JavaScript function.
- __ testq(rdi, Immediate(kSmiTagMask));
+ __ testl(rdi, Immediate(kSmiTagMask));
__ j(zero, &slow);
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
@@ -2583,7 +2685,7 @@
// Patch the arguments.length and the parameters pointer.
__ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ movq(Operand(rsp, 1 * kPointerSize), rcx);
- __ lea(rdx, Operand(rdx, rcx, kTimes4, kDisplacement));
+ __ lea(rdx, Operand(rdx, rcx, times_4, kDisplacement));
__ movq(Operand(rsp, 2 * kPointerSize), rdx);
// Do the runtime call to allocate the arguments object.
@@ -2621,9 +2723,9 @@
// Shifting code depends on SmiEncoding being equivalent to left shift:
// we multiply by four to get pointer alignment.
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
- __ lea(rbx, Operand(rbp, rax, kTimes4, 0));
+ __ lea(rbx, Operand(rbp, rax, times_4, 0));
__ neg(rdx);
- __ movq(rax, Operand(rbx, rdx, kTimes4, kDisplacement));
+ __ movq(rax, Operand(rbx, rdx, times_4, kDisplacement));
__ Ret();
// Arguments adaptor case: Check index against actual arguments
@@ -2638,9 +2740,9 @@
// Shifting code depends on SmiEncoding being equivalent to left shift:
// we multiply by four to get pointer alignment.
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
- __ lea(rbx, Operand(rbx, rcx, kTimes4, 0));
+ __ lea(rbx, Operand(rbx, rcx, times_4, 0));
__ neg(rdx);
- __ movq(rax, Operand(rbx, rdx, kTimes4, kDisplacement));
+ __ movq(rax, Operand(rbx, rdx, times_4, kDisplacement));
__ Ret();
// Slow-case: Handle non-smi or out-of-bounds access to arguments
« src/x64/builtins-x64.cc ('K') | « src/x64/builtins-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698