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/builtins.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
11 #include "src/bootstrapper.h" | 11 #include "src/bootstrapper.h" |
12 #include "src/compiler/code-stub-assembler.h" | |
12 #include "src/dateparser-inl.h" | 13 #include "src/dateparser-inl.h" |
13 #include "src/elements.h" | 14 #include "src/elements.h" |
14 #include "src/frames-inl.h" | 15 #include "src/frames-inl.h" |
15 #include "src/gdb-jit.h" | 16 #include "src/gdb-jit.h" |
16 #include "src/ic/handler-compiler.h" | 17 #include "src/ic/handler-compiler.h" |
17 #include "src/ic/ic.h" | 18 #include "src/ic/ic.h" |
18 #include "src/isolate-inl.h" | 19 #include "src/isolate-inl.h" |
19 #include "src/messages.h" | 20 #include "src/messages.h" |
20 #include "src/profiler/cpu-profiler.h" | 21 #include "src/profiler/cpu-profiler.h" |
21 #include "src/property-descriptor.h" | 22 #include "src/property-descriptor.h" |
(...skipping 4329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4351 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) { | 4352 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) { |
4352 masm->TailCallRuntime(Runtime::kInterrupt); | 4353 masm->TailCallRuntime(Runtime::kInterrupt); |
4353 } | 4354 } |
4354 | 4355 |
4355 | 4356 |
4356 void Builtins::Generate_StackCheck(MacroAssembler* masm) { | 4357 void Builtins::Generate_StackCheck(MacroAssembler* masm) { |
4357 masm->TailCallRuntime(Runtime::kStackGuard); | 4358 masm->TailCallRuntime(Runtime::kStackGuard); |
4358 } | 4359 } |
4359 | 4360 |
4360 | 4361 |
4362 namespace { | |
4363 | |
4364 void ValidateSharedTypedArray(compiler::CodeStubAssembler* a, | |
4365 compiler::Node* tagged) { | |
4366 using namespace compiler; | |
4367 CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a), | |
4368 not_typed_array(a), is_shared(a), not_shared(a), is_float(a), | |
4369 not_float(a), invalid(a); | |
4370 Node* context = a->Context(); | |
4371 | |
4372 // Check if it is a heap object. | |
4373 a->Branch(a->WordIsSmi(tagged), &is_smi, ¬_smi); | |
4374 a->Bind(&is_smi); | |
4375 a->Goto(&invalid); | |
binji
2016/02/12 01:46:56
This Bind/Goto dance I end up having to do a lot o
| |
4376 | |
4377 // Check if the array's instance type is JSTypedArray. | |
4378 a->Bind(¬_smi); | |
4379 a->Branch(a->WordEqual(a->InstanceType(tagged), | |
4380 a->Int32Constant(JS_TYPED_ARRAY_TYPE)), | |
4381 &is_typed_array, ¬_typed_array); | |
4382 a->Bind(¬_typed_array); | |
4383 a->Goto(&invalid); | |
4384 | |
4385 // Check if the array's JSArrayBuffer is shared. | |
4386 a->Bind(&is_typed_array); | |
4387 Node* is_buffer_shared = | |
4388 a->BitFieldValue<JSArrayBuffer::IsShared>(a->LoadObjectField( | |
4389 a->LoadObjectField(tagged, JSTypedArray::kBufferOffset), | |
4390 JSArrayBuffer::kBitFieldOffset)); | |
4391 a->Branch(is_buffer_shared, &is_shared, ¬_shared); | |
4392 a->Bind(¬_shared); | |
4393 a->Goto(&invalid); | |
4394 | |
4395 // Check if the array's element type is float32 or float64. | |
4396 // TODO(binji): should fail on clamped as well. | |
4397 a->Bind(&is_shared); | |
4398 Node* elements_instance_type = | |
4399 a->InstanceType(a->LoadObjectField(tagged, JSObject::kElementsOffset)); | |
4400 a->Branch(a->WordOr(a->WordEqual(elements_instance_type, | |
4401 a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)), | |
4402 a->WordEqual(elements_instance_type, | |
4403 a->Int32Constant(FIXED_FLOAT64_ARRAY_TYPE))), | |
4404 &is_float, ¬_float); | |
4405 a->Bind(&is_float); | |
4406 a->Goto(&invalid); | |
4407 | |
4408 a->Bind(&invalid); | |
4409 a->TailCallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context, | |
4410 tagged); | |
4411 | |
4412 a->Bind(¬_float); | |
4413 } | |
4414 | |
4415 | |
4416 compiler::Node* TaggedNumberAsWord32(compiler::CodeStubAssembler* a, | |
4417 compiler::Node* tagged) { | |
4418 using namespace compiler; | |
4419 CodeStubAssembler::Label is_smi(a), is_not_smi(a), is_word(a); | |
4420 CodeStubAssembler::Variable result(a, MachineRepresentation::kWord32); | |
4421 | |
4422 a->Branch(a->WordIsSmi(tagged), &is_smi, &is_not_smi); | |
4423 | |
4424 a->Bind(&is_smi); | |
4425 result.Bind(a->SmiUntag(tagged)); | |
4426 a->Goto(&is_word); | |
4427 | |
4428 a->Bind(&is_not_smi); | |
4429 result.Bind(a->ChangeFloat64ToUint32(a->LoadHeapNumber(tagged))); | |
4430 a->Goto(&is_word); | |
4431 | |
4432 a->Bind(&is_word); | |
4433 return result.value(); | |
4434 } | |
4435 | |
4436 | |
4437 compiler::Node* ConvertTaggedAtomicIndexToWord32(compiler::CodeStubAssembler* a, | |
4438 compiler::Node* tagged) { | |
4439 using namespace compiler; | |
4440 CodeStubAssembler::Label is_smi(a), is_not_smi(a), is_string(a), | |
4441 is_not_string(a), strings_equal(a), strings_not_equal(a), | |
4442 string_number_is_smi(a), string_number_is_not_smi(a), is_number(a), | |
4443 convert_number(a), is_unknown(a), is_integer(a), is_not_integer(a), | |
4444 is_word(a), invalid(a); | |
4445 CodeStubAssembler::Variable number(a, MachineRepresentation::kTagged); | |
4446 CodeStubAssembler::Variable word(a, MachineRepresentation::kWord32); | |
4447 Node* context = a->Context(); | |
4448 | |
4449 // Check if the index's type is a Smi. | |
4450 a->Branch(a->WordIsSmi(tagged), &is_smi, &is_not_smi); | |
4451 | |
4452 // Check if the index's type is a String. | |
4453 a->Bind(&is_not_smi); | |
4454 Node* instance_type = a->InstanceType(tagged); | |
4455 a->Branch(a->WordEqual( | |
4456 a->WordAnd(instance_type, a->Int32Constant(kIsNotStringMask)), | |
4457 a->Int32Constant(0)), | |
4458 &is_string, &is_not_string); | |
4459 | |
4460 // Check that converting the string to a number and back is equal to itself. | |
4461 a->Bind(&is_string); | |
4462 Node* string_as_number = | |
4463 a->CallRuntime(Runtime::kStringToNumber, context, tagged); | |
4464 a->Branch( | |
4465 a->WordEqual(a->CallRuntime(Runtime::kStringEquals, context, | |
4466 a->CallRuntime(Runtime::kNumberToString, | |
4467 context, string_as_number), | |
4468 tagged), | |
4469 a->Int32Constant(EQUAL)), | |
4470 &strings_equal, &strings_not_equal); | |
4471 | |
4472 a->Bind(&strings_not_equal); | |
4473 a->Goto(&invalid); | |
4474 | |
4475 // Check if the string converted to a number is a Smi. | |
4476 a->Bind(&strings_equal); | |
4477 a->Branch(a->WordIsSmi(string_as_number), &string_number_is_smi, | |
4478 &string_number_is_not_smi); | |
4479 | |
4480 // If the string-number is a Smi, untag it. | |
4481 a->Bind(&string_number_is_smi); | |
4482 word.Bind(a->SmiUntag(string_as_number)); | |
4483 a->Goto(&is_word); | |
4484 | |
4485 // If the string-number is a HeapNumber, convert it to a word32. | |
4486 a->Bind(&string_number_is_not_smi); | |
4487 number.Bind(string_as_number); | |
4488 a->Goto(&convert_number); | |
4489 | |
4490 // Check if the index's type is a HeapNumber. | |
4491 a->Bind(&is_not_string); | |
4492 a->Branch(a->WordEqual(instance_type, a->Int32Constant(HEAP_NUMBER_TYPE)), | |
4493 &is_number, &is_unknown); | |
4494 | |
4495 // Index is an invalid type, throw. | |
4496 a->Bind(&is_unknown); | |
4497 a->Goto(&invalid); | |
4498 | |
4499 a->Bind(&is_number); | |
4500 number.Bind(tagged); | |
4501 a->Goto(&convert_number); | |
4502 | |
4503 // Convert index from a HeapNumber to a word32. | |
4504 a->Bind(&convert_number); | |
4505 Node* number_value = a->LoadHeapNumber(number.value()); | |
4506 word.Bind(a->ChangeFloat64ToUint32(number_value)); | |
4507 | |
4508 // Check that the index is an integer. | |
4509 a->Branch( | |
4510 a->Float64Equal(a->ChangeUint32ToFloat64(word.value()), number_value), | |
4511 &is_integer, &is_not_integer); | |
4512 | |
4513 a->Bind(&is_not_integer); | |
4514 a->Goto(&invalid); | |
4515 | |
4516 a->Bind(&is_integer); | |
4517 a->Goto(&is_word); | |
4518 | |
4519 // Index is a Smi, untag. | |
4520 a->Bind(&is_smi); | |
4521 word.Bind(a->SmiUntag(tagged)); | |
4522 a->Goto(&is_word); | |
4523 | |
4524 a->Bind(&invalid); | |
4525 a->TailCallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); | |
4526 | |
4527 a->Bind(&is_word); | |
4528 return word.value(); | |
4529 } | |
4530 | |
4531 | |
4532 void ValidateAtomicIndex(compiler::CodeStubAssembler* a, | |
4533 compiler::Node* index_word, | |
4534 compiler::Node* array_length_word) { | |
4535 using namespace compiler; | |
4536 // Check if the index is in bounds. If not, throw RangeError. | |
4537 CodeStubAssembler::Label in_bounds(a), not_in_bounds(a); | |
4538 a->Branch( | |
4539 a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)), | |
4540 a->Int32GreaterThanOrEqual(index_word, array_length_word)), | |
4541 ¬_in_bounds, &in_bounds); | |
4542 a->Bind(¬_in_bounds); | |
4543 a->TailCallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, | |
4544 a->Context()); | |
4545 a->Bind(&in_bounds); | |
4546 } | |
4547 | |
4548 } // anonymous namespace | |
4549 | |
4550 | |
4551 void Builtins::Generate_AtomicsLoadCheck(MacroAssembler* masm) { | |
4552 using namespace compiler; | |
4553 Isolate* isolate = masm->isolate(); | |
4554 Zone zone; | |
4555 CodeStubAssembler a(isolate, &zone, 2, Code::ComputeFlags(Code::STUB), | |
4556 "AtomicsLoadCheck"); | |
4557 | |
4558 Node* array = a.Parameter(0); | |
4559 Node* index = a.Parameter(1); | |
4560 ValidateSharedTypedArray(&a, array); | |
4561 Node* index_word = ConvertTaggedAtomicIndexToWord32(&a, index); | |
4562 Node* array_length_word = TaggedNumberAsWord32( | |
4563 &a, a.LoadObjectField(array, JSTypedArray::kLengthOffset)); | |
4564 ValidateAtomicIndex(&a, index_word, array_length_word); | |
4565 | |
4566 AtomicsLoadStub stub(isolate); | |
4567 // TODO(binji): can't just re-tag index, because it might be out of range. | |
4568 // Can we just pass the untagged index value to the code stub? | |
4569 Node* stub_args[] = {array, a.SmiTag(index_word), a.Context()}; | |
4570 a.TailCallStub(stub, stub_args); | |
4571 | |
4572 masm->Jump(a.GenerateCode(), RelocInfo::CODE_TARGET); | |
binji
2016/02/12 01:46:56
Is this right? I've seen some errors when I run ce
| |
4573 } | |
4574 | |
4575 | |
4361 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \ | 4576 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \ |
4362 Handle<Code> Builtins::name() { \ | 4577 Handle<Code> Builtins::name() { \ |
4363 Code** code_address = \ | 4578 Code** code_address = \ |
4364 reinterpret_cast<Code**>(builtin_address(k##name)); \ | 4579 reinterpret_cast<Code**>(builtin_address(k##name)); \ |
4365 return Handle<Code>(code_address); \ | 4580 return Handle<Code>(code_address); \ |
4366 } | 4581 } |
4367 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \ | 4582 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \ |
4368 Handle<Code> Builtins::name() { \ | 4583 Handle<Code> Builtins::name() { \ |
4369 Code** code_address = \ | 4584 Code** code_address = \ |
4370 reinterpret_cast<Code**>(builtin_address(k##name)); \ | 4585 reinterpret_cast<Code**>(builtin_address(k##name)); \ |
4371 return Handle<Code>(code_address); \ | 4586 return Handle<Code>(code_address); \ |
4372 } | 4587 } |
4373 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \ | 4588 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \ |
4374 Handle<Code> Builtins::name() { \ | 4589 Handle<Code> Builtins::name() { \ |
4375 Code** code_address = \ | 4590 Code** code_address = \ |
4376 reinterpret_cast<Code**>(builtin_address(k##name)); \ | 4591 reinterpret_cast<Code**>(builtin_address(k##name)); \ |
4377 return Handle<Code>(code_address); \ | 4592 return Handle<Code>(code_address); \ |
4378 } | 4593 } |
4379 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 4594 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
4380 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 4595 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
4381 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4596 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
4382 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4597 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
4383 #undef DEFINE_BUILTIN_ACCESSOR_C | 4598 #undef DEFINE_BUILTIN_ACCESSOR_C |
4384 #undef DEFINE_BUILTIN_ACCESSOR_A | 4599 #undef DEFINE_BUILTIN_ACCESSOR_A |
4385 | 4600 |
4386 | 4601 |
4387 } // namespace internal | 4602 } // namespace internal |
4388 } // namespace v8 | 4603 } // namespace v8 |
OLD | NEW |