OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 4323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4334 Label fast_elements_case; | 4334 Label fast_elements_case; |
4335 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 4335 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
4336 __ j(equal, &fast_elements_case); | 4336 __ j(equal, &fast_elements_case); |
4337 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 4337 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
4338 | 4338 |
4339 __ bind(&fast_elements_case); | 4339 __ bind(&fast_elements_case); |
4340 GenerateCase(masm, FAST_ELEMENTS); | 4340 GenerateCase(masm, FAST_ELEMENTS); |
4341 } | 4341 } |
4342 | 4342 |
4343 | 4343 |
| 4344 // Generates an Operand for saving parameters after PrepareCallApiFunction. |
| 4345 static Operand ApiParameterOperand(int index) { |
| 4346 return Operand(esp, index * kPointerSize); |
| 4347 } |
| 4348 |
| 4349 |
| 4350 // Prepares stack to put arguments (aligns and so on). Reserves |
| 4351 // space for return value if needed (assumes the return value is a handle). |
| 4352 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) |
| 4353 // etc. Saves context (esi). If space was reserved for return value then |
| 4354 // stores the pointer to the reserved slot into esi. |
| 4355 static void PrepareCallApiFunction(MacroAssembler* masm, int argc) { |
| 4356 __ EnterApiExitFrame(argc); |
| 4357 if (__ emit_debug_code()) { |
| 4358 __ mov(esi, Immediate(bit_cast<int32_t>(kZapValue))); |
| 4359 } |
| 4360 } |
| 4361 |
| 4362 |
| 4363 // Calls an API function. Allocates HandleScope, extracts returned value |
| 4364 // from handle and propagates exceptions. Clobbers ebx, edi and |
| 4365 // caller-save registers. Restores context. On return removes |
| 4366 // stack_space * kPointerSize (GCed). |
| 4367 static void CallApiFunctionAndReturn(MacroAssembler* masm, |
| 4368 Register function_address, |
| 4369 ExternalReference thunk_ref, |
| 4370 Operand thunk_last_arg, int stack_space, |
| 4371 Operand* stack_space_operand, |
| 4372 Operand return_value_operand, |
| 4373 Operand* context_restore_operand) { |
| 4374 Isolate* isolate = masm->isolate(); |
| 4375 |
| 4376 ExternalReference next_address = |
| 4377 ExternalReference::handle_scope_next_address(isolate); |
| 4378 ExternalReference limit_address = |
| 4379 ExternalReference::handle_scope_limit_address(isolate); |
| 4380 ExternalReference level_address = |
| 4381 ExternalReference::handle_scope_level_address(isolate); |
| 4382 |
| 4383 DCHECK(edx.is(function_address)); |
| 4384 // Allocate HandleScope in callee-save registers. |
| 4385 __ mov(ebx, Operand::StaticVariable(next_address)); |
| 4386 __ mov(edi, Operand::StaticVariable(limit_address)); |
| 4387 __ add(Operand::StaticVariable(level_address), Immediate(1)); |
| 4388 |
| 4389 if (FLAG_log_timer_events) { |
| 4390 FrameScope frame(masm, StackFrame::MANUAL); |
| 4391 __ PushSafepointRegisters(); |
| 4392 __ PrepareCallCFunction(1, eax); |
| 4393 __ mov(Operand(esp, 0), |
| 4394 Immediate(ExternalReference::isolate_address(isolate))); |
| 4395 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), |
| 4396 1); |
| 4397 __ PopSafepointRegisters(); |
| 4398 } |
| 4399 |
| 4400 |
| 4401 Label profiler_disabled; |
| 4402 Label end_profiler_check; |
| 4403 __ mov(eax, Immediate(ExternalReference::is_profiling_address(isolate))); |
| 4404 __ cmpb(Operand(eax, 0), 0); |
| 4405 __ j(zero, &profiler_disabled); |
| 4406 |
| 4407 // Additional parameter is the address of the actual getter function. |
| 4408 __ mov(thunk_last_arg, function_address); |
| 4409 // Call the api function. |
| 4410 __ mov(eax, Immediate(thunk_ref)); |
| 4411 __ call(eax); |
| 4412 __ jmp(&end_profiler_check); |
| 4413 |
| 4414 __ bind(&profiler_disabled); |
| 4415 // Call the api function. |
| 4416 __ call(function_address); |
| 4417 __ bind(&end_profiler_check); |
| 4418 |
| 4419 if (FLAG_log_timer_events) { |
| 4420 FrameScope frame(masm, StackFrame::MANUAL); |
| 4421 __ PushSafepointRegisters(); |
| 4422 __ PrepareCallCFunction(1, eax); |
| 4423 __ mov(Operand(esp, 0), |
| 4424 Immediate(ExternalReference::isolate_address(isolate))); |
| 4425 __ CallCFunction(ExternalReference::log_leave_external_function(isolate), |
| 4426 1); |
| 4427 __ PopSafepointRegisters(); |
| 4428 } |
| 4429 |
| 4430 Label prologue; |
| 4431 // Load the value from ReturnValue |
| 4432 __ mov(eax, return_value_operand); |
| 4433 |
| 4434 Label promote_scheduled_exception; |
| 4435 Label exception_handled; |
| 4436 Label delete_allocated_handles; |
| 4437 Label leave_exit_frame; |
| 4438 |
| 4439 __ bind(&prologue); |
| 4440 // No more valid handles (the result handle was the last one). Restore |
| 4441 // previous handle scope. |
| 4442 __ mov(Operand::StaticVariable(next_address), ebx); |
| 4443 __ sub(Operand::StaticVariable(level_address), Immediate(1)); |
| 4444 __ Assert(above_equal, kInvalidHandleScopeLevel); |
| 4445 __ cmp(edi, Operand::StaticVariable(limit_address)); |
| 4446 __ j(not_equal, &delete_allocated_handles); |
| 4447 __ bind(&leave_exit_frame); |
| 4448 |
| 4449 // Check if the function scheduled an exception. |
| 4450 ExternalReference scheduled_exception_address = |
| 4451 ExternalReference::scheduled_exception_address(isolate); |
| 4452 __ cmp(Operand::StaticVariable(scheduled_exception_address), |
| 4453 Immediate(isolate->factory()->the_hole_value())); |
| 4454 __ j(not_equal, &promote_scheduled_exception); |
| 4455 __ bind(&exception_handled); |
| 4456 |
| 4457 #if DEBUG |
| 4458 // Check if the function returned a valid JavaScript value. |
| 4459 Label ok; |
| 4460 Register return_value = eax; |
| 4461 Register map = ecx; |
| 4462 |
| 4463 __ JumpIfSmi(return_value, &ok, Label::kNear); |
| 4464 __ mov(map, FieldOperand(return_value, HeapObject::kMapOffset)); |
| 4465 |
| 4466 __ CmpInstanceType(map, LAST_NAME_TYPE); |
| 4467 __ j(below_equal, &ok, Label::kNear); |
| 4468 |
| 4469 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
| 4470 __ j(above_equal, &ok, Label::kNear); |
| 4471 |
| 4472 __ cmp(map, isolate->factory()->heap_number_map()); |
| 4473 __ j(equal, &ok, Label::kNear); |
| 4474 |
| 4475 __ cmp(return_value, isolate->factory()->undefined_value()); |
| 4476 __ j(equal, &ok, Label::kNear); |
| 4477 |
| 4478 __ cmp(return_value, isolate->factory()->true_value()); |
| 4479 __ j(equal, &ok, Label::kNear); |
| 4480 |
| 4481 __ cmp(return_value, isolate->factory()->false_value()); |
| 4482 __ j(equal, &ok, Label::kNear); |
| 4483 |
| 4484 __ cmp(return_value, isolate->factory()->null_value()); |
| 4485 __ j(equal, &ok, Label::kNear); |
| 4486 |
| 4487 __ Abort(kAPICallReturnedInvalidObject); |
| 4488 |
| 4489 __ bind(&ok); |
| 4490 #endif |
| 4491 |
| 4492 bool restore_context = context_restore_operand != NULL; |
| 4493 if (restore_context) { |
| 4494 __ mov(esi, *context_restore_operand); |
| 4495 } |
| 4496 if (stack_space_operand != nullptr) { |
| 4497 __ mov(ebx, *stack_space_operand); |
| 4498 } |
| 4499 __ LeaveApiExitFrame(!restore_context); |
| 4500 if (stack_space_operand != nullptr) { |
| 4501 DCHECK_EQ(0, stack_space); |
| 4502 __ pop(ecx); |
| 4503 __ add(esp, ebx); |
| 4504 __ jmp(ecx); |
| 4505 } else { |
| 4506 __ ret(stack_space * kPointerSize); |
| 4507 } |
| 4508 |
| 4509 __ bind(&promote_scheduled_exception); |
| 4510 { |
| 4511 FrameScope frame(masm, StackFrame::INTERNAL); |
| 4512 __ CallRuntime(Runtime::kPromoteScheduledException, 0); |
| 4513 } |
| 4514 __ jmp(&exception_handled); |
| 4515 |
| 4516 // HandleScope limit has changed. Delete allocated extensions. |
| 4517 ExternalReference delete_extensions = |
| 4518 ExternalReference::delete_handle_scope_extensions(isolate); |
| 4519 __ bind(&delete_allocated_handles); |
| 4520 __ mov(Operand::StaticVariable(limit_address), edi); |
| 4521 __ mov(edi, eax); |
| 4522 __ mov(Operand(esp, 0), |
| 4523 Immediate(ExternalReference::isolate_address(isolate))); |
| 4524 __ mov(eax, Immediate(delete_extensions)); |
| 4525 __ call(eax); |
| 4526 __ mov(eax, edi); |
| 4527 __ jmp(&leave_exit_frame); |
| 4528 } |
| 4529 |
| 4530 |
4344 static void CallApiFunctionStubHelper(MacroAssembler* masm, | 4531 static void CallApiFunctionStubHelper(MacroAssembler* masm, |
4345 const ParameterCount& argc, | 4532 const ParameterCount& argc, |
4346 bool return_first_arg, | 4533 bool return_first_arg, |
4347 bool call_data_undefined) { | 4534 bool call_data_undefined) { |
4348 // ----------- S t a t e ------------- | 4535 // ----------- S t a t e ------------- |
4349 // -- eax : callee | 4536 // -- eax : callee |
4350 // -- ebx : call_data | 4537 // -- ebx : call_data |
4351 // -- ecx : holder | 4538 // -- ecx : holder |
4352 // -- edx : api_function_address | 4539 // -- edx : api_function_address |
4353 // -- esi : context | 4540 // -- esi : context |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4416 // API function gets reference to the v8::Arguments. If CPU profiler | 4603 // API function gets reference to the v8::Arguments. If CPU profiler |
4417 // is enabled wrapper function will be called and we need to pass | 4604 // is enabled wrapper function will be called and we need to pass |
4418 // address of the callback as additional parameter, always allocate | 4605 // address of the callback as additional parameter, always allocate |
4419 // space for it. | 4606 // space for it. |
4420 const int kApiArgc = 1 + 1; | 4607 const int kApiArgc = 1 + 1; |
4421 | 4608 |
4422 // Allocate the v8::Arguments structure in the arguments' space since | 4609 // Allocate the v8::Arguments structure in the arguments' space since |
4423 // it's not controlled by GC. | 4610 // it's not controlled by GC. |
4424 const int kApiStackSpace = 4; | 4611 const int kApiStackSpace = 4; |
4425 | 4612 |
4426 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); | 4613 PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace); |
4427 | 4614 |
4428 // FunctionCallbackInfo::implicit_args_. | 4615 // FunctionCallbackInfo::implicit_args_. |
4429 __ mov(ApiParameterOperand(2), scratch); | 4616 __ mov(ApiParameterOperand(2), scratch); |
4430 if (argc.is_immediate()) { | 4617 if (argc.is_immediate()) { |
4431 __ add(scratch, | 4618 __ add(scratch, |
4432 Immediate((argc.immediate() + FCA::kArgsLength - 1) * kPointerSize)); | 4619 Immediate((argc.immediate() + FCA::kArgsLength - 1) * kPointerSize)); |
4433 // FunctionCallbackInfo::values_. | 4620 // FunctionCallbackInfo::values_. |
4434 __ mov(ApiParameterOperand(3), scratch); | 4621 __ mov(ApiParameterOperand(3), scratch); |
4435 // FunctionCallbackInfo::length_. | 4622 // FunctionCallbackInfo::length_. |
4436 __ Move(ApiParameterOperand(4), Immediate(argc.immediate())); | 4623 __ Move(ApiParameterOperand(4), Immediate(argc.immediate())); |
(...skipping 29 matching lines...) Expand all Loading... |
4466 return_value_offset = 2 + FCA::kReturnValueOffset; | 4653 return_value_offset = 2 + FCA::kReturnValueOffset; |
4467 } | 4654 } |
4468 Operand return_value_operand(ebp, return_value_offset * kPointerSize); | 4655 Operand return_value_operand(ebp, return_value_offset * kPointerSize); |
4469 int stack_space = 0; | 4656 int stack_space = 0; |
4470 Operand is_construct_call_operand = ApiParameterOperand(5); | 4657 Operand is_construct_call_operand = ApiParameterOperand(5); |
4471 Operand* stack_space_operand = &is_construct_call_operand; | 4658 Operand* stack_space_operand = &is_construct_call_operand; |
4472 if (argc.is_immediate()) { | 4659 if (argc.is_immediate()) { |
4473 stack_space = argc.immediate() + FCA::kArgsLength + 1; | 4660 stack_space = argc.immediate() + FCA::kArgsLength + 1; |
4474 stack_space_operand = nullptr; | 4661 stack_space_operand = nullptr; |
4475 } | 4662 } |
4476 __ CallApiFunctionAndReturn( | 4663 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
4477 api_function_address, thunk_ref, ApiParameterOperand(1), stack_space, | 4664 ApiParameterOperand(1), stack_space, |
4478 stack_space_operand, return_value_operand, &context_restore_operand); | 4665 stack_space_operand, return_value_operand, |
| 4666 &context_restore_operand); |
4479 } | 4667 } |
4480 | 4668 |
4481 | 4669 |
4482 void CallApiFunctionStub::Generate(MacroAssembler* masm) { | 4670 void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
4483 // TODO(dcarney): make eax contain the function address. | 4671 // TODO(dcarney): make eax contain the function address. |
4484 bool call_data_undefined = this->call_data_undefined(); | 4672 bool call_data_undefined = this->call_data_undefined(); |
4485 CallApiFunctionStubHelper(masm, ParameterCount(edi), false, | 4673 CallApiFunctionStubHelper(masm, ParameterCount(edi), false, |
4486 call_data_undefined); | 4674 call_data_undefined); |
4487 } | 4675 } |
4488 | 4676 |
(...skipping 23 matching lines...) Expand all Loading... |
4512 // Allocate space for opional callback address parameter in case | 4700 // Allocate space for opional callback address parameter in case |
4513 // CPU profiler is active. | 4701 // CPU profiler is active. |
4514 const int kApiArgc = 2 + 1; | 4702 const int kApiArgc = 2 + 1; |
4515 | 4703 |
4516 Register api_function_address = edx; | 4704 Register api_function_address = edx; |
4517 Register scratch = ebx; | 4705 Register scratch = ebx; |
4518 | 4706 |
4519 // load address of name | 4707 // load address of name |
4520 __ lea(scratch, Operand(esp, 1 * kPointerSize)); | 4708 __ lea(scratch, Operand(esp, 1 * kPointerSize)); |
4521 | 4709 |
4522 __ PrepareCallApiFunction(kApiArgc); | 4710 PrepareCallApiFunction(masm, kApiArgc); |
4523 __ mov(ApiParameterOperand(0), scratch); // name. | 4711 __ mov(ApiParameterOperand(0), scratch); // name. |
4524 __ add(scratch, Immediate(kPointerSize)); | 4712 __ add(scratch, Immediate(kPointerSize)); |
4525 __ mov(ApiParameterOperand(1), scratch); // arguments pointer. | 4713 __ mov(ApiParameterOperand(1), scratch); // arguments pointer. |
4526 | 4714 |
4527 ExternalReference thunk_ref = | 4715 ExternalReference thunk_ref = |
4528 ExternalReference::invoke_accessor_getter_callback(isolate()); | 4716 ExternalReference::invoke_accessor_getter_callback(isolate()); |
4529 | 4717 |
4530 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, | 4718 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
4531 ApiParameterOperand(2), kStackSpace, nullptr, | 4719 ApiParameterOperand(2), kStackSpace, nullptr, |
4532 Operand(ebp, 7 * kPointerSize), NULL); | 4720 Operand(ebp, 7 * kPointerSize), NULL); |
4533 } | 4721 } |
4534 | 4722 |
4535 | 4723 |
4536 #undef __ | 4724 #undef __ |
4537 | 4725 |
4538 } } // namespace v8::internal | 4726 } } // namespace v8::internal |
4539 | 4727 |
4540 #endif // V8_TARGET_ARCH_X87 | 4728 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |