2012-01-24 08:43:12 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
#ifndef V8_DEOPTIMIZER_H_
|
|
|
|
#define V8_DEOPTIMIZER_H_
|
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
#include <stack>
|
2017-09-07 11:53:26 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/allocation.h"
|
2017-09-12 19:54:11 +00:00
|
|
|
#include "src/base/macros.h"
|
2017-07-20 09:41:09 +00:00
|
|
|
#include "src/boxed-float.h"
|
2018-07-12 11:40:37 +00:00
|
|
|
#include "src/code-tracer.h"
|
2016-07-18 09:23:28 +00:00
|
|
|
#include "src/deoptimize-reason.h"
|
2018-03-07 10:05:14 +00:00
|
|
|
#include "src/feedback-vector.h"
|
2017-08-03 09:35:57 +00:00
|
|
|
#include "src/frame-constants.h"
|
Reland "[deoptimizer] Refactor GenerateDeoptimizationEntries"
This is a reland of f63a657ed95e2778c6b8261fd7aff171df9180d4
Original change's description:
> [deoptimizer] Refactor GenerateDeoptimizationEntries
>
> This reduces preprocessor-expanded source size by 64,359 from
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,830 to 52,964,659 ( 144x)
> test ( 392 files): 490,924 to 37,360,916 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,093 to 102,461,098 ( 87x)
>
> to
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,837 to 52,919,005 ( 144x)
> test ( 392 files): 490,924 to 37,342,211 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,100 to 102,396,739 ( 86x)
>
> Bug: v8:8562
> Change-Id: Iee474e22ababa1e080b8d6359af4d0076903e59a
> Reviewed-on: https://chromium-review.googlesource.com/c/1384091
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58424}
TBR=jarin@chromium.org,ulan@chromium.org
Bug: v8:8562
Change-Id: I7a8a350414941f49c6155ff43e36e0cb0b2006e5
Reviewed-on: https://chromium-review.googlesource.com/c/1387497
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58437}
2018-12-21 11:18:52 +00:00
|
|
|
#include "src/frames.h"
|
2018-06-13 10:50:19 +00:00
|
|
|
#include "src/globals.h"
|
2018-03-21 11:12:49 +00:00
|
|
|
#include "src/isolate.h"
|
Reland "[deoptimizer] Refactor GenerateDeoptimizationEntries"
This is a reland of f63a657ed95e2778c6b8261fd7aff171df9180d4
Original change's description:
> [deoptimizer] Refactor GenerateDeoptimizationEntries
>
> This reduces preprocessor-expanded source size by 64,359 from
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,830 to 52,964,659 ( 144x)
> test ( 392 files): 490,924 to 37,360,916 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,093 to 102,461,098 ( 87x)
>
> to
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,837 to 52,919,005 ( 144x)
> test ( 392 files): 490,924 to 37,342,211 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,100 to 102,396,739 ( 86x)
>
> Bug: v8:8562
> Change-Id: Iee474e22ababa1e080b8d6359af4d0076903e59a
> Reviewed-on: https://chromium-review.googlesource.com/c/1384091
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58424}
TBR=jarin@chromium.org,ulan@chromium.org
Bug: v8:8562
Change-Id: I7a8a350414941f49c6155ff43e36e0cb0b2006e5
Reviewed-on: https://chromium-review.googlesource.com/c/1387497
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58437}
2018-12-21 11:18:52 +00:00
|
|
|
#include "src/label.h"
|
2018-08-02 09:10:10 +00:00
|
|
|
#include "src/objects/shared-function-info.h"
|
Reland "[deoptimizer] Refactor GenerateDeoptimizationEntries"
This is a reland of f63a657ed95e2778c6b8261fd7aff171df9180d4
Original change's description:
> [deoptimizer] Refactor GenerateDeoptimizationEntries
>
> This reduces preprocessor-expanded source size by 64,359 from
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,830 to 52,964,659 ( 144x)
> test ( 392 files): 490,924 to 37,360,916 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,093 to 102,461,098 ( 87x)
>
> to
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,837 to 52,919,005 ( 144x)
> test ( 392 files): 490,924 to 37,342,211 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,100 to 102,396,739 ( 86x)
>
> Bug: v8:8562
> Change-Id: Iee474e22ababa1e080b8d6359af4d0076903e59a
> Reviewed-on: https://chromium-review.googlesource.com/c/1384091
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58424}
TBR=jarin@chromium.org,ulan@chromium.org
Bug: v8:8562
Change-Id: I7a8a350414941f49c6155ff43e36e0cb0b2006e5
Reviewed-on: https://chromium-review.googlesource.com/c/1387497
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58437}
2018-12-21 11:18:52 +00:00
|
|
|
#include "src/register-arch.h"
|
2016-08-23 12:35:20 +00:00
|
|
|
#include "src/source-position.h"
|
2016-11-03 17:16:00 +00:00
|
|
|
#include "src/zone/zone-chunk-list.h"
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
class FrameDescription;
|
|
|
|
class TranslationIterator;
|
2011-06-29 13:02:00 +00:00
|
|
|
class DeoptimizedFrameInfo;
|
2015-06-08 10:04:51 +00:00
|
|
|
class TranslatedState;
|
|
|
|
class RegisterValues;
|
Reland "[deoptimizer] Refactor GenerateDeoptimizationEntries"
This is a reland of f63a657ed95e2778c6b8261fd7aff171df9180d4
Original change's description:
> [deoptimizer] Refactor GenerateDeoptimizationEntries
>
> This reduces preprocessor-expanded source size by 64,359 from
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,830 to 52,964,659 ( 144x)
> test ( 392 files): 490,924 to 37,360,916 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,093 to 102,461,098 ( 87x)
>
> to
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,837 to 52,919,005 ( 144x)
> test ( 392 files): 490,924 to 37,342,211 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,100 to 102,396,739 ( 86x)
>
> Bug: v8:8562
> Change-Id: Iee474e22ababa1e080b8d6359af4d0076903e59a
> Reviewed-on: https://chromium-review.googlesource.com/c/1384091
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58424}
TBR=jarin@chromium.org,ulan@chromium.org
Bug: v8:8562
Change-Id: I7a8a350414941f49c6155ff43e36e0cb0b2006e5
Reviewed-on: https://chromium-review.googlesource.com/c/1387497
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58437}
2018-12-21 11:18:52 +00:00
|
|
|
class MacroAssembler;
|
2015-06-08 10:04:51 +00:00
|
|
|
|
2015-06-30 08:24:44 +00:00
|
|
|
class TranslatedValue {
|
2015-06-08 10:04:51 +00:00
|
|
|
public:
|
|
|
|
// Allocation-less getter of the value.
|
2018-07-04 09:10:05 +00:00
|
|
|
// Returns ReadOnlyRoots::arguments_marker() if allocation would be necessary
|
|
|
|
// to get the value.
|
2018-12-25 00:19:47 +00:00
|
|
|
Object GetRawValue() const;
|
2017-12-11 08:14:34 +00:00
|
|
|
|
|
|
|
// Getter for the value, takes care of materializing the subgraph
|
|
|
|
// reachable from this value.
|
2015-06-08 10:04:51 +00:00
|
|
|
Handle<Object> GetValue();
|
|
|
|
|
|
|
|
bool IsMaterializedObject() const;
|
2016-02-15 07:36:15 +00:00
|
|
|
bool IsMaterializableByDebugger() const;
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
friend class TranslatedState;
|
|
|
|
friend class TranslatedFrame;
|
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
enum Kind : uint8_t {
|
2015-06-08 10:04:51 +00:00
|
|
|
kInvalid,
|
|
|
|
kTagged,
|
|
|
|
kInt32,
|
2018-09-14 15:28:42 +00:00
|
|
|
kInt64,
|
2015-06-08 10:04:51 +00:00
|
|
|
kUInt32,
|
|
|
|
kBoolBit,
|
2016-06-03 14:16:15 +00:00
|
|
|
kFloat,
|
2015-06-08 10:04:51 +00:00
|
|
|
kDouble,
|
2017-06-26 12:40:11 +00:00
|
|
|
kCapturedObject, // Object captured by the escape analysis.
|
|
|
|
// The number of nested objects can be obtained
|
|
|
|
// with the DeferredObjectLength() method
|
|
|
|
// (the values of the nested objects follow
|
|
|
|
// this value in the depth-first order.)
|
|
|
|
kDuplicatedObject // Duplicated object of a deferred object.
|
2015-06-08 10:04:51 +00:00
|
|
|
};
|
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
enum MaterializationState : uint8_t {
|
|
|
|
kUninitialized,
|
|
|
|
kAllocated, // Storage for the object has been allocated (or
|
|
|
|
// enqueued for allocation).
|
|
|
|
kFinished, // The object has been initialized (or enqueued for
|
|
|
|
// initialization).
|
|
|
|
};
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
TranslatedValue(TranslatedState* container, Kind kind)
|
|
|
|
: kind_(kind), container_(container) {}
|
|
|
|
Kind kind() const { return kind_; }
|
2017-12-11 08:14:34 +00:00
|
|
|
MaterializationState materialization_state() const {
|
|
|
|
return materialization_state_;
|
|
|
|
}
|
2015-06-08 10:04:51 +00:00
|
|
|
void Handlify();
|
|
|
|
int GetChildrenCount() const;
|
|
|
|
|
|
|
|
static TranslatedValue NewDeferredObject(TranslatedState* container,
|
|
|
|
int length, int object_index);
|
|
|
|
static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
|
2017-01-26 09:25:59 +00:00
|
|
|
static TranslatedValue NewFloat(TranslatedState* container, Float32 value);
|
|
|
|
static TranslatedValue NewDouble(TranslatedState* container, Float64 value);
|
2015-06-08 10:04:51 +00:00
|
|
|
static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
|
2018-09-14 15:28:42 +00:00
|
|
|
static TranslatedValue NewInt64(TranslatedState* container, int64_t value);
|
2015-06-08 10:04:51 +00:00
|
|
|
static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
|
|
|
|
static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
|
2018-12-25 00:19:47 +00:00
|
|
|
static TranslatedValue NewTagged(TranslatedState* container, Object literal);
|
2015-06-09 13:10:10 +00:00
|
|
|
static TranslatedValue NewInvalid(TranslatedState* container);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
Isolate* isolate() const;
|
|
|
|
void MaterializeSimple();
|
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
void set_storage(Handle<HeapObject> storage) { storage_ = storage; }
|
|
|
|
void set_initialized_storage(Handle<Object> storage);
|
|
|
|
void mark_finished() { materialization_state_ = kFinished; }
|
|
|
|
void mark_allocated() { materialization_state_ = kAllocated; }
|
|
|
|
|
|
|
|
Handle<Object> GetStorage() {
|
|
|
|
DCHECK_NE(kUninitialized, materialization_state());
|
|
|
|
return storage_;
|
|
|
|
}
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
Kind kind_;
|
2017-12-11 08:14:34 +00:00
|
|
|
MaterializationState materialization_state_ = kUninitialized;
|
2015-06-08 10:04:51 +00:00
|
|
|
TranslatedState* container_; // This is only needed for materialization of
|
|
|
|
// objects and constructing handles (to get
|
|
|
|
// to the isolate).
|
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
Handle<Object> storage_; // Contains the materialized value or the
|
|
|
|
// byte-array that will be later morphed into
|
|
|
|
// the materialized object.
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
struct MaterializedObjectInfo {
|
|
|
|
int id_;
|
2017-06-26 12:40:11 +00:00
|
|
|
int length_; // Applies only to kCapturedObject kinds.
|
2015-06-08 10:04:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
union {
|
|
|
|
// kind kTagged. After handlification it is always nullptr.
|
2018-12-25 00:19:47 +00:00
|
|
|
Object raw_literal_;
|
2015-06-08 10:04:51 +00:00
|
|
|
// kind is kUInt32 or kBoolBit.
|
|
|
|
uint32_t uint32_value_;
|
|
|
|
// kind is kInt32.
|
|
|
|
int32_t int32_value_;
|
2018-09-14 15:28:42 +00:00
|
|
|
// kind is kInt64.
|
|
|
|
int64_t int64_value_;
|
2016-06-03 14:16:15 +00:00
|
|
|
// kind is kFloat
|
2017-01-26 09:25:59 +00:00
|
|
|
Float32 float_value_;
|
2015-06-08 10:04:51 +00:00
|
|
|
// kind is kDouble
|
2017-01-26 09:25:59 +00:00
|
|
|
Float64 double_value_;
|
2017-06-26 12:40:11 +00:00
|
|
|
// kind is kDuplicatedObject or kCapturedObject.
|
2015-06-08 10:04:51 +00:00
|
|
|
MaterializedObjectInfo materialization_info_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Checked accessors for the union members.
|
2018-12-25 00:19:47 +00:00
|
|
|
Object raw_literal() const;
|
2015-06-08 10:04:51 +00:00
|
|
|
int32_t int32_value() const;
|
2018-09-14 15:28:42 +00:00
|
|
|
int64_t int64_value() const;
|
2015-06-08 10:04:51 +00:00
|
|
|
uint32_t uint32_value() const;
|
2017-01-26 09:25:59 +00:00
|
|
|
Float32 float_value() const;
|
|
|
|
Float64 double_value() const;
|
2015-06-08 10:04:51 +00:00
|
|
|
int object_length() const;
|
|
|
|
int object_index() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class TranslatedFrame {
|
|
|
|
public:
|
|
|
|
enum Kind {
|
2015-12-18 18:34:21 +00:00
|
|
|
kInterpretedFunction,
|
2015-06-08 10:04:51 +00:00
|
|
|
kArgumentsAdaptor,
|
|
|
|
kConstructStub,
|
2017-06-07 13:23:33 +00:00
|
|
|
kBuiltinContinuation,
|
|
|
|
kJavaScriptBuiltinContinuation,
|
2018-04-04 06:31:33 +00:00
|
|
|
kJavaScriptBuiltinContinuationWithCatch,
|
2015-06-08 10:04:51 +00:00
|
|
|
kInvalid
|
|
|
|
};
|
|
|
|
|
|
|
|
int GetValueCount();
|
|
|
|
|
|
|
|
Kind kind() const { return kind_; }
|
2015-06-09 13:10:10 +00:00
|
|
|
BailoutId node_id() const { return node_id_; }
|
2015-06-10 11:52:35 +00:00
|
|
|
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
|
2015-06-09 13:10:10 +00:00
|
|
|
int height() const { return height_; }
|
2018-11-12 18:56:11 +00:00
|
|
|
int return_value_offset() const { return return_value_offset_; }
|
|
|
|
int return_value_count() const { return return_value_count_; }
|
2015-06-08 10:04:51 +00:00
|
|
|
|
2018-11-28 19:57:30 +00:00
|
|
|
SharedFunctionInfo raw_shared_info() const {
|
|
|
|
CHECK(!raw_shared_info_.is_null());
|
2016-02-11 12:03:29 +00:00
|
|
|
return raw_shared_info_;
|
|
|
|
}
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
class iterator {
|
|
|
|
public:
|
|
|
|
iterator& operator++() {
|
2018-04-23 07:49:39 +00:00
|
|
|
++input_index_;
|
2015-06-08 10:04:51 +00:00
|
|
|
AdvanceIterator(&position_);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator operator++(int) {
|
2018-11-12 18:56:11 +00:00
|
|
|
iterator original(position_, input_index_);
|
2018-04-23 07:49:39 +00:00
|
|
|
++input_index_;
|
2015-06-08 10:04:51 +00:00
|
|
|
AdvanceIterator(&position_);
|
|
|
|
return original;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const iterator& other) const {
|
2018-04-23 07:49:39 +00:00
|
|
|
// Ignore {input_index_} for equality.
|
2015-06-08 10:04:51 +00:00
|
|
|
return position_ == other.position_;
|
|
|
|
}
|
|
|
|
bool operator!=(const iterator& other) const { return !(*this == other); }
|
|
|
|
|
|
|
|
TranslatedValue& operator*() { return (*position_); }
|
|
|
|
TranslatedValue* operator->() { return &(*position_); }
|
2018-04-20 10:16:00 +00:00
|
|
|
const TranslatedValue& operator*() const { return (*position_); }
|
|
|
|
const TranslatedValue* operator->() const { return &(*position_); }
|
2015-06-08 10:04:51 +00:00
|
|
|
|
2018-04-23 07:49:39 +00:00
|
|
|
int input_index() const { return input_index_; }
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
private:
|
|
|
|
friend TranslatedFrame;
|
|
|
|
|
2018-11-12 18:56:11 +00:00
|
|
|
explicit iterator(std::deque<TranslatedValue>::iterator position,
|
|
|
|
int input_index = 0)
|
|
|
|
: position_(position), input_index_(input_index) {}
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
std::deque<TranslatedValue>::iterator position_;
|
2018-04-23 07:49:39 +00:00
|
|
|
int input_index_;
|
2015-06-08 10:04:51 +00:00
|
|
|
};
|
|
|
|
|
2015-06-09 13:10:10 +00:00
|
|
|
typedef TranslatedValue& reference;
|
|
|
|
typedef TranslatedValue const& const_reference;
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
iterator begin() { return iterator(values_.begin()); }
|
|
|
|
iterator end() { return iterator(values_.end()); }
|
2015-06-10 11:52:35 +00:00
|
|
|
|
2015-06-09 13:10:10 +00:00
|
|
|
reference front() { return values_.front(); }
|
|
|
|
const_reference front() const { return values_.front(); }
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
friend class TranslatedState;
|
|
|
|
|
|
|
|
// Constructor static methods.
|
2015-12-18 18:34:21 +00:00
|
|
|
static TranslatedFrame InterpretedFrame(BailoutId bytecode_offset,
|
2018-11-28 19:57:30 +00:00
|
|
|
SharedFunctionInfo shared_info,
|
2018-11-12 18:56:11 +00:00
|
|
|
int height, int return_value_offset,
|
|
|
|
int return_value_count);
|
2015-06-10 11:52:35 +00:00
|
|
|
static TranslatedFrame AccessorFrame(Kind kind,
|
2018-11-28 19:57:30 +00:00
|
|
|
SharedFunctionInfo shared_info);
|
|
|
|
static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo shared_info,
|
2015-06-08 10:04:51 +00:00
|
|
|
int height);
|
2017-02-09 13:13:06 +00:00
|
|
|
static TranslatedFrame ConstructStubFrame(BailoutId bailout_id,
|
2018-11-28 19:57:30 +00:00
|
|
|
SharedFunctionInfo shared_info,
|
2015-06-10 11:52:35 +00:00
|
|
|
int height);
|
2017-06-07 13:23:33 +00:00
|
|
|
static TranslatedFrame BuiltinContinuationFrame(
|
2018-11-28 19:57:30 +00:00
|
|
|
BailoutId bailout_id, SharedFunctionInfo shared_info, int height);
|
2017-06-07 13:23:33 +00:00
|
|
|
static TranslatedFrame JavaScriptBuiltinContinuationFrame(
|
2018-11-28 19:57:30 +00:00
|
|
|
BailoutId bailout_id, SharedFunctionInfo shared_info, int height);
|
2018-04-04 06:31:33 +00:00
|
|
|
static TranslatedFrame JavaScriptBuiltinContinuationWithCatchFrame(
|
2018-11-28 19:57:30 +00:00
|
|
|
BailoutId bailout_id, SharedFunctionInfo shared_info, int height);
|
2015-06-08 10:04:51 +00:00
|
|
|
static TranslatedFrame InvalidFrame() {
|
2018-11-28 19:57:30 +00:00
|
|
|
return TranslatedFrame(kInvalid, SharedFunctionInfo());
|
2015-06-08 10:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
|
|
|
|
|
2018-11-28 19:57:30 +00:00
|
|
|
TranslatedFrame(Kind kind,
|
|
|
|
SharedFunctionInfo shared_info = SharedFunctionInfo(),
|
2018-11-12 18:56:11 +00:00
|
|
|
int height = 0, int return_value_offset = 0,
|
|
|
|
int return_value_count = 0)
|
2015-06-08 10:04:51 +00:00
|
|
|
: kind_(kind),
|
|
|
|
node_id_(BailoutId::None()),
|
2015-06-10 11:52:35 +00:00
|
|
|
raw_shared_info_(shared_info),
|
2018-11-12 18:56:11 +00:00
|
|
|
height_(height),
|
|
|
|
return_value_offset_(return_value_offset),
|
|
|
|
return_value_count_(return_value_count) {}
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
void Add(const TranslatedValue& value) { values_.push_back(value); }
|
2017-12-11 08:14:34 +00:00
|
|
|
TranslatedValue* ValueAt(int index) { return &(values_[index]); }
|
2015-06-10 11:52:35 +00:00
|
|
|
void Handlify();
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
Kind kind_;
|
|
|
|
BailoutId node_id_;
|
2018-11-28 19:57:30 +00:00
|
|
|
SharedFunctionInfo raw_shared_info_;
|
2015-06-10 11:52:35 +00:00
|
|
|
Handle<SharedFunctionInfo> shared_info_;
|
2015-06-08 10:04:51 +00:00
|
|
|
int height_;
|
2018-11-12 18:56:11 +00:00
|
|
|
int return_value_offset_;
|
|
|
|
int return_value_count_;
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
typedef std::deque<TranslatedValue> ValuesContainer;
|
|
|
|
|
|
|
|
ValuesContainer values_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Auxiliary class for translating deoptimization values.
|
|
|
|
// Typical usage sequence:
|
|
|
|
//
|
|
|
|
// 1. Construct the instance. This will involve reading out the translations
|
|
|
|
// and resolving them to values using the supplied frame pointer and
|
|
|
|
// machine state (registers). This phase is guaranteed not to allocate
|
|
|
|
// and not to use any HandleScope. Any object pointers will be stored raw.
|
|
|
|
//
|
|
|
|
// 2. Handlify pointers. This will convert all the raw pointers to handles.
|
|
|
|
//
|
|
|
|
// 3. Reading out the frame values.
|
|
|
|
//
|
|
|
|
// Note: After the instance is constructed, it is possible to iterate over
|
|
|
|
// the values eagerly.
|
|
|
|
|
|
|
|
class TranslatedState {
|
|
|
|
public:
|
2018-09-19 17:03:08 +00:00
|
|
|
TranslatedState() = default;
|
2017-08-01 13:44:59 +00:00
|
|
|
explicit TranslatedState(const JavaScriptFrame* frame);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
2017-08-01 12:10:32 +00:00
|
|
|
void Prepare(Address stack_frame_pointer);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
// Store newly materialized values into the isolate.
|
2016-11-29 11:34:07 +00:00
|
|
|
void StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
2015-06-10 11:52:35 +00:00
|
|
|
typedef std::vector<TranslatedFrame>::iterator iterator;
|
|
|
|
iterator begin() { return frames_.begin(); }
|
|
|
|
iterator end() { return frames_.end(); }
|
|
|
|
|
2015-06-09 13:10:10 +00:00
|
|
|
typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
|
|
|
|
const_iterator begin() const { return frames_.begin(); }
|
|
|
|
const_iterator end() const { return frames_.end(); }
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
std::vector<TranslatedFrame>& frames() { return frames_; }
|
|
|
|
|
2017-09-27 11:47:10 +00:00
|
|
|
TranslatedFrame* GetFrameFromJSFrameIndex(int jsframe_index);
|
2015-06-08 10:04:51 +00:00
|
|
|
TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
|
|
|
|
int* arguments_count);
|
|
|
|
|
|
|
|
Isolate* isolate() { return isolate_; }
|
|
|
|
|
2018-06-19 14:26:39 +00:00
|
|
|
void Init(Isolate* isolate, Address input_frame_pointer,
|
2018-11-25 02:24:43 +00:00
|
|
|
TranslationIterator* iterator, FixedArray literal_array,
|
2018-06-19 14:26:39 +00:00
|
|
|
RegisterValues* registers, FILE* trace_file, int parameter_count);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
void VerifyMaterializedObjects();
|
2018-01-10 14:57:54 +00:00
|
|
|
bool DoUpdateFeedback();
|
2017-12-11 08:14:34 +00:00
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
private:
|
|
|
|
friend TranslatedValue;
|
|
|
|
|
|
|
|
TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
|
2018-11-25 02:24:43 +00:00
|
|
|
FixedArray literal_array,
|
|
|
|
Address fp, FILE* trace_file);
|
2017-02-28 11:16:27 +00:00
|
|
|
int CreateNextTranslatedValue(int frame_index, TranslationIterator* iterator,
|
2018-11-25 02:24:43 +00:00
|
|
|
FixedArray literal_array, Address fp,
|
2017-02-28 11:16:27 +00:00
|
|
|
RegisterValues* registers, FILE* trace_file);
|
2017-09-04 11:49:25 +00:00
|
|
|
Address ComputeArgumentsPosition(Address input_frame_pointer,
|
|
|
|
CreateArgumentsType type, int* length);
|
2017-02-28 11:16:27 +00:00
|
|
|
void CreateArgumentsElementsTranslatedValues(int frame_index,
|
|
|
|
Address input_frame_pointer,
|
2017-09-04 11:49:25 +00:00
|
|
|
CreateArgumentsType type,
|
|
|
|
FILE* trace_file);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
void UpdateFromPreviouslyMaterializedObjects();
|
2017-12-11 08:14:34 +00:00
|
|
|
void MaterializeFixedDoubleArray(TranslatedFrame* frame, int* value_index,
|
|
|
|
TranslatedValue* slot, Handle<Map> map);
|
|
|
|
void MaterializeMutableHeapNumber(TranslatedFrame* frame, int* value_index,
|
|
|
|
TranslatedValue* slot);
|
|
|
|
|
|
|
|
void EnsureObjectAllocatedAt(TranslatedValue* slot);
|
|
|
|
|
|
|
|
void SkipSlots(int slots_to_skip, TranslatedFrame* frame, int* value_index);
|
|
|
|
|
|
|
|
Handle<ByteArray> AllocateStorageFor(TranslatedValue* slot);
|
|
|
|
void EnsureJSObjectAllocated(TranslatedValue* slot, Handle<Map> map);
|
|
|
|
void EnsurePropertiesAllocatedAndMarked(TranslatedValue* properties_slot,
|
|
|
|
Handle<Map> map);
|
|
|
|
void EnsureChildrenAllocated(int count, TranslatedFrame* frame,
|
|
|
|
int* value_index, std::stack<int>* worklist);
|
|
|
|
void EnsureCapturedObjectAllocatedAt(int object_index,
|
|
|
|
std::stack<int>* worklist);
|
|
|
|
Handle<Object> InitializeObjectAt(TranslatedValue* slot);
|
|
|
|
void InitializeCapturedObjectAt(int object_index, std::stack<int>* worklist,
|
|
|
|
const DisallowHeapAllocation& no_allocation);
|
|
|
|
void InitializeJSObjectAt(TranslatedFrame* frame, int* value_index,
|
|
|
|
TranslatedValue* slot, Handle<Map> map,
|
|
|
|
const DisallowHeapAllocation& no_allocation);
|
|
|
|
void InitializeObjectWithTaggedFieldsAt(
|
|
|
|
TranslatedFrame* frame, int* value_index, TranslatedValue* slot,
|
|
|
|
Handle<Map> map, const DisallowHeapAllocation& no_allocation);
|
|
|
|
|
2017-12-12 15:54:02 +00:00
|
|
|
void ReadUpdateFeedback(TranslationIterator* iterator,
|
2018-11-25 02:24:43 +00:00
|
|
|
FixedArray literal_array, FILE* trace_file);
|
2017-12-12 15:54:02 +00:00
|
|
|
|
2017-12-11 08:14:34 +00:00
|
|
|
TranslatedValue* ResolveCapturedObject(TranslatedValue* slot);
|
|
|
|
TranslatedValue* GetValueByObjectIndex(int object_index);
|
|
|
|
Handle<Object> GetValueAndAdvance(TranslatedFrame* frame, int* value_index);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
static uint32_t GetUInt32Slot(Address fp, int slot_index);
|
2018-09-14 15:28:42 +00:00
|
|
|
static uint64_t GetUInt64Slot(Address fp, int slot_index);
|
2017-01-26 09:25:59 +00:00
|
|
|
static Float32 GetFloatSlot(Address fp, int slot_index);
|
|
|
|
static Float64 GetDoubleSlot(Address fp, int slot_index);
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
std::vector<TranslatedFrame> frames_;
|
2017-12-12 15:54:02 +00:00
|
|
|
Isolate* isolate_ = nullptr;
|
2018-04-13 22:28:05 +00:00
|
|
|
Address stack_frame_pointer_ = kNullAddress;
|
2017-02-28 11:16:27 +00:00
|
|
|
int formal_parameter_count_;
|
2015-06-08 10:04:51 +00:00
|
|
|
|
|
|
|
struct ObjectPosition {
|
|
|
|
int frame_index_;
|
|
|
|
int value_index_;
|
|
|
|
};
|
|
|
|
std::deque<ObjectPosition> object_positions_;
|
2017-12-12 15:54:02 +00:00
|
|
|
Handle<FeedbackVector> feedback_vector_handle_;
|
2018-11-30 19:58:04 +00:00
|
|
|
FeedbackVector feedback_vector_;
|
2017-12-12 15:54:02 +00:00
|
|
|
FeedbackSlot feedback_slot_;
|
2015-06-08 10:04:51 +00:00
|
|
|
};
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2018-09-06 09:08:10 +00:00
|
|
|
class OptimizedFunctionVisitor {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2018-09-19 17:03:08 +00:00
|
|
|
virtual ~OptimizedFunctionVisitor() = default;
|
2018-12-08 02:59:17 +00:00
|
|
|
virtual void VisitFunction(JSFunction function) = 0;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Deoptimizer : public Malloced {
|
|
|
|
public:
|
2015-02-10 14:32:42 +00:00
|
|
|
struct DeoptInfo {
|
2016-07-18 09:23:28 +00:00
|
|
|
DeoptInfo(SourcePosition position, DeoptimizeReason deopt_reason,
|
|
|
|
int deopt_id)
|
2016-05-13 08:49:49 +00:00
|
|
|
: position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
|
2014-09-22 14:16:38 +00:00
|
|
|
|
2015-02-27 13:34:23 +00:00
|
|
|
SourcePosition position;
|
2016-07-18 09:23:28 +00:00
|
|
|
DeoptimizeReason deopt_reason;
|
2016-05-13 08:49:49 +00:00
|
|
|
int deopt_id;
|
|
|
|
|
|
|
|
static const int kNoDeoptId = -1;
|
2014-09-22 06:36:57 +00:00
|
|
|
};
|
|
|
|
|
2018-11-08 21:42:34 +00:00
|
|
|
static DeoptInfo GetDeoptInfo(Code code, Address from);
|
2015-02-10 14:32:42 +00:00
|
|
|
|
2018-11-28 19:57:30 +00:00
|
|
|
static int ComputeSourcePositionFromBytecodeArray(SharedFunctionInfo shared,
|
2016-08-12 12:01:37 +00:00
|
|
|
BailoutId node_id);
|
2016-05-13 08:49:49 +00:00
|
|
|
|
2018-06-13 10:50:19 +00:00
|
|
|
static const char* MessageFor(DeoptimizeKind kind);
|
2012-12-21 07:18:56 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
int output_count() const { return output_count_; }
|
|
|
|
|
2017-09-13 10:56:20 +00:00
|
|
|
Handle<JSFunction> function() const;
|
|
|
|
Handle<Code> compiled_code() const;
|
2018-06-13 10:50:19 +00:00
|
|
|
DeoptimizeKind deopt_kind() const { return deopt_kind_; }
|
2012-12-18 16:25:45 +00:00
|
|
|
|
2012-01-24 08:43:12 +00:00
|
|
|
// Number of created JS frames. Not all created frames are necessarily JS.
|
|
|
|
int jsframe_count() const { return jsframe_count_; }
|
|
|
|
|
2018-12-08 02:59:17 +00:00
|
|
|
static Deoptimizer* New(Address raw_function, DeoptimizeKind kind,
|
2018-06-13 10:50:19 +00:00
|
|
|
unsigned bailout_id, Address from, int fp_to_sp_delta,
|
2011-03-18 20:35:07 +00:00
|
|
|
Isolate* isolate);
|
|
|
|
static Deoptimizer* Grab(Isolate* isolate);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2011-06-29 13:02:00 +00:00
|
|
|
// The returned object with information on the optimized frame needs to be
|
|
|
|
// freed before another one can be generated.
|
|
|
|
static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
|
2012-01-24 08:43:12 +00:00
|
|
|
int jsframe_index,
|
2011-06-29 13:02:00 +00:00
|
|
|
Isolate* isolate);
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
// Deoptimize the function now. Its current optimized code will never be run
|
|
|
|
// again and any activations of the optimized code will get deoptimized when
|
2016-11-29 11:34:07 +00:00
|
|
|
// execution returns. If {code} is specified then the given code is targeted
|
|
|
|
// instead of the function code (e.g. OSR code not installed on function).
|
2018-12-08 02:59:17 +00:00
|
|
|
static void DeoptimizeFunction(JSFunction function, Code code = Code());
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2013-09-04 13:53:24 +00:00
|
|
|
// Deoptimize all code in the given isolate.
|
2019-04-04 08:46:51 +00:00
|
|
|
V8_EXPORT_PRIVATE static void DeoptimizeAll(Isolate* isolate);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2013-09-04 13:53:24 +00:00
|
|
|
// Deoptimizes all optimized code that has been previously marked
|
|
|
|
// (via code->set_marked_for_deoptimization) and unlinks all functions that
|
|
|
|
// refer to that code.
|
|
|
|
static void DeoptimizeMarkedCode(Isolate* isolate);
|
2012-12-17 10:23:52 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
~Deoptimizer();
|
|
|
|
|
2017-09-04 16:56:30 +00:00
|
|
|
void MaterializeHeapObjects();
|
2014-04-25 11:00:37 +00:00
|
|
|
|
2011-03-30 18:05:16 +00:00
|
|
|
static void ComputeOutputFrames(Deoptimizer* deoptimizer);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2019-01-08 13:31:38 +00:00
|
|
|
static Address GetDeoptimizationEntry(Isolate* isolate, DeoptimizeKind kind);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2018-06-19 11:39:25 +00:00
|
|
|
// Returns true if {addr} is a deoptimization entry and stores its type in
|
|
|
|
// {type}. Returns false if {addr} is not a deoptimization entry.
|
|
|
|
static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
|
|
|
|
DeoptimizeKind* type);
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
// Code generation support.
|
|
|
|
static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
|
|
|
|
static int output_count_offset() {
|
|
|
|
return OFFSET_OF(Deoptimizer, output_count_);
|
|
|
|
}
|
|
|
|
static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
|
|
|
|
|
2016-03-09 11:33:10 +00:00
|
|
|
static int caller_frame_top_offset() {
|
|
|
|
return OFFSET_OF(Deoptimizer, caller_frame_top_);
|
|
|
|
}
|
|
|
|
|
2019-04-04 08:46:51 +00:00
|
|
|
V8_EXPORT_PRIVATE static int GetDeoptimizedCodeCount(Isolate* isolate);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
static const int kNotDeoptimizationEntry = -1;
|
|
|
|
|
2013-02-27 14:45:59 +00:00
|
|
|
static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
|
2018-06-13 10:50:19 +00:00
|
|
|
DeoptimizeKind kind);
|
2019-01-08 13:31:38 +00:00
|
|
|
static void EnsureCodeForDeoptimizationEntries(Isolate* isolate);
|
2012-12-18 16:25:45 +00:00
|
|
|
|
2013-03-18 13:57:49 +00:00
|
|
|
Isolate* isolate() const { return isolate_; }
|
|
|
|
|
2019-01-08 13:31:38 +00:00
|
|
|
static const int kMaxNumberOfEntries = 16384;
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
private:
|
2018-04-20 10:16:00 +00:00
|
|
|
friend class FrameWriter;
|
2018-12-25 00:19:47 +00:00
|
|
|
void QueueValueForMaterialization(Address output_address, Object obj,
|
2018-04-23 07:31:54 +00:00
|
|
|
const TranslatedFrame::iterator& iterator);
|
2018-04-20 10:16:00 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2018-12-08 02:59:17 +00:00
|
|
|
Deoptimizer(Isolate* isolate, JSFunction function, DeoptimizeKind kind,
|
2016-08-25 08:14:14 +00:00
|
|
|
unsigned bailout_id, Address from, int fp_to_sp_delta);
|
2018-11-08 21:42:34 +00:00
|
|
|
Code FindOptimizedCode();
|
2012-12-21 07:18:56 +00:00
|
|
|
void PrintFunctionName();
|
2010-12-07 11:31:57 +00:00
|
|
|
void DeleteFrameDescriptions();
|
|
|
|
|
2019-01-08 13:31:38 +00:00
|
|
|
static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
|
|
|
|
DeoptimizeKind type);
|
2018-06-19 11:39:25 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
void DoComputeOutputFrames();
|
2016-03-09 11:33:10 +00:00
|
|
|
void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
|
|
|
|
int frame_index, bool goto_catch_handler);
|
|
|
|
void DoComputeArgumentsAdaptorFrame(TranslatedFrame* translated_frame,
|
|
|
|
int frame_index);
|
|
|
|
void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
|
|
|
|
int frame_index);
|
2018-04-04 06:31:33 +00:00
|
|
|
|
|
|
|
enum class BuiltinContinuationMode {
|
|
|
|
STUB,
|
|
|
|
JAVASCRIPT,
|
|
|
|
JAVASCRIPT_WITH_CATCH,
|
|
|
|
JAVASCRIPT_HANDLE_EXCEPTION
|
|
|
|
};
|
|
|
|
static bool BuiltinContinuationModeIsWithCatch(BuiltinContinuationMode mode);
|
|
|
|
static bool BuiltinContinuationModeIsJavaScript(BuiltinContinuationMode mode);
|
|
|
|
static StackFrame::Type BuiltinContinuationModeToFrameType(
|
|
|
|
BuiltinContinuationMode mode);
|
|
|
|
static Builtins::Name TrampolineForBuiltinContinuation(
|
|
|
|
BuiltinContinuationMode mode, bool must_handle_result);
|
|
|
|
|
2017-06-07 13:23:33 +00:00
|
|
|
void DoComputeBuiltinContinuation(TranslatedFrame* translated_frame,
|
2018-04-04 06:31:33 +00:00
|
|
|
int frame_index,
|
|
|
|
BuiltinContinuationMode mode);
|
2013-04-02 11:28:01 +00:00
|
|
|
|
2016-03-07 12:18:43 +00:00
|
|
|
unsigned ComputeInputFrameAboveFpFixedSize() const;
|
2010-12-07 11:31:57 +00:00
|
|
|
unsigned ComputeInputFrameSize() const;
|
2018-11-28 19:57:30 +00:00
|
|
|
static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo shared);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2018-11-28 19:57:30 +00:00
|
|
|
static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo shared);
|
2018-11-08 21:42:34 +00:00
|
|
|
static unsigned ComputeOutgoingArgumentSize(Code code, unsigned bailout_id);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
Reland "[deoptimizer] Refactor GenerateDeoptimizationEntries"
This is a reland of f63a657ed95e2778c6b8261fd7aff171df9180d4
Original change's description:
> [deoptimizer] Refactor GenerateDeoptimizationEntries
>
> This reduces preprocessor-expanded source size by 64,359 from
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,830 to 52,964,659 ( 144x)
> test ( 392 files): 490,924 to 37,360,916 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,093 to 102,461,098 ( 87x)
>
> to
>
> gen ( 21 files): 71,570 to 1,613,100 ( 23x)
> src ( 624 files): 367,837 to 52,919,005 ( 144x)
> test ( 392 files): 490,924 to 37,342,211 ( 76x)
> third_party ( 432 files): 239,085 to 9,547,902 ( 40x)
> total ( 1521 files): 1,184,100 to 102,396,739 ( 86x)
>
> Bug: v8:8562
> Change-Id: Iee474e22ababa1e080b8d6359af4d0076903e59a
> Reviewed-on: https://chromium-review.googlesource.com/c/1384091
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58424}
TBR=jarin@chromium.org,ulan@chromium.org
Bug: v8:8562
Change-Id: I7a8a350414941f49c6155ff43e36e0cb0b2006e5
Reviewed-on: https://chromium-review.googlesource.com/c/1387497
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58437}
2018-12-21 11:18:52 +00:00
|
|
|
static void GenerateDeoptimizationEntries(MacroAssembler* masm,
|
2019-01-08 13:31:38 +00:00
|
|
|
Isolate* isolate,
|
2018-06-13 10:50:19 +00:00
|
|
|
DeoptimizeKind kind);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2013-09-04 13:53:24 +00:00
|
|
|
// Marks all the code in the given context for deoptimization.
|
2018-11-23 10:06:32 +00:00
|
|
|
static void MarkAllCodeForContext(Context native_context);
|
2013-09-04 13:53:24 +00:00
|
|
|
|
|
|
|
// Deoptimizes all code marked in the given context.
|
2018-11-23 10:06:32 +00:00
|
|
|
static void DeoptimizeMarkedCodeForContext(Context native_context);
|
2013-07-24 11:12:17 +00:00
|
|
|
|
2017-10-04 13:25:07 +00:00
|
|
|
// Some architectures need to push padding together with the TOS register
|
|
|
|
// in order to maintain stack alignment.
|
|
|
|
static bool PadTopOfStackRegister();
|
|
|
|
|
2013-09-04 13:53:24 +00:00
|
|
|
// Searches the list of known deoptimizing code for a Code object
|
|
|
|
// containing the given address (which is supposedly faster than
|
|
|
|
// searching all code objects).
|
2018-11-08 21:42:34 +00:00
|
|
|
Code FindDeoptimizingCode(Address addr);
|
2013-09-04 13:53:24 +00:00
|
|
|
|
2011-03-18 20:35:07 +00:00
|
|
|
Isolate* isolate_;
|
2018-12-08 02:59:17 +00:00
|
|
|
JSFunction function_;
|
2018-11-08 21:42:34 +00:00
|
|
|
Code compiled_code_;
|
2010-12-07 11:31:57 +00:00
|
|
|
unsigned bailout_id_;
|
2018-06-13 10:50:19 +00:00
|
|
|
DeoptimizeKind deopt_kind_;
|
2010-12-07 11:31:57 +00:00
|
|
|
Address from_;
|
|
|
|
int fp_to_sp_delta_;
|
2016-02-12 10:14:42 +00:00
|
|
|
bool deoptimizing_throw_;
|
|
|
|
int catch_handler_data_;
|
|
|
|
int catch_handler_pc_offset_;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
// Input frame description.
|
|
|
|
FrameDescription* input_;
|
|
|
|
// Number of output frames.
|
|
|
|
int output_count_;
|
2012-01-24 08:43:12 +00:00
|
|
|
// Number of output js frames.
|
|
|
|
int jsframe_count_;
|
2010-12-07 11:31:57 +00:00
|
|
|
// Array of output frame descriptions.
|
|
|
|
FrameDescription** output_;
|
|
|
|
|
2016-03-07 12:18:43 +00:00
|
|
|
// Caller frame details computed from input frame.
|
|
|
|
intptr_t caller_frame_top_;
|
|
|
|
intptr_t caller_fp_;
|
|
|
|
intptr_t caller_pc_;
|
|
|
|
intptr_t caller_constant_pool_;
|
|
|
|
intptr_t input_frame_context_;
|
|
|
|
|
The current
version is passing all the existing test + a bunch of new tests
(packaged in the change list, too).
The patch extends the SlotRef object to describe captured and duplicated
objects. Since the SlotRefs are not independent of each other anymore,
there is a new SlotRefValueBuilder class that stores the SlotRefs and
later materializes the objects from the SlotRefs.
Note that unlike the previous implementation of SlotRefs, we now build
the SlotRef entries for the entire frame, not just the particular
function. This is because duplicate objects might refer to previous
captured objects (that might live inside other inlined function's part
of the frame).
We also need to store the materialized objects between other potential
invocations of the same arguments object so that we materialize each
captured object at most once. The materialized objects of frames live
in the new MaterielizedObjectStore object (contained in Isolate),
indexed by the frame's FP address. Each argument materialization (and
deoptimization) tries to lookup its captured objects in the store before
building new ones. Deoptimization also removes the materialized objects
from the store. We also schedule a lazy deopt to be sure that we always
get rid of the materialized objects and that the optmized function
adopts the materialized objects (instead of happily computing with its
captured representations).
Concerns:
- Is the FP address the right key for a frame? (Note that deoptimizer's
representation of frame is different from the argument object
materializer's one - it is not easy to find common ground.)
- Performance is suboptimal in several places, but a quick local run of
benchmarks does not seem to show a perf hit. Examples of possible
improvements: smarter generation of SlotRefs (build other functions'
SlotRefs only for captured objects and only if necessary), smarter
lookup of stored materialized objects.
- Ideally, we would like to share the code for argument materialization
with deoptimizer's materializer. However, the supporting data structures
(mainly the frame descriptor) are quite different in each case, so it
looks more like a separate project.
Thanks for any feedback.
R=danno@chromium.org, mstarzinger@chromium.org
LOG=N
BUG=
Committed: https://code.google.com/p/v8/source/detail?r=18918
Review URL: https://codereview.chromium.org/103243005
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-30 10:33:53 +00:00
|
|
|
// Key for lookup of previously materialized objects
|
2016-03-07 12:18:43 +00:00
|
|
|
intptr_t stack_fp_;
|
The current
version is passing all the existing test + a bunch of new tests
(packaged in the change list, too).
The patch extends the SlotRef object to describe captured and duplicated
objects. Since the SlotRefs are not independent of each other anymore,
there is a new SlotRefValueBuilder class that stores the SlotRefs and
later materializes the objects from the SlotRefs.
Note that unlike the previous implementation of SlotRefs, we now build
the SlotRef entries for the entire frame, not just the particular
function. This is because duplicate objects might refer to previous
captured objects (that might live inside other inlined function's part
of the frame).
We also need to store the materialized objects between other potential
invocations of the same arguments object so that we materialize each
captured object at most once. The materialized objects of frames live
in the new MaterielizedObjectStore object (contained in Isolate),
indexed by the frame's FP address. Each argument materialization (and
deoptimization) tries to lookup its captured objects in the store before
building new ones. Deoptimization also removes the materialized objects
from the store. We also schedule a lazy deopt to be sure that we always
get rid of the materialized objects and that the optmized function
adopts the materialized objects (instead of happily computing with its
captured representations).
Concerns:
- Is the FP address the right key for a frame? (Note that deoptimizer's
representation of frame is different from the argument object
materializer's one - it is not easy to find common ground.)
- Performance is suboptimal in several places, but a quick local run of
benchmarks does not seem to show a perf hit. Examples of possible
improvements: smarter generation of SlotRefs (build other functions'
SlotRefs only for captured objects and only if necessary), smarter
lookup of stored materialized objects.
- Ideally, we would like to share the code for argument materialization
with deoptimizer's materializer. However, the supporting data structures
(mainly the frame descriptor) are quite different in each case, so it
looks more like a separate project.
Thanks for any feedback.
R=danno@chromium.org, mstarzinger@chromium.org
LOG=N
BUG=
Committed: https://code.google.com/p/v8/source/detail?r=18918
Review URL: https://codereview.chromium.org/103243005
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-30 10:33:53 +00:00
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
TranslatedState translated_state_;
|
|
|
|
struct ValueToMaterialize {
|
|
|
|
Address output_slot_address_;
|
|
|
|
TranslatedFrame::iterator value_;
|
|
|
|
};
|
|
|
|
std::vector<ValueToMaterialize> values_to_materialize_;
|
2013-08-07 11:24:14 +00:00
|
|
|
|
2013-06-03 15:32:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
DisallowHeapAllocation* disallow_heap_allocation_;
|
|
|
|
#endif // DEBUG
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2013-11-07 16:35:27 +00:00
|
|
|
CodeTracer::Scope* trace_scope_;
|
2013-02-05 16:28:36 +00:00
|
|
|
|
2011-08-05 11:32:46 +00:00
|
|
|
static const int table_entry_size_;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
friend class FrameDescription;
|
2011-06-29 13:02:00 +00:00
|
|
|
friend class DeoptimizedFrameInfo;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
class RegisterValues {
|
|
|
|
public:
|
|
|
|
intptr_t GetRegister(unsigned n) const {
|
|
|
|
#if DEBUG
|
|
|
|
// This convoluted DCHECK is needed to work around a gcc problem that
|
|
|
|
// improperly detects an array bounds overflow in optimized debug builds
|
|
|
|
// when using a plain DCHECK.
|
|
|
|
if (n >= arraysize(registers_)) {
|
|
|
|
DCHECK(false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return registers_[n];
|
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
Float32 GetFloatRegister(unsigned n) const {
|
2016-06-03 14:16:15 +00:00
|
|
|
DCHECK(n < arraysize(float_registers_));
|
|
|
|
return float_registers_[n];
|
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
Float64 GetDoubleRegister(unsigned n) const {
|
2015-06-08 10:04:51 +00:00
|
|
|
DCHECK(n < arraysize(double_registers_));
|
|
|
|
return double_registers_[n];
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetRegister(unsigned n, intptr_t value) {
|
|
|
|
DCHECK(n < arraysize(registers_));
|
|
|
|
registers_[n] = value;
|
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
void SetFloatRegister(unsigned n, Float32 value) {
|
2016-06-03 14:16:15 +00:00
|
|
|
DCHECK(n < arraysize(float_registers_));
|
|
|
|
float_registers_[n] = value;
|
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
void SetDoubleRegister(unsigned n, Float64 value) {
|
2015-06-08 10:04:51 +00:00
|
|
|
DCHECK(n < arraysize(double_registers_));
|
|
|
|
double_registers_[n] = value;
|
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
// Generated code is writing directly into the below arrays, make sure their
|
|
|
|
// element sizes fit what the machine instructions expect.
|
|
|
|
static_assert(sizeof(Float32) == kFloatSize, "size mismatch");
|
|
|
|
static_assert(sizeof(Float64) == kDoubleSize, "size mismatch");
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
intptr_t registers_[Register::kNumRegisters];
|
[assembler] Make Register et al. real classes
Up to now, each architecture defined all Register types as structs,
with lots of redundancy. An often found comment noted that they cannot
be classes due to initialization order problems. As these problems are
gone with C++11 constexpr constants, I now tried making Registers
classes again.
All register types now inherit from RegisterBase, which provides a
default set of methods and named constructors (like ::from_code,
code(), bit(), is_valid(), ...).
This design allows to guarantee an interesting property: Each register
is either valid, or it's the no_reg register. There are no other
invalid registers. This is guaranteed statically by the constexpr
constructor, and dynamically by ::from_code.
I decided to disallow the default constructor completely, so instead of
"Register reg;" you now need "Register reg = no_reg;". This makes
explicit how the Register is initialized.
I did this change to the x64, ia32, arm, arm64, mips and mips64 ports.
Overall, code got much more compact and more safe. In theory, it should
also increase performance (since the is_valid() check is simpler), but
this is probably not measurable.
R=mstarzinger@chromium.org
Change-Id: I5ccfa4050daf4e146a557970e9d37fd3d2788d4a
Reviewed-on: https://chromium-review.googlesource.com/650927
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47847}
2017-09-06 08:05:07 +00:00
|
|
|
Float32 float_registers_[FloatRegister::kNumRegisters];
|
|
|
|
Float64 double_registers_[DoubleRegister::kNumRegisters];
|
2015-06-08 10:04:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
class FrameDescription {
|
|
|
|
public:
|
2016-02-15 07:36:15 +00:00
|
|
|
explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
void* operator new(size_t size, uint32_t frame_size) {
|
2019-01-17 18:02:38 +00:00
|
|
|
// Subtracts kSystemPointerSize, as the member frame_content_ already
|
|
|
|
// supplies the first element of the area to store the frame.
|
|
|
|
return malloc(size + frame_size - kSystemPointerSize);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2011-08-29 09:14:59 +00:00
|
|
|
void operator delete(void* pointer, uint32_t frame_size) {
|
|
|
|
free(pointer);
|
|
|
|
}
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
void operator delete(void* description) {
|
|
|
|
free(description);
|
|
|
|
}
|
|
|
|
|
2011-06-30 15:57:56 +00:00
|
|
|
uint32_t GetFrameSize() const {
|
2017-09-12 19:54:11 +00:00
|
|
|
USE(frame_content_);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
|
2011-06-30 15:57:56 +00:00
|
|
|
return static_cast<uint32_t>(frame_size_);
|
|
|
|
}
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t GetFrameSlot(unsigned offset) {
|
2010-12-07 11:31:57 +00:00
|
|
|
return *GetFrameSlotPointer(offset);
|
|
|
|
}
|
|
|
|
|
2017-12-18 18:55:23 +00:00
|
|
|
unsigned GetLastArgumentSlotOffset() {
|
|
|
|
int parameter_slots = parameter_count();
|
|
|
|
if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
|
2019-01-17 18:02:38 +00:00
|
|
|
return GetFrameSize() - parameter_slots * kSystemPointerSize;
|
2017-12-18 18:55:23 +00:00
|
|
|
}
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
Address GetFramePointerAddress() {
|
2017-12-18 18:55:23 +00:00
|
|
|
int fp_offset =
|
|
|
|
GetLastArgumentSlotOffset() - StandardFrameConstants::kCallerSPOffset;
|
2015-06-08 10:04:51 +00:00
|
|
|
return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
RegisterValues* GetRegisterValues() { return ®ister_values_; }
|
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
void SetFrameSlot(unsigned offset, intptr_t value) {
|
2010-12-07 11:31:57 +00:00
|
|
|
*GetFrameSlotPointer(offset) = value;
|
|
|
|
}
|
|
|
|
|
2013-07-23 13:46:10 +00:00
|
|
|
void SetCallerPc(unsigned offset, intptr_t value);
|
|
|
|
|
|
|
|
void SetCallerFp(unsigned offset, intptr_t value);
|
|
|
|
|
2014-03-14 15:11:58 +00:00
|
|
|
void SetCallerConstantPool(unsigned offset, intptr_t value);
|
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t GetRegister(unsigned n) const {
|
2015-06-08 10:04:51 +00:00
|
|
|
return register_values_.GetRegister(n);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
Float64 GetDoubleRegister(unsigned n) const {
|
2015-06-08 10:04:51 +00:00
|
|
|
return register_values_.GetDoubleRegister(n);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
void SetRegister(unsigned n, intptr_t value) {
|
2015-06-08 10:04:51 +00:00
|
|
|
register_values_.SetRegister(n, value);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 09:25:59 +00:00
|
|
|
void SetDoubleRegister(unsigned n, Float64 value) {
|
2015-06-08 10:04:51 +00:00
|
|
|
register_values_.SetDoubleRegister(n, value);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t GetTop() const { return top_; }
|
|
|
|
void SetTop(intptr_t top) { top_ = top; }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t GetPc() const { return pc_; }
|
|
|
|
void SetPc(intptr_t pc) { pc_ = pc; }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t GetFp() const { return fp_; }
|
|
|
|
void SetFp(intptr_t fp) { fp_ = fp; }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2012-02-28 09:05:55 +00:00
|
|
|
intptr_t GetContext() const { return context_; }
|
|
|
|
void SetContext(intptr_t context) { context_ = context; }
|
|
|
|
|
2013-12-30 11:23:59 +00:00
|
|
|
intptr_t GetConstantPool() const { return constant_pool_; }
|
|
|
|
void SetConstantPool(intptr_t constant_pool) {
|
|
|
|
constant_pool_ = constant_pool;
|
|
|
|
}
|
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
void SetContinuation(intptr_t pc) { continuation_ = pc; }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2016-02-15 07:36:15 +00:00
|
|
|
// Argument count, including receiver.
|
|
|
|
int parameter_count() { return parameter_count_; }
|
2011-06-29 13:02:00 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
static int registers_offset() {
|
2015-06-08 10:04:51 +00:00
|
|
|
return OFFSET_OF(FrameDescription, register_values_.registers_);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int double_registers_offset() {
|
2015-06-08 10:04:51 +00:00
|
|
|
return OFFSET_OF(FrameDescription, register_values_.double_registers_);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2017-03-22 16:56:03 +00:00
|
|
|
static int float_registers_offset() {
|
|
|
|
return OFFSET_OF(FrameDescription, register_values_.float_registers_);
|
|
|
|
}
|
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
static int frame_size_offset() {
|
2015-06-17 09:06:44 +00:00
|
|
|
return offsetof(FrameDescription, frame_size_);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
2015-06-17 09:06:44 +00:00
|
|
|
static int pc_offset() { return offsetof(FrameDescription, pc_); }
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
static int continuation_offset() {
|
2015-06-17 09:06:44 +00:00
|
|
|
return offsetof(FrameDescription, continuation_);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int frame_content_offset() {
|
2015-06-17 09:06:44 +00:00
|
|
|
return offsetof(FrameDescription, frame_content_);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static const uint32_t kZapUint32 = 0xbeeddead;
|
|
|
|
|
2011-06-30 15:57:56 +00:00
|
|
|
// Frame_size_ must hold a uint32_t value. It is only a uintptr_t to
|
|
|
|
// keep the variable-size array frame_content_ of type intptr_t at
|
|
|
|
// the end of the structure aligned.
|
2010-12-07 11:53:19 +00:00
|
|
|
uintptr_t frame_size_; // Number of bytes.
|
2016-02-15 07:36:15 +00:00
|
|
|
int parameter_count_;
|
2015-06-08 10:04:51 +00:00
|
|
|
RegisterValues register_values_;
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t top_;
|
|
|
|
intptr_t pc_;
|
|
|
|
intptr_t fp_;
|
2012-02-28 09:05:55 +00:00
|
|
|
intptr_t context_;
|
2013-12-30 11:23:59 +00:00
|
|
|
intptr_t constant_pool_;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
// Continuation is the PC where the execution continues after
|
|
|
|
// deoptimizing.
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t continuation_;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2011-03-25 13:26:55 +00:00
|
|
|
// This must be at the end of the object as the object is allocated larger
|
|
|
|
// than it's definition indicate to extend this array.
|
|
|
|
intptr_t frame_content_[1];
|
|
|
|
|
2010-12-07 11:53:19 +00:00
|
|
|
intptr_t* GetFrameSlotPointer(unsigned offset) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(offset < frame_size_);
|
2010-12-07 11:53:19 +00:00
|
|
|
return reinterpret_cast<intptr_t*>(
|
2010-12-07 11:31:57 +00:00
|
|
|
reinterpret_cast<Address>(this) + frame_content_offset() + offset);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-14 11:45:33 +00:00
|
|
|
class DeoptimizerData {
|
|
|
|
public:
|
2017-11-08 11:53:07 +00:00
|
|
|
explicit DeoptimizerData(Heap* heap);
|
2013-05-14 11:45:33 +00:00
|
|
|
~DeoptimizerData();
|
|
|
|
|
2019-01-30 15:18:02 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
bool IsDeoptEntryCode(Code code) const {
|
|
|
|
for (int i = 0; i < kLastDeoptimizeKind + 1; i++) {
|
|
|
|
if (code == deopt_entry_code_[i]) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2013-05-14 11:45:33 +00:00
|
|
|
private:
|
2017-11-08 11:53:07 +00:00
|
|
|
Heap* heap_;
|
2018-06-13 10:50:19 +00:00
|
|
|
static const int kLastDeoptimizeKind =
|
|
|
|
static_cast<int>(DeoptimizeKind::kLastDeoptimizeKind);
|
2018-11-08 21:42:34 +00:00
|
|
|
Code deopt_entry_code_[kLastDeoptimizeKind + 1];
|
|
|
|
Code deopt_entry_code(DeoptimizeKind kind);
|
|
|
|
void set_deopt_entry_code(DeoptimizeKind kind, Code code);
|
2013-05-14 11:45:33 +00:00
|
|
|
|
2013-09-04 13:53:24 +00:00
|
|
|
Deoptimizer* current_;
|
2013-05-14 11:45:33 +00:00
|
|
|
|
|
|
|
friend class Deoptimizer;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
|
|
|
|
};
|
|
|
|
|
2018-09-06 09:08:10 +00:00
|
|
|
class TranslationBuffer {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2016-11-03 17:16:00 +00:00
|
|
|
explicit TranslationBuffer(Zone* zone) : contents_(zone) {}
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2016-11-03 17:16:00 +00:00
|
|
|
int CurrentIndex() const { return static_cast<int>(contents_.size()); }
|
|
|
|
void Add(int32_t value);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2013-03-18 13:57:49 +00:00
|
|
|
Handle<ByteArray> CreateByteArray(Factory* factory);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
private:
|
2016-11-03 17:16:00 +00:00
|
|
|
ZoneChunkList<uint8_t> contents_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
2018-09-06 09:08:10 +00:00
|
|
|
class TranslationIterator {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2018-11-24 08:51:21 +00:00
|
|
|
TranslationIterator(ByteArray buffer, int index);
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
int32_t Next();
|
|
|
|
|
2017-09-13 10:56:20 +00:00
|
|
|
bool HasNext() const;
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
void Skip(int n) {
|
|
|
|
for (int i = 0; i < n; i++) Next();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-11-24 08:51:21 +00:00
|
|
|
ByteArray buffer_;
|
2010-12-07 11:31:57 +00:00
|
|
|
int index_;
|
|
|
|
};
|
|
|
|
|
2018-04-04 06:31:33 +00:00
|
|
|
#define TRANSLATION_OPCODE_LIST(V) \
|
|
|
|
V(BEGIN) \
|
|
|
|
V(INTERPRETED_FRAME) \
|
|
|
|
V(BUILTIN_CONTINUATION_FRAME) \
|
|
|
|
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME) \
|
|
|
|
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) \
|
|
|
|
V(CONSTRUCT_STUB_FRAME) \
|
|
|
|
V(ARGUMENTS_ADAPTOR_FRAME) \
|
|
|
|
V(DUPLICATED_OBJECT) \
|
|
|
|
V(ARGUMENTS_ELEMENTS) \
|
|
|
|
V(ARGUMENTS_LENGTH) \
|
|
|
|
V(CAPTURED_OBJECT) \
|
|
|
|
V(REGISTER) \
|
|
|
|
V(INT32_REGISTER) \
|
2018-09-14 15:28:42 +00:00
|
|
|
V(INT64_REGISTER) \
|
2018-04-04 06:31:33 +00:00
|
|
|
V(UINT32_REGISTER) \
|
|
|
|
V(BOOL_REGISTER) \
|
|
|
|
V(FLOAT_REGISTER) \
|
|
|
|
V(DOUBLE_REGISTER) \
|
|
|
|
V(STACK_SLOT) \
|
|
|
|
V(INT32_STACK_SLOT) \
|
2018-09-14 15:28:42 +00:00
|
|
|
V(INT64_STACK_SLOT) \
|
2018-04-04 06:31:33 +00:00
|
|
|
V(UINT32_STACK_SLOT) \
|
|
|
|
V(BOOL_STACK_SLOT) \
|
|
|
|
V(FLOAT_STACK_SLOT) \
|
|
|
|
V(DOUBLE_STACK_SLOT) \
|
|
|
|
V(LITERAL) \
|
2017-12-12 15:54:02 +00:00
|
|
|
V(UPDATE_FEEDBACK)
|
2013-10-01 11:18:30 +00:00
|
|
|
|
2018-09-06 09:08:10 +00:00
|
|
|
class Translation {
|
2010-12-07 11:31:57 +00:00
|
|
|
public:
|
2013-10-01 11:18:30 +00:00
|
|
|
#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
|
2010-12-07 11:31:57 +00:00
|
|
|
enum Opcode {
|
2013-10-01 11:18:30 +00:00
|
|
|
TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
|
|
|
|
LAST = LITERAL
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
2013-10-01 11:18:30 +00:00
|
|
|
#undef DECLARE_TRANSLATION_OPCODE_ENUM
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2012-06-04 14:42:58 +00:00
|
|
|
Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
|
2017-12-12 15:54:02 +00:00
|
|
|
int update_feedback_count, Zone* zone)
|
|
|
|
: buffer_(buffer), index_(buffer->CurrentIndex()), zone_(zone) {
|
2016-11-03 17:16:00 +00:00
|
|
|
buffer_->Add(BEGIN);
|
|
|
|
buffer_->Add(frame_count);
|
|
|
|
buffer_->Add(jsframe_count);
|
2017-12-12 15:54:02 +00:00
|
|
|
buffer_->Add(update_feedback_count);
|
2010-12-07 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int index() const { return index_; }
|
|
|
|
|
|
|
|
// Commands.
|
2015-12-18 18:34:21 +00:00
|
|
|
void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
|
2018-11-12 18:56:11 +00:00
|
|
|
unsigned height, int return_value_offset,
|
|
|
|
int return_value_count);
|
2012-01-24 08:43:12 +00:00
|
|
|
void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
|
2017-02-09 13:13:06 +00:00
|
|
|
void BeginConstructStubFrame(BailoutId bailout_id, int literal_id,
|
|
|
|
unsigned height);
|
2017-06-07 13:23:33 +00:00
|
|
|
void BeginBuiltinContinuationFrame(BailoutId bailout_id, int literal_id,
|
|
|
|
unsigned height);
|
|
|
|
void BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
|
|
|
|
int literal_id, unsigned height);
|
2018-04-04 06:31:33 +00:00
|
|
|
void BeginJavaScriptBuiltinContinuationWithCatchFrame(BailoutId bailout_id,
|
|
|
|
int literal_id,
|
|
|
|
unsigned height);
|
2017-09-04 11:49:25 +00:00
|
|
|
void ArgumentsElements(CreateArgumentsType type);
|
|
|
|
void ArgumentsLength(CreateArgumentsType type);
|
2013-08-07 11:24:14 +00:00
|
|
|
void BeginCapturedObject(int length);
|
2017-12-12 15:54:02 +00:00
|
|
|
void AddUpdateFeedback(int vector_literal, int slot);
|
2013-08-07 11:24:14 +00:00
|
|
|
void DuplicateObject(int object_index);
|
2010-12-07 11:31:57 +00:00
|
|
|
void StoreRegister(Register reg);
|
|
|
|
void StoreInt32Register(Register reg);
|
2018-09-14 15:28:42 +00:00
|
|
|
void StoreInt64Register(Register reg);
|
2012-08-22 15:44:17 +00:00
|
|
|
void StoreUint32Register(Register reg);
|
2015-04-23 08:07:12 +00:00
|
|
|
void StoreBoolRegister(Register reg);
|
2016-06-03 14:16:15 +00:00
|
|
|
void StoreFloatRegister(FloatRegister reg);
|
2010-12-07 11:31:57 +00:00
|
|
|
void StoreDoubleRegister(DoubleRegister reg);
|
|
|
|
void StoreStackSlot(int index);
|
|
|
|
void StoreInt32StackSlot(int index);
|
2018-09-14 15:28:42 +00:00
|
|
|
void StoreInt64StackSlot(int index);
|
2012-08-22 15:44:17 +00:00
|
|
|
void StoreUint32StackSlot(int index);
|
2015-04-23 08:07:12 +00:00
|
|
|
void StoreBoolStackSlot(int index);
|
2016-06-03 14:16:15 +00:00
|
|
|
void StoreFloatStackSlot(int index);
|
2010-12-07 11:31:57 +00:00
|
|
|
void StoreDoubleStackSlot(int index);
|
|
|
|
void StoreLiteral(int literal_id);
|
2015-06-10 11:52:35 +00:00
|
|
|
void StoreJSFrameFunction();
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2012-06-11 12:42:31 +00:00
|
|
|
Zone* zone() const { return zone_; }
|
2012-06-04 14:42:58 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
static int NumberOfOperandsFor(Opcode opcode);
|
|
|
|
|
2011-06-16 07:58:47 +00:00
|
|
|
#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
|
2010-12-07 11:31:57 +00:00
|
|
|
static const char* StringFor(Opcode opcode);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
private:
|
|
|
|
TranslationBuffer* buffer_;
|
|
|
|
int index_;
|
2012-06-04 14:42:58 +00:00
|
|
|
Zone* zone_;
|
2010-12-07 11:31:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
The current
version is passing all the existing test + a bunch of new tests
(packaged in the change list, too).
The patch extends the SlotRef object to describe captured and duplicated
objects. Since the SlotRefs are not independent of each other anymore,
there is a new SlotRefValueBuilder class that stores the SlotRefs and
later materializes the objects from the SlotRefs.
Note that unlike the previous implementation of SlotRefs, we now build
the SlotRef entries for the entire frame, not just the particular
function. This is because duplicate objects might refer to previous
captured objects (that might live inside other inlined function's part
of the frame).
We also need to store the materialized objects between other potential
invocations of the same arguments object so that we materialize each
captured object at most once. The materialized objects of frames live
in the new MaterielizedObjectStore object (contained in Isolate),
indexed by the frame's FP address. Each argument materialization (and
deoptimization) tries to lookup its captured objects in the store before
building new ones. Deoptimization also removes the materialized objects
from the store. We also schedule a lazy deopt to be sure that we always
get rid of the materialized objects and that the optmized function
adopts the materialized objects (instead of happily computing with its
captured representations).
Concerns:
- Is the FP address the right key for a frame? (Note that deoptimizer's
representation of frame is different from the argument object
materializer's one - it is not easy to find common ground.)
- Performance is suboptimal in several places, but a quick local run of
benchmarks does not seem to show a perf hit. Examples of possible
improvements: smarter generation of SlotRefs (build other functions'
SlotRefs only for captured objects and only if necessary), smarter
lookup of stored materialized objects.
- Ideally, we would like to share the code for argument materialization
with deoptimizer's materializer. However, the supporting data structures
(mainly the frame descriptor) are quite different in each case, so it
looks more like a separate project.
Thanks for any feedback.
R=danno@chromium.org, mstarzinger@chromium.org
LOG=N
BUG=
Committed: https://code.google.com/p/v8/source/detail?r=18918
Review URL: https://codereview.chromium.org/103243005
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-30 10:33:53 +00:00
|
|
|
class MaterializedObjectStore {
|
|
|
|
public:
|
|
|
|
explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle<FixedArray> Get(Address fp);
|
|
|
|
void Set(Address fp, Handle<FixedArray> materialized_objects);
|
2015-05-04 16:43:56 +00:00
|
|
|
bool Remove(Address fp);
|
The current
version is passing all the existing test + a bunch of new tests
(packaged in the change list, too).
The patch extends the SlotRef object to describe captured and duplicated
objects. Since the SlotRefs are not independent of each other anymore,
there is a new SlotRefValueBuilder class that stores the SlotRefs and
later materializes the objects from the SlotRefs.
Note that unlike the previous implementation of SlotRefs, we now build
the SlotRef entries for the entire frame, not just the particular
function. This is because duplicate objects might refer to previous
captured objects (that might live inside other inlined function's part
of the frame).
We also need to store the materialized objects between other potential
invocations of the same arguments object so that we materialize each
captured object at most once. The materialized objects of frames live
in the new MaterielizedObjectStore object (contained in Isolate),
indexed by the frame's FP address. Each argument materialization (and
deoptimization) tries to lookup its captured objects in the store before
building new ones. Deoptimization also removes the materialized objects
from the store. We also schedule a lazy deopt to be sure that we always
get rid of the materialized objects and that the optmized function
adopts the materialized objects (instead of happily computing with its
captured representations).
Concerns:
- Is the FP address the right key for a frame? (Note that deoptimizer's
representation of frame is different from the argument object
materializer's one - it is not easy to find common ground.)
- Performance is suboptimal in several places, but a quick local run of
benchmarks does not seem to show a perf hit. Examples of possible
improvements: smarter generation of SlotRefs (build other functions'
SlotRefs only for captured objects and only if necessary), smarter
lookup of stored materialized objects.
- Ideally, we would like to share the code for argument materialization
with deoptimizer's materializer. However, the supporting data structures
(mainly the frame descriptor) are quite different in each case, so it
looks more like a separate project.
Thanks for any feedback.
R=danno@chromium.org, mstarzinger@chromium.org
LOG=N
BUG=
Committed: https://code.google.com/p/v8/source/detail?r=18918
Review URL: https://codereview.chromium.org/103243005
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-30 10:33:53 +00:00
|
|
|
|
|
|
|
private:
|
2017-04-04 11:29:59 +00:00
|
|
|
Isolate* isolate() const { return isolate_; }
|
The current
version is passing all the existing test + a bunch of new tests
(packaged in the change list, too).
The patch extends the SlotRef object to describe captured and duplicated
objects. Since the SlotRefs are not independent of each other anymore,
there is a new SlotRefValueBuilder class that stores the SlotRefs and
later materializes the objects from the SlotRefs.
Note that unlike the previous implementation of SlotRefs, we now build
the SlotRef entries for the entire frame, not just the particular
function. This is because duplicate objects might refer to previous
captured objects (that might live inside other inlined function's part
of the frame).
We also need to store the materialized objects between other potential
invocations of the same arguments object so that we materialize each
captured object at most once. The materialized objects of frames live
in the new MaterielizedObjectStore object (contained in Isolate),
indexed by the frame's FP address. Each argument materialization (and
deoptimization) tries to lookup its captured objects in the store before
building new ones. Deoptimization also removes the materialized objects
from the store. We also schedule a lazy deopt to be sure that we always
get rid of the materialized objects and that the optmized function
adopts the materialized objects (instead of happily computing with its
captured representations).
Concerns:
- Is the FP address the right key for a frame? (Note that deoptimizer's
representation of frame is different from the argument object
materializer's one - it is not easy to find common ground.)
- Performance is suboptimal in several places, but a quick local run of
benchmarks does not seem to show a perf hit. Examples of possible
improvements: smarter generation of SlotRefs (build other functions'
SlotRefs only for captured objects and only if necessary), smarter
lookup of stored materialized objects.
- Ideally, we would like to share the code for argument materialization
with deoptimizer's materializer. However, the supporting data structures
(mainly the frame descriptor) are quite different in each case, so it
looks more like a separate project.
Thanks for any feedback.
R=danno@chromium.org, mstarzinger@chromium.org
LOG=N
BUG=
Committed: https://code.google.com/p/v8/source/detail?r=18918
Review URL: https://codereview.chromium.org/103243005
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-01-30 10:33:53 +00:00
|
|
|
Handle<FixedArray> GetStackEntries();
|
|
|
|
Handle<FixedArray> EnsureStackEntries(int size);
|
|
|
|
|
|
|
|
int StackIdToIndex(Address fp);
|
|
|
|
|
|
|
|
Isolate* isolate_;
|
2017-09-07 11:53:26 +00:00
|
|
|
std::vector<Address> frame_fps_;
|
2011-04-01 11:41:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-06-29 13:02:00 +00:00
|
|
|
// Class used to represent an unoptimized frame when the debugger
|
|
|
|
// needs to inspect a frame that is part of an optimized frame. The
|
|
|
|
// internally used FrameDescription objects are not GC safe so for use
|
|
|
|
// by the debugger frame information is copied to an object of this type.
|
2012-01-24 08:43:12 +00:00
|
|
|
// Represents parameters in unadapted form so their number might mismatch
|
|
|
|
// formal parameter count.
|
2011-06-29 13:02:00 +00:00
|
|
|
class DeoptimizedFrameInfo : public Malloced {
|
|
|
|
public:
|
2016-02-15 07:36:15 +00:00
|
|
|
DeoptimizedFrameInfo(TranslatedState* state,
|
|
|
|
TranslatedState::iterator frame_it, Isolate* isolate);
|
|
|
|
|
2011-07-07 14:29:16 +00:00
|
|
|
// Return the number of incoming arguments.
|
2016-02-12 05:49:46 +00:00
|
|
|
int parameters_count() { return static_cast<int>(parameters_.size()); }
|
2011-07-07 14:29:16 +00:00
|
|
|
|
2011-06-29 13:02:00 +00:00
|
|
|
// Return the height of the expression stack.
|
2016-02-12 05:49:46 +00:00
|
|
|
int expression_count() { return static_cast<int>(expression_stack_.size()); }
|
2011-06-29 13:02:00 +00:00
|
|
|
|
2011-07-06 13:02:17 +00:00
|
|
|
// Get the frame function.
|
2016-02-12 05:49:46 +00:00
|
|
|
Handle<JSFunction> GetFunction() { return function_; }
|
2011-07-06 13:02:17 +00:00
|
|
|
|
2014-09-01 09:31:14 +00:00
|
|
|
// Get the frame context.
|
2016-02-12 05:49:46 +00:00
|
|
|
Handle<Object> GetContext() { return context_; }
|
2014-09-01 09:31:14 +00:00
|
|
|
|
2011-07-07 14:29:16 +00:00
|
|
|
// Get an incoming argument.
|
2016-02-12 05:49:46 +00:00
|
|
|
Handle<Object> GetParameter(int index) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(0 <= index && index < parameters_count());
|
2011-07-07 14:29:16 +00:00
|
|
|
return parameters_[index];
|
|
|
|
}
|
|
|
|
|
2011-06-29 13:02:00 +00:00
|
|
|
// Get an expression from the expression stack.
|
2016-02-12 05:49:46 +00:00
|
|
|
Handle<Object> GetExpression(int index) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(0 <= index && index < expression_count());
|
2011-06-29 13:02:00 +00:00
|
|
|
return expression_stack_[index];
|
|
|
|
}
|
|
|
|
|
2012-01-31 12:08:33 +00:00
|
|
|
int GetSourcePosition() {
|
|
|
|
return source_position_;
|
2012-01-30 13:07:01 +00:00
|
|
|
}
|
|
|
|
|
2011-06-29 13:02:00 +00:00
|
|
|
private:
|
2011-07-07 14:29:16 +00:00
|
|
|
// Set an incoming argument.
|
2016-02-12 05:49:46 +00:00
|
|
|
void SetParameter(int index, Handle<Object> obj) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(0 <= index && index < parameters_count());
|
2011-07-07 14:29:16 +00:00
|
|
|
parameters_[index] = obj;
|
|
|
|
}
|
|
|
|
|
2011-06-29 13:02:00 +00:00
|
|
|
// Set an expression on the expression stack.
|
2016-02-12 05:49:46 +00:00
|
|
|
void SetExpression(int index, Handle<Object> obj) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(0 <= index && index < expression_count());
|
2011-06-29 13:02:00 +00:00
|
|
|
expression_stack_[index] = obj;
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:49:46 +00:00
|
|
|
Handle<JSFunction> function_;
|
|
|
|
Handle<Object> context_;
|
|
|
|
std::vector<Handle<Object> > parameters_;
|
|
|
|
std::vector<Handle<Object> > expression_stack_;
|
2012-01-31 12:08:33 +00:00
|
|
|
int source_position_;
|
2011-06-29 13:02:00 +00:00
|
|
|
|
|
|
|
friend class Deoptimizer;
|
|
|
|
};
|
|
|
|
|
2015-06-08 10:04:51 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
2010-12-07 11:31:57 +00:00
|
|
|
|
|
|
|
#endif // V8_DEOPTIMIZER_H_
|