Chromium Code Reviews| 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, compiler::Node* context) { | |
| 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 | |
| 4371 // Check if it is a heap object. | |
| 4372 a->Branch(a->WordIsSmi(tagged), &is_smi, ¬_smi); | |
| 4373 a->Bind(&is_smi); | |
| 4374 a->Goto(&invalid); | |
| 4375 | |
| 4376 // Check if the array's instance type is JSTypedArray. | |
| 4377 a->Bind(¬_smi); | |
| 4378 a->Branch(a->WordEqual(a->InstanceType(tagged), | |
| 4379 a->Int32Constant(JS_TYPED_ARRAY_TYPE)), | |
| 4380 &is_typed_array, ¬_typed_array); | |
| 4381 a->Bind(¬_typed_array); | |
| 4382 a->Goto(&invalid); | |
| 4383 | |
| 4384 // Check if the array's JSArrayBuffer is shared. | |
| 4385 a->Bind(&is_typed_array); | |
| 4386 Node* is_buffer_shared = | |
| 4387 a->BitFieldValue<JSArrayBuffer::IsShared>(a->LoadObjectField( | |
| 4388 a->LoadObjectField(tagged, JSTypedArray::kBufferOffset), | |
| 4389 JSArrayBuffer::kBitFieldOffset)); | |
| 4390 a->Branch(is_buffer_shared, &is_shared, ¬_shared); | |
| 4391 a->Bind(¬_shared); | |
| 4392 a->Goto(&invalid); | |
| 4393 | |
| 4394 // Check if the array's element type is float32 or float64. | |
| 4395 // TODO(binji): should fail on clamped as well. | |
| 4396 a->Bind(&is_shared); | |
| 4397 Node* elements_instance_type = | |
| 4398 a->InstanceType(a->LoadObjectField(tagged, JSObject::kElementsOffset)); | |
| 4399 a->Branch(a->WordOr(a->WordEqual(elements_instance_type, | |
| 4400 a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)), | |
| 4401 a->WordEqual(elements_instance_type, | |
| 4402 a->Int32Constant(FIXED_FLOAT64_ARRAY_TYPE))), | |
| 4403 &is_float, ¬_float); | |
| 4404 a->Bind(&is_float); | |
| 4405 a->Goto(&invalid); | |
| 4406 | |
| 4407 a->Bind(&invalid); | |
| 4408 a->TailCallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context, | |
| 4409 tagged); | |
| 4410 | |
| 4411 a->Bind(¬_float); | |
| 4412 } | |
| 4413 | |
| 4414 | |
| 4415 compiler::Node* TaggedNumberAsWord32(compiler::CodeStubAssembler* a, | |
| 4416 compiler::Node* tagged) { | |
| 4417 using namespace compiler; | |
| 4418 CodeStubAssembler::Label is_smi(a), is_not_smi(a), is_word(a); | |
| 4419 CodeStubAssembler::Variable result(a, MachineRepresentation::kWord32); | |
| 4420 | |
| 4421 a->Branch(a->WordIsSmi(tagged), &is_smi, &is_not_smi); | |
| 4422 | |
| 4423 a->Bind(&is_smi); | |
| 4424 result.Bind(a->SmiUntag(tagged)); | |
| 4425 a->Goto(&is_word); | |
| 4426 | |
| 4427 a->Bind(&is_not_smi); | |
| 4428 result.Bind(a->ChangeFloat64ToUint32(a->LoadHeapNumber(tagged))); | |
| 4429 a->Goto(&is_word); | |
| 4430 | |
| 4431 a->Bind(&is_word); | |
| 4432 return result.value(); | |
| 4433 } | |
| 4434 | |
| 4435 | |
| 4436 compiler::Node* ConvertTaggedAtomicIndexToWord32(compiler::CodeStubAssembler* a, | |
| 4437 compiler::Node* tagged, | |
| 4438 compiler::Node* context) { | |
| 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 | |
| 4448 // Check if the index's type is a Smi. | |
| 4449 a->Branch(a->WordIsSmi(tagged), &is_smi, &is_not_smi); | |
| 4450 | |
| 4451 // Check if the index's type is a String. | |
| 4452 a->Bind(&is_not_smi); | |
| 4453 Node* instance_type = a->InstanceType(tagged); | |
| 4454 a->Branch(a->WordEqual( | |
| 4455 a->WordAnd(instance_type, a->Int32Constant(kIsNotStringMask)), | |
| 4456 a->Int32Constant(0)), | |
| 4457 &is_string, &is_not_string); | |
| 4458 | |
| 4459 // Check that converting the string to a number and back is equal to itself. | |
| 4460 a->Bind(&is_string); | |
| 4461 Node* string_as_number = | |
| 4462 a->CallRuntime(Runtime::kStringToNumber, context, tagged); | |
| 4463 a->Branch( | |
| 4464 a->WordEqual(a->CallRuntime(Runtime::kStringEquals, context, | |
| 4465 a->CallRuntime(Runtime::kNumberToString, | |
| 4466 context, string_as_number), | |
| 4467 tagged), | |
| 4468 a->Int32Constant(EQUAL)), | |
| 4469 &strings_equal, &strings_not_equal); | |
| 4470 | |
| 4471 a->Bind(&strings_not_equal); | |
| 4472 a->Goto(&invalid); | |
| 4473 | |
| 4474 // Check if the string converted to a number is a Smi. | |
| 4475 a->Bind(&strings_equal); | |
| 4476 a->Branch(a->WordIsSmi(string_as_number), &string_number_is_smi, | |
| 4477 &string_number_is_not_smi); | |
| 4478 | |
| 4479 // If the string-number is a Smi, untag it. | |
| 4480 a->Bind(&string_number_is_smi); | |
| 4481 word.Bind(a->SmiUntag(string_as_number)); | |
| 4482 a->Goto(&is_word); | |
| 4483 | |
| 4484 // If the string-number is a HeapNumber, convert it to a word32. | |
| 4485 a->Bind(&string_number_is_not_smi); | |
| 4486 number.Bind(string_as_number); | |
| 4487 a->Goto(&convert_number); | |
| 4488 | |
| 4489 // Check if the index's type is a HeapNumber. | |
| 4490 a->Bind(&is_not_string); | |
| 4491 a->Branch(a->WordEqual(instance_type, a->Int32Constant(HEAP_NUMBER_TYPE)), | |
| 4492 &is_number, &is_unknown); | |
| 4493 | |
| 4494 // Index is an invalid type, throw. | |
| 4495 a->Bind(&is_unknown); | |
| 4496 a->Goto(&invalid); | |
| 4497 | |
| 4498 a->Bind(&is_number); | |
| 4499 number.Bind(tagged); | |
| 4500 a->Goto(&convert_number); | |
| 4501 | |
| 4502 // Convert index from a HeapNumber to a word32. | |
| 4503 a->Bind(&convert_number); | |
| 4504 Node* number_value = a->LoadHeapNumber(number.value()); | |
| 4505 word.Bind(a->ChangeFloat64ToUint32(number_value)); | |
| 4506 | |
| 4507 // Check that the index is an integer. | |
| 4508 a->Branch( | |
| 4509 a->Float64Equal(a->ChangeUint32ToFloat64(word.value()), number_value), | |
| 4510 &is_integer, &is_not_integer); | |
| 4511 | |
| 4512 a->Bind(&is_not_integer); | |
| 4513 a->Goto(&invalid); | |
| 4514 | |
| 4515 a->Bind(&is_integer); | |
| 4516 a->Goto(&is_word); | |
| 4517 | |
| 4518 // Index is a Smi, untag. | |
| 4519 a->Bind(&is_smi); | |
| 4520 word.Bind(a->SmiUntag(tagged)); | |
| 4521 a->Goto(&is_word); | |
| 4522 | |
| 4523 a->Bind(&invalid); | |
| 4524 a->TailCallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); | |
| 4525 | |
| 4526 a->Bind(&is_word); | |
| 4527 return word.value(); | |
| 4528 } | |
| 4529 | |
| 4530 | |
| 4531 void ValidateAtomicIndex(compiler::CodeStubAssembler* a, | |
| 4532 compiler::Node* index_word, | |
| 4533 compiler::Node* array_length_word, | |
| 4534 compiler::Node* context) { | |
| 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 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 Node* context = a.Parameter(2); | |
|
Jarin
2016/02/15 10:30:15
I am a bit surprised that the parameters work here
binji
2016/02/15 20:31:31
Yes, you're right! Thanks, that was the bug I was
| |
| 4561 ValidateSharedTypedArray(&a, array, context); | |
| 4562 Node* index_word = ConvertTaggedAtomicIndexToWord32(&a, index, context); | |
| 4563 Node* array_length_word = TaggedNumberAsWord32( | |
| 4564 &a, a.LoadObjectField(array, JSTypedArray::kLengthOffset)); | |
| 4565 ValidateAtomicIndex(&a, index_word, array_length_word, context); | |
| 4566 | |
| 4567 AtomicsLoadStub stub(isolate); | |
| 4568 // TODO(binji): can't just re-tag index, because it might be out of range. | |
| 4569 // Can we just pass the untagged index value to the code stub? | |
| 4570 Node* stub_args[] = {array, a.SmiTag(index_word), context}; | |
| 4571 a.TailCallStub(stub, stub_args); | |
| 4572 | |
| 4573 masm->Jump(a.GenerateCode(), RelocInfo::CODE_TARGET); | |
| 4574 } | |
| 4575 | |
| 4576 | |
| 4361 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \ | 4577 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \ |
| 4362 Handle<Code> Builtins::name() { \ | 4578 Handle<Code> Builtins::name() { \ |
| 4363 Code** code_address = \ | 4579 Code** code_address = \ |
| 4364 reinterpret_cast<Code**>(builtin_address(k##name)); \ | 4580 reinterpret_cast<Code**>(builtin_address(k##name)); \ |
| 4365 return Handle<Code>(code_address); \ | 4581 return Handle<Code>(code_address); \ |
| 4366 } | 4582 } |
| 4367 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \ | 4583 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \ |
| 4368 Handle<Code> Builtins::name() { \ | 4584 Handle<Code> Builtins::name() { \ |
| 4369 Code** code_address = \ | 4585 Code** code_address = \ |
| 4370 reinterpret_cast<Code**>(builtin_address(k##name)); \ | 4586 reinterpret_cast<Code**>(builtin_address(k##name)); \ |
| 4371 return Handle<Code>(code_address); \ | 4587 return Handle<Code>(code_address); \ |
| 4372 } | 4588 } |
| 4373 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \ | 4589 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \ |
| 4374 Handle<Code> Builtins::name() { \ | 4590 Handle<Code> Builtins::name() { \ |
| 4375 Code** code_address = \ | 4591 Code** code_address = \ |
| 4376 reinterpret_cast<Code**>(builtin_address(k##name)); \ | 4592 reinterpret_cast<Code**>(builtin_address(k##name)); \ |
| 4377 return Handle<Code>(code_address); \ | 4593 return Handle<Code>(code_address); \ |
| 4378 } | 4594 } |
| 4379 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 4595 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 4380 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 4596 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4381 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4597 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 4382 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4598 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4383 #undef DEFINE_BUILTIN_ACCESSOR_C | 4599 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 4384 #undef DEFINE_BUILTIN_ACCESSOR_A | 4600 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 4385 | 4601 |
| 4386 | 4602 |
| 4387 } // namespace internal | 4603 } // namespace internal |
| 4388 } // namespace v8 | 4604 } // namespace v8 |
| OLD | NEW |