blob: 7128c6e937bccbdf3896b83bf86dbe5297b5053d [file] [log] [blame]
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Carl Shapiro9b9ba282011-08-14 15:30:39 -07002
3#include "jni_internal.h"
4
5#include "assembler.h"
6#include "object.h"
7
8namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -07009namespace x86 {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070010
11// Creates a function which invokes a managed method with an array of
12// arguments.
13//
14// Immediately after the call, the environment looks like this:
15//
16// [SP+0 ] = Return address
17// [SP+4 ]= method pointer
18// [SP+8 ] = receiver pointer or NULL for static methods
19// [SP+12] = (managed) thread pointer
20// [SP+16] = argument array or NULL for no argument methods
21// [SP+20] = JValue* result or NULL for void returns
22//
23// As the JNI call has already transitioned the thread into the
24// "running" state the remaining responsibilities of this routine are
25// to save the native registers and set up the managed registers. On
26// return, the return value must be store into the result JValue.
Ian Rogers2c8f6532011-09-02 17:16:34 -070027void X86CreateInvokeStub(Method* method) {
28 UniquePtr<X86Assembler> assembler(
29 down_cast<X86Assembler*>(Assembler::Create(kX86)));
30#define __ assembler->
Ian Rogers67375ac2011-09-14 00:55:44 -070031 // Size of frame - return address + Method* + possible receiver + arg array
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070032 size_t frame_size = (2 * kPointerSize) +
33 (method->IsStatic() ? 0 : kPointerSize) +
34 method->NumArgArrayBytes();
35 size_t pad_size = RoundUp(frame_size, kStackAlignment) - frame_size;
36
Ian Rogers67375ac2011-09-14 00:55:44 -070037 __ movl(EAX, Address(ESP, 4)); // EAX = method
38 __ movl(ECX, Address(ESP, 8)); // ECX = receiver
39 __ movl(EDX, Address(ESP, 16)); // EDX = arg array
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070040
41 // Push padding
42 if (pad_size != 0) {
43 __ addl(ESP, Immediate(-pad_size));
44 }
45
46 // Push/copy arguments
47 for (size_t off = method->NumArgArrayBytes(); off > 0; off -= kPointerSize) {
48 __ pushl(Address(EDX, off - kPointerSize));
49 }
50 if (!method->IsStatic()) {
Ian Rogers67375ac2011-09-14 00:55:44 -070051 __ pushl(ECX);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070052 }
Ian Rogersed8952f2011-08-19 17:11:22 -070053 // Push 0 as NULL Method* thereby terminating managed stack crawls
54 __ pushl(Immediate(0));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070055
Ian Rogers67375ac2011-09-14 00:55:44 -070056 __ call(Address(EAX, method->GetCodeOffset())); // Call code off of method
57
58 // pop arguments up to the return address
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070059 __ addl(ESP, Immediate(frame_size + pad_size - kPointerSize));
Brian Carlstrom2ed67392011-09-09 14:53:28 -070060 char ch = method->GetShorty()->CharAt(0);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070061 if (ch != 'V') {
62 // Load the result JValue pointer.
Ian Rogers67375ac2011-09-14 00:55:44 -070063 __ movl(ECX, Address(ESP, 20));
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070064 switch (ch) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070065 case 'D':
Ian Rogers67375ac2011-09-14 00:55:44 -070066 __ fstpl(Address(ECX, 0));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070067 break;
68 case 'F':
Ian Rogers67375ac2011-09-14 00:55:44 -070069 __ fstps(Address(ECX, 0));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070070 break;
71 case 'J':
Ian Rogers67375ac2011-09-14 00:55:44 -070072 __ movl(Address(ECX, 0), EAX);
73 __ movl(Address(ECX, 4), EDX);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070074 break;
75 default:
Ian Rogers67375ac2011-09-14 00:55:44 -070076 __ movl(Address(ECX, 0), EAX);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070077 break;
78 }
79 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070080 __ ret();
Ian Rogers2c8f6532011-09-02 17:16:34 -070081 // TODO: store native_entry in the stub table
82 ByteArray* code = ByteArray::Alloc(assembler->CodeSize());
83 MemoryRegion region(code->GetData(), code->GetLength());
84 assembler->FinalizeInstructions(region);
85 method->SetInvokeStub(code);
86 CHECK(method->GetInvokeStub() != NULL);
87#undef __
Carl Shapiro9b9ba282011-08-14 15:30:39 -070088}
89
Ian Rogers2c8f6532011-09-02 17:16:34 -070090} // namespace x86
Carl Shapiro9b9ba282011-08-14 15:30:39 -070091} // namespace art