[wasm] Randomize code generation order.
Security feature: pick compiled functions randomly Bug: v8:6417 Change-Id: Ibcef9ba94e3730a47cd43d2a59b23d5cee3fad40 Reviewed-on: https://chromium-review.googlesource.com/511842 Commit-Queue: Brad Nelson <bradnelson@chromium.org> Reviewed-by: Brad Nelson <bradnelson@chromium.org> Cr-Commit-Position: refs/heads/master@{#45472}
This commit is contained in:
parent
6a9f54e875
commit
44951380ee
@ -8,6 +8,7 @@
|
|||||||
#include "src/asmjs/asm-js.h"
|
#include "src/asmjs/asm-js.h"
|
||||||
#include "src/assembler-inl.h"
|
#include "src/assembler-inl.h"
|
||||||
#include "src/base/atomic-utils.h"
|
#include "src/base/atomic-utils.h"
|
||||||
|
#include "src/base/utils/random-number-generator.h"
|
||||||
#include "src/code-stubs.h"
|
#include "src/code-stubs.h"
|
||||||
#include "src/compiler/wasm-compiler.h"
|
#include "src/compiler/wasm-compiler.h"
|
||||||
#include "src/debug/interface-types.h"
|
#include "src/debug/interface-types.h"
|
||||||
@ -290,6 +291,42 @@ bool compile_lazy(const WasmModule* module) {
|
|||||||
(FLAG_asm_wasm_lazy_compilation && module->is_asm_js());
|
(FLAG_asm_wasm_lazy_compilation && module->is_asm_js());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CodeGenerationSchedule {
|
||||||
|
public:
|
||||||
|
explicit CodeGenerationSchedule(
|
||||||
|
base::RandomNumberGenerator* random_number_generator)
|
||||||
|
: random_number_generator_(random_number_generator) {
|
||||||
|
DCHECK_NOT_NULL(random_number_generator_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Schedule(std::unique_ptr<compiler::WasmCompilationUnit>&& item) {
|
||||||
|
schedule_.push_back(std::move(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const { return schedule_.empty(); }
|
||||||
|
|
||||||
|
std::unique_ptr<compiler::WasmCompilationUnit> GetNext() {
|
||||||
|
DCHECK(!IsEmpty());
|
||||||
|
size_t index = GetRandomIndexInSchedule();
|
||||||
|
auto ret = std::move(schedule_[index]);
|
||||||
|
std::swap(schedule_[schedule_.size() - 1], schedule_[index]);
|
||||||
|
schedule_.pop_back();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t GetRandomIndexInSchedule() {
|
||||||
|
double factor = random_number_generator_->NextDouble();
|
||||||
|
size_t index = (size_t)(factor * schedule_.size());
|
||||||
|
DCHECK_GE(index, 0);
|
||||||
|
DCHECK_LT(index, schedule_.size());
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::RandomNumberGenerator* random_number_generator_ = nullptr;
|
||||||
|
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> schedule_;
|
||||||
|
};
|
||||||
|
|
||||||
// A helper for compiling an entire module.
|
// A helper for compiling an entire module.
|
||||||
class CompilationHelper {
|
class CompilationHelper {
|
||||||
public:
|
public:
|
||||||
@ -299,7 +336,10 @@ class CompilationHelper {
|
|||||||
// reclaimed by explicitely releasing the {module_} field.
|
// reclaimed by explicitely releasing the {module_} field.
|
||||||
CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module,
|
CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module,
|
||||||
bool is_sync)
|
bool is_sync)
|
||||||
: isolate_(isolate), module_(std::move(module)), is_sync_(is_sync) {}
|
: isolate_(isolate),
|
||||||
|
module_(std::move(module)),
|
||||||
|
is_sync_(is_sync),
|
||||||
|
executed_units_(isolate->random_number_generator()) {}
|
||||||
|
|
||||||
// The actual runnable task that performs compilations in the background.
|
// The actual runnable task that performs compilations in the background.
|
||||||
class CompilationTask : public CancelableTask {
|
class CompilationTask : public CancelableTask {
|
||||||
@ -320,7 +360,7 @@ class CompilationHelper {
|
|||||||
bool is_sync_;
|
bool is_sync_;
|
||||||
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>>
|
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>>
|
||||||
compilation_units_;
|
compilation_units_;
|
||||||
std::queue<std::unique_ptr<compiler::WasmCompilationUnit>> executed_units_;
|
CodeGenerationSchedule executed_units_;
|
||||||
base::Mutex result_mutex_;
|
base::Mutex result_mutex_;
|
||||||
base::AtomicNumber<size_t> next_unit_;
|
base::AtomicNumber<size_t> next_unit_;
|
||||||
size_t num_background_tasks_ = 0;
|
size_t num_background_tasks_ = 0;
|
||||||
@ -349,7 +389,7 @@ class CompilationHelper {
|
|||||||
unit->ExecuteCompilation();
|
unit->ExecuteCompilation();
|
||||||
{
|
{
|
||||||
base::LockGuard<base::Mutex> guard(&result_mutex_);
|
base::LockGuard<base::Mutex> guard(&result_mutex_);
|
||||||
executed_units_.push(std::move(unit));
|
executed_units_.Schedule(std::move(unit));
|
||||||
if (!finisher_is_running_) {
|
if (!finisher_is_running_) {
|
||||||
no_finisher_callback();
|
no_finisher_callback();
|
||||||
// We set the flag here so that not more than one finisher is started.
|
// We set the flag here so that not more than one finisher is started.
|
||||||
@ -429,9 +469,8 @@ class CompilationHelper {
|
|||||||
std::unique_ptr<compiler::WasmCompilationUnit> unit;
|
std::unique_ptr<compiler::WasmCompilationUnit> unit;
|
||||||
{
|
{
|
||||||
base::LockGuard<base::Mutex> guard(&result_mutex_);
|
base::LockGuard<base::Mutex> guard(&result_mutex_);
|
||||||
if (executed_units_.empty()) return Handle<Code>::null();
|
if (executed_units_.IsEmpty()) return Handle<Code>::null();
|
||||||
unit = std::move(executed_units_.front());
|
unit = executed_units_.GetNext();
|
||||||
executed_units_.pop();
|
|
||||||
}
|
}
|
||||||
*func_index = unit->func_index();
|
*func_index = unit->func_index();
|
||||||
Handle<Code> result = unit->FinishCompilation(thrower);
|
Handle<Code> result = unit->FinishCompilation(thrower);
|
||||||
|
Loading…
Reference in New Issue
Block a user