diff --git a/HISTORY.md b/HISTORY.md
index 0491618..28819bc 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,7 +2,9 @@
 
 ## [Unreleased changes](http://github.com/ms-ati/docile/compare/v1.3.5...master)
 
-  ...
+  - Short-circuit to calling #instance_exec directly on the DSL object (prior to
+    constructing a proxy object) when the DSL object and block context object are
+    identical
 
 ## [v1.3.5 (Jan 13, 2021)](http://github.com/ms-ati/docile/compare/v1.3.4...v1.3.5)
 
diff --git a/lib/docile/execution.rb b/lib/docile/execution.rb
index 38cdb2c..253227c 100644
--- a/lib/docile/execution.rb
+++ b/lib/docile/execution.rb
@@ -16,6 +16,13 @@ module Execution
     # @return           [Object] the return value of the block
     def exec_in_proxy_context(dsl, proxy_type, *args, &block)
       block_context = eval("self", block.binding)
+
+      # Use #equal? to test strict object identity (assuming that this dictum
+      # from the Ruby docs holds: "[u]nlike ==, the equal? method should never
+      # be overridden by subclasses as it is used to determine object
+      # identity")
+      return dsl.instance_exec(*args, &block) if dsl.equal?(block_context)
+
       proxy_context = proxy_type.new(dsl, block_context)
       begin
         block_context.instance_variables.each do |ivar|
diff --git a/spec/docile_spec.rb b/spec/docile_spec.rb
index dd26d08..d118426 100644
--- a/spec/docile_spec.rb
+++ b/spec/docile_spec.rb
@@ -414,6 +414,12 @@ def dsl_eval_string(string)
         expect(dsl.foo).to eq(0)
         expect(dsl.bar).to eq(1)
       end
+
+      context "when the DSL object is frozen" do
+        it "can call non-mutative code without raising an exception" do
+          expect { dsl.freeze.dsl_eval_string('1 + 2') }.not_to raise_error
+        end
+      end
     end
 
     context "when NoMethodError is raised" do