diff options
Diffstat (limited to 'chromium/v8/src')
64 files changed, 496 insertions, 232 deletions
diff --git a/chromium/v8/src/accessors.cc b/chromium/v8/src/accessors.cc index 8cdbcc37f07..374c0a21f84 100644 --- a/chromium/v8/src/accessors.cc +++ b/chromium/v8/src/accessors.cc @@ -32,6 +32,7 @@ Handle<AccessorInfo> Accessors::MakeAccessor( info->set_all_can_read(false); info->set_all_can_write(false); info->set_is_special_data_property(true); + info->set_is_sloppy(false); name = factory->InternalizeName(name); info->set_name(*name); Handle<Object> get = v8::FromCData(isolate, getter); diff --git a/chromium/v8/src/arm/code-stubs-arm.cc b/chromium/v8/src/arm/code-stubs-arm.cc index 459cb008b0d..31e3e95f032 100644 --- a/chromium/v8/src/arm/code-stubs-arm.cc +++ b/chromium/v8/src/arm/code-stubs-arm.cc @@ -1066,9 +1066,9 @@ void CEntryStub::Generate(MacroAssembler* masm) { if (result_size() > 2) { DCHECK_EQ(3, result_size()); // Read result values stored on stack. - __ ldr(r2, MemOperand(r0, 2 * kPointerSize)); - __ ldr(r1, MemOperand(r0, 1 * kPointerSize)); - __ ldr(r0, MemOperand(r0, 0 * kPointerSize)); + __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); + __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); + __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); } // Result returned in r0, r1:r0 or r2:r1:r0 - do not destroy these registers! diff --git a/chromium/v8/src/bootstrapper.cc b/chromium/v8/src/bootstrapper.cc index 993aba448ed..f67065dec4b 100644 --- a/chromium/v8/src/bootstrapper.cc +++ b/chromium/v8/src/bootstrapper.cc @@ -1248,6 +1248,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, attribs); string_map->AppendDescriptor(&d); } + + // Install the String.fromCharCode function. + SimpleInstallFunction(string_fun, "fromCharCode", + Builtins::kStringFromCharCode, 1, false); } { diff --git a/chromium/v8/src/builtins.cc b/chromium/v8/src/builtins.cc index 3be314ed2b4..9c3ff5956b2 100644 --- a/chromium/v8/src/builtins.cc +++ b/chromium/v8/src/builtins.cc @@ -658,11 +658,11 @@ BUILTIN(ArraySlice) { if (receiver->IsJSArray()) { DisallowHeapAllocation no_gc; JSArray* array = JSArray::cast(*receiver); - if (!array->HasFastElements() || - !IsJSArrayFastElementMovingAllowed(isolate, array) || - !isolate->IsArraySpeciesLookupChainIntact() || - // If this is a subclass of Array, then call out to JS - !array->map()->new_target_is_base()) { + if (V8_UNLIKELY(!array->HasFastElements() || + !IsJSArrayFastElementMovingAllowed(isolate, array) || + !isolate->IsArraySpeciesLookupChainIntact() || + // If this is a subclass of Array, then call out to JS + !array->HasArrayPrototype(isolate))) { AllowHeapAllocation allow_allocation; return CallJsIntrinsic(isolate, isolate->array_slice(), args); } @@ -720,11 +720,12 @@ BUILTIN(ArraySlice) { BUILTIN(ArraySplice) { HandleScope scope(isolate); Handle<Object> receiver = args.receiver(); - if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) || - // If this is a subclass of Array, then call out to JS. - !JSArray::cast(*receiver)->map()->new_target_is_base() || - // If anything with @@species has been messed with, call out to JS. - !isolate->IsArraySpeciesLookupChainIntact()) { + if (V8_UNLIKELY( + !EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) || + // If this is a subclass of Array, then call out to JS. + !Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) || + // If anything with @@species has been messed with, call out to JS. + !isolate->IsArraySpeciesLookupChainIntact())) { return CallJsIntrinsic(isolate, isolate->array_splice(), args); } Handle<JSArray> array = Handle<JSArray>::cast(receiver); @@ -1591,12 +1592,21 @@ BUILTIN(ArrayConcat) { Handle<JSArray> result_array; + // Avoid a real species read to avoid extra lookups to the array constructor + if (V8_LIKELY(receiver->IsJSArray() && + Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) && + isolate->IsArraySpeciesLookupChainIntact())) { + if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { + return *result_array; + } + if (isolate->has_pending_exception()) return isolate->heap()->exception(); + } // Reading @@species happens before anything else with a side effect, so // we can do it here to determine whether to take the fast path. Handle<Object> species; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, species, Object::ArraySpeciesConstructor(isolate, receiver)); - if (*species == isolate->context()->native_context()->array_function()) { + if (*species == *isolate->array_function()) { if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { return *result_array; } @@ -4052,6 +4062,74 @@ BUILTIN(ObjectProtoToString) { return *result; } +// ----------------------------------------------------------------------------- +// ES6 section 21.1 String Objects + +namespace { + +bool ToUint16(Handle<Object> value, uint16_t* result) { + if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) { + *result = DoubleToUint32(value->Number()); + return true; + } + return false; +} + +} // namespace + +// ES6 21.1.2.1 String.fromCharCode ( ...codeUnits ) +BUILTIN(StringFromCharCode) { + HandleScope scope(isolate); + // Check resulting string length. + int index = 0; + Handle<String> result; + int const length = args.length() - 1; + if (length == 0) return isolate->heap()->empty_string(); + DCHECK_LT(0, length); + // Load the first character code. + uint16_t code; + if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception(); + // Assume that the resulting String contains only one byte characters. + if (code <= String::kMaxOneByteCharCodeU) { + // Check for single one-byte character fast case. + if (length == 1) { + return *isolate->factory()->LookupSingleCharacterStringFromCode(code); + } + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, isolate->factory()->NewRawOneByteString(length)); + do { + Handle<SeqOneByteString>::cast(result)->Set(index, code); + if (++index == length) break; + if (!ToUint16(args.at<Object>(1 + index), &code)) { + return isolate->heap()->exception(); + } + } while (code <= String::kMaxOneByteCharCodeU); + } + // Check if all characters fit into the one byte range. + if (index < length) { + // Fallback to two byte string. + Handle<String> new_result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, new_result, isolate->factory()->NewRawTwoByteString(length)); + for (int new_index = 0; new_index < index; ++new_index) { + uint16_t new_code = + Handle<SeqOneByteString>::cast(result)->Get(new_index); + Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code); + } + while (true) { + Handle<SeqTwoByteString>::cast(new_result)->Set(index, code); + if (++index == length) break; + if (!ToUint16(args.at<Object>(1 + index), &code)) { + return isolate->heap()->exception(); + } + } + result = new_result; + } + return *result; +} + +// ----------------------------------------------------------------------------- +// ES6 section 21.1 ArrayBuffer Objects // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case. BUILTIN(ArrayBufferConstructor) { diff --git a/chromium/v8/src/builtins.h b/chromium/v8/src/builtins.h index ac4d7890dc4..221d06f30f8 100644 --- a/chromium/v8/src/builtins.h +++ b/chromium/v8/src/builtins.h @@ -161,6 +161,8 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) { V(ReflectSet, kNone) \ V(ReflectSetPrototypeOf, kNone) \ \ + V(StringFromCharCode, kNone) \ + \ V(SymbolConstructor, kNone) \ V(SymbolConstructor_ConstructStub, kTarget) \ \ diff --git a/chromium/v8/src/compiler/ast-graph-builder.cc b/chromium/v8/src/compiler/ast-graph-builder.cc index 272eef1f316..89bb61949a0 100644 --- a/chromium/v8/src/compiler/ast-graph-builder.cc +++ b/chromium/v8/src/compiler/ast-graph-builder.cc @@ -3078,7 +3078,7 @@ void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { LanguageMode AstGraphBuilder::language_mode() const { - return info()->language_mode(); + return current_scope()->language_mode(); } diff --git a/chromium/v8/src/compiler/instruction.h b/chromium/v8/src/compiler/instruction.h index 7f64dce978b..a1fe4947612 100644 --- a/chromium/v8/src/compiler/instruction.h +++ b/chromium/v8/src/compiler/instruction.h @@ -773,6 +773,9 @@ class Instruction final { DCHECK(output_count == 0 || outputs != nullptr); DCHECK(input_count == 0 || inputs != nullptr); DCHECK(temp_count == 0 || temps != nullptr); + // TODO(jarin/mstarzinger): Handle this gracefully. See crbug.com/582702. + CHECK(InputCountField::is_valid(input_count)); + size_t total_extra_ops = output_count + input_count + temp_count; if (total_extra_ops != 0) total_extra_ops--; int size = static_cast<int>( diff --git a/chromium/v8/src/compiler/js-builtin-reducer.cc b/chromium/v8/src/compiler/js-builtin-reducer.cc index b5caf9f1fe6..41f9c30707b 100644 --- a/chromium/v8/src/compiler/js-builtin-reducer.cc +++ b/chromium/v8/src/compiler/js-builtin-reducer.cc @@ -117,13 +117,15 @@ Reduction JSBuiltinReducer::ReduceMathMax(Node* node) { return NoChange(); } - -// ES6 draft 08-24-14, section 20.2.2.19. +// ES6 section 20.2.2.19 Math.imul ( x, y ) Reduction JSBuiltinReducer::ReduceMathImul(Node* node) { JSCallReduction r(node); - if (r.InputsMatchTwo(Type::Integral32(), Type::Integral32())) { - // Math.imul(a:int32, b:int32) -> Int32Mul(a, b) - Node* value = graph()->NewNode(machine()->Int32Mul(), r.left(), r.right()); + if (r.InputsMatchTwo(Type::Number(), Type::Number())) { + // Math.imul(a:number, b:number) -> NumberImul(NumberToUint32(a), + // NumberToUint32(b)) + Node* a = graph()->NewNode(simplified()->NumberToUint32(), r.left()); + Node* b = graph()->NewNode(simplified()->NumberToUint32(), r.right()); + Node* value = graph()->NewNode(simplified()->NumberImul(), a, b); return Replace(value); } return NoChange(); diff --git a/chromium/v8/src/compiler/js-create-lowering.cc b/chromium/v8/src/compiler/js-create-lowering.cc index df5c8d07df1..20033636edc 100644 --- a/chromium/v8/src/compiler/js-create-lowering.cc +++ b/chromium/v8/src/compiler/js-create-lowering.cc @@ -905,8 +905,17 @@ Node* JSCreateLowering::AllocateFastLiteral( site_context->ExitScope(current_site, boilerplate_object); } else if (property_details.representation().IsDouble()) { // Allocate a mutable HeapNumber box and store the value into it. - value = effect = AllocateMutableHeapNumber( - Handle<HeapNumber>::cast(boilerplate_value)->value(), + Callable callable = CodeFactory::AllocateMutableHeapNumber(isolate()); + CallDescriptor* desc = Linkage::GetStubCallDescriptor( + isolate(), jsgraph()->zone(), callable.descriptor(), 0, + CallDescriptor::kNoFlags, Operator::kNoThrow); + value = effect = graph()->NewNode( + common()->Call(desc), jsgraph()->HeapConstant(callable.code()), + jsgraph()->NoContextConstant(), effect, control); + effect = graph()->NewNode( + simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), + value, jsgraph()->Constant( + Handle<HeapNumber>::cast(boilerplate_value)->value()), effect, control); } else if (property_details.representation().IsSmi()) { // Ensure that value is stored as smi. @@ -1028,23 +1037,6 @@ Node* JSCreateLowering::AllocateFastLiteralElements( return builder.Finish(); } -Node* JSCreateLowering::AllocateMutableHeapNumber(double value, Node* effect, - Node* control) { - // TODO(turbofan): Support inline allocation of MutableHeapNumber - // (requires proper alignment on Allocate, and Begin/FinishRegion). - Callable callable = CodeFactory::AllocateMutableHeapNumber(isolate()); - CallDescriptor* desc = Linkage::GetStubCallDescriptor( - isolate(), jsgraph()->zone(), callable.descriptor(), 0, - CallDescriptor::kNoFlags, Operator::kNoThrow); - Node* result = effect = graph()->NewNode( - common()->Call(desc), jsgraph()->HeapConstant(callable.code()), - jsgraph()->NoContextConstant(), effect, control); - effect = graph()->NewNode( - simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result, - jsgraph()->Constant(value), effect, control); - return result; -} - MaybeHandle<LiteralsArray> JSCreateLowering::GetSpecializationLiterals( Node* node) { Node* const closure = NodeProperties::GetValueInput(node, 0); diff --git a/chromium/v8/src/compiler/js-create-lowering.h b/chromium/v8/src/compiler/js-create-lowering.h index d9d184b8e29..52e7ec254ad 100644 --- a/chromium/v8/src/compiler/js-create-lowering.h +++ b/chromium/v8/src/compiler/js-create-lowering.h @@ -70,7 +70,6 @@ class JSCreateLowering final : public AdvancedReducer { Handle<JSObject> boilerplate, PretenureFlag pretenure, AllocationSiteUsageContext* site_context); - Node* AllocateMutableHeapNumber(double value, Node* effect, Node* control); // Infers the LiteralsArray to use for a given {node}. MaybeHandle<LiteralsArray> GetSpecializationLiterals(Node* node); diff --git a/chromium/v8/src/compiler/opcodes.h b/chromium/v8/src/compiler/opcodes.h index c8b3671a9ec..b038d154b77 100644 --- a/chromium/v8/src/compiler/opcodes.h +++ b/chromium/v8/src/compiler/opcodes.h @@ -185,6 +185,7 @@ V(NumberShiftLeft) \ V(NumberShiftRight) \ V(NumberShiftRightLogical) \ + V(NumberImul) \ V(NumberClz32) \ V(NumberCeil) \ V(NumberFloor) \ diff --git a/chromium/v8/src/compiler/representation-change.cc b/chromium/v8/src/compiler/representation-change.cc index fedf7afc0e9..f59c8bc909a 100644 --- a/chromium/v8/src/compiler/representation-change.cc +++ b/chromium/v8/src/compiler/representation-change.cc @@ -467,6 +467,8 @@ const Operator* RepresentationChanger::Uint32OperatorFor( return machine()->Uint32LessThanOrEqual(); case IrOpcode::kNumberClz32: return machine()->Word32Clz(); + case IrOpcode::kNumberImul: + return machine()->Int32Mul(); default: UNREACHABLE(); return nullptr; diff --git a/chromium/v8/src/compiler/s390/code-generator-s390.cc b/chromium/v8/src/compiler/s390/code-generator-s390.cc index 7439008d891..68c1d9d587a 100644 --- a/chromium/v8/src/compiler/s390/code-generator-s390.cc +++ b/chromium/v8/src/compiler/s390/code-generator-s390.cc @@ -1692,7 +1692,8 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, // Overflow checked for add/sub only. DCHECK((condition != kOverflow && condition != kNotOverflow) || - (op == kS390_AddWithOverflow32 || op == kS390_SubWithOverflow32)); + (op == kS390_AddWithOverflow32 || op == kS390_SubWithOverflow32) || + (op == kS390_Add || op == kS390_Sub)); // Materialize a full 32-bit 1 or 0 value. The result register is always the // last output of the instruction. diff --git a/chromium/v8/src/compiler/simplified-lowering.cc b/chromium/v8/src/compiler/simplified-lowering.cc index 255699f0f25..88931f5df7e 100644 --- a/chromium/v8/src/compiler/simplified-lowering.cc +++ b/chromium/v8/src/compiler/simplified-lowering.cc @@ -962,6 +962,12 @@ class RepresentationSelector { } break; } + case IrOpcode::kNumberImul: { + VisitBinop(node, UseInfo::TruncatingWord32(), + UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); + if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); + break; + } case IrOpcode::kNumberClz32: { VisitUnop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); diff --git a/chromium/v8/src/compiler/simplified-operator.cc b/chromium/v8/src/compiler/simplified-operator.cc index 98a5c6cd1a7..daa9501b8ca 100644 --- a/chromium/v8/src/compiler/simplified-operator.cc +++ b/chromium/v8/src/compiler/simplified-operator.cc @@ -173,6 +173,7 @@ const ElementAccess& ElementAccessOf(const Operator* op) { V(NumberShiftLeft, Operator::kNoProperties, 2) \ V(NumberShiftRight, Operator::kNoProperties, 2) \ V(NumberShiftRightLogical, Operator::kNoProperties, 2) \ + V(NumberImul, Operator::kNoProperties, 2) \ V(NumberClz32, Operator::kNoProperties, 1) \ V(NumberCeil, Operator::kNoProperties, 1) \ V(NumberFloor, Operator::kNoProperties, 1) \ diff --git a/chromium/v8/src/compiler/simplified-operator.h b/chromium/v8/src/compiler/simplified-operator.h index 737974d03b4..a39d864914b 100644 --- a/chromium/v8/src/compiler/simplified-operator.h +++ b/chromium/v8/src/compiler/simplified-operator.h @@ -143,6 +143,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject { const Operator* NumberShiftLeft(); const Operator* NumberShiftRight(); const Operator* NumberShiftRightLogical(); + const Operator* NumberImul(); const Operator* NumberClz32(); const Operator* NumberCeil(); const Operator* NumberFloor(); diff --git a/chromium/v8/src/compiler/typer.cc b/chromium/v8/src/compiler/typer.cc index 2f784f7af8f..81c3d3d928d 100644 --- a/chromium/v8/src/compiler/typer.cc +++ b/chromium/v8/src/compiler/typer.cc @@ -1757,6 +1757,8 @@ Type* Typer::Visitor::TypeNumberShiftRightLogical(Node* node) { return Type::Unsigned32(); } +Type* Typer::Visitor::TypeNumberImul(Node* node) { return Type::Signed32(); } + Type* Typer::Visitor::TypeNumberClz32(Node* node) { return typer_->cache_.kZeroToThirtyTwo; } diff --git a/chromium/v8/src/compiler/verifier.cc b/chromium/v8/src/compiler/verifier.cc index 1fe71205da4..a69ace94808 100644 --- a/chromium/v8/src/compiler/verifier.cc +++ b/chromium/v8/src/compiler/verifier.cc @@ -685,6 +685,12 @@ void Verifier::Visitor::Check(Node* node) { CheckValueInputIs(node, 1, Type::Unsigned32()); CheckUpperIs(node, Type::Unsigned32()); break; + case IrOpcode::kNumberImul: + // (Unsigned32, Unsigned32) -> Signed32 + CheckValueInputIs(node, 0, Type::Unsigned32()); + CheckValueInputIs(node, 1, Type::Unsigned32()); + CheckUpperIs(node, Type::Signed32()); + break; case IrOpcode::kNumberClz32: // Unsigned32 -> Unsigned32 CheckValueInputIs(node, 0, Type::Unsigned32()); diff --git a/chromium/v8/src/crankshaft/arm/lithium-codegen-arm.cc b/chromium/v8/src/crankshaft/arm/lithium-codegen-arm.cc index b179a18ff10..c64aac3cc87 100644 --- a/chromium/v8/src/crankshaft/arm/lithium-codegen-arm.cc +++ b/chromium/v8/src/crankshaft/arm/lithium-codegen-arm.cc @@ -2439,11 +2439,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); - __ CompareObjectType(input, temp, temp2, JS_FUNCTION_TYPE); + __ CompareObjectType(input, temp, temp2, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ b(eq, is_true); + __ b(hs, is_true); } else { - __ b(eq, is_false); + __ b(hs, is_false); } // Check if the constructor in the map is a function. diff --git a/chromium/v8/src/crankshaft/arm64/lithium-codegen-arm64.cc b/chromium/v8/src/crankshaft/arm64/lithium-codegen-arm64.cc index eefa9e08336..9bbc8b87e84 100644 --- a/chromium/v8/src/crankshaft/arm64/lithium-codegen-arm64.cc +++ b/chromium/v8/src/crankshaft/arm64/lithium-codegen-arm64.cc @@ -2205,11 +2205,12 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { __ JumpIfSmi(input, false_label); Register map = scratch2; - __ CompareObjectType(input, map, scratch1, JS_FUNCTION_TYPE); + __ CompareObjectType(input, map, scratch1, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ B(eq, true_label); + __ B(hs, true_label); } else { - __ B(eq, false_label); + __ B(hs, false_label); } // Check if the constructor in the map is a function. diff --git a/chromium/v8/src/crankshaft/ia32/lithium-codegen-ia32.cc b/chromium/v8/src/crankshaft/ia32/lithium-codegen-ia32.cc index df459fc23f0..ae1ca1f1014 100644 --- a/chromium/v8/src/crankshaft/ia32/lithium-codegen-ia32.cc +++ b/chromium/v8/src/crankshaft/ia32/lithium-codegen-ia32.cc @@ -2235,11 +2235,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true, DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); - __ CmpObjectType(input, JS_FUNCTION_TYPE, temp); + __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ j(equal, is_true); + __ j(above_equal, is_true); } else { - __ j(equal, is_false); + __ j(above_equal, is_false); } // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. diff --git a/chromium/v8/src/crankshaft/mips/lithium-codegen-mips.cc b/chromium/v8/src/crankshaft/mips/lithium-codegen-mips.cc index d578df6e8af..f1717ca4744 100644 --- a/chromium/v8/src/crankshaft/mips/lithium-codegen-mips.cc +++ b/chromium/v8/src/crankshaft/mips/lithium-codegen-mips.cc @@ -2351,10 +2351,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); __ GetObjectType(input, temp, temp2); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ Branch(is_true, eq, temp2, Operand(JS_FUNCTION_TYPE)); + __ Branch(is_true, hs, temp2, Operand(FIRST_FUNCTION_TYPE)); } else { - __ Branch(is_false, eq, temp2, Operand(JS_FUNCTION_TYPE)); + __ Branch(is_false, hs, temp2, Operand(FIRST_FUNCTION_TYPE)); } // Check if the constructor in the map is a function. diff --git a/chromium/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc b/chromium/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc index d14efafd4d6..c7bbe9f07a6 100644 --- a/chromium/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc +++ b/chromium/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc @@ -2470,10 +2470,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); __ GetObjectType(input, temp, temp2); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ Branch(is_true, eq, temp2, Operand(JS_FUNCTION_TYPE)); + __ Branch(is_true, hs, temp2, Operand(FIRST_FUNCTION_TYPE)); } else { - __ Branch(is_false, eq, temp2, Operand(JS_FUNCTION_TYPE)); + __ Branch(is_false, hs, temp2, Operand(FIRST_FUNCTION_TYPE)); } // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. diff --git a/chromium/v8/src/crankshaft/ppc/lithium-codegen-ppc.cc b/chromium/v8/src/crankshaft/ppc/lithium-codegen-ppc.cc index 425ac7ea80f..d5d01043dd3 100644 --- a/chromium/v8/src/crankshaft/ppc/lithium-codegen-ppc.cc +++ b/chromium/v8/src/crankshaft/ppc/lithium-codegen-ppc.cc @@ -2496,11 +2496,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false, __ JumpIfSmi(input, is_false); - __ CompareObjectType(input, temp, temp2, JS_FUNCTION_TYPE); + __ CompareObjectType(input, temp, temp2, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ beq(is_true); + __ bge(is_true); } else { - __ beq(is_false); + __ bge(is_false); } // Check if the constructor in the map is a function. diff --git a/chromium/v8/src/crankshaft/s390/lithium-codegen-s390.cc b/chromium/v8/src/crankshaft/s390/lithium-codegen-s390.cc index 6b4b3881b84..689f4bc1ae8 100644 --- a/chromium/v8/src/crankshaft/s390/lithium-codegen-s390.cc +++ b/chromium/v8/src/crankshaft/s390/lithium-codegen-s390.cc @@ -2485,11 +2485,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false, __ JumpIfSmi(input, is_false); - __ CompareObjectType(input, temp, temp2, JS_FUNCTION_TYPE); + __ CompareObjectType(input, temp, temp2, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ beq(is_true); + __ bge(is_true); } else { - __ beq(is_false); + __ bge(is_false); } // Check if the constructor in the map is a function. diff --git a/chromium/v8/src/crankshaft/x64/lithium-codegen-x64.cc b/chromium/v8/src/crankshaft/x64/lithium-codegen-x64.cc index 24436336716..fbda59b66c4 100644 --- a/chromium/v8/src/crankshaft/x64/lithium-codegen-x64.cc +++ b/chromium/v8/src/crankshaft/x64/lithium-codegen-x64.cc @@ -2384,11 +2384,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); - __ CmpObjectType(input, JS_FUNCTION_TYPE, temp); + __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ j(equal, is_true); + __ j(above_equal, is_true); } else { - __ j(equal, is_false); + __ j(above_equal, is_false); } // Check if the constructor in the map is a function. diff --git a/chromium/v8/src/crankshaft/x87/lithium-codegen-x87.cc b/chromium/v8/src/crankshaft/x87/lithium-codegen-x87.cc index 1283ac07581..17511994010 100644 --- a/chromium/v8/src/crankshaft/x87/lithium-codegen-x87.cc +++ b/chromium/v8/src/crankshaft/x87/lithium-codegen-x87.cc @@ -2516,11 +2516,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true, DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); - __ CmpObjectType(input, JS_FUNCTION_TYPE, temp); + __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - __ j(equal, is_true); + __ j(above_equal, is_true); } else { - __ j(equal, is_false); + __ j(above_equal, is_false); } // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. diff --git a/chromium/v8/src/factory.cc b/chromium/v8/src/factory.cc index 6e6d893403c..41c3cb5eaae 100644 --- a/chromium/v8/src/factory.cc +++ b/chromium/v8/src/factory.cc @@ -875,6 +875,7 @@ Handle<AccessorInfo> Factory::NewAccessorInfo() { Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE)); info->set_flag(0); // Must clear the flag, it was initialized as undefined. + info->set_is_sloppy(true); return info; } diff --git a/chromium/v8/src/full-codegen/arm/full-codegen-arm.cc b/chromium/v8/src/full-codegen/arm/full-codegen-arm.cc index 27985fbe490..81c5ff2ae77 100644 --- a/chromium/v8/src/full-codegen/arm/full-codegen-arm.cc +++ b/chromium/v8/src/full-codegen/arm/full-codegen-arm.cc @@ -3000,9 +3000,10 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // Map is now in r0. __ b(lt, &null); - // Return 'Function' for JSFunction objects. - __ cmp(r1, Operand(JS_FUNCTION_TYPE)); - __ b(eq, &function); + // Return 'Function' for JSFunction and JSBoundFunction objects. + __ cmp(r1, Operand(FIRST_FUNCTION_TYPE)); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ b(hs, &function); // Check if the constructor in the map is a JS function. Register instance_type = r2; diff --git a/chromium/v8/src/full-codegen/arm64/full-codegen-arm64.cc b/chromium/v8/src/full-codegen/arm64/full-codegen-arm64.cc index eb044dbfd9d..aa67117a7f4 100644 --- a/chromium/v8/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/chromium/v8/src/full-codegen/arm64/full-codegen-arm64.cc @@ -2805,8 +2805,9 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { __ B(lt, &null); // Return 'Function' for JSFunction objects. - __ Cmp(x11, JS_FUNCTION_TYPE); - __ B(eq, &function); + __ Cmp(x11, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ B(hs, &function); // Check if the constructor in the map is a JS function. Register instance_type = x14; diff --git a/chromium/v8/src/full-codegen/full-codegen.cc b/chromium/v8/src/full-codegen/full-codegen.cc index 8c0cddc0d01..af5dd41885c 100644 --- a/chromium/v8/src/full-codegen/full-codegen.cc +++ b/chromium/v8/src/full-codegen/full-codegen.cc @@ -1488,6 +1488,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { Comment cmnt(masm_, "[ ClassLiteral"); { + NestedClassLiteral nested_class_literal(this, lit); EnterBlockScopeIfNeeded block_scope_state( this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId()); diff --git a/chromium/v8/src/full-codegen/full-codegen.h b/chromium/v8/src/full-codegen/full-codegen.h index b41de6dbeda..0c12937149d 100644 --- a/chromium/v8/src/full-codegen/full-codegen.h +++ b/chromium/v8/src/full-codegen/full-codegen.h @@ -211,6 +211,23 @@ class FullCodeGenerator: public AstVisitor { } }; + // A class literal expression + class NestedClassLiteral : public NestedStatement { + public: + NestedClassLiteral(FullCodeGenerator* codegen, ClassLiteral* lit) + : NestedStatement(codegen), + needs_context_(lit->scope() != nullptr && + lit->scope()->NeedsContext()) {} + + NestedStatement* Exit(int* context_length) override { + if (needs_context_) ++(*context_length); + return previous_; + } + + private: + const bool needs_context_; + }; + class DeferredCommands { public: enum Command { kReturn, kThrow, kBreak, kContinue }; @@ -714,7 +731,7 @@ class FullCodeGenerator: public AstVisitor { Handle<Script> script() { return info_->script(); } bool is_eval() { return info_->is_eval(); } bool is_native() { return info_->is_native(); } - LanguageMode language_mode() { return literal()->language_mode(); } + LanguageMode language_mode() { return scope()->language_mode(); } bool has_simple_parameters() { return info_->has_simple_parameters(); } FunctionLiteral* literal() const { return info_->literal(); } Scope* scope() { return scope_; } diff --git a/chromium/v8/src/full-codegen/ia32/full-codegen-ia32.cc b/chromium/v8/src/full-codegen/ia32/full-codegen-ia32.cc index 4dfe9023866..f1945c897cf 100644 --- a/chromium/v8/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/chromium/v8/src/full-codegen/ia32/full-codegen-ia32.cc @@ -2879,9 +2879,10 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax); __ j(below, &null, Label::kNear); - // Return 'Function' for JSFunction objects. - __ CmpInstanceType(eax, JS_FUNCTION_TYPE); - __ j(equal, &function, Label::kNear); + // Return 'Function' for JSFunction and JSBoundFunction objects. + __ CmpInstanceType(eax, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ j(above_equal, &function, Label::kNear); // Check if the constructor in the map is a JS function. __ GetMapConstructor(eax, eax, ebx); diff --git a/chromium/v8/src/full-codegen/mips/full-codegen-mips.cc b/chromium/v8/src/full-codegen/mips/full-codegen-mips.cc index d84678040ed..f329a23d00c 100644 --- a/chromium/v8/src/full-codegen/mips/full-codegen-mips.cc +++ b/chromium/v8/src/full-codegen/mips/full-codegen-mips.cc @@ -2997,8 +2997,9 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { __ GetObjectType(v0, v0, a1); // Map is now in v0. __ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE)); - // Return 'Function' for JSFunction objects. - __ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE)); + // Return 'Function' for JSFunction and JSBoundFunction objects. + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ Branch(&function, hs, a1, Operand(FIRST_FUNCTION_TYPE)); // Check if the constructor in the map is a JS function. Register instance_type = a2; diff --git a/chromium/v8/src/full-codegen/mips64/full-codegen-mips64.cc b/chromium/v8/src/full-codegen/mips64/full-codegen-mips64.cc index c9075f5f517..681abd12303 100644 --- a/chromium/v8/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/chromium/v8/src/full-codegen/mips64/full-codegen-mips64.cc @@ -2998,8 +2998,9 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { __ GetObjectType(v0, v0, a1); // Map is now in v0. __ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE)); - // Return 'Function' for JSFunction objects. - __ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE)); + // Return 'Function' for JSFunction and JSBoundFunction objects. + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ Branch(&function, hs, a1, Operand(FIRST_FUNCTION_TYPE)); // Check if the constructor in the map is a JS function. Register instance_type = a2; diff --git a/chromium/v8/src/full-codegen/ppc/full-codegen-ppc.cc b/chromium/v8/src/full-codegen/ppc/full-codegen-ppc.cc index b0855053ac3..301ccf53cc3 100644 --- a/chromium/v8/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/chromium/v8/src/full-codegen/ppc/full-codegen-ppc.cc @@ -3001,9 +3001,10 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // Map is now in r3. __ blt(&null); - // Return 'Function' for JSFunction objects. - __ cmpi(r4, Operand(JS_FUNCTION_TYPE)); - __ beq(&function); + // Return 'Function' for JSFunction and JSBoundFunction objects. + __ cmpli(r4, Operand(FIRST_FUNCTION_TYPE)); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ bge(&function); // Check if the constructor in the map is a JS function. Register instance_type = r5; diff --git a/chromium/v8/src/full-codegen/s390/full-codegen-s390.cc b/chromium/v8/src/full-codegen/s390/full-codegen-s390.cc index 29a7f761b29..88bec4cab6e 100644 --- a/chromium/v8/src/full-codegen/s390/full-codegen-s390.cc +++ b/chromium/v8/src/full-codegen/s390/full-codegen-s390.cc @@ -2924,9 +2924,10 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // Map is now in r2. __ blt(&null); - // Return 'Function' for JSFunction objects. - __ CmpP(r3, Operand(JS_FUNCTION_TYPE)); - __ beq(&function); + // Return 'Function' for JSFunction and JSBoundFunction objects. + __ CmpLogicalP(r3, Operand(FIRST_FUNCTION_TYPE)); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ bge(&function); // Check if the constructor in the map is a JS function. Register instance_type = r4; diff --git a/chromium/v8/src/full-codegen/x64/full-codegen-x64.cc b/chromium/v8/src/full-codegen/x64/full-codegen-x64.cc index b7e7cdd2ef8..992e7fe4f72 100644 --- a/chromium/v8/src/full-codegen/x64/full-codegen-x64.cc +++ b/chromium/v8/src/full-codegen/x64/full-codegen-x64.cc @@ -2871,9 +2871,10 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax); __ j(below, &null, Label::kNear); - // Return 'Function' for JSFunction objects. - __ CmpInstanceType(rax, JS_FUNCTION_TYPE); - __ j(equal, &function, Label::kNear); + // Return 'Function' for JSFunction and JSBoundFunction objects. + __ CmpInstanceType(rax, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ j(above_equal, &function, Label::kNear); // Check if the constructor in the map is a JS function. __ GetMapConstructor(rax, rax, rbx); diff --git a/chromium/v8/src/full-codegen/x87/full-codegen-x87.cc b/chromium/v8/src/full-codegen/x87/full-codegen-x87.cc index 8d2114340d9..f14aaf69b02 100644 --- a/chromium/v8/src/full-codegen/x87/full-codegen-x87.cc +++ b/chromium/v8/src/full-codegen/x87/full-codegen-x87.cc @@ -2871,9 +2871,10 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax); __ j(below, &null, Label::kNear); - // Return 'Function' for JSFunction objects. - __ CmpInstanceType(eax, JS_FUNCTION_TYPE); - __ j(equal, &function, Label::kNear); + // Return 'Function' for JSFunction and JSBoundFunction objects. + __ CmpInstanceType(eax, FIRST_FUNCTION_TYPE); + STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); + __ j(above_equal, &function, Label::kNear); // Check if the constructor in the map is a JS function. __ GetMapConstructor(eax, eax, ebx); diff --git a/chromium/v8/src/heap/heap.cc b/chromium/v8/src/heap/heap.cc index 70e6c53d98b..c3f56ac4c52 100644 --- a/chromium/v8/src/heap/heap.cc +++ b/chromium/v8/src/heap/heap.cc @@ -3138,9 +3138,11 @@ void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) { // the heap using HeapIterator, we can update the live byte count. We cannot // update while using HeapIterator because the iterator is temporarily // marking the whole object graph, without updating live bytes. - if (!in_heap_iterator() && - !mark_compact_collector()->sweeping_in_progress() && - Marking::IsBlack(Marking::MarkBitFrom(object->address()))) { + if (lo_space()->Contains(object)) { + lo_space()->AdjustLiveBytes(by); + } else if (!in_heap_iterator() && + !mark_compact_collector()->sweeping_in_progress() && + Marking::IsBlack(Marking::MarkBitFrom(object->address()))) { if (mode == SEQUENTIAL_TO_SWEEPER) { MemoryChunk::IncrementLiveBytesFromGC(object, by); } else { diff --git a/chromium/v8/src/heap/heap.h b/chromium/v8/src/heap/heap.h index f6b49a33a74..94574535619 100644 --- a/chromium/v8/src/heap/heap.h +++ b/chromium/v8/src/heap/heap.h @@ -551,6 +551,7 @@ class Heap { STATIC_ASSERT(kUndefinedValueRootIndex == Internals::kUndefinedValueRootIndex); + STATIC_ASSERT(kTheHoleValueRootIndex == Internals::kTheHoleValueRootIndex); STATIC_ASSERT(kNullValueRootIndex == Internals::kNullValueRootIndex); STATIC_ASSERT(kTrueValueRootIndex == Internals::kTrueValueRootIndex); STATIC_ASSERT(kFalseValueRootIndex == Internals::kFalseValueRootIndex); diff --git a/chromium/v8/src/heap/incremental-marking.cc b/chromium/v8/src/heap/incremental-marking.cc index c82fc83ff7f..376e8488ced 100644 --- a/chromium/v8/src/heap/incremental-marking.cc +++ b/chromium/v8/src/heap/incremental-marking.cc @@ -568,10 +568,6 @@ void IncrementalMarking::StartMarking() { IncrementalMarkingRootMarkingVisitor visitor(this); heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); - if (FLAG_black_allocation) { - StartBlackAllocation(); - } - // Ready to start incremental marking. if (FLAG_trace_incremental_marking) { PrintF("[IncrementalMarking] Running\n"); @@ -591,9 +587,11 @@ void IncrementalMarking::StartBlackAllocation() { } void IncrementalMarking::FinishBlackAllocation() { - black_allocation_ = false; - if (FLAG_trace_incremental_marking) { - PrintF("[IncrementalMarking] Black allocation finished\n"); + if (black_allocation_) { + black_allocation_ = false; + if (FLAG_trace_incremental_marking) { + PrintF("[IncrementalMarking] Black allocation finished\n"); + } } } @@ -768,6 +766,13 @@ void IncrementalMarking::FinalizeIncrementally() { FLAG_min_progress_during_incremental_marking_finalization)) { finalize_marking_completed_ = true; } + + if (FLAG_black_allocation && !heap()->ShouldReduceMemory() && + !black_allocation_) { + // TODO(hpayer): Move to an earlier point as soon as we make faster marking + // progress. + StartBlackAllocation(); + } } diff --git a/chromium/v8/src/heap/spaces.h b/chromium/v8/src/heap/spaces.h index c66aef0a183..93a81cc9333 100644 --- a/chromium/v8/src/heap/spaces.h +++ b/chromium/v8/src/heap/spaces.h @@ -3024,6 +3024,8 @@ class LargeObjectSpace : public Space { // Checks whether the space is empty. bool IsEmpty() { return first_page_ == NULL; } + void AdjustLiveBytes(int by) { objects_size_ += by; } + LargePage* first_page() { return first_page_; } #ifdef VERIFY_HEAP diff --git a/chromium/v8/src/ic/ic.cc b/chromium/v8/src/ic/ic.cc index ebf4bda33a0..c5835e4f54e 100644 --- a/chromium/v8/src/ic/ic.cc +++ b/chromium/v8/src/ic/ic.cc @@ -1207,6 +1207,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, break; } if (!holder->HasFastProperties()) break; + if (info->is_sloppy() && !receiver->IsJSReceiver()) break; NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); return compiler.CompileLoadCallback(lookup->name(), info); @@ -1756,6 +1757,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); break; } + if (info->is_sloppy() && !receiver->IsJSReceiver()) break; NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); return compiler.CompileStoreCallback(receiver, lookup->name(), info, language_mode()); @@ -2798,12 +2800,17 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) { DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); Handle<Name> name = args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); - Handle<JSObject> receiver = - args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); + Handle<Object> receiver = + args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); Handle<JSObject> holder = args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); HandleScope scope(isolate); + if (!receiver->IsJSReceiver()) { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, receiver, Object::ConvertReceiver(isolate, receiver)); + } + InterceptorInfo* interceptor = holder->GetNamedInterceptor(); PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, *holder, Object::DONT_THROW); @@ -2829,11 +2836,16 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) { DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); Handle<Name> name = args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); - Handle<JSObject> receiver = - args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); + Handle<Object> receiver = + args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); Handle<JSObject> holder = args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); + if (!receiver->IsJSReceiver()) { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, receiver, Object::ConvertReceiver(isolate, receiver)); + } + InterceptorInfo* interceptor = holder->GetNamedInterceptor(); PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, *holder, Object::DONT_THROW); diff --git a/chromium/v8/src/interpreter/bytecode-generator.cc b/chromium/v8/src/interpreter/bytecode-generator.cc index 6d8288acd45..b0fa245e18d 100644 --- a/chromium/v8/src/interpreter/bytecode-generator.cc +++ b/chromium/v8/src/interpreter/bytecode-generator.cc @@ -3151,7 +3151,7 @@ void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { LanguageMode BytecodeGenerator::language_mode() const { - return info()->language_mode(); + return execution_context()->scope()->language_mode(); } diff --git a/chromium/v8/src/isolate-inl.h b/chromium/v8/src/isolate-inl.h index c27b7a700d4..da36f769a0a 100644 --- a/chromium/v8/src/isolate-inl.h +++ b/chromium/v8/src/isolate-inl.h @@ -97,6 +97,24 @@ Isolate::ExceptionScope::~ExceptionScope() { NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSOR) #undef NATIVE_CONTEXT_FIELD_ACCESSOR +bool Isolate::IsArraySpeciesLookupChainIntact() { + if (!FLAG_harmony_species) return true; + // Note: It would be nice to have debug checks to make sure that the + // species protector is accurate, but this would be hard to do for most of + // what the protector stands for: + // - You'd need to traverse the heap to check that no Array instance has + // a constructor property + // - To check that Array[Symbol.species] == Array, JS code has to execute, + // but JS cannot be invoked in callstack overflow situations + // All that could be checked reliably is that + // Array.prototype.constructor == Array. Given that limitation, no check is + // done here. In place, there are mjsunit tests harmony/array-species* which + // ensure that behavior is correct in various invalid protector cases. + + PropertyCell* species_cell = heap()->species_protector(); + return species_cell->value()->IsSmi() && + Smi::cast(species_cell->value())->value() == kArrayProtectorValid; +} } // namespace internal } // namespace v8 diff --git a/chromium/v8/src/isolate.cc b/chromium/v8/src/isolate.cc index 34bb33b03d1..c9f01118c5e 100644 --- a/chromium/v8/src/isolate.cc +++ b/chromium/v8/src/isolate.cc @@ -2547,25 +2547,6 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { return cell_reports_intact; } -bool Isolate::IsArraySpeciesLookupChainIntact() { - if (!FLAG_harmony_species) return true; - // Note: It would be nice to have debug checks to make sure that the - // species protector is accurate, but this would be hard to do for most of - // what the protector stands for: - // - You'd need to traverse the heap to check that no Array instance has - // a constructor property or a modified __proto__ - // - To check that Array[Symbol.species] == Array, JS code has to execute, - // but JS cannot be invoked in callstack overflow situations - // All that could be checked reliably is that - // Array.prototype.constructor == Array. Given that limitation, no check is - // done here. In place, there are mjsunit tests harmony/array-species* which - // ensure that behavior is correct in various invalid protector cases. - - PropertyCell* species_cell = heap()->species_protector(); - return species_cell->value()->IsSmi() && - Smi::cast(species_cell->value())->value() == kArrayProtectorValid; -} - void Isolate::InvalidateArraySpeciesProtector() { if (!FLAG_harmony_species) return; DCHECK(factory()->species_protector()->value()->IsSmi()); diff --git a/chromium/v8/src/isolate.h b/chromium/v8/src/isolate.h index e8d963db846..88471640121 100644 --- a/chromium/v8/src/isolate.h +++ b/chromium/v8/src/isolate.h @@ -973,7 +973,7 @@ class Isolate { static const int kArrayProtectorInvalid = 0; bool IsFastArrayConstructorPrototypeChainIntact(); - bool IsArraySpeciesLookupChainIntact(); + inline bool IsArraySpeciesLookupChainIntact(); // On intent to set an element in object, make sure that appropriate // notifications occur if the set is on the elements of the array or diff --git a/chromium/v8/src/js/string.js b/chromium/v8/src/js/string.js index ede5f881604..0eb394e173a 100644 --- a/chromium/v8/src/js/string.js +++ b/chromium/v8/src/js/string.js @@ -564,18 +564,6 @@ function StringTrimRight() { } -// ECMA-262, section 15.5.3.2 -function StringFromCharCode(_) { // length == 1 - "use strict"; - var s = ""; - var n = arguments.length; - for (var i = 0; i < n; ++i) { - s += %_StringCharFromCode(arguments[i] & 0xffff); - } - return s; -} - - // ES6 draft, revision 26 (2014-07-18), section B.2.3.2.1 function HtmlEscape(str) { return %_Call(StringReplace, TO_STRING(str), /"/g, """); @@ -866,7 +854,6 @@ function StringRaw(callSite) { // Set up the non-enumerable functions on the String object. utils.InstallFunctions(GlobalString, DONT_ENUM, [ - "fromCharCode", StringFromCharCode, "fromCodePoint", StringFromCodePoint, "raw", StringRaw ]); diff --git a/chromium/v8/src/messages.h b/chromium/v8/src/messages.h index 3b0538c3617..4aa0b73e717 100644 --- a/chromium/v8/src/messages.h +++ b/chromium/v8/src/messages.h @@ -474,6 +474,7 @@ class CallSite { T(InvalidHexEscapeSequence, "Invalid hexadecimal escape sequence") \ T(InvalidUnicodeEscapeSequence, "Invalid Unicode escape sequence") \ T(UndefinedUnicodeCodePoint, "Undefined Unicode code-point") \ + T(YieldInParameter, "Yield expression not allowed in formal parameter") \ /* EvalError */ \ T(CodeGenFromStrings, "%") \ /* URIError */ \ diff --git a/chromium/v8/src/objects-inl.h b/chromium/v8/src/objects-inl.h index 30ef4e007dc..f4d7fb9fa2e 100644 --- a/chromium/v8/src/objects-inl.h +++ b/chromium/v8/src/objects-inl.h @@ -22,6 +22,7 @@ #include "src/heap/heap-inl.h" #include "src/heap/heap.h" #include "src/isolate.h" +#include "src/isolate-inl.h" #include "src/layout-descriptor-inl.h" #include "src/lookup.h" #include "src/objects.h" @@ -2251,7 +2252,6 @@ void Struct::InitializeBody(int object_size) { } } - bool Object::ToArrayLength(uint32_t* index) { return Object::ToUint32(index); } @@ -7225,6 +7225,11 @@ void AccessorInfo::set_is_special_data_property(bool value) { set_flag(BooleanBit::set(flag(), kSpecialDataProperty, value)); } +bool AccessorInfo::is_sloppy() { return BooleanBit::get(flag(), kIsSloppy); } + +void AccessorInfo::set_is_sloppy(bool value) { + set_flag(BooleanBit::set(flag(), kIsSloppy, value)); +} PropertyAttributes AccessorInfo::property_attributes() { return AttributesField::decode(static_cast<uint32_t>(flag())); @@ -7584,6 +7589,11 @@ void JSArray::SetContent(Handle<JSArray> array, } +bool JSArray::HasArrayPrototype(Isolate* isolate) { + return map()->prototype() == *isolate->initial_array_prototype(); +} + + int TypeFeedbackInfo::ic_total_count() { int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); return ICTotalCountField::decode(current); diff --git a/chromium/v8/src/objects.cc b/chromium/v8/src/objects.cc index baec0b73781..1a82c3c07ba 100644 --- a/chromium/v8/src/objects.cc +++ b/chromium/v8/src/objects.cc @@ -115,6 +115,17 @@ MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate, return result; } +// ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee. +// static +MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate, + Handle<Object> object) { + if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object); + if (*object == isolate->heap()->null_value() || + *object == isolate->heap()->undefined_value()) { + return handle(isolate->global_proxy(), isolate); + } + return Object::ToObject(isolate, object); +} // static MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { @@ -719,9 +730,14 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { case LookupIterator::NOT_FOUND: case LookupIterator::TRANSITION: UNREACHABLE(); - case LookupIterator::JSPROXY: - return JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(), - it->GetName(), it->GetReceiver()); + case LookupIterator::JSPROXY: { + bool was_found; + MaybeHandle<Object> result = + JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(), + it->GetName(), it->GetReceiver(), &was_found); + if (!was_found) it->NotFound(); + return result; + } case LookupIterator::INTERCEPTOR: { bool done; Handle<Object> result; @@ -761,7 +777,9 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate, Handle<JSProxy> proxy, Handle<Name> name, - Handle<Object> receiver) { + Handle<Object> receiver, + bool* was_found) { + *was_found = true; if (receiver->IsJSGlobalObject()) { THROW_NEW_ERROR( isolate, @@ -794,7 +812,9 @@ MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate, // 7.a Return target.[[Get]](P, Receiver). LookupIterator it = LookupIterator::PropertyOrElement(isolate, receiver, name, target); - return Object::GetProperty(&it); + MaybeHandle<Object> result = Object::GetProperty(&it); + *was_found = it.IsFound(); + return result; } // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»). Handle<Object> trap_result; @@ -1060,6 +1080,12 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) { v8::ToCData<v8::AccessorNameGetterCallback>(info->getter()); if (call_fun == nullptr) return isolate->factory()->undefined_value(); + if (info->is_sloppy() && !receiver->IsJSReceiver()) { + ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver, + Object::ConvertReceiver(isolate, receiver), + Object); + } + PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, Object::DONT_THROW); Handle<Object> result = args.Call(call_fun, name); @@ -1130,6 +1156,12 @@ Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, // have a setter. if (call_fun == nullptr) return Just(true); + if (info->is_sloppy() && !receiver->IsJSReceiver()) { + ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, receiver, Object::ConvertReceiver(isolate, receiver), + Nothing<bool>()); + } + PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, should_throw); args.Call(call_fun, name, value); @@ -1529,7 +1561,7 @@ MaybeHandle<Object> Object::ArraySpeciesConstructor( return default_species; } if (original_array->IsJSArray() && - Handle<JSReceiver>::cast(original_array)->map()->new_target_is_base() && + Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) && isolate->IsArraySpeciesLookupChainIntact()) { return default_species; } @@ -4084,8 +4116,14 @@ Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, Handle<JSObject> holder = it->GetHolder<JSObject>(); bool result; - PropertyCallbackArguments args(isolate, interceptor->data(), - *it->GetReceiver(), *holder, should_throw); + Handle<Object> receiver = it->GetReceiver(); + if (!receiver->IsJSReceiver()) { + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, + Object::ConvertReceiver(isolate, receiver), + Nothing<bool>()); + } + PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, + *holder, should_throw); if (it->IsElement()) { uint32_t index = it->index(); @@ -5416,9 +5454,14 @@ Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( !interceptor->can_intercept_symbols()) { return Just(ABSENT); } - PropertyCallbackArguments args(isolate, interceptor->data(), - *it->GetReceiver(), *holder, - Object::DONT_THROW); + Handle<Object> receiver = it->GetReceiver(); + if (!receiver->IsJSReceiver()) { + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, + Object::ConvertReceiver(isolate, receiver), + Nothing<PropertyAttributes>()); + } + PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, + *holder, Object::DONT_THROW); if (!interceptor->query()->IsUndefined()) { Handle<Object> result; if (it->IsElement()) { @@ -6018,9 +6061,15 @@ Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it, if (interceptor->deleter()->IsUndefined()) return Nothing<bool>(); Handle<JSObject> holder = it->GetHolder<JSObject>(); + Handle<Object> receiver = it->GetReceiver(); + if (!receiver->IsJSReceiver()) { + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, + Object::ConvertReceiver(isolate, receiver), + Nothing<bool>()); + } - PropertyCallbackArguments args(isolate, interceptor->data(), - *it->GetReceiver(), *holder, should_throw); + PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, + *holder, should_throw); Handle<Object> result; if (it->IsElement()) { uint32_t index = it->index(); @@ -13247,6 +13296,18 @@ Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) { return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource); } +// static +MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate, + Handle<JSBoundFunction> function) { + Handle<String> prefix = isolate->factory()->bound__string(); + if (!function->bound_target_function()->IsJSFunction()) return prefix; + Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()), + isolate); + Handle<Object> target_name = JSFunction::GetName(target); + if (!target_name->IsString()) return prefix; + Factory* factory = isolate->factory(); + return factory->NewConsString(prefix, Handle<String>::cast(target_name)); +} // static Handle<String> JSFunction::ToString(Handle<JSFunction> function) { @@ -15613,16 +15674,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, ShouldThrow should_throw) { Isolate* isolate = object->GetIsolate(); - // Setting the prototype of an Array instance invalidates the species - // protector - // because it could change the constructor property of the instance, which - // could change the @@species constructor. - if (object->IsJSArray() && isolate->IsArraySpeciesLookupChainIntact()) { - isolate->CountUsage( - v8::Isolate::UseCounterFeature::kArrayInstanceProtoModified); - isolate->InvalidateArraySpeciesProtector(); - } - const bool observed = from_javascript && object->map()->is_observed(); Handle<Object> old_value; if (observed) { @@ -16295,9 +16346,13 @@ MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it, Handle<JSObject> holder = it->GetHolder<JSObject>(); Handle<Object> result; - PropertyCallbackArguments args(isolate, interceptor->data(), - *it->GetReceiver(), *holder, - Object::DONT_THROW); + Handle<Object> receiver = it->GetReceiver(); + if (!receiver->IsJSReceiver()) { + ASSIGN_RETURN_ON_EXCEPTION( + isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object); + } + PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, + *holder, Object::DONT_THROW); if (it->IsElement()) { uint32_t index = it->index(); diff --git a/chromium/v8/src/objects.h b/chromium/v8/src/objects.h index ba319d1df17..cbc9c04cddb 100644 --- a/chromium/v8/src/objects.h +++ b/chromium/v8/src/objects.h @@ -1131,6 +1131,10 @@ class Object { MUST_USE_RESULT static MaybeHandle<JSReceiver> ToObject( Isolate* isolate, Handle<Object> object, Handle<Context> context); + // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee. + MUST_USE_RESULT static MaybeHandle<JSReceiver> ConvertReceiver( + Isolate* isolate, Handle<Object> object); + // ES6 section 7.1.14 ToPropertyKey MUST_USE_RESULT static inline MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> input); @@ -7470,6 +7474,9 @@ class JSBoundFunction : public JSObject { // to ES6 section 19.2.3.5 Function.prototype.toString ( ). static Handle<String> ToString(Handle<JSBoundFunction> function); + static MaybeHandle<String> GetName(Isolate* isolate, + Handle<JSBoundFunction> function); + // Layout description. static const int kBoundTargetFunctionOffset = JSObject::kHeaderSize; static const int kBoundThisOffset = kBoundTargetFunctionOffset + kPointerSize; @@ -9817,7 +9824,7 @@ class JSProxy: public JSReceiver { // ES6 9.5.8 MUST_USE_RESULT static MaybeHandle<Object> GetProperty( Isolate* isolate, Handle<JSProxy> proxy, Handle<Name> name, - Handle<Object> receiver); + Handle<Object> receiver, bool* was_found); // ES6 9.5.9 MUST_USE_RESULT static Maybe<bool> SetProperty(Handle<JSProxy> proxy, @@ -10319,6 +10326,12 @@ class JSArray: public JSObject { PropertyDescriptor* desc, ShouldThrow should_throw); + // Checks whether the Array has the current realm's Array.prototype as its + // prototype. This function is best-effort and only gives a conservative + // approximation, erring on the side of false, in particular with respect + // to Proxies and objects with a hidden prototype. + inline bool HasArrayPrototype(Isolate* isolate); + DECLARE_CAST(JSArray) // Dispatched behavior. @@ -10399,6 +10412,9 @@ class AccessorInfo: public Struct { inline bool is_special_data_property(); inline void set_is_special_data_property(bool value); + inline bool is_sloppy(); + inline void set_is_sloppy(bool value); + inline PropertyAttributes property_attributes(); inline void set_property_attributes(PropertyAttributes attributes); @@ -10435,7 +10451,8 @@ class AccessorInfo: public Struct { static const int kAllCanReadBit = 0; static const int kAllCanWriteBit = 1; static const int kSpecialDataProperty = 2; - class AttributesField : public BitField<PropertyAttributes, 3, 3> {}; + static const int kIsSloppy = 3; + class AttributesField : public BitField<PropertyAttributes, 4, 3> {}; DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo); }; diff --git a/chromium/v8/src/parsing/parser-base.h b/chromium/v8/src/parsing/parser-base.h index cdfbe7e0f32..dde6b1dd863 100644 --- a/chromium/v8/src/parsing/parser-base.h +++ b/chromium/v8/src/parsing/parser-base.h @@ -710,15 +710,6 @@ class ParserBase : public Traits { classifier->RecordArrowFormalParametersError(location, message, arg); } - void FormalParameterInitializerUnexpectedToken( - ExpressionClassifier* classifier) { - MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; - const char* arg; - Scanner::Location location = scanner()->peek_location(); - GetUnexpectedTokenMessage(peek(), &message, &location, &arg); - classifier->RecordFormalParameterInitializerError(location, message, arg); - } - // Recursive descent functions: // Parses an identifier that is valid for the current scope, in particular it @@ -838,8 +829,12 @@ class ParserBase : public Traits { void CheckPossibleEvalCall(ExpressionT expression, Scope* scope) { if (Traits::IsIdentifier(expression) && Traits::IsEval(Traits::AsIdentifier(expression))) { - scope->DeclarationScope()->RecordEvalCall(); scope->RecordEvalCall(); + if (is_sloppy(scope->language_mode())) { + // For sloppy scopes we also have to record the call at function level, + // in case it includes declarations that will be hoisted. + scope->DeclarationScope()->RecordEvalCall(); + } } } @@ -1343,7 +1338,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, CHECK_OK); class_name_location = scanner()->location(); } - return this->ParseClassLiteral(name, class_name_location, + return this->ParseClassLiteral(classifier, name, class_name_location, is_strict_reserved_name, class_token_position, ok); } @@ -1917,6 +1912,13 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, Token::String(Token::ARROW)); ValidateArrowFormalParameters(&arrow_formals_classifier, expression, parenthesized_formals, CHECK_OK); + // This reads strangely, but is correct: it checks whether any + // sub-expression of the parameter list failed to be a valid formal + // parameter initializer. Since YieldExpressions are banned anywhere + // in an arrow parameter list, this is correct. + // TODO(adamk): Rename "FormalParameterInitializerError" to refer to + // "YieldExpression", which is its only use. + ValidateFormalParameterInitializer(&arrow_formals_classifier, ok); Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos); Scope* scope = this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); @@ -2052,7 +2054,8 @@ ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier, int pos = peek_position(); classifier->RecordPatternError(scanner()->peek_location(), MessageTemplate::kInvalidDestructuringTarget); - FormalParameterInitializerUnexpectedToken(classifier); + classifier->RecordFormalParameterInitializerError( + scanner()->peek_location(), MessageTemplate::kYieldInParameter); Expect(Token::YIELD, CHECK_OK); ExpressionT generator_object = factory()->NewVariableProxy(function_state_->generator_object_variable()); diff --git a/chromium/v8/src/parsing/parser.cc b/chromium/v8/src/parsing/parser.cc index 717b3f6491f..fa2893b64b9 100644 --- a/chromium/v8/src/parsing/parser.cc +++ b/chromium/v8/src/parsing/parser.cc @@ -756,11 +756,11 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( function_token_position, type, language_mode, ok); } - ClassLiteral* ParserTraits::ParseClassLiteral( - const AstRawString* name, Scanner::Location class_name_location, - bool name_is_strict_reserved, int pos, bool* ok) { - return parser_->ParseClassLiteral(name, class_name_location, + Type::ExpressionClassifier* classifier, const AstRawString* name, + Scanner::Location class_name_location, bool name_is_strict_reserved, + int pos, bool* ok) { + return parser_->ParseClassLiteral(classifier, name, class_name_location, name_is_strict_reserved, pos, ok); } @@ -1571,9 +1571,9 @@ Statement* Parser::ParseExportDefault(bool* ok) { if (peek() == Token::EXTENDS || peek() == Token::LBRACE) { // ClassDeclaration[+Default] :: // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' - default_export = - ParseClassLiteral(default_string, Scanner::Location::invalid(), - false, position(), CHECK_OK); + default_export = ParseClassLiteral(nullptr, default_string, + Scanner::Location::invalid(), false, + position(), CHECK_OK); result = factory()->NewEmptyStatement(RelocInfo::kNoPosition); } else { result = ParseClassDeclaration(&names, CHECK_OK); @@ -2156,7 +2156,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, bool is_strict_reserved = false; const AstRawString* name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); - ClassLiteral* value = ParseClassLiteral(name, scanner()->location(), + ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(), is_strict_reserved, pos, CHECK_OK); VariableProxy* proxy = NewUnresolved(name, LET); @@ -4697,8 +4697,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( return result; } - -ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, +ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, + const AstRawString* name, Scanner::Location class_name_location, bool name_is_strict_reserved, int pos, bool* ok) { @@ -4731,9 +4731,13 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, Expression* extends = NULL; if (Check(Token::EXTENDS)) { block_scope->set_start_position(scanner()->location().end_pos); - ExpressionClassifier classifier(this); - extends = ParseLeftHandSideExpression(&classifier, CHECK_OK); - RewriteNonPattern(&classifier, CHECK_OK); + ExpressionClassifier extends_classifier(this); + extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK); + RewriteNonPattern(&extends_classifier, CHECK_OK); + if (classifier != nullptr) { + classifier->Accumulate(&extends_classifier, + ExpressionClassifier::ExpressionProductions); + } } else { block_scope->set_start_position(scanner()->location().end_pos); } @@ -4754,12 +4758,16 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, const bool is_static = false; bool is_computed_name = false; // Classes do not care about computed // property names here. - ExpressionClassifier classifier(this); + ExpressionClassifier property_classifier(this); const AstRawString* property_name = nullptr; ObjectLiteral::Property* property = ParsePropertyDefinition( &checker, in_class, has_extends, is_static, &is_computed_name, - &has_seen_constructor, &classifier, &property_name, CHECK_OK); - RewriteNonPattern(&classifier, CHECK_OK); + &has_seen_constructor, &property_classifier, &property_name, CHECK_OK); + RewriteNonPattern(&property_classifier, CHECK_OK); + if (classifier != nullptr) { + classifier->Accumulate(&property_classifier, + ExpressionClassifier::ExpressionProductions); + } if (has_seen_constructor && constructor == NULL) { constructor = GetPropertyValue(property)->AsFunctionLiteral(); diff --git a/chromium/v8/src/parsing/parser.h b/chromium/v8/src/parsing/parser.h index 3c8d07e6f52..c82682e3236 100644 --- a/chromium/v8/src/parsing/parser.h +++ b/chromium/v8/src/parsing/parser.h @@ -573,7 +573,8 @@ class ParserTraits { const ParserFormalParameters& parameters, FunctionKind kind, FunctionLiteral::FunctionType function_type, bool* ok); - ClassLiteral* ParseClassLiteral(const AstRawString* name, + ClassLiteral* ParseClassLiteral(Type::ExpressionClassifier* classifier, + const AstRawString* name, Scanner::Location class_name_location, bool name_is_strict_reserved, int pos, bool* ok); @@ -964,8 +965,8 @@ class Parser : public ParserBase<ParserTraits> { int function_token_position, FunctionLiteral::FunctionType type, LanguageMode language_mode, bool* ok); - - ClassLiteral* ParseClassLiteral(const AstRawString* name, + ClassLiteral* ParseClassLiteral(ExpressionClassifier* classifier, + const AstRawString* name, Scanner::Location class_name_location, bool name_is_strict_reserved, int pos, bool* ok); diff --git a/chromium/v8/src/parsing/preparser.cc b/chromium/v8/src/parsing/preparser.cc index 613651a3b1a..da1c35bcc06 100644 --- a/chromium/v8/src/parsing/preparser.cc +++ b/chromium/v8/src/parsing/preparser.cc @@ -135,11 +135,11 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( return kPreParseSuccess; } - PreParserExpression PreParserTraits::ParseClassLiteral( - PreParserIdentifier name, Scanner::Location class_name_location, - bool name_is_strict_reserved, int pos, bool* ok) { - return pre_parser_->ParseClassLiteral(name, class_name_location, + Type::ExpressionClassifier* classifier, PreParserIdentifier name, + Scanner::Location class_name_location, bool name_is_strict_reserved, + int pos, bool* ok) { + return pre_parser_->ParseClassLiteral(classifier, name, class_name_location, name_is_strict_reserved, pos, ok); } @@ -413,8 +413,8 @@ PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { bool is_strict_reserved = false; Identifier name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); - ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, - CHECK_OK); + ParseClassLiteral(nullptr, name, scanner()->location(), is_strict_reserved, + pos, CHECK_OK); return Statement::Default(); } @@ -1061,10 +1061,10 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok, scope_->uses_super_property(), scope_->calls_eval()); } - PreParserExpression PreParser::ParseClassLiteral( - PreParserIdentifier name, Scanner::Location class_name_location, - bool name_is_strict_reserved, int pos, bool* ok) { + ExpressionClassifier* classifier, PreParserIdentifier name, + Scanner::Location class_name_location, bool name_is_strict_reserved, + int pos, bool* ok) { // All parts of a ClassDeclaration and ClassExpression are strict code. if (name_is_strict_reserved) { ReportMessageAt(class_name_location, @@ -1088,9 +1088,13 @@ PreParserExpression PreParser::ParseClassLiteral( bool has_extends = Check(Token::EXTENDS); if (has_extends) { - ExpressionClassifier classifier(this); - ParseLeftHandSideExpression(&classifier, CHECK_OK); - ValidateExpression(&classifier, CHECK_OK); + ExpressionClassifier extends_classifier(this); + ParseLeftHandSideExpression(&extends_classifier, CHECK_OK); + ValidateExpression(&extends_classifier, CHECK_OK); + if (classifier != nullptr) { + classifier->Accumulate(&extends_classifier, + ExpressionClassifier::ExpressionProductions); + } } ClassLiteralChecker checker(this); @@ -1104,11 +1108,15 @@ PreParserExpression PreParser::ParseClassLiteral( bool is_computed_name = false; // Classes do not care about computed // property names here. Identifier name; - ExpressionClassifier classifier(this); + ExpressionClassifier property_classifier(this); ParsePropertyDefinition(&checker, in_class, has_extends, is_static, &is_computed_name, &has_seen_constructor, - &classifier, &name, CHECK_OK); - ValidateExpression(&classifier, CHECK_OK); + &property_classifier, &name, CHECK_OK); + ValidateExpression(&property_classifier, CHECK_OK); + if (classifier != nullptr) { + classifier->Accumulate(&property_classifier, + ExpressionClassifier::ExpressionProductions); + } } Expect(Token::RBRACE, CHECK_OK); diff --git a/chromium/v8/src/parsing/preparser.h b/chromium/v8/src/parsing/preparser.h index 0effa21d5f1..f2f69517b25 100644 --- a/chromium/v8/src/parsing/preparser.h +++ b/chromium/v8/src/parsing/preparser.h @@ -882,7 +882,8 @@ class PreParserTraits { int function_token_position, FunctionLiteral::FunctionType type, LanguageMode language_mode, bool* ok); - PreParserExpression ParseClassLiteral(PreParserIdentifier name, + PreParserExpression ParseClassLiteral(Type::ExpressionClassifier* classifier, + PreParserIdentifier name, Scanner::Location class_name_location, bool name_is_strict_reserved, int pos, bool* ok); @@ -1071,7 +1072,8 @@ class PreParser : public ParserBase<PreParserTraits> { void ParseLazyFunctionLiteralBody(bool* ok, Scanner::BookmarkScope* bookmark = nullptr); - PreParserExpression ParseClassLiteral(PreParserIdentifier name, + PreParserExpression ParseClassLiteral(ExpressionClassifier* classifier, + PreParserIdentifier name, Scanner::Location class_name_location, bool name_is_strict_reserved, int pos, bool* ok); diff --git a/chromium/v8/src/regexp/regexp-parser.cc b/chromium/v8/src/regexp/regexp-parser.cc index b0dcaa8ee95..d433fc8578a 100644 --- a/chromium/v8/src/regexp/regexp-parser.cc +++ b/chromium/v8/src/regexp/regexp-parser.cc @@ -1430,14 +1430,10 @@ void RegExpBuilder::FlushTerms() { bool RegExpBuilder::NeedsDesugaringForUnicode(RegExpCharacterClass* cc) { if (!unicode()) return false; - switch (cc->standard_type()) { - case 's': // white space - case 'w': // ASCII word character - case 'd': // ASCII digit - return false; // These characters do not need desugaring. - default: - break; - } + // TODO(yangguo): we could be smarter than this. Case-insensitivity does not + // necessarily mean that we need to desugar. It's probably nicer to have a + // separate pass to figure out unicode desugarings. + if (ignore_case()) return true; ZoneList<CharacterRange>* ranges = cc->ranges(zone()); CharacterRange::Canonicalize(ranges); for (int i = ranges->length() - 1; i >= 0; i--) { diff --git a/chromium/v8/src/runtime/runtime-function.cc b/chromium/v8/src/runtime/runtime-function.cc index 939bd53e6a8..011f9ff820a 100644 --- a/chromium/v8/src/runtime/runtime-function.cc +++ b/chromium/v8/src/runtime/runtime-function.cc @@ -16,11 +16,20 @@ namespace v8 { namespace internal { RUNTIME_FUNCTION(Runtime_FunctionGetName) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(JSFunction, f, 0); - return f->shared()->name(); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); + if (function->IsJSBoundFunction()) { + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, JSBoundFunction::GetName( + isolate, Handle<JSBoundFunction>::cast(function))); + return *result; + } else { + RUNTIME_ASSERT(function->IsJSFunction()); + return Handle<JSFunction>::cast(function)->shared()->name(); + } } diff --git a/chromium/v8/src/runtime/runtime-test.cc b/chromium/v8/src/runtime/runtime-test.cc index 5117e42679b..a0f05665a32 100644 --- a/chromium/v8/src/runtime/runtime-test.cc +++ b/chromium/v8/src/runtime/runtime-test.cc @@ -503,5 +503,14 @@ ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties) TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION + + +RUNTIME_FUNCTION(Runtime_SpeciesProtector) { + SealHandleScope shs(isolate); + DCHECK_EQ(0, args.length()); + return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact()); +} + + } // namespace internal } // namespace v8 diff --git a/chromium/v8/src/runtime/runtime.h b/chromium/v8/src/runtime/runtime.h index a55deddb7d2..dc1678bb73e 100644 --- a/chromium/v8/src/runtime/runtime.h +++ b/chromium/v8/src/runtime/runtime.h @@ -922,7 +922,8 @@ namespace internal { F(HasFixedInt32Elements, 1, 1) \ F(HasFixedFloat32Elements, 1, 1) \ F(HasFixedFloat64Elements, 1, 1) \ - F(HasFixedUint8ClampedElements, 1, 1) + F(HasFixedUint8ClampedElements, 1, 1) \ + F(SpeciesProtector, 0, 1) #define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \ F(ArrayBufferGetByteLength, 1, 1) \ diff --git a/chromium/v8/src/s390/code-stubs-s390.cc b/chromium/v8/src/s390/code-stubs-s390.cc index aab8f0d1892..1c7d27b5cae 100644 --- a/chromium/v8/src/s390/code-stubs-s390.cc +++ b/chromium/v8/src/s390/code-stubs-s390.cc @@ -1193,7 +1193,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) { ProfileEntryHookStub::MaybeCallEntryHook(masm); // saving floating point registers -#if V8_HOST_ARCH_S390X +#if V8_TARGET_ARCH_S390X // 64bit ABI requires f8 to f15 be saved __ lay(sp, MemOperand(sp, -8 * kDoubleSize)); __ std(d8, MemOperand(sp)); @@ -1355,7 +1355,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) { __ la(sp, MemOperand(sp, 10 * kPointerSize)); // saving floating point registers -#if V8_HOST_ARCH_S390X +#if V8_TARGET_ARCH_S390X // 64bit ABI requires f8 to f15 be saved __ ld(d8, MemOperand(sp)); __ ld(d9, MemOperand(sp, 1 * kDoubleSize)); diff --git a/chromium/v8/src/typing-asm.cc b/chromium/v8/src/typing-asm.cc index 942b57b66b7..7482c4f6519 100644 --- a/chromium/v8/src/typing-asm.cc +++ b/chromium/v8/src/typing-asm.cc @@ -1553,8 +1553,6 @@ AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable, if (!entry && in_function_) { entry = global_variable_type_.Lookup(variable, ComputePointerHash(variable)); - if (entry && entry->value) { - } } } if (!entry) return NULL; |