diff options
Diffstat (limited to 'chromium/v8/src/lithium.cc')
-rw-r--r-- | chromium/v8/src/lithium.cc | 267 |
1 files changed, 204 insertions, 63 deletions
diff --git a/chromium/v8/src/lithium.cc b/chromium/v8/src/lithium.cc index 414d5f4edeb..b292b4ffd3a 100644 --- a/chromium/v8/src/lithium.cc +++ b/chromium/v8/src/lithium.cc @@ -1,46 +1,30 @@ // Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "v8.h" -#include "lithium.h" -#include "scopes.h" +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/v8.h" +#include "src/lithium.h" +#include "src/scopes.h" +#include "src/serialize.h" #if V8_TARGET_ARCH_IA32 -#include "ia32/lithium-ia32.h" -#include "ia32/lithium-codegen-ia32.h" +#include "src/ia32/lithium-ia32.h" +#include "src/ia32/lithium-codegen-ia32.h" #elif V8_TARGET_ARCH_X64 -#include "x64/lithium-x64.h" -#include "x64/lithium-codegen-x64.h" +#include "src/x64/lithium-x64.h" +#include "src/x64/lithium-codegen-x64.h" #elif V8_TARGET_ARCH_ARM -#include "arm/lithium-arm.h" -#include "arm/lithium-codegen-arm.h" +#include "src/arm/lithium-arm.h" +#include "src/arm/lithium-codegen-arm.h" #elif V8_TARGET_ARCH_MIPS -#include "mips/lithium-mips.h" -#include "mips/lithium-codegen-mips.h" +#include "src/mips/lithium-mips.h" +#include "src/mips/lithium-codegen-mips.h" +#elif V8_TARGET_ARCH_ARM64 +#include "src/arm64/lithium-arm64.h" +#include "src/arm64/lithium-codegen-arm64.h" +#elif V8_TARGET_ARCH_X87 +#include "src/x87/lithium-x87.h" +#include "src/x87/lithium-codegen-x87.h" #else #error "Unknown architecture." #endif @@ -82,6 +66,9 @@ void LOperand::PrintTo(StringStream* stream) { case LUnallocated::MUST_HAVE_REGISTER: stream->Add("(R)"); break; + case LUnallocated::MUST_HAVE_DOUBLE_REGISTER: + stream->Add("(D)"); + break; case LUnallocated::WRITABLE_REGISTER: stream->Add("(WR)"); break; @@ -108,39 +95,40 @@ void LOperand::PrintTo(StringStream* stream) { case DOUBLE_REGISTER: stream->Add("[%s|R]", DoubleRegister::AllocationIndexToString(index())); break; - case ARGUMENT: - stream->Add("[arg:%d]", index()); - break; } } -#define DEFINE_OPERAND_CACHE(name, type) \ - L##name* L##name::cache = NULL; \ - \ - void L##name::SetUpCache() { \ - if (cache) return; \ - cache = new L##name[kNumCachedOperands]; \ - for (int i = 0; i < kNumCachedOperands; i++) { \ - cache[i].ConvertTo(type, i); \ - } \ - } \ - \ - void L##name::TearDownCache() { \ - delete[] cache; \ + +template<LOperand::Kind kOperandKind, int kNumCachedOperands> +LSubKindOperand<kOperandKind, kNumCachedOperands>* +LSubKindOperand<kOperandKind, kNumCachedOperands>::cache = NULL; + + +template<LOperand::Kind kOperandKind, int kNumCachedOperands> +void LSubKindOperand<kOperandKind, kNumCachedOperands>::SetUpCache() { + if (cache) return; + cache = new LSubKindOperand[kNumCachedOperands]; + for (int i = 0; i < kNumCachedOperands; i++) { + cache[i].ConvertTo(kOperandKind, i); } +} + + +template<LOperand::Kind kOperandKind, int kNumCachedOperands> +void LSubKindOperand<kOperandKind, kNumCachedOperands>::TearDownCache() { + delete[] cache; +} -LITHIUM_OPERAND_LIST(DEFINE_OPERAND_CACHE) -#undef DEFINE_OPERAND_CACHE void LOperand::SetUpCaches() { -#define LITHIUM_OPERAND_SETUP(name, type) L##name::SetUpCache(); +#define LITHIUM_OPERAND_SETUP(name, type, number) L##name::SetUpCache(); LITHIUM_OPERAND_LIST(LITHIUM_OPERAND_SETUP) #undef LITHIUM_OPERAND_SETUP } void LOperand::TearDownCaches() { -#define LITHIUM_OPERAND_TEARDOWN(name, type) L##name::TearDownCache(); +#define LITHIUM_OPERAND_TEARDOWN(name, type, number) L##name::TearDownCache(); LITHIUM_OPERAND_LIST(LITHIUM_OPERAND_TEARDOWN) #undef LITHIUM_OPERAND_TEARDOWN } @@ -252,7 +240,9 @@ LChunk::LChunk(CompilationInfo* info, HGraph* graph) graph_(graph), instructions_(32, graph->zone()), pointer_maps_(8, graph->zone()), - inlined_closures_(1, graph->zone()) { + inlined_closures_(1, graph->zone()), + deprecation_dependencies_(MapLess(), MapAllocator(graph->zone())), + stability_dependencies_(MapLess(), MapAllocator(graph->zone())) { } @@ -391,6 +381,27 @@ Representation LChunk::LookupLiteralRepresentation( } +void LChunk::CommitDependencies(Handle<Code> code) const { + for (MapSet::const_iterator it = deprecation_dependencies_.begin(), + iend = deprecation_dependencies_.end(); it != iend; ++it) { + Handle<Map> map = *it; + ASSERT(!map->is_deprecated()); + ASSERT(map->CanBeDeprecated()); + Map::AddDependentCode(map, DependentCode::kTransitionGroup, code); + } + + for (MapSet::const_iterator it = stability_dependencies_.begin(), + iend = stability_dependencies_.end(); it != iend; ++it) { + Handle<Map> map = *it; + ASSERT(map->is_stable()); + ASSERT(map->CanTransition()); + Map::AddDependentCode(map, DependentCode::kPrototypeCheckGroup, code); + } + + info_->CommitDependencies(code); +} + + LChunk* LChunk::NewChunk(HGraph* graph) { DisallowHandleAllocation no_handles; DisallowHeapAllocation no_gc; @@ -428,11 +439,13 @@ Handle<Code> LChunk::Codegen() { MarkEmptyBlocks(); if (generator.GenerateCode()) { + generator.CheckEnvironmentUsage(); CodeGenerator::MakeCodePrologue(info(), "optimized"); Code::Flags flags = info()->flags(); Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&assembler, flags, info()); generator.FinishCode(code); + CommitDependencies(code); code->set_is_crankshafted(true); void* jit_handler_data = assembler.positions_recorder()->DetachJITHandlerData(); @@ -440,8 +453,12 @@ Handle<Code> LChunk::Codegen() { CodeEndLinePosInfoRecordEvent(*code, jit_handler_data)); CodeGenerator::PrintCode(code, info()); + ASSERT(!(info()->isolate()->serializer_enabled() && + info()->GetMustNotHaveEagerFrame() && + generator.NeedsEagerFrame())); return code; } + assembler.AbortedCodeGeneration(); return Handle<Code>::null(); } @@ -463,11 +480,135 @@ void LChunk::set_allocated_double_registers(BitVector* allocated_registers) { } -LInstruction* LChunkBuilder::CheckElideControlInstruction( - HControlInstruction* instr) { - HBasicBlock* successor; - if (!instr->KnownSuccessorBlock(&successor)) return NULL; - return new(zone()) LGoto(successor); +LEnvironment* LChunkBuilderBase::CreateEnvironment( + HEnvironment* hydrogen_env, + int* argument_index_accumulator, + ZoneList<HValue*>* objects_to_materialize) { + if (hydrogen_env == NULL) return NULL; + + LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(), + argument_index_accumulator, + objects_to_materialize); + BailoutId ast_id = hydrogen_env->ast_id(); + ASSERT(!ast_id.IsNone() || + hydrogen_env->frame_type() != JS_FUNCTION); + int value_count = hydrogen_env->length() - hydrogen_env->specials_count(); + LEnvironment* result = + new(zone()) LEnvironment(hydrogen_env->closure(), + hydrogen_env->frame_type(), + ast_id, + hydrogen_env->parameter_count(), + argument_count_, + value_count, + outer, + hydrogen_env->entry(), + zone()); + int argument_index = *argument_index_accumulator; + + // Store the environment description into the environment + // (with holes for nested objects) + for (int i = 0; i < hydrogen_env->length(); ++i) { + if (hydrogen_env->is_special_index(i)) continue; + + LOperand* op; + HValue* value = hydrogen_env->values()->at(i); + CHECK(!value->IsPushArguments()); // Do not deopt outgoing arguments + if (value->IsArgumentsObject() || value->IsCapturedObject()) { + op = LEnvironment::materialization_marker(); + } else { + op = UseAny(value); + } + result->AddValue(op, + value->representation(), + value->CheckFlag(HInstruction::kUint32)); + } + + // Recursively store the nested objects into the environment + for (int i = 0; i < hydrogen_env->length(); ++i) { + if (hydrogen_env->is_special_index(i)) continue; + + HValue* value = hydrogen_env->values()->at(i); + if (value->IsArgumentsObject() || value->IsCapturedObject()) { + AddObjectToMaterialize(value, objects_to_materialize, result); + } + } + + if (hydrogen_env->frame_type() == JS_FUNCTION) { + *argument_index_accumulator = argument_index; + } + + return result; +} + + +// Add an object to the supplied environment and object materialization list. +// +// Notes: +// +// We are building three lists here: +// +// 1. In the result->object_mapping_ list (added to by the +// LEnvironment::Add*Object methods), we store the lengths (number +// of fields) of the captured objects in depth-first traversal order, or +// in case of duplicated objects, we store the index to the duplicate object +// (with a tag to differentiate between captured and duplicated objects). +// +// 2. The object fields are stored in the result->values_ list +// (added to by the LEnvironment.AddValue method) sequentially as lists +// of fields with holes for nested objects (the holes will be expanded +// later by LCodegen::AddToTranslation according to the +// LEnvironment.object_mapping_ list). +// +// 3. The auxiliary objects_to_materialize array stores the hydrogen values +// in the same order as result->object_mapping_ list. This is used +// to detect duplicate values and calculate the corresponding object index. +void LChunkBuilderBase::AddObjectToMaterialize(HValue* value, + ZoneList<HValue*>* objects_to_materialize, LEnvironment* result) { + int object_index = objects_to_materialize->length(); + // Store the hydrogen value into the de-duplication array + objects_to_materialize->Add(value, zone()); + // Find out whether we are storing a duplicated value + int previously_materialized_object = -1; + for (int prev = 0; prev < object_index; ++prev) { + if (objects_to_materialize->at(prev) == value) { + previously_materialized_object = prev; + break; + } + } + // Store the captured object length (or duplicated object index) + // into the environment. For duplicated objects, we stop here. + int length = value->OperandCount(); + bool is_arguments = value->IsArgumentsObject(); + if (previously_materialized_object >= 0) { + result->AddDuplicateObject(previously_materialized_object); + return; + } else { + result->AddNewObject(is_arguments ? length - 1 : length, is_arguments); + } + // Store the captured object's fields into the environment + for (int i = is_arguments ? 1 : 0; i < length; ++i) { + LOperand* op; + HValue* arg_value = value->OperandAt(i); + if (arg_value->IsArgumentsObject() || arg_value->IsCapturedObject()) { + // Insert a hole for nested objects + op = LEnvironment::materialization_marker(); + } else { + ASSERT(!arg_value->IsPushArguments()); + // For ordinary values, tell the register allocator we need the value + // to be alive here + op = UseAny(arg_value); + } + result->AddValue(op, + arg_value->representation(), + arg_value->CheckFlag(HInstruction::kUint32)); + } + // Recursively store all the nested captured objects into the environment + for (int i = is_arguments ? 1 : 0; i < length; ++i) { + HValue* arg_value = value->OperandAt(i); + if (arg_value->IsArgumentsObject() || arg_value->IsCapturedObject()) { + AddObjectToMaterialize(arg_value, objects_to_materialize, result); + } + } } |