summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/lithium.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/lithium.cc')
-rw-r--r--chromium/v8/src/lithium.cc267
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);
+ }
+ }
}