Register context = cp;
int argc = ArgumentBits::decode(bit_field_);
- bool restore_context = RestoreContextBits::decode(bit_field_);
+ bool is_store = IsStoreBits::decode(bit_field_);
bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_);
typedef FunctionCallbackArguments FCA;
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
- MemOperand return_value_operand(fp,
- (2 + FCA::kReturnValueOffset) * kPointerSize);
+ // Stores return the first js argument
+ int return_value_offset =
+ 2 + (is_store ? FCA::kArgsLength : FCA::kReturnValueOffset);
+ MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
const int spill_offset = 1 + kApiStackSpace;
__ CallApiFunctionAndReturn(api_function_address,
kStackUnwindSpace,
spill_offset,
return_value_operand,
- restore_context ?
- &context_restore_operand : NULL);
+ &context_restore_operand);
}
Handle<Map> receiver_map,
Register receiver,
Register scratch,
+ bool is_store,
int argc,
Register* values) {
ASSERT(!AreAliased(receiver, scratch));
__ Mov(api_function_address, Operand(ref));
// Jump to stub.
- CallApiFunctionStub stub(true, call_data_undefined, argc);
+ CallApiFunctionStub stub(is_store, call_data_undefined, argc);
__ TailCallStub(&stub);
}
const CallOptimization& call_optimization,
Handle<Map> receiver_map) {
GenerateFastApiCall(
- masm(), call_optimization, receiver_map, receiver(), scratch3(), 0, NULL);
+ masm(), call_optimization, receiver_map,
+ receiver(), scratch3(), false, 0, NULL);
}
Register values[] = { value() };
GenerateFastApiCall(masm(), call_optimization, handle(object->map()),
- receiver(), scratch3(), 1, values);
+ receiver(), scratch3(), true, 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
Register context = cp;
int argc = ArgumentBits::decode(bit_field_);
- bool restore_context = RestoreContextBits::decode(bit_field_);
+ bool is_store = IsStoreBits::decode(bit_field_);
bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_);
typedef FunctionCallbackArguments FCA;
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
- MemOperand return_value_operand(fp,
- (2 + FCA::kReturnValueOffset) * kPointerSize);
+ // Stores return the first js argument
+ int return_value_offset =
+ 2 + (is_store ? FCA::kArgsLength : FCA::kReturnValueOffset);
+ MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
__ CallApiFunctionAndReturn(api_function_address,
thunk_ref,
kStackUnwindSpace,
return_value_operand,
- restore_context ?
- &context_restore_operand : NULL);
+ &context_restore_operand);
}
Handle<Map> receiver_map,
Register receiver,
Register scratch_in,
+ bool is_store,
int argc,
Register* values) {
ASSERT(!receiver.is(scratch_in));
__ mov(api_function_address, Operand(ref));
// Jump to stub.
- CallApiFunctionStub stub(true, call_data_undefined, argc);
+ CallApiFunctionStub stub(is_store, call_data_undefined, argc);
__ TailCallStub(&stub);
}
Handle<Map> receiver_map) {
GenerateFastApiCall(
masm(), call_optimization, receiver_map,
- receiver(), scratch3(), 0, NULL);
+ receiver(), scratch3(), false, 0, NULL);
}
Register values[] = { value() };
GenerateFastApiCall(
masm(), call_optimization, handle(object->map()),
- receiver(), scratch3(), 1, values);
+ receiver(), scratch3(), true, 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
class CallApiFunctionStub : public PlatformCodeStub {
public:
- CallApiFunctionStub(bool restore_context,
+ CallApiFunctionStub(bool is_store,
bool call_data_undefined,
int argc) {
bit_field_ =
- RestoreContextBits::encode(restore_context) |
+ IsStoreBits::encode(is_store) |
CallDataUndefinedBits::encode(call_data_undefined) |
ArgumentBits::encode(argc);
+ ASSERT(!is_store || argc == 1);
}
private:
virtual Major MajorKey() V8_OVERRIDE { return CallApiFunction; }
virtual int MinorKey() V8_OVERRIDE { return bit_field_; }
- class RestoreContextBits: public BitField<bool, 0, 1> {};
+ class IsStoreBits: public BitField<bool, 0, 1> {};
class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
}
bool drop_extra = false;
+ bool is_store = false;
switch (call_type) {
case kCallApiFunction:
case kCallApiMethod:
break;
case kCallApiSetter:
{
+ is_store = true;
// Receiver and prototype chain cannot have changed.
ASSERT_EQ(1, argc);
ASSERT_EQ(NULL, receiver);
CallInterfaceDescriptor* descriptor =
isolate()->call_descriptor(Isolate::ApiFunctionCall);
- CallApiFunctionStub stub(true, call_data_is_undefined, argc);
+ CallApiFunctionStub stub(is_store, call_data_is_undefined, argc);
Handle<Code> code = stub.GetCode(isolate());
HConstant* code_value = Add<HConstant>(code);
Register context = esi;
int argc = ArgumentBits::decode(bit_field_);
- bool restore_context = RestoreContextBits::decode(bit_field_);
+ bool is_store = IsStoreBits::decode(bit_field_);
bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_);
typedef FunctionCallbackArguments FCA;
Operand context_restore_operand(ebp,
(2 + FCA::kContextSaveIndex) * kPointerSize);
- Operand return_value_operand(ebp,
- (2 + FCA::kReturnValueOffset) * kPointerSize);
+ // Stores return the first js argument
+ int return_value_offset =
+ 2 + (is_store ? FCA::kArgsLength : FCA::kReturnValueOffset);
+ Operand return_value_operand(ebp, return_value_offset * kPointerSize);
__ CallApiFunctionAndReturn(api_function_address,
thunk_address,
ApiParameterOperand(1),
argc + FCA::kArgsLength + 1,
return_value_operand,
- restore_context ?
- &context_restore_operand : NULL);
+ &context_restore_operand);
}
Handle<Map> receiver_map,
Register receiver,
Register scratch_in,
+ bool is_store,
int argc,
Register* values) {
// Copy return value.
__ mov(api_function_address, Immediate(function_address));
// Jump to stub.
- CallApiFunctionStub stub(true, call_data_undefined, argc);
+ CallApiFunctionStub stub(is_store, call_data_undefined, argc);
__ TailCallStub(&stub);
}
Handle<Map> receiver_map) {
GenerateFastApiCall(
masm(), call_optimization, receiver_map,
- receiver(), scratch1(), 0, NULL);
+ receiver(), scratch1(), false, 0, NULL);
}
Register values[] = { value() };
GenerateFastApiCall(
masm(), call_optimization, handle(object->map()),
- receiver(), scratch1(), 1, values);
+ receiver(), scratch1(), true, 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
Register context = rsi;
int argc = ArgumentBits::decode(bit_field_);
- bool restore_context = RestoreContextBits::decode(bit_field_);
+ bool is_store = IsStoreBits::decode(bit_field_);
bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_);
typedef FunctionCallbackArguments FCA;
Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
- StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength,
+ // Accessor for FunctionCallbackInfo and first js arg.
+ StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1,
ARGUMENTS_DONT_CONTAIN_RECEIVER);
Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
- FCA::kArgsLength - 1 - FCA::kContextSaveIndex);
+ FCA::kArgsLength - FCA::kContextSaveIndex);
+ // Stores return the first js argument
Operand return_value_operand = args_from_rbp.GetArgumentOperand(
- FCA::kArgsLength - 1 - FCA::kReturnValueOffset);
+ is_store ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset);
__ CallApiFunctionAndReturn(
api_function_address,
thunk_address,
callback_arg,
argc + FCA::kArgsLength + 1,
return_value_operand,
- restore_context ? &context_restore_operand : NULL);
+ &context_restore_operand);
}
Handle<Map> receiver_map,
Register receiver,
Register scratch_in,
+ bool is_store,
int argc,
Register* values) {
ASSERT(optimization.is_simple_api_call());
api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE);
// Jump to stub.
- CallApiFunctionStub stub(true, call_data_undefined, argc);
+ CallApiFunctionStub stub(is_store, call_data_undefined, argc);
__ TailCallStub(&stub);
}
Handle<Map> receiver_map) {
GenerateFastApiCall(
masm(), call_optimization, receiver_map,
- receiver(), scratch1(), 0, NULL);
+ receiver(), scratch1(), false, 0, NULL);
}
Register values[] = { value() };
GenerateFastApiCall(
masm(), call_optimization, handle(object->map()),
- receiver(), scratch1(), 1, values);
+ receiver(), scratch1(), true, 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
CHECK_EQ(x_holder, info.This());
CHECK_EQ(x_holder, info.Holder());
x_register[offset] = value->Int32Value();
+ info.GetReturnValue().Set(v8_num(-1));
}
"var key_1 = 'x1';"
"for (var j = 0; j < 10; j++) {"
" var i = 4*j;"
- " holder.x0 = i;"
+ " result.push(holder.x0 = i);"
" result.push(obj.x0);"
- " holder.x1 = i + 1;"
+ " result.push(holder.x1 = i + 1);"
" result.push(obj.x1);"
- " holder[key_0] = i + 2;"
+ " result.push(holder[key_0] = i + 2);"
" result.push(obj[key_0]);"
- " holder[key_1] = i + 3;"
+ " result.push(holder[key_1] = i + 3);"
" result.push(obj[key_1]);"
"}"
"result"));
- CHECK_EQ(40, array->Length());
- for (int i = 0; i < 40; i++) {
+ CHECK_EQ(80, array->Length());
+ for (int i = 0; i < 80; i++) {
v8::Handle<Value> entry = array->Get(v8::Integer::New(isolate, i));
- CHECK_EQ(v8::Integer::New(isolate, i), entry);
+ CHECK_EQ(v8::Integer::New(isolate, i/2), entry);
}
}
}
CHECK(holder == info.Holder());
count++;
+ info.GetReturnValue().Set(v8_str("returned"));
}
// TODO(dcarney): move this to v8.h
wrap_function,
"function wrap_f_%d() { var f = g_f; return f(); }\n"
"function wrap_get_%d() { return this.g_acc; }\n"
- "function wrap_set_%d() { this.g_acc = 1; }\n",
+ "function wrap_set_%d() { return this.g_acc = 1; }\n",
key, key, key);
} else {
i::OS::SNPrintF(
wrap_function,
"function wrap_f_%d() { return receiver_subclass.f(); }\n"
"function wrap_get_%d() { return receiver_subclass.acc; }\n"
- "function wrap_set_%d() { receiver_subclass.acc = 1; }\n",
+ "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
key, key, key);
}
// build source string
- i::ScopedVector<char> source(500);
+ i::ScopedVector<char> source(1000);
i::OS::SNPrintF(
source,
"%s\n" // wrap functions
- "function wrap_f() { wrap_f_%d(); }\n"
- "function wrap_get() { wrap_get_%d(); }\n"
- "function wrap_set() { wrap_set_%d(); }\n"
+ "function wrap_f() { return wrap_f_%d(); }\n"
+ "function wrap_get() { return wrap_get_%d(); }\n"
+ "function wrap_set() { return wrap_set_%d(); }\n"
+ "check = function(returned) {\n"
+ " if (returned !== 'returned') { throw returned; }\n"
+ "}\n"
"\n"
- "wrap_f();\n"
- "wrap_f();\n"
+ "check(wrap_f());\n"
+ "check(wrap_f());\n"
"%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
- "wrap_f();\n"
+ "check(wrap_f());\n"
"\n"
- "wrap_get();\n"
- "wrap_get();\n"
+ "check(wrap_get());\n"
+ "check(wrap_get());\n"
"%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
- "wrap_get();\n"
+ "check(wrap_get());\n"
"\n"
- "wrap_set();\n"
- "wrap_set();\n"
+ "check = function(returned) {\n"
+ " if (returned !== 1) { throw returned; }\n"
+ "}\n"
+ "check(wrap_set());\n"
+ "check(wrap_set());\n"
"%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
- "wrap_set();\n",
+ "check(wrap_set());\n",
wrap_function.start(), key, key, key, key, key, key);
v8::TryCatch try_catch;
CompileRun(source.start());